1.10
imageholder.h
1/*
2 * Copyright (C) 2021 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef EGT_IMAGE_HOLDER_H
7#define EGT_IMAGE_HOLDER_H
8
14#include "egt/detail/alignment.h"
15#include <egt/detail/meta.h>
16#include <egt/frame.h>
17#include <egt/geometry.h>
18#include <egt/image.h>
19#include <egt/painter.h>
20#include "egt/serialize.h"
21#include <egt/text.h>
22#include <egt/textwidget.h>
23#include <egt/widget.h>
24
25namespace egt
26{
27inline namespace v1
28{
29
30template<class T,
31 Palette::ColorId id_bg,
32 Palette::ColorId id_border,
33 Palette::ColorId id_text>
34class EGT_API ImageHolder : public T
35{
36public:
41 explicit ImageHolder(const std::string& text = {},
42 const AlignFlags& text_align = T::default_text_align()) noexcept
43 : ImageHolder(Image(), text, text_align)
44 {}
45
51 explicit ImageHolder(const Image& image,
52 const std::string& text = {},
53 const AlignFlags& text_align = T::default_text_align()) noexcept
54 : ImageHolder(image, text, {}, text_align)
55 {}
56
63 explicit ImageHolder(const Image& image,
64 const std::string& text,
65 const Rect& rect,
66 const AlignFlags& text_align = T::default_text_align()) noexcept
67 : T(text, rect, text_align)
68 {
69 this->name(type() + std::to_string(this->m_widgetid));
70
71 if (text.empty())
72 {
73 show_label(false);
74 image_align(AlignFlag::center | AlignFlag::expand);
75 }
76 do_set_image(image);
77 }
78
85 explicit ImageHolder(Frame& parent,
86 const Image& image = {},
87 const std::string& text = {},
88 const AlignFlags& text_align = T::default_text_align()) noexcept
89 : ImageHolder(image, text, text_align)
90 {
91 parent.add(*this);
92 }
93
102 const Image& image,
103 const std::string& text,
104 const Rect& rect,
105 const AlignFlags& text_align = T::default_text_align()) noexcept
106 : ImageHolder(image, text, rect, text_align)
107 {
108 parent.add(*this);
109 }
110
114 explicit ImageHolder(Serializer::Properties& props) noexcept
115 : ImageHolder(props, false)
116 {}
117
118 ImageHolder(const ImageHolder&) noexcept = delete;
119 ImageHolder& operator=(const ImageHolder&) noexcept = delete;
120 ImageHolder(ImageHolder&&) noexcept = default;
121 ImageHolder& operator=(ImageHolder&&) noexcept = default;
122
123 virtual ~ImageHolder() = default;
124
125 EGT_NODISCARD std::string type() const override
126 {
127 auto t = detail::demangle(typeid(T).name());
128 return std::string("Image") + detail::replace_all(t, "egt::v1::", {});
129 }
130
134 EGT_NODISCARD std::string uri() const
135 {
136 return m_image.uri();
137 }
138
144 void uri(const std::string& uri)
145 {
146 m_image.uri(uri);
147 refresh();
148 }
149
154 {
155 m_image.reset_uri();
156 refresh();
157 }
158
162 EGT_NODISCARD float hscale() const { return m_image.hscale(); }
163
167 void hscale(float hscale)
168 {
169 m_image.scale(hscale, m_image.vscale());
170 refresh();
171 }
172
176 EGT_NODISCARD float vscale() const { return m_image.vscale(); }
177
181 void vscale(float vscale)
182 {
183 m_image.scale(m_image.hscale(), vscale);
184 refresh();
185 }
186
190 void image_scale(float scale)
191 {
192 m_image.scale(scale);
193 refresh();
194 }
195
199 void image_scale(const SizeF& scale)
200 {
201 m_image.scale(scale.width(), scale.height());
202 refresh();
203 }
204
208 EGT_NODISCARD SizeF image_scale() const { return SizeF(hscale(), vscale()); }
209
215 void image(const Image& image)
216 {
217 do_set_image(image);
218 }
219
237 void scale_image(float hscale, float vscale,
238 bool approximate = false)
239 {
240 m_image.scale(hscale, vscale, approximate);
241 this->parent_layout();
242 }
243
253 void scale_image(float scale, bool approximate = false)
254 {
255 scale_image(scale, scale, approximate);
256 }
257
264 void auto_scale_image(bool enable)
265 {
266 if (enable)
267 m_image_align.set(AlignFlag::expand);
268 else
269 m_image_align.clear(AlignFlag::expand);
270 refresh();
271 }
272
276 bool auto_scale_image() const
277 {
278 return m_image_align.is_set(AlignFlag::expand);
279 }
280
287 void keep_image_ratio(bool enable)
288 {
289 image().keep_image_ratio(enable);
290 refresh();
291 }
292
296 bool keep_image_ratio() const
297 {
298 return image().keep_image_ratio();
299 }
300
304 EGT_NODISCARD const Image& image() const { return m_image; }
305
309 Image& image() { return m_image; }
310
316 void image_align(const AlignFlags& align)
317 {
318 if (detail::change_if_diff<>(m_image_align, align))
319 this->damage();
320 }
321
325 EGT_NODISCARD AlignFlags image_align() const { return m_image_align; }
326
332 void show_label(bool value)
333 {
334 if (detail::change_if_diff<>(m_show_label, value))
335 refresh();
336 }
337
341 EGT_NODISCARD bool show_label() const { return m_show_label; }
342
343 void draw(Painter& painter, const Rect& rect) override
344 {
345 Drawer<ImageHolder>::draw(*this, painter, rect);
346 }
347
349 static void default_draw(ImageHolder& widget, Painter& painter, const Rect& rect)
350 {
351 detail::ignoreparam(rect);
352
353 widget.draw_box(painter, id_bg, id_border);
354
355 if (widget.show_label())
356 {
357 const std::string& text = widget.text();
358
359 if (!widget.image().empty())
360 {
361 detail::draw_text(painter,
362 widget.content_area(),
363 text,
364 widget.font(),
365 TextBox::TextFlags({TextBox::TextFlag::multiline, TextBox::TextFlag::word_wrap}),
366 widget.text_align(),
367 Justification::middle,
368 widget.color(id_text),
369 widget.image_align(),
370 widget.image());
371 }
372 else
373 {
374 detail::draw_text(painter,
375 widget.content_area(),
376 text,
377 widget.font(),
378 TextBox::TextFlags({TextBox::TextFlag::multiline, TextBox::TextFlag::word_wrap}),
379 widget.text_align(),
380 Justification::middle,
381 widget.color(id_text));
382 }
383 }
384 else if (!widget.image().empty())
385 {
386 auto target = widget.image().align(widget.content_area(), widget.image_align());
387 painter.draw(target.point());
388 painter.draw(widget.image());
389 }
390 }
391
392protected:
393 explicit ImageHolder(Serializer::Properties& props, bool is_derived) noexcept
394 : T(props, true)
395 {
396 deserialize(props);
397
398 if (!is_derived)
399 this->deserialize_leaf(props);
400 }
401
402 void refresh()
403 {
404 this->damage();
405 this->layout();
406 }
407
409 void do_set_image(const Image& image)
410 {
411 if (this->size().empty() && !image.empty())
412 this->resize(image.size() + Size(this->moat() * 2, this->moat() * 2));
413
414 m_image = image;
415 this->damage();
416 }
417
418public:
419 using T::min_size_hint;
420
421 EGT_NODISCARD Size min_size_hint() const override
422 {
423 if (!this->m_min_size.empty())
424 return this->m_min_size;
425
426 Size min_size_constraint;
427 if (this->show_label() && !this->text().empty())
428 min_size_constraint = T::min_size_hint();
429 else
430 min_size_constraint = Widget::min_size_hint();
431
432 if (!show_label() && auto_scale_image())
433 return min_size_constraint;
434
435 Rect size = min_size_constraint - Size(this->moat() * 2, this->moat() * 2);
436
437 if (!m_image.size().empty())
438 {
439 if (image_align().is_set(AlignFlag::left) ||
440 image_align().is_set(AlignFlag::right))
441 {
442 size += Size(m_image.width(), 0);
443 }
444 else if (image_align().is_set(AlignFlag::top) ||
445 image_align().is_set(AlignFlag::bottom))
446 {
447 size += Size(0, m_image.height());
448 }
449
450 size = Rect::merge(size, m_image.size());
451 }
452
453 auto res = size.size() + Size(this->moat() * 2, this->moat() * 2);
454 return res;
455 }
456
457 void serialize(Serializer& serializer) const override
458 {
459 T::serialize(serializer);
460
461 serializer.add_property("showlabel", show_label());
462 if (!m_image.empty())
463 m_image.serialize("image", serializer);
464 if (!image_align().empty())
465 serializer.add_property("image_align", image_align());
466 }
467
468protected:
470 {
471 // TODO proper loading of all image properties
472 m_image_align.clear();
473 props.erase(std::remove_if(props.begin(), props.end(), [&](auto & p)
474 {
475 switch (detail::hash(std::get<0>(p)))
476 {
477 case detail::hash("showlabel"):
478 show_label(egt::detail::from_string(std::get<1>(p)));
479 break;
480 case detail::hash("image"):
481 m_image.deserialize(std::get<0>(p), std::get<1>(p), std::get<2>(p));
482 break;
483 case detail::hash("image_align"):
484 image_align(AlignFlags(std::get<1>(p)));
485 break;
486 default:
487 return false;
488 }
489 return true;
490 }), props.end());
491 }
492
495
497 bool m_show_label{true};
498
501};
502
503}
504}
505
506#endif
static constexpr ExpandBitField expand
Definition widgetflags.h:301
static constexpr HorizontalBitField left
Definition widgetflags.h:290
Alignment flags.
Definition widgetflags.h:379
Manager of the Drawable for each widget type.
Definition theme.h:104
Utility class for managing a set of flags with the ability to observe changes to the flags.
Definition flags.h:40
A Frame is a Widget that has children widgets.
Definition frame.h:45
virtual void add(const std::shared_ptr< Widget > &widget)
Add a child widget.
Definition imageholder.h:35
void image_scale(float scale)
Scale the image in both direction with the same ratio.
Definition imageholder.h:190
EGT_NODISCARD float hscale() const
Get the horizontal scale value.
Definition imageholder.h:162
EGT_NODISCARD Size min_size_hint() const override
Definition imageholder.h:421
ImageHolder(Serializer::Properties &props, bool is_derived) noexcept
Definition imageholder.h:393
void draw(Painter &painter, const Rect &rect) override
Definition imageholder.h:343
EGT_NODISCARD bool show_label() const
Get the show label state.
Definition imageholder.h:341
void vscale(float vscale)
Set the vertical scale value.
Definition imageholder.h:181
void deserialize(Serializer::Properties &props)
Definition imageholder.h:469
void keep_image_ratio(bool enable)
Enable/disable ratio preservation while scaling the image.
Definition imageholder.h:287
bool keep_image_ratio() const
Get the keep image ratio state.
Definition imageholder.h:296
Image & image()
Get a non-const reference to the image.
Definition imageholder.h:309
EGT_NODISCARD float vscale() const
Get the vertical scale value.
Definition imageholder.h:176
void image_align(const AlignFlags &align)
Set the alignment of the image relative to the text.
Definition imageholder.h:316
void refresh()
Definition imageholder.h:402
void hscale(float hscale)
Set the horizontal scale value.
Definition imageholder.h:167
static void default_draw(ImageHolder &widget, Painter &painter, const Rect &rect)
Default draw method for the widget.
Definition imageholder.h:349
ImageHolder(Frame &parent, const Image &image, const std::string &text, const Rect &rect, const AlignFlags &text_align=T::default_text_align()) noexcept
Definition imageholder.h:101
ImageHolder(const std::string &text={}, const AlignFlags &text_align=T::default_text_align()) noexcept
Definition imageholder.h:41
void image(const Image &image)
Set a new Image.
Definition imageholder.h:215
void scale_image(float hscale, float vscale, bool approximate=false)
Scale the image.
Definition imageholder.h:237
EGT_NODISCARD std::string uri() const
Get the URI of the current image.
Definition imageholder.h:134
ImageHolder & operator=(const ImageHolder &) noexcept=delete
void image_scale(const SizeF &scale)
Scale the image in both direction.
Definition imageholder.h:199
EGT_NODISCARD AlignFlags image_align() const
Get the image alignment.
Definition imageholder.h:325
ImageHolder(Frame &parent, const Image &image={}, const std::string &text={}, const AlignFlags &text_align=T::default_text_align()) noexcept
Definition imageholder.h:85
void uri(const std::string &uri)
Load a new Image from an uri.
Definition imageholder.h:144
EGT_NODISCARD const Image & image() const
Get a const reference of the image.
Definition imageholder.h:304
void serialize(Serializer &serializer) const override
Definition imageholder.h:457
void auto_scale_image(bool enable)
Enable/disable the auto scale of the image.
Definition imageholder.h:264
ImageHolder(ImageHolder &&) noexcept=default
void show_label(bool value)
Enable/disable showing the label text.
Definition imageholder.h:332
EGT_NODISCARD SizeF image_scale() const
Get both scale values.
Definition imageholder.h:208
ImageHolder(Serializer::Properties &props) noexcept
Definition imageholder.h:114
ImageHolder(const Image &image, const std::string &text={}, const AlignFlags &text_align=T::default_text_align()) noexcept
Definition imageholder.h:51
void scale_image(float scale, bool approximate=false)
Scale the image.
Definition imageholder.h:253
ImageHolder(const ImageHolder &) noexcept=delete
bool auto_scale_image() const
Get the auto scale image state.
Definition imageholder.h:276
void reset_uri()
Reset the URI, therefore clear the current image, if any.
Definition imageholder.h:153
Image m_image
The image. Allowed to be empty.
Definition imageholder.h:494
ImageHolder(const Image &image, const std::string &text, const Rect &rect, const AlignFlags &text_align=T::default_text_align()) noexcept
Definition imageholder.h:63
Raster image resource used for drawing or displaying.
Definition image.h:39
void keep_image_ratio(bool enable)
Enable/disable ratio preservation while scaling the image.
Definition image.h:223
EGT_NODISCARD Size size() const
Get the absolute size of the image.
Definition image.h:158
EGT_NODISCARD bool empty() const
Returns true if no internal surface is set.
Definition image.h:180
Drawing interface for 2D graphics.
Definition painter.h:45
Painter & draw(const PointType< T, detail::Compatible::normal > &point)
Move to a point.
Definition painter.h:182
ColorId
The Pattern identifier in the Palette.
Definition palette.h:239
Abstract base serializer class.
Definition serialize.h:34
virtual void add_property(const std::string &name, const std::string &value, const Attributes &attrs={})=0
Add a property.
std::list< std::tuple< std::string, std::string, Serializer::Attributes > > Properties
Definition serialize.h:47
EGT_NODISCARD constexpr Dim width() const noexcept
Get the width value.
Definition geometry.h:457
EGT_NODISCARD constexpr Dim height() const noexcept
Get the height value.
Definition geometry.h:459
T & align(T &widget, const AlignFlags &a)
Helper to set alignment of a widget.
Definition widgetflags.h:624
EGT framework namespace.
Definition animation.h:24