diff --git a/src/ui/trackerview.cpp b/src/ui/trackerview.cpp index bfded6db..ecc901ac 100644 --- a/src/ui/trackerview.cpp +++ b/src/ui/trackerview.cpp @@ -767,7 +767,9 @@ bool TrackerView::addLayoutNode(Container* container, const LayoutNode& node, si for (const auto& row: rows) { if (row.size()>colCount) colCount = row.size(); } - Container *w = new SimpleContainer(0,0,container->getWidth(),container->getHeight()); // TODO: itemgrid + auto w = new SimpleContainer(0,0,container->getWidth(),container->getHeight()); // TODO: itemgrid + w->setHAlign(str2itemHalign(node.getHAlignment())); + w->setVAlign(str2itemValign(node.getVAlignment())); w->setDropShaodw(node.getDropShadow(container->getDropShadow())); auto m = node.getMargin(); w->setMargin({m.left, m.top, m.right, m.bottom}); diff --git a/src/uilib/container.h b/src/uilib/container.h index 1d5bec33..e12ba890 100644 --- a/src/uilib/container.h +++ b/src/uilib/container.h @@ -1,29 +1,36 @@ -#ifndef _UILIB_CONTAINER_H -#define _UILIB_CONTAINER_H +#pragma once -#include "widget.h" -#include #include +#include +#include +#include "label.h" // HAlign, VAlign +#include "widget.h" #ifndef NDEBUG #include #include #endif + namespace Ui { class Container : public Widget { public: - virtual ~Container() { + virtual ~Container() + { clearChildren(); } - virtual void addChild(Widget* child) { + + virtual void addChild(Widget* child) + { if (!child) return; _children.push_back(child); if (child->getHGrow()>_hGrow) _hGrow = child->getHGrow(); if (child->getVGrow()>_vGrow) _vGrow = child->getVGrow(); } - virtual void removeChild(Widget* child) { + + virtual void removeChild(Widget* child) + { if (!child) return; if (child == _hoverChild) { _hoverChild = nullptr; @@ -46,7 +53,8 @@ class Container : public Widget { return std::find(_children.begin(), _children.end(), child) != _children.end(); } - virtual void clearChildren() { + virtual void clearChildren() + { if (_hoverChild) { _hoverChild->onMouseLeave.emit(_hoverChild); _hoverChild = nullptr; @@ -56,7 +64,9 @@ class Container : public Widget { } _children.clear(); } - virtual void raiseChild(Widget* child) { + + virtual void raiseChild(Widget* child) + { if (!child) return; for (auto it=_children.begin(); it!=_children.end(); it++) { if (*it == child) { @@ -66,7 +76,45 @@ class Container : public Widget { } } } - virtual void render(Renderer renderer, int offX, int offY) override { + + void render(Renderer renderer, int offX, int offY) override + { + if (_hAlign == Label::HAlign::LEFT) { + _renderOffset.left = 0; + } else { + int maxX = 0; + int minX = std::numeric_limits::max(); + for (const auto child : _children) { + if (child->getLeft() < minX) + minX = child->getLeft(); + if (child->getLeft() + child->getWidth() > maxX) + maxX = child->getLeft() + child->getWidth(); + } + if (_hAlign == Label::HAlign::RIGHT) { + _renderOffset.left = std::max(0, _size.width - (maxX - minX)); + } else { + _renderOffset.left = std::max(0, (_size.width - (maxX - minX))/2); + } + } + + if (_vAlign == Label::VAlign::TOP) { + _renderOffset.top = 0; + } else { + int maxY = 0; + int minY = std::numeric_limits::max(); + for (const auto child : _children) { + if (child->getTop() < minY) + minY = child->getTop(); + if (child->getTop() + child->getHeight() > maxY) + maxY = child->getTop() + child->getHeight(); + } + if (_vAlign == Label::VAlign::BOTTOM) { + _renderOffset.top = std::max(0, _size.height - (maxY - minY)); + } else { + _renderOffset.top = std::max(0, (_size.height - (maxY - minY))/2); + } + } + if (_backgroundColor.a > 0) { const auto& c = _backgroundColor; SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a); @@ -78,23 +126,31 @@ class Container : public Widget { SDL_RenderFillRect(renderer, &r); } // TODO: background image + offX += _renderOffset.left; + offY += _renderOffset.top; for (auto& child: _children) if (child->getVisible()) child->render(renderer, offX+_pos.left, offY+_pos.top); } - const std::deque getChildren() const { return _children; } - virtual bool isHover(Widget* w) const override { + const std::deque& getChildren() const + { + return _children; + } + + bool isHover(Widget* w) const override + { return (w == this || (_hoverChild && _hoverChild->isHover(w))); } - virtual bool isHit(int x, int y) const override { + bool isHit(int x, int y) const override + { if (!_mouseInteraction) return false; if (_backgroundColor.a && Widget::isHit(x, y)) return true; - x -= _pos.left; - y -= _pos.top; + x -= _pos.left + _renderOffset.left; + y -= _pos.top + _renderOffset.top; for (const auto& w: _children) { if (w->isHit(x, y)) return true; @@ -102,14 +158,28 @@ class Container : public Widget { return false; } - virtual const Widget* getHit(int x, int y) const override { + const Widget* getHit(int x, int y) const override + { for (const auto& w: _children) { - if (w->getHit(x - w->getLeft(), y - w->getTop())) return w; + if (w->getHit(x - w->getLeft() - _renderOffset.left, + y - w->getTop() - _renderOffset.top)) + return w; } - if (Widget::isHit(x + _pos.left, y + _pos.top)) return this; + if (Widget::isHit(x + _pos.left, y + _pos.top)) + return this; return nullptr; } + void setHAlign(const Label::HAlign hAlign) + { + _hAlign = hAlign; + } + + void setVAlign(const Label::VAlign vAlign) + { + _vAlign = vAlign; + } + #ifndef NDEBUG void dumpTree(size_t depth=0) { printf("%s", std::string(depth, ' ').c_str()); @@ -129,11 +199,16 @@ class Container : public Widget { protected: std::deque _children; Widget* _hoverChild = nullptr; - + Position _renderOffset = {0, 0}; + Label::HAlign _hAlign = Label::HAlign::LEFT; + Label::VAlign _vAlign = Label::VAlign::TOP; + Container(int x=0, int y=0, int w=0, int h=0) : Widget(x,y,w,h) { onClick += { this, [this](void* s, int x, int y, int button) { + x -= _renderOffset.left; + y -= _renderOffset.top; for (auto childIt = _children.rbegin(); childIt != _children.rend(); childIt++) { auto& child = *childIt; if (child->getVisible() && child->isHit(x, y)) { @@ -142,7 +217,10 @@ class Container : public Widget { } } }}; + onMouseMove += { this, [this](void* s, int x, int y, unsigned buttons) { + x -= _renderOffset.left; + y -= _renderOffset.top; auto oldHoverChild = _hoverChild; bool match = false; for (auto childIt = _children.rbegin(); childIt != _children.rend(); childIt++) { @@ -171,6 +249,7 @@ class Container : public Widget { if (oldHoverChild && !_hoverChild) oldHoverChild->onMouseLeave.emit(oldHoverChild); }}; + onMouseLeave += { this, [this](void* s) { auto oldHoverChild = _hoverChild; if (oldHoverChild) { @@ -178,7 +257,10 @@ class Container : public Widget { oldHoverChild->onMouseLeave.emit(oldHoverChild); } }}; + onScroll += { this, [this](void* s, int x, int y, unsigned mod) { + x -= _renderOffset.left; + y -= _renderOffset.top; if (_hoverChild) _hoverChild->onScroll.emit(_hoverChild, x, y, mod); }}; @@ -186,5 +268,3 @@ class Container : public Widget { }; } // namespace Ui - -#endif // _UILIB_CONTAINER_H diff --git a/src/uilib/simplecontainer.h b/src/uilib/simplecontainer.h index fee45b03..51051b2d 100644 --- a/src/uilib/simplecontainer.h +++ b/src/uilib/simplecontainer.h @@ -1,8 +1,8 @@ -#ifndef _UILIB_SIMPLECONTAINER_H -#define _UILIB_SIMPLECONTAINER_H +#pragma once #include "container.h" + namespace Ui { // 1 child that spans the whole container @@ -12,7 +12,7 @@ class SimpleContainer : public Container { : Container(x,y,w,h) {} - virtual void setSize(Size size) override + void setSize(Size size) override { if (size == _size) return; Container::setSize(size); @@ -30,7 +30,8 @@ class SimpleContainer : public Container { break; // only the first child for now; TODO: only container-sized widgets? } } - virtual void addChild(Widget* child) override + + void addChild(Widget* child) override { if (!child) return; Container::addChild(child); @@ -39,7 +40,8 @@ class SimpleContainer : public Container { if (fireMin) onMinSizeChanged.emit(this); if (fireMax) onMaxSizeChanged.emit(this); } - virtual void removeChild(Widget* child) override + + void removeChild(Widget* child) override { if (!child) return; Container::removeChild(child); @@ -74,7 +76,7 @@ class SimpleContainer : public Container { } return res; } - + Signal<> onMinSizeChanged; // TODO: make split between simplecontainer and container more logical Signal<> onMaxSizeChanged; @@ -88,6 +90,7 @@ class SimpleContainer : public Container { if (minh>_minSize.height) _minSize.height = minh; return (old != _minSize); } + bool calculateMaxSize(Widget* child) { int maxw = child->getMaxWidth(); @@ -104,5 +107,3 @@ class SimpleContainer : public Container { }; } // namespace - -#endif // _UILIB_SIMPLECONTAINER_H