#pragma once #include #include #include #include #include #include #include namespace psemek::ui { struct label : element { enum class halignment { left, center, right, stretch, }; enum class valignment { top, center, bottom, }; enum class overflow_mode { ignore, drop, ellipsis, }; label() = default; explicit label(std::string text); virtual void set_text(std::string text); virtual void set_tagged_text(std::string text); virtual std::string_view text() const { return text_; } virtual void set_text_style(ui::text_style style); virtual ui::text_style text_style() const { return text_style_; } virtual void set_halign(halignment value); virtual halignment halign() const { return halign_; } virtual void set_valign(valignment value); virtual valignment valign() const { return valign_; } virtual void set_wrap(bool value); virtual bool wrap() const { return wrap_; } virtual void set_overflow(overflow_mode value); virtual overflow_mode overflow() const { return overflow_; } virtual void set_skip_spaces(bool value); virtual bool skip_spaces() const { return skip_spaces_; } virtual struct image_provider * set_image_provider(struct image_provider * provider); virtual struct image_provider * image_provider() const { return image_provider_; } virtual void set_tag_mapper(tagged_text::mapper mapper); using link_mouseover_callback = std::function const &)>; using link_callback = std::function; virtual void on_link_mouseover(link_mouseover_callback callback); virtual void on_link_click(link_callback callback); struct shape const & shape() const override { return shape_; } void reshape(math::box const & bbox) override; bool on_event(ui::mouse_move const & e) override; bool on_event(ui::mouse_click const & e) override; math::box size_constraints() const override; math::interval width_constraints(float height) const override; math::interval height_constraints(float width) const override; void style_updated() const override; void own_style_updated() const override; bool transparent() const override { return !hint(); } void draw(painter & p) const override; protected: virtual void on_state_changed(); private: halignment halign_ = halignment::left; valignment valign_ = valignment::top; bool wrap_ = true; overflow_mode overflow_ = overflow_mode::ignore; bool skip_spaces_ = false; ui::text_style text_style_ = {}; struct image_provider * image_provider_ = nullptr; tagged_text::mapper tag_mapper_ = nullptr; link_mouseover_callback link_mouseover_callback_; link_callback link_callback_; box_shape shape_; struct text_chunk { std::string text; ui::text_style style; // to be OR'd with base style std::optional color; std::optional link; }; struct image_chunk { std::string id; std::optional color; std::optional link; }; using chunk = std::variant; std::string text_; bool tagged_ = false; std::vector chunks_; struct cached_state { struct image { math::box texcoords; math::box position; }; struct batch { gfx::texture_2d const * texture; gfx::color_rgba color; bool text; std::vector images; }; std::vector batches; math::vector size{0.f, 0.f}; fonts::font_type font_type = fonts::font_type::bitmap; float sdf_scale = 0.f; std::vector, std::string>> link_bboxes; }; mutable std::optional cached_state_; mutable std::optional cached_state_inf_; std::optional selected_link_; bool mouse_down_ = false; void update_cached_state() const; cached_state cached_state_for(math::box const & bbox) const; mutable std::shared_ptr single_white_pixel_texture_; std::shared_ptr single_white_pixel_texture() const; }; }