#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(); }