]> git.localhorst.tv Git - blobs.git/commitdiff
fix layout
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 4 Dec 2017 15:01:47 +0000 (16:01 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 4 Dec 2017 15:01:47 +0000 (16:01 +0100)
src/ui/Label.hpp
src/ui/Meter.hpp
src/ui/Panel.hpp
src/ui/Widget.hpp
src/ui/ui.cpp
src/ui/widgets.cpp

index 1bc7e86bc4f0de8e733818c5eb3bd427b556bf1c..7ba884b3d6d47430df5c406d05d28395a746946b 100644 (file)
@@ -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;
 
 };
 
index 9f2db65b80667f2609151e21ce94d347ae294d17..722372684c2267670747d25b124856d945b08fb9 100644 (file)
@@ -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; }
index d49dbf411a94534f513cce6a54f9320cf9d7a42c..cf72e72a9c8668309f5ca9abd0ef8e9a110320de 100644 (file)
@@ -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:
index a69defbcfc45a4cb1b2dcd510b9fb4a2cb540eb5..84570a3f70ca81e32bbb21ef43ee4aae07819517 100644 (file)
@@ -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;
 
 };
 
index 88d128877c3c900cffcbf5da15f4cdc8214dd264..c4d35e3177e9f3b502ad657e556079963bacadd6 100644 (file)
@@ -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);
 }
 
index a81defc0e549cc983795808a71c45988c154e4f7..554a6854876f22f0f5bd9425046342a1251318d4 100644 (file)
@@ -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> 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;
 }
 
@@ -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;
+       }
+}
+
 }
 }