Support non-propagating styles in ui elements

This commit is contained in:
Nikita Lisitsa 2021-10-13 22:52:45 +03:00
parent 5ddf8795d5
commit 7499785c72
5 changed files with 72 additions and 39 deletions

View file

@ -52,8 +52,9 @@ namespace psemek::ui
virtual void show() { set_hidden(false); }
virtual std::shared_ptr<struct style const> style() const { return style_; }
virtual std::shared_ptr<struct style const> own_style() const { return own_style_; }
virtual std::shared_ptr<struct style const> set_style(std::shared_ptr<struct style const> st);
virtual std::shared_ptr<struct style const> merged_style() const;
virtual std::shared_ptr<struct style const> set_own_style(std::shared_ptr<struct style const> st);
virtual void update(float /* dt */) {}
@ -67,13 +68,18 @@ namespace psemek::ui
protected:
virtual void release_children();
virtual std::shared_ptr<struct style const> merged_style() const;
virtual std::shared_ptr<struct style const> merged_own_style() const;
private:
element * parent_ = nullptr;
async::event_loop * loop_ = nullptr;
bool enabled_ = true;
bool hidden_ = false;
std::shared_ptr<struct style const> style_;
std::shared_ptr<struct style const> own_style_;
mutable std::shared_ptr<struct style const> merged_style_;
mutable std::shared_ptr<struct style const> merged_own_style_;
};
}

View file

@ -23,7 +23,7 @@ namespace psemek::ui
void reshape(geom::box<float, 2> 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<float, 2> 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<float, 2> 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<float, 2> 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<float>(*st->shadow_offset), *st->shadow_color);

View file

@ -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<struct style const> element::set_own_style(std::shared_ptr<struct style const> 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<struct style>(default_style());
}
else
{
auto merged_style = std::make_shared<struct style>(*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<ui::style>(result);
}
return merged_style_;
}
std::shared_ptr<struct style const> 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<ui::style>(result);
}
return merged_own_style_;
}
void element::post(util::function<void()> f) const
{
auto l = loop();

View file

@ -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;

View file

@ -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_)
{