From 7499785c72add0d61f04f893754ebfd702f47777 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Wed, 13 Oct 2021 22:52:45 +0300 Subject: [PATCH] Support non-propagating styles in ui elements --- libs/ui/include/psemek/ui/element.hpp | 8 ++- libs/ui/source/default_element_factory.cpp | 38 +++++++------- libs/ui/source/element.cpp | 59 ++++++++++++++++------ libs/ui/source/label.cpp | 4 +- libs/ui/source/rich_image_view.cpp | 2 +- 5 files changed, 72 insertions(+), 39 deletions(-) diff --git a/libs/ui/include/psemek/ui/element.hpp b/libs/ui/include/psemek/ui/element.hpp index 176d5413..eae0ef23 100644 --- a/libs/ui/include/psemek/ui/element.hpp +++ b/libs/ui/include/psemek/ui/element.hpp @@ -52,8 +52,9 @@ namespace psemek::ui virtual void show() { set_hidden(false); } virtual std::shared_ptr style() const { return style_; } + virtual std::shared_ptr own_style() const { return own_style_; } virtual std::shared_ptr set_style(std::shared_ptr st); - virtual std::shared_ptr merged_style() const; + virtual std::shared_ptr set_own_style(std::shared_ptr st); virtual void update(float /* dt */) {} @@ -67,13 +68,18 @@ namespace psemek::ui protected: virtual void release_children(); + virtual std::shared_ptr merged_style() const; + virtual std::shared_ptr merged_own_style() const; + private: element * parent_ = nullptr; async::event_loop * loop_ = nullptr; bool enabled_ = true; bool hidden_ = false; std::shared_ptr style_; + std::shared_ptr own_style_; mutable std::shared_ptr merged_style_; + mutable std::shared_ptr merged_own_style_; }; } diff --git a/libs/ui/source/default_element_factory.cpp b/libs/ui/source/default_element_factory.cpp index cb62ec32..77013f6e 100644 --- a/libs/ui/source/default_element_factory.cpp +++ b/libs/ui/source/default_element_factory.cpp @@ -23,7 +23,7 @@ namespace psemek::ui void reshape(geom::box const & bbox) override { shape_.box = bbox; - auto st = merged_style(); + auto st = merged_own_style(); geom::vector offset{0.f, 0.f}; if (state() == state_t::mousedown) @@ -56,7 +56,7 @@ namespace psemek::ui void draw(painter & p) const override { - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return; if (st->shadow_offset != geom::vector{0, 0}) @@ -87,7 +87,7 @@ namespace psemek::ui { sc = c->size_constraints(); - if (auto st = merged_style()) + if (auto st = merged_own_style()) { float extra = 2.f * (*st->border_width + *st->inner_margin); sc[0] += extra; @@ -110,7 +110,7 @@ namespace psemek::ui void reshape(geom::box const & bbox) override { shape_.box = bbox; - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return; for (auto c : children()) if (c) c->reshape(geom::shrink(bbox, 1.f * (*st->border_width + *st->outer_margin))); @@ -124,7 +124,7 @@ namespace psemek::ui if (c) r = c->size_constraints(); - auto st = merged_style(); + auto st = merged_own_style(); if (st) { float extra = 2.f * (*st->border_width + *st->outer_margin); @@ -151,7 +151,7 @@ namespace psemek::ui void draw(painter & p) const override { - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return; if (st->shadow_offset != geom::vector{0, 0}) @@ -281,7 +281,7 @@ namespace psemek::ui auto lc = caption_->size_constraints(); auto bc = close_button_->size_constraints(); - auto st = merged_style(); + auto st = merged_own_style(); float const header_height = std::max(lc[1].min + 2.f * (*st->inner_margin) + 2.f * (*st->border_width), bc[1].min); @@ -322,7 +322,7 @@ namespace psemek::ui auto lc = caption_->size_constraints(); auto bc = close_button_->size_constraints(); - auto st = merged_style(); + auto st = merged_own_style(); float const header_height = std::max(lc[1].min + 2.f * (*st->inner_margin) + 2.f * (*st->border_width), bc[1].min); @@ -334,7 +334,7 @@ namespace psemek::ui void draw(painter & p) const override { - auto st = merged_style(); + auto st = merged_own_style(); auto lc = caption_->size_constraints(); auto bc = close_button_->size_constraints(); @@ -382,7 +382,7 @@ namespace psemek::ui void draw(painter & p) const override { - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return; geom::box boxes[5]; @@ -431,17 +431,17 @@ namespace psemek::ui int size() const { - return *merged_style()->ref_height; + return *merged_own_style()->ref_height; } int outer_width() const { - return *merged_style()->ref_height / 8; + return *merged_own_style()->ref_height / 8; } int outer_margin() const { - return *merged_style()->ref_height / 8; + return *merged_own_style()->ref_height / 8; } }; @@ -463,7 +463,7 @@ namespace psemek::ui void draw(painter & p) const override { - auto st = merged_style(); + auto st = merged_own_style(); geom::box ab; ab[0] = shape_.box[0]; @@ -508,19 +508,19 @@ namespace psemek::ui int button_width() const { - auto st = merged_style(); + auto st = merged_own_style(); return *st->ref_height / 3; } int button_height() const { - auto st = merged_style(); + auto st = merged_own_style(); return *st->ref_height; } int axis_width() const { - auto st = merged_style(); + auto st = merged_own_style(); return *st->ref_height / 5; } }; @@ -536,7 +536,7 @@ namespace psemek::ui { auto b = button::size_constraints(); - auto st = merged_style(); + auto st = merged_own_style(); b[0].min = *st->ref_height / 2.f; b[1].min = *st->ref_height / 2.f; @@ -584,7 +584,7 @@ namespace psemek::ui void draw(painter &p) const override { - auto st = merged_style(); + auto st = merged_own_style(); if (*st->shadow_offset != geom::vector{0, 0}) p.draw_triangle(triangle_ + geom::cast(*st->shadow_offset), *st->shadow_color); diff --git a/libs/ui/source/element.cpp b/libs/ui/source/element.cpp index 0612f746..1be9ab1c 100644 --- a/libs/ui/source/element.cpp +++ b/libs/ui/source/element.cpp @@ -45,6 +45,22 @@ namespace psemek::ui auto visitor = util::recursive([](auto && self, element * e) -> void { e->merged_style_ = nullptr; + e->merged_own_style_ = nullptr; + for (auto c : e->children()) + if (c) self(c); + }); + visitor(this); + + return st; + } + + std::shared_ptr element::set_own_style(std::shared_ptr st) + { + std::swap(st, own_style_); + + auto visitor = util::recursive([](auto && self, element * e) -> void { + e->merged_style_ = nullptr; + e->merged_own_style_ = nullptr; for (auto c : e->children()) if (c) self(c); }); @@ -57,28 +73,39 @@ namespace psemek::ui { if (!merged_style_) { - if (!style_) - { - if (parent()) - merged_style_ = parent()->merged_style(); - else - merged_style_ = std::make_shared(default_style()); - } - else - { - auto merged_style = std::make_shared(*style_); - if (parent()) - merge(*merged_style, *parent()->merged_style()); - else - merge(*merged_style, default_style()); + ui::style result; - merged_style_ = merged_style; - } + if (style_) + merge(result, *style_); + + if (parent()) + merge(result, *parent()->merged_style()); + + merge(result, default_style()); + + merged_style_ = std::make_shared(result); } return merged_style_; } + std::shared_ptr element::merged_own_style() const + { + if (!merged_own_style_) + { + ui::style result; + + if (own_style_) + merge(result, *own_style_); + + merge(result, *merged_style()); + + merged_own_style_ = std::make_shared(result); + } + + return merged_own_style_; + } + void element::post(util::function f) const { auto l = loop(); diff --git a/libs/ui/source/label.cpp b/libs/ui/source/label.cpp index 6cf555eb..8bedd159 100644 --- a/libs/ui/source/label.cpp +++ b/libs/ui/source/label.cpp @@ -62,7 +62,7 @@ namespace psemek::ui if (!cached_state_->font) return; - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return; if (st->text_shadow_offset != geom::vector{0, 0}) @@ -95,7 +95,7 @@ namespace psemek::ui if (text_.empty()) return state; - auto st = merged_style(); + auto st = merged_own_style(); if (!st) return state; if (!st->font) return state; diff --git a/libs/ui/source/rich_image_view.cpp b/libs/ui/source/rich_image_view.cpp index cdbbbb46..7d12f56f 100644 --- a/libs/ui/source/rich_image_view.cpp +++ b/libs/ui/source/rich_image_view.cpp @@ -150,7 +150,7 @@ namespace psemek::ui void rich_image_view::draw(painter & p) const { - auto st = merged_style(); + auto st = merged_own_style(); if (image_) {