55 set_attributes(std::forward<Attributes>(attributes)...);
58 void set_attributes() noexcept {}
60 template<icon_widget_attribute First, icon_widget_attribute... Rest>
61 void set_attributes(First&& first, Rest&&... rest)
noexcept
63 if constexpr (forward_of<First, observer<hi::icon>>) {
64 icon = std::forward<First>(first);
65 }
else if constexpr (forward_of<First, observer<hi::alignment>>) {
67 }
else if constexpr (forward_of<First, observer<hi::color>>) {
68 color = std::forward<First>(first);
70 hi_static_no_default();
72 set_attributes(std::forward<Rest>(rest)...);
76 [[nodiscard]] box_constraints update_constraints() noexcept
override
80 if (_icon_has_modified.
exchange(
false)) {
81 _icon_type = icon_type::no;
87 _icon_type = icon_type::pixmap;
88 _icon_size = extent2{narrow_cast<float>(pixmap->width()), narrow_cast<float>(pixmap->height())};
90 if (not(_pixmap_backing = gfx_pipeline_image::paged_image{surface(), *pixmap})) {
92 _icon_has_modified =
true;
93 ++global_counter<
"icon_widget:no-backing-image:constrain">;
97 }
else if (
auto const g1 = std::get_if<font_book::font_glyph_type>(&
icon)) {
99 _icon_type = icon_type::glyph;
100 _icon_size = _glyph.get_metrics().bounding_rectangle.size() *
101 (theme().text_style(semantic_text_style::label)->size * theme().pixel_density).in(pixels_per_em);
103 }
else if (
auto const g2 = std::get_if<elusive_icon>(&
icon)) {
105 _icon_type = icon_type::glyph;
106 _icon_size = _glyph.get_metrics().bounding_rectangle.size() *
107 (theme().text_style(semantic_text_style::label)->size * theme().pixel_density).in(pixels_per_em);
109 }
else if (
auto const g3 = std::get_if<hikogui_icon>(&
icon)) {
111 _icon_type = icon_type::glyph;
112 _icon_size = _glyph.get_metrics().bounding_rectangle.size() *
113 (theme().text_style(semantic_text_style::label)->size * theme().pixel_density).in(pixels_per_em);
117 auto const resolved_alignment = resolve(*
alignment, os_settings::left_to_right());
118 auto const icon_constraints = box_constraints{
120 narrow_cast<extent2>(_icon_size),
121 narrow_cast<extent2>(_icon_size),
123 theme().margin<
float>()};
126 void set_layout(widget_layout
const& context)
noexcept override
129 if (_icon_type == icon_type::no or not _icon_size) {
130 _icon_rectangle = {};
132 auto const width = std::clamp(context.shape.width(),
minimum->width(),
maximum->width());
133 auto const height = std::clamp(context.shape.height(),
minimum->height(),
maximum->height());
135 auto const icon_scale =
136 scale2::uniform(_icon_size, extent2{narrow_cast<float>(width), narrow_cast<float>(height)});
137 auto const new_icon_size = narrow_cast<extent2>(icon_scale * _icon_size);
138 auto const resolved_alignment = resolve(*
alignment, os_settings::left_to_right());
139 _icon_rectangle =
align(context.rectangle(), new_icon_size, resolved_alignment);
143 void draw(draw_context
const& context)
noexcept override
146 switch (_icon_type) {
150 case icon_type::pixmap:
151 if (not context.draw_image(
layout(), _icon_rectangle, _pixmap_backing)) {
157 case icon_type::glyph:
159 context.draw_glyph(
layout(), _icon_rectangle, _glyph, theme().
color(*
color));
170 enum class icon_type { no, glyph, pixmap };
172 icon_type _icon_type;
173 font_book::font_glyph_type _glyph;
174 gfx_pipeline_image::paged_image _pixmap_backing;
178 aarectangle _icon_rectangle;
180 callback<void(hi::icon)> _icon_cbt;
182 icon_widget(widget_intf
const*
parent) noexcept : super(
parent)
185 _icon_has_modified =
true;
186 ++global_counter<
"icon_widget:icon:constrain">;