From bf25780e00b719b0e5fa5d0191087bca2d99462b Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 4 Dec 2017 16:01:47 +0100 Subject: [PATCH] fix layout --- src/ui/Label.hpp | 3 +- src/ui/Meter.hpp | 6 ++-- src/ui/Panel.hpp | 2 +- src/ui/Widget.hpp | 15 ++++++++++ src/ui/ui.cpp | 5 ++++ src/ui/widgets.cpp | 69 +++++++++++++++++++++++++++++----------------- 6 files changed, 68 insertions(+), 32 deletions(-) diff --git a/src/ui/Label.hpp b/src/ui/Label.hpp index 1bc7e86..7ba884b 100644 --- a/src/ui/Label.hpp +++ b/src/ui/Label.hpp @@ -30,7 +30,7 @@ public: void Draw(app::Assets &, graphics::Viewport &) noexcept override; private: - void Update(); + void FixLayout() override; private: const graphics::Font *font; @@ -38,7 +38,6 @@ private: graphics::Texture tex; glm::vec4 fg_color; glm::vec4 bg_color; - bool dirty; }; diff --git a/src/ui/Meter.hpp b/src/ui/Meter.hpp index 9f2db65..7223726 100644 --- a/src/ui/Meter.hpp +++ b/src/ui/Meter.hpp @@ -15,9 +15,9 @@ public: ~Meter() override; public: - Meter *Size(const glm::vec2 &s) noexcept { size = s; return this; } - Meter *Padding(const glm::vec2 &p) noexcept { padding = p; return this; } - Meter *Border(float b) noexcept { border = b; return this; } + Meter *Size(const glm::vec2 &s) noexcept { size = s; BreakParentLayout(); return this; } + Meter *Padding(const glm::vec2 &p) noexcept { padding = p; BreakParentLayout(); return this; } + Meter *Border(float b) noexcept { border = b; BreakParentLayout(); return this; } Meter *FillColor(const glm::vec4 &c) noexcept { fill_color = c; return this; } Meter *BorderColor(const glm::vec4 &c) noexcept { border_color = c; return this; } diff --git a/src/ui/Panel.hpp b/src/ui/Panel.hpp index d49dbf4..cf72e72 100644 --- a/src/ui/Panel.hpp +++ b/src/ui/Panel.hpp @@ -37,7 +37,7 @@ public: Panel *Direction(Dir); glm::vec2 Size() override; - void Layout(); + void FixLayout(); void Draw(app::Assets &, graphics::Viewport &) noexcept override; private: diff --git a/src/ui/Widget.hpp b/src/ui/Widget.hpp index a69defb..84570a3 100644 --- a/src/ui/Widget.hpp +++ b/src/ui/Widget.hpp @@ -26,18 +26,33 @@ public: Widget &operator =(Widget &&) = delete; public: + void SetParent(Widget &) noexcept; + bool HasParent() const noexcept { return parent; } + Widget &GetParent() noexcept { return *parent; } + const Widget &GetParent() const noexcept { return *parent; } + Widget *Position(const glm::vec2 &p) noexcept { pos = p; return this; } const glm::vec2 &Position() const noexcept { return pos; } Widget *ZIndex(float z) noexcept { z_index = z; return this; } float ZIndex() const noexcept { return z_index; } + bool DirtyLayout() const noexcept { return dirty_layout; } + void BreakLayout() noexcept; + void BreakParentLayout() noexcept; + void Layout(); + virtual glm::vec2 Size() = 0; virtual void Draw(app::Assets &, graphics::Viewport &) noexcept = 0; private: + virtual void FixLayout() { } + +private: + Widget *parent; glm::vec2 pos; float z_index; + bool dirty_layout; }; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 88d1288..c4d35e3 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -91,6 +91,8 @@ CreaturePanel::CreaturePanel(app::Assets &assets) ->Spacing(2) ->Direction(Panel::VERTICAL); Panel *stat_meter_panel = new Panel; + stat_label[0]->Layout(); + stats[0]->Layout(); stat_meter_panel ->Spacing(stat_label[0]->Size().y - stats[0]->Size().y + 2) ->Direction(Panel::VERTICAL); @@ -241,6 +243,7 @@ void CreaturePanel::Draw(graphics::Viewport &viewport) noexcept { const glm::vec2 margin(20.0f); panel.Position(glm::vec2(viewport.Width() - margin.x - panel.Size().x, margin.y)); + panel.Layout(); panel.Draw(assets, viewport); } @@ -339,6 +342,7 @@ void RecordsPanel::Draw(graphics::Viewport &viewport) noexcept { const glm::vec2 margin(20.0f); panel.Position(glm::vec2(margin.x, margin.y)); + panel.Layout(); panel.Draw(sim.Assets(), viewport); } @@ -388,6 +392,7 @@ void TimePanel::Draw(graphics::Viewport &viewport) noexcept { const glm::vec2 margin(20.0f); panel.Position(glm::vec2(margin.x, viewport.Height() - margin.y - panel.Size().y)); + panel.Layout(); panel.Draw(sim.Assets(), viewport); } diff --git a/src/ui/widgets.cpp b/src/ui/widgets.cpp index a81defc..554a685 100644 --- a/src/ui/widgets.cpp +++ b/src/ui/widgets.cpp @@ -20,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() { @@ -29,7 +28,7 @@ Label::~Label() { Label *Label::Text(const std::string &t) { if (text != t) { - dirty = true; + BreakLayout(); } text = t; return this; @@ -37,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; @@ -57,13 +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 { if (text.empty()) return; - Update(); glm::vec2 size = Size(); assets.shaders.alpha_sprite.Activate(); @@ -75,10 +72,9 @@ void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept { assets.shaders.alpha_sprite.DrawRect(); } -void Label::Update() { - if (!dirty || text.empty()) return; +void Label::FixLayout() { + if (text.empty()) return; font->Render(text, tex); - dirty = false; } @@ -137,22 +133,15 @@ Panel::~Panel() { } Panel *Panel::Add(Widget *w) { - std::unique_ptr 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(w)); + BreakLayout(); return this; } Panel *Panel::Clear() { widgets.clear(); - size = glm::vec2(0.0f); + BreakLayout(); return this; } @@ -163,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; - Layout(); + BreakLayout(); return this; } @@ -183,7 +174,10 @@ glm::vec2 Panel::Size() { return (2.0f * padding) + space + size; } -void Panel::Layout() { +void Panel::FixLayout() { + for (auto &w : widgets) { + w->Layout(); + } size = glm::vec2(0.0f); if (dir == HORIZONTAL) { for (auto &w : widgets) { @@ -201,8 +195,6 @@ void Panel::Layout() { } void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept { - // TODO: separate draw and layout, it's inefficient and the wrong tree order anyway - Layout(); if (bg_color.a > 0.0f) { assets.shaders.canvas.Activate(); assets.shaders.canvas.ZIndex(ZIndex()); @@ -220,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; + } +} + } } -- 2.39.2