diff --git a/src/uilib/hbox.h b/src/uilib/hbox.h index 0650c44..f56e980 100644 --- a/src/uilib/hbox.h +++ b/src/uilib/hbox.h @@ -43,22 +43,30 @@ class HBox : public Container { size.width = _minSize.width; } Container::setSize(size); - // TODO: move this to relayout and run relayout instead - for (auto child : _children) { - child->setTop(_padding + child->getMargin().top); - child->setHeight(size.height - child->getTop() - child->getMargin().bottom - _padding); - } - // FIXME: make this depend on vgrow of *all* chrildren - if (!_children.empty() && _children.back()->getHGrow()) { - // FIXME: this code actually gets run for every addChild() - _children.back()->setWidth(size.width - _children.back()->getLeft() - _padding); - } + relayout(); } + void relayout() { // TODO: virtual? + if (!_children.empty()) { + // sum up all hgrow and resize children based on their hgrow + int totalHGrow = 0; + int extraWidth = _size.width - _minSize.width; + for (auto child: _children) totalHGrow += child->getHGrow(); + // if only the last child grows, we can skip resizing all children and we could skip the relayout + if (extraWidth != 0 && totalHGrow == _children.back()->getHGrow() && _children.back()->getMaxWidth() != _children.back()->getWidth()) { + auto child = _children.back(); + child->setWidth(_size.width - _padding - child->getLeft()); + } + else if (extraWidth != 0 && totalHGrow > 0) { + for (auto child: _children) + child->setWidth(child->getMinWidth() + extraWidth * child->getHGrow() / totalHGrow); + } + } int x=_padding; for (auto& child : _children) { x += child->getMargin().left; child->setTop(child->getMargin().top + _padding); + child->setHeight(_size.height - child->getTop() - child->getMargin().bottom - _padding); child->setLeft(x); x += child->getWidth() + child->getMargin().right + _spacing; } diff --git a/src/uilib/simplecontainer.h b/src/uilib/simplecontainer.h index 0a0b0a7..b585059 100644 --- a/src/uilib/simplecontainer.h +++ b/src/uilib/simplecontainer.h @@ -50,10 +50,28 @@ class SimpleContainer : public Container { if (fireMin) onMinSizeChanged.emit(this); if (fireMax) onMaxSizeChanged.emit(this); } + + bool calculateMinSize() + { + bool res = false; + for (auto child: _children) { + res |= calculateMinSize(child); + } + return res; + } + + bool calculateMaxSize() + { + bool res = false; + for (auto child: _children) { + res |= calculateMaxSize(child); + } + return res; + } Signal<> onMinSizeChanged; // TODO: make split between simplecontainer and container more logical Signal<> onMaxSizeChanged; - + private: bool calculateMinSize(Widget* child) {