168 lines
4.9 KiB
C++
168 lines
4.9 KiB
C++
|
|
#include "LinearLayout.hh"
|
|
|
|
LinearLayout::LinearLayout(int direction, int width, int height, std::string name)
|
|
: View(width, height, std::move(name)), direction_(direction), padChildren_(0)
|
|
{
|
|
}
|
|
|
|
LinearLayout::~LinearLayout()
|
|
{
|
|
}
|
|
|
|
void LinearLayout::setChildPadding(int pad)
|
|
{
|
|
if (pad != padChildren_) {
|
|
padChildren_ = pad;
|
|
|
|
layout();
|
|
}
|
|
}
|
|
|
|
void LinearLayout::layout(Widget *caller)
|
|
{
|
|
int width, height;
|
|
std::tie(width, height) = Widget::baseLayout(caller);
|
|
|
|
bool widthChanged = false, heightChanged = false;
|
|
|
|
if (direction_ == DIR_VERTICAL) {
|
|
int contentWidth = 0;
|
|
|
|
if (width == 0) {
|
|
// Clear realWidth_ to signal WRAP_CONTENT_FILL children to use WRAP_CONTENT
|
|
realWidth_ = 0;
|
|
// Determine content width
|
|
if (children_.size() == 0)
|
|
return;
|
|
for(auto& ent : children_) {
|
|
auto& child = *(std::get<1>(ent));
|
|
assert(child.getHeight() != MATCH_PARENT);
|
|
if (child.getWidth() == MATCH_PARENT)
|
|
continue;
|
|
if ((child.getWidth() == WRAP_CONTENT) || (child.getWidth() == WRAP_CONTENT_FILL))
|
|
_layout(child);
|
|
contentWidth = std::max(contentWidth, child.getRealWidth());
|
|
}
|
|
assert(contentWidth > 0);
|
|
if (realWidth_ != contentWidth + padLeft_ + padRight_) {
|
|
realWidth_ = contentWidth + padLeft_ + padRight_;
|
|
widthChanged = true;
|
|
}
|
|
printf("Inner width: %d, outer width: %d\n", contentWidth, realWidth_);
|
|
} else
|
|
contentWidth = realWidth_ - padLeft_ - padRight_;
|
|
|
|
// Layout children
|
|
int currentY = padTop_;
|
|
|
|
for(auto& ent : children_) {
|
|
auto& child = *(std::get<1>(ent));
|
|
if (child.getWidth() == MATCH_PARENT)
|
|
_layout(child);
|
|
// Second layout pass for WRAP_CONTENT_FILL children
|
|
if ((child.getWidth() == WRAP_CONTENT_FILL) &&
|
|
(child.getRealWidth() != contentWidth))
|
|
_layout(child);
|
|
|
|
SDL_Rect cr;
|
|
cr.x = padLeft_;
|
|
cr.y = currentY;
|
|
if (contentWidth > child.getRealWidth()) {
|
|
cr.w = child.getRealWidth();
|
|
auto space = contentWidth - child.getRealWidth();
|
|
if (child.getContainerAlignmentHoriz() == ALIGN_CENTER)
|
|
cr.x += space/2;
|
|
else if (child.getContainerAlignmentHoriz() == ALIGN_RIGHT)
|
|
cr.x += space;
|
|
} else
|
|
cr.w = contentWidth;
|
|
cr.h = child.getRealHeight();
|
|
|
|
std::get<2>(ent) = cr;
|
|
|
|
currentY += child.getRealHeight() + padChildren_;
|
|
}
|
|
|
|
if (height == 0)
|
|
if (realHeight_ != currentY - padChildren_ + padBottom_) {
|
|
realHeight_ = currentY - padChildren_ + padBottom_;
|
|
heightChanged = true;
|
|
}
|
|
} else { // direction == DIR_HORIZONTAL
|
|
int contentHeight = 0;
|
|
|
|
if (height == 0) {
|
|
// Clear realHeight_ to signal WRAP_CONTENT_FILL children to use WRAP_CONTENT
|
|
realHeight_ = 0;
|
|
// Determine content height
|
|
if (children_.size() == 0)
|
|
return;
|
|
for(auto& ent : children_) {
|
|
auto& child = *(std::get<1>(ent));
|
|
assert(child.getWidth() != MATCH_PARENT);
|
|
if (child.getHeight() == MATCH_PARENT)
|
|
continue;
|
|
if ((child.getHeight() == WRAP_CONTENT) || (child.getHeight() == WRAP_CONTENT_FILL))
|
|
_layout(child);
|
|
contentHeight = std::max(contentHeight, child.getRealHeight());
|
|
}
|
|
assert(contentHeight > 0);
|
|
if (realHeight_ != contentHeight + padTop_ + padBottom_) {
|
|
realHeight_ = contentHeight + padTop_ + padBottom_;
|
|
heightChanged = true;
|
|
}
|
|
printf("Inner height: %d, outer height: %d\n", contentHeight, realHeight_);
|
|
} else
|
|
contentHeight = realHeight_ - padTop_ - padBottom_;
|
|
|
|
// Layout children
|
|
int currentX = padLeft_;
|
|
|
|
for(auto& ent : children_) {
|
|
auto& child = *(std::get<1>(ent));
|
|
if (child.getHeight() == MATCH_PARENT)
|
|
_layout(child);
|
|
// Second layout pass for WRAP_CONTENT_FILL children
|
|
if ((child.getHeight() == WRAP_CONTENT_FILL) &&
|
|
(child.getRealHeight() != contentHeight))
|
|
_layout(child);
|
|
|
|
SDL_Rect cr;
|
|
cr.x = currentX;
|
|
cr.y = padTop_;
|
|
cr.w = child.getRealWidth();
|
|
if (contentHeight > child.getRealHeight()) {
|
|
cr.h = child.getRealHeight();
|
|
auto space = contentHeight - child.getRealHeight();
|
|
if (child.getContainerAlignmentVert() == ALIGN_CENTER)
|
|
cr.y += space/2;
|
|
else if (child.getContainerAlignmentVert() == ALIGN_BOTTOM)
|
|
cr.y += space;
|
|
} else
|
|
cr.h = contentHeight;
|
|
|
|
std::get<2>(ent) = cr;
|
|
|
|
currentX += child.getRealWidth() + padChildren_;
|
|
}
|
|
|
|
if (width == 0)
|
|
if (realWidth_ != currentX - padChildren_ + padRight_) {
|
|
realWidth_ = currentX - padChildren_ + padRight_;
|
|
widthChanged = true;
|
|
}
|
|
}
|
|
|
|
if (parent_ && (parent_ != caller) &&
|
|
((widthChanged && ((parent_->getWidth() == WRAP_CONTENT) ||
|
|
(parent_->getWidth() == WRAP_CONTENT_FILL))) ||
|
|
(heightChanged && ((parent_->getHeight() == WRAP_CONTENT) ||
|
|
(parent_->getHeight() == WRAP_CONTENT_FILL)))))
|
|
_layout(*parent_);
|
|
|
|
printf("Layout %s now %d, %d\n", name_.c_str(), realWidth_, realHeight_);
|
|
|
|
invalidateGL();
|
|
}
|