]> git.localhorst.tv Git - blobs.git/blobdiff - src/ui/widgets.cpp
fix layout
[blobs.git] / src / ui / widgets.cpp
index 6d88ad71b46772d7b636c53c6c3e89beee853a30..554a6854876f22f0f5bd9425046342a1251318d4 100644 (file)
@@ -7,6 +7,8 @@
 #include "../graphics/Font.hpp"
 #include "../graphics/Viewport.hpp"
 
+#include <iomanip>
+#include <sstream>
 #include <glm/gtx/transform.hpp>
 
 
@@ -18,8 +20,7 @@ Label::Label(const graphics::Font &f)
 , text()
 , tex()
 , fg_color(0.0f, 0.0f, 0.0f, 1.0f)
-, bg_color(0.0f, 0.0f, 0.0f, 0.0f)
-, dirty(true) {
+, bg_color(0.0f, 0.0f, 0.0f, 0.0f) {
 }
 
 Label::~Label() {
@@ -27,7 +28,7 @@ Label::~Label() {
 
 Label *Label::Text(const std::string &t) {
        if (text != t) {
-               dirty = true;
+               BreakLayout();
        }
        text = t;
        return this;
@@ -35,7 +36,7 @@ Label *Label::Text(const std::string &t) {
 
 Label *Label::Font(const graphics::Font &f) {
        if (font != &f) {
-               dirty = true;
+               BreakLayout();
        }
        font = &f;
        return this;
@@ -55,12 +56,11 @@ glm::vec2 Label::Size() {
        if (text.empty()) {
                return glm::vec2(0.0f);
        }
-       Update();
        return tex.Size();
 }
 
 void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
-       Update();
+       if (text.empty()) return;
        glm::vec2 size = Size();
 
        assets.shaders.alpha_sprite.Activate();
@@ -72,10 +72,9 @@ void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
        assets.shaders.alpha_sprite.DrawRect();
 }
 
-void Label::Update() {
-       if (!dirty) return;
+void Label::FixLayout() {
+       if (text.empty()) return;
        font->Render(text, tex);
-       dirty = false;
 }
 
 
@@ -134,22 +133,15 @@ Panel::~Panel() {
 }
 
 Panel *Panel::Add(Widget *w) {
-       std::unique_ptr<Widget> widget(w);
-       glm::vec2 wsize = widget->Size();
-       if (dir == HORIZONTAL) {
-               size.x += wsize.x;
-               size.y = std::max(size.y, wsize.y);
-       } else {
-               size.x = std::max(size.x, wsize.x);
-               size.y += wsize.y;
-       }
-       widgets.emplace_back(std::move(widget));
+       w->SetParent(*this);
+       widgets.emplace_back(std::unique_ptr<Widget>(w));
+       BreakLayout();
        return this;
 }
 
 Panel *Panel::Clear() {
        widgets.clear();
-       size = glm::vec2(0.0f);
+       BreakLayout();
        return this;
 }
 
@@ -160,17 +152,19 @@ Panel *Panel::Background(const glm::vec4 &c) {
 
 Panel *Panel::Padding(const glm::vec2 &p) {
        padding = p;
+       BreakParentLayout();
        return this;
 }
 
 Panel *Panel::Spacing(float s) {
        spacing = s;
+       BreakParentLayout();
        return this;
 }
 
 Panel *Panel::Direction(Dir d) {
        dir = d;
-       Relayout();
+       BreakLayout();
        return this;
 }
 
@@ -180,7 +174,10 @@ glm::vec2 Panel::Size() {
        return (2.0f * padding) + space + size;
 }
 
-void Panel::Relayout() {
+void Panel::FixLayout() {
+       for (auto &w : widgets) {
+               w->Layout();
+       }
        size = glm::vec2(0.0f);
        if (dir == HORIZONTAL) {
                for (auto &w : widgets) {
@@ -205,9 +202,7 @@ void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
                assets.shaders.canvas.FillRect(Position(), Position() + Size());
        }
 
-       glm::vec2 cursor = Position();
-       cursor.x += padding.x;
-       cursor.y += padding.y;
+       glm::vec2 cursor = Position() + padding;
        for (auto &w : widgets) {
                w->Position(cursor)->ZIndex(ZIndex() + 1.0f);
                w->Draw(assets, viewport);
@@ -217,12 +212,37 @@ void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
 
 
 Widget::Widget()
-: pos(0.0f)
-, z_index(1.0f)  {
+: parent(nullptr)
+, pos(0.0f)
+, z_index(1.0f)
+, dirty_layout(false) {
 }
 
 Widget::~Widget() {
 }
 
+void Widget::SetParent(Widget &p) noexcept {
+       parent = &p;
+}
+
+void Widget::BreakLayout() noexcept {
+       if (dirty_layout) return;
+       dirty_layout = true;
+       BreakParentLayout();
+}
+
+void Widget::BreakParentLayout() noexcept {
+       if (HasParent()) {
+               GetParent().BreakLayout();
+       }
+}
+
+void Widget::Layout() {
+       if (dirty_layout) {
+               FixLayout();
+               dirty_layout = false;
+       }
+}
+
 }
 }