psemek/libs/ui_legacy/include/psemek/ui/label.hpp

171 lines
4.2 KiB
C++

#pragma once
#include <psemek/ui/element.hpp>
#include <psemek/ui/box_shape.hpp>
#include <psemek/ui/tagged_text.hpp>
#include <psemek/ui/image_provider.hpp>
#include <string>
#include <string_view>
#include <variant>
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<void(std::optional<std::string> const &)>;
using link_callback = std::function<void(std::string const &)>;
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<float, 2> const & bbox) override;
bool on_event(ui::mouse_move const & e) override;
bool on_event(ui::mouse_click const & e) override;
math::box<float, 2> size_constraints() const override;
math::interval<float> width_constraints(float height) const override;
math::interval<float> 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<gfx::color_rgba> color;
std::optional<std::string> link;
};
struct image_chunk
{
std::string id;
std::optional<gfx::color_rgba> color;
std::optional<std::string> link;
};
using chunk = std::variant<text_chunk, image_chunk>;
std::string text_;
bool tagged_ = false;
std::vector<chunk> chunks_;
struct cached_state
{
struct image
{
math::box<float, 2> texcoords;
math::box<float, 2> position;
};
struct batch
{
gfx::texture_2d const * texture;
gfx::color_rgba color;
bool text;
std::vector<image> images;
};
std::vector<batch> batches;
math::vector<float, 2> size{0.f, 0.f};
fonts::font_type font_type = fonts::font_type::bitmap;
float sdf_scale = 0.f;
std::vector<std::pair<math::box<float, 2>, std::string>> link_bboxes;
};
mutable std::optional<cached_state> cached_state_;
mutable std::optional<cached_state> cached_state_inf_;
std::optional<std::string> selected_link_;
bool mouse_down_ = false;
void update_cached_state() const;
cached_state cached_state_for(math::box<float, 2> const & bbox) const;
mutable std::shared_ptr<gfx::texture_2d> single_white_pixel_texture_;
std::shared_ptr<gfx::texture_2d> single_white_pixel_texture() const;
};
}