From 69bd54684854674affc77cee522812f630d3df46 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 25 Feb 2021 11:42:47 +0300 Subject: [PATCH] Label implementation wip --- examples/ui.cpp | 1 + libs/ui/include/psemek/ui/label.hpp | 15 +++++++ libs/ui/include/psemek/ui/style.hpp | 4 ++ libs/ui/source/default_element_factory.cpp | 7 ++++ libs/ui/source/label.cpp | 47 +++++++++++++++++++++- 5 files changed, 72 insertions(+), 2 deletions(-) diff --git a/examples/ui.cpp b/examples/ui.cpp index cbadb121..1478bb8f 100644 --- a/examples/ui.cpp +++ b/examples/ui.cpp @@ -19,6 +19,7 @@ struct ui_example { auto style = std::make_shared(); style->font = ui::make_default_9x12_font(); + style->text_scale = 2; element_factory.set_style(style); auto screen = element_factory.make_screen(); diff --git a/libs/ui/include/psemek/ui/label.hpp b/libs/ui/include/psemek/ui/label.hpp index daa65415..0485ef32 100644 --- a/libs/ui/include/psemek/ui/label.hpp +++ b/libs/ui/include/psemek/ui/label.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -54,6 +55,10 @@ namespace psemek::ui virtual void set_overflow(overflow_mode value); virtual overflow_mode overflow() const { return overflow_; } + struct shape const & shape() const override { return shape_; } + void reshape(geom::box const & bbox) override; + void draw(painter & p) const override; + protected: virtual void on_state_changed(); @@ -63,6 +68,16 @@ namespace psemek::ui valignment valign_; multiline_mode multiline_; overflow_mode overflow_; + + box_shape shape_; + + struct cached_state + { + struct font const * font = nullptr; + std::vector glyphs; + }; + + mutable std::optional cached_state_; }; } diff --git a/libs/ui/include/psemek/ui/style.hpp b/libs/ui/include/psemek/ui/style.hpp index ccdb6a7d..b04c5582 100644 --- a/libs/ui/include/psemek/ui/style.hpp +++ b/libs/ui/include/psemek/ui/style.hpp @@ -19,7 +19,11 @@ namespace psemek::ui geom::vector shadow_offset{1, 1}; gfx::color_rgba shadow_color{0, 0, 0, 255}; + int inner_margin = 5; + int outer_margin = 10; + gfx::color_rgba text_color{0, 0, 0, 255}; + int text_scale = 1; std::shared_ptr font; }; diff --git a/libs/ui/source/default_element_factory.cpp b/libs/ui/source/default_element_factory.cpp index df784584..29494dab 100644 --- a/libs/ui/source/default_element_factory.cpp +++ b/libs/ui/source/default_element_factory.cpp @@ -14,6 +14,10 @@ namespace psemek::ui button_impl() { set_label(std::make_unique()); + label()->set_valign(label::valignment::center); + label()->set_halign(label::halignment::center); + label()->set_overflow(label::overflow_mode::drop); + label()->set_multiline(label::multiline_mode::none); } struct shape const & shape() const override @@ -24,6 +28,8 @@ namespace psemek::ui void reshape(geom::box const & bbox) override { shape_.box = bbox; + auto s = style(); + if (s && label()) label()->reshape(geom::shrink(bbox, 1.f * (s->border_width + s->inner_margin))); } void draw(painter & p) const override @@ -95,6 +101,7 @@ namespace psemek::ui { auto r = impl().create(); r->label()->set_text(std::move(text)); + r->label()->set_style(impl().style); return r; } diff --git a/libs/ui/source/label.cpp b/libs/ui/source/label.cpp index 087bca2c..529f4b82 100644 --- a/libs/ui/source/label.cpp +++ b/libs/ui/source/label.cpp @@ -3,8 +3,6 @@ namespace psemek::ui { - // TODO: changes should notify parent about content change - void label::set_text(std::string text) { text_ = std::move(text); @@ -35,4 +33,49 @@ namespace psemek::ui on_state_changed(); } + void label::reshape(geom::box const & bbox) + { + shape_.box = bbox; + cached_state_.reset(); + } + + void label::draw(painter & p) const + { + if (text_.empty()) return; + + auto st = style(); + if (!st) return; + if (!st->font) return; + + if (!cached_state_ || cached_state_->font != st->font.get()) + { + cached_state_ = cached_state{}; + cached_state_->font = st->font.get(); + + shape_options opts; + opts.scale = st->text_scale; + cached_state_->glyphs = st->font->shape(text_, opts); + + geom::box bbox; + for (auto const & g : cached_state_->glyphs) + bbox |= g.position; + + geom::vector offset; + offset[0] = shape_.box[0].center() - bbox[0].length() / 2.f; + offset[1] = shape_.box[1].center() - st->text_scale * st->font->size()[1] / 2.f; + + for (auto & g : cached_state_->glyphs) + g.position += offset; + } + + for (auto & g : cached_state_->glyphs) + p.draw_rect(g.position, st->text_color); + } + + void label::on_state_changed() + { + // TODO: changes should notify parent about content change + element::reshape(); + } + }