1.11
slider.h
1/*
2 * Copyright (C) 2018 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef EGT_SLIDER_H
7#define EGT_SLIDER_H
8
14#include <egt/app.h>
15#include <egt/detail/alignment.h>
16#include <egt/detail/enum.h>
17#include <egt/detail/math.h>
18#include <egt/detail/meta.h>
19#include <egt/detail/screen/composerscreen.h>
20#include <egt/flags.h>
21#include <egt/frame.h>
22#include <egt/imagegroup.h>
23#include <egt/painter.h>
24#include <egt/serialize.h>
25#include <egt/textwidget.h>
26#include <egt/valuewidget.h>
27#include <egt/widgetflags.h>
28
29namespace egt
30{
31inline namespace v1
32{
33
38{
40 enum class SliderFlag
41 {
44
47
50
53
56
62
65
68 };
69
72
74 {
75 to_end,
78 };
79};
80
93template <class T>
94class SliderType : protected SliderBase, public ValueRangeWidget<T>
95{
96public:
97
100
108 explicit SliderType(const Rect& rect, T start = 0, T end = 100, T value = 0,
110
117 explicit SliderType(T start = 0, T end = 100, T value = 0,
119 : SliderType(Rect(), start, end, value, orient)
120 {
121 }
122
131 SliderType(Frame& parent, const Rect& rect, T start = 0, T end = 100, T value = 0,
133 : SliderType(rect, start, end, value, orient)
134 {
135 parent.add(*this);
136 }
137
145 explicit SliderType(Frame& parent, T start = 0, T end = 100, T value = 0,
147 : SliderType(Rect(), start, end, value, orient)
148 {
149 parent.add(*this);
150 }
151
155 explicit SliderType(Serializer::Properties& props) noexcept
156 : SliderType(props, false)
157 {
158 }
159
160protected:
161
162 explicit SliderType(Serializer::Properties& props, bool is_derived) noexcept;
163
164public:
165
166 void handle(Event& event) override
167 {
168 Widget::handle(event);
169
170 switch (event.id())
171 {
174 {
175 m_invoke_pending = false;
176 this->on_value_changed.invoke();
177 }
178 break;
181 break;
184 {
185 const auto diff = event.pointer().point - event.pointer().drag_start;
186 if (slider_flags().is_set(SliderFlag::inverted))
188 else
190 }
191 else
192 {
193 const auto diff = event.pointer().point - event.pointer().drag_start;
194 if (slider_flags().is_set(SliderFlag::inverted))
196 else
198 }
199 break;
200 default:
201 break;
202 }
203 }
204
205 void draw(Painter& painter, const Rect& rect) override;
206
215 bool allow_fallback = false) const;
216
223 void handle_image(const Image& image,
225
232
242 {
243 if (detail::change_if_diff<>(m_label_offset, offset))
244 this->damage();
245 }
246
250 EGT_NODISCARD DefaultDim label_offset() const { return m_label_offset; }
251
261 {
262 if (detail::change_if_diff<>(m_handle_offset, offset))
263 {
264 this->damage();
265 this->layout();
266 }
267 }
268
272 EGT_NODISCARD DefaultDim handle_offset() const { return m_handle_offset; }
273
283 {
284 if (detail::change_if_diff<>(m_handle_margin, margin))
285 this->damage();
286 }
287
291 EGT_NODISCARD DefaultDim handle_margin() const { return m_handle_margin; }
292
294
295 T value(T value) override
296 {
297 T orig = this->value();
298
299 update_value(value);
300
302 {
303 m_invoke_pending = false;
304 this->on_value_changed.invoke();
305 }
306
307 return orig;
308 }
309
319 {
321 }
322
326 EGT_NODISCARD bool live_update() const { return m_live_update; }
327
331 EGT_NODISCARD Orientation orient() const { return m_orient; }
332
339 {
340 if (detail::change_if_diff<>(m_orient, orient))
341 {
342 this->damage();
343 this->layout();
344 }
345 }
346
351
358 {
359 if (detail::change_if_diff<>(m_line_transition, transition))
360 this->damage();
361 }
362
364 EGT_NODISCARD const SliderFlags& slider_flags() const { return m_slider_flags; }
365
368
370
374 static void default_size(const Size& size);
375
376 EGT_NODISCARD Size min_size_hint() const override
377 {
378 if (!this->m_min_size.empty())
379 return this->m_min_size;
380
381 auto* image = this->background(Palette::GroupId::normal);
382 Rect rect(image ? image->size() : default_size());
383
385 if (image)
386 {
387 Rect r(image->size());
388 r.move_to_center(rect.center());
390 r.y(r.y() + m_handle_offset);
391 else
392 r.x(r.x() + m_handle_offset);
393 rect = Rect::merge(rect, r);
394 }
395
396 return rect.size() + Widget::min_size_hint();
397 }
398
399 void serialize(Serializer& serializer) const override;
400
401protected:
402
403 bool internal_drag() const override { return true; }
404 bool internal_track_drag() const override { return true; }
405
407 EGT_NODISCARD int to_offset(T value) const
408 {
409 if (detail::float_equal(static_cast<float>(this->m_start), static_cast<float>(this->m_end)))
410 return m_handle_margin;
411
412 const auto m = m_handle_margin;
413 const auto b = this->content_area();
415 return egt::detail::normalize<float>(value, this->m_start, this->m_end,
416 m, b.width() - m - handle_width());
417 else
418 return egt::detail::normalize<float>(value, this->m_start, this->m_end,
419 m, b.height() - m - handle_height());
420 }
421
423 EGT_NODISCARD T to_value(int offset) const
424 {
425 const auto m = m_handle_margin;
426 const auto b = this->content_area();
428 return egt::detail::normalize<float>(offset, m, b.width() - m - handle_width(),
429 this->m_start, this->m_end);
430 else
431 return egt::detail::normalize<float>(offset, m, b.height() - m - handle_height(),
432 this->m_start, this->m_end);
433 }
434
437 {
438 T prev_value = this->m_value;
439 if (this->set_value(value))
440 {
441 auto r = Rect::merge(handle_box(prev_value), handle_box());
442 this->damage(r);
443
444 if (slider_flags().is_set(SliderFlag::show_label))
445 {
446 std::string text;
447 auto label_rect = label_box(prev_value, text);
448 this->damage(label_rect);
449
450 label_rect = label_box(this->m_value, text);
451 this->damage(label_rect);
452 }
453
454 if (m_live_update)
455 {
456 this->on_value_changed.invoke();
457 }
458 else
459 m_invoke_pending = true;
460 }
461 }
462
464 EGT_NODISCARD int handle_width() const;
465
467 EGT_NODISCARD int handle_height() const;
468
470 EGT_NODISCARD Rect handle_box() const
471 {
472 return handle_box(this->m_value);
473 }
474
476 EGT_NODISCARD Rect handle_box(T value) const;
477
479 EGT_NODISCARD Rect label_box(T value, std::string& text) const
480 {
481 const auto b = this->content_area();
482 auto handle_rect = handle_box(value);
483
486 {
487 auto shift = image ? 0 : (b.height() / 2);
488 handle_rect += Point(0, m_label_offset - shift);
489 }
490 else
491 {
492 auto shift = image ? 0 : (b.width() / 2);
493 handle_rect += Point(m_label_offset - shift, 0);
494 }
495
496 text = format_label(value);
497
498 const auto text_size = this->font().text_size(text);
499 auto target = detail::align_algorithm(text_size,
500 handle_rect,
502 5);
503
505 if (target.width() <= b.width())
506 {
507 if (target.x() < b.x())
508 target.x(b.x());
509
510 if (target.x() + target.width() > b.x() + b.width())
511 target.x(b.x() + b.width() - target.width());
512 }
513
514 if (target.height() <= b.height())
515 {
516 if (target.y() < b.y())
517 target.y(b.y());
518
519 if (target.y() + target.height() > b.y() + b.height())
520 target.y(b.y() + b.height() - target.height());
521 }
522
523 return target;
524 }
525
527
529 void draw_label(Painter& painter, T value)
530 {
531 std::string text;
532 const auto target = label_box(value, text);
533 painter.draw(target.point());
534 painter.set(this->color(Palette::ColorId::label_text));
535 painter.draw(text);
536 }
537
539 void draw_handle(Painter& painter, const Rect& handle_rect);
540
542 void draw_line(Painter& painter, const Rect& handle_rect);
543
545 static std::string format_label(T value)
546 {
547 return std::to_string(value);
548 }
549
552
554 bool m_invoke_pending{false};
555
557 bool m_live_update{false};
558
561
564
567
568private:
570 static Size m_default_size;
571 static Signal<>::RegisterHandle m_default_size_handle;
572 static void register_handler();
573 static void unregister_handler();
574
576 ImageGroup m_handles{"handle"};
577 DefaultDim m_handle_offset{0};
578 DefaultDim m_handle_margin{0};
579
580 DefaultDim m_label_offset{0};
581
582 void deserialize(Serializer::Properties& props);
583};
584
590class EGT_API Slider : public SliderType<int>
591{
592public:
593 using SliderType<int>::SliderType;
594
595 EGT_NODISCARD std::string type() const override
596 {
597 return "Slider";
598 }
599};
600
606class EGT_API SliderF : public SliderType<float>
607{
608public:
609 using SliderType<float>::SliderType;
610
611 EGT_NODISCARD std::string type() const override
612 {
613 return "SliderF";
614 }
615};
616
617template <class T>
619
620template <class T>
622
623template <class T>
625{
626 if (m_default_size_handle == Signal<>::INVALID_HANDLE)
627 {
628 m_default_size_handle = detail::ComposerScreen::register_screen_resize_hook([]()
629 {
630 m_default_size.clear();
631 });
632 }
633}
634
635template <class T>
636void SliderType<T>::unregister_handler()
637{
639 m_default_size_handle = Signal<>::INVALID_HANDLE;
640}
641
642template <class T>
644{
646 {
647 register_handler();
648 auto ss = egt::Application::instance().screen()->size();
649 SliderType<T>::m_default_size = Size(ss.width() * 0.20, ss.height() * 0.10);
650 }
651
653}
654
655template <class T>
657{
658 if (!size.empty())
659 unregister_handler();
660
662}
663
664template <class T>
665SliderType<T>::SliderType(const Rect& rect, T start, T end, T value,
666 Orientation orient) noexcept
667 : ValueRangeWidget<T>(rect, start, end, value),
668 m_orient(orient)
669{
670 this->name("Slider" + std::to_string(this->m_widgetid));
671 this->fill_flags(Theme::FillFlag::blend);
672 this->grab_mouse(true);
673 this->slider_flags().set(SliderFlag::rectangle_handle);
674 this->border_radius(4.0);
675}
676
677template <class T>
678SliderType<T>::SliderType(Serializer::Properties& props, bool is_derived) noexcept
679 : ValueRangeWidget<T>(props, true)
680{
681 deserialize(props);
682
683 if (!is_derived)
684 this->deserialize_leaf(props);
685}
686
687
688template <class T>
689void SliderType<T>::draw(Painter& painter, const Rect& rect)
690{
691 Painter::AutoSaveRestore sr(painter);
692
693 if (this->clip())
694 {
695 painter.draw(rect);
696 painter.clip();
697 }
698
699 painter.alpha_blending(true);
700
701 Rect background, handle;
702 compute_boxes(this->value(), &background, &handle);
703
704 auto* bg = this->background(true);
705 if (bg)
706 painter.draw(*bg, background.point(), background);
707
708 // line
709 draw_line(painter, handle);
710
711 // handle
712 draw_handle(painter, handle);
713
718 if (slider_flags().is_set(SliderFlag::show_label))
719 {
720 draw_label(painter, this->value());
721 }
722 else if (slider_flags().is_set(SliderFlag::show_labels))
723 {
724 draw_label(painter, this->starting());
725 draw_label(painter, this->starting() + ((this->ending() - this->starting()) / 2));
726 draw_label(painter, this->ending());
727 }
728}
729
730template <class T>
732{
733 auto* image = handle_image(Palette::GroupId::normal);
734 if (image)
735 return image->width();
736
737 const auto b = this->content_area();
738 auto width = b.width();
739 auto height = b.height();
740
741 if (slider_flags().is_set(SliderFlag::show_labels) ||
742 slider_flags().is_set(SliderFlag::show_label))
743 {
744 if (m_orient == Orientation::horizontal)
745 height /= 2;
746 else
747 width /= 2;
748 }
749
750 if (slider_flags().is_set(SliderFlag::square_handle) ||
751 slider_flags().is_set(SliderFlag::round_handle))
752 {
753 if (m_orient == Orientation::horizontal)
754 return std::min<DefaultDim>(width / 6, height);
755 else
756 return std::min<DefaultDim>(height / 6, width);
757 }
758 else
759 {
760 if (m_orient == Orientation::horizontal)
761 return std::min<DefaultDim>(width / 6, height) * 2;
762 else
763 return std::min<DefaultDim>(height / 6, width);
764 }
765}
766
767template <class T>
769{
770 auto* image = handle_image(Palette::GroupId::normal);
771 if (image)
772 return image->height();
773
774 const auto b = this->content_area();
775 auto width = b.width();
776 auto height = b.height();
777
778 if (slider_flags().is_set(SliderFlag::show_labels) ||
779 slider_flags().is_set(SliderFlag::show_label))
780 {
781 if (m_orient == Orientation::horizontal)
782 height /= 2;
783 else
784 width /= 2;
785 }
786
787 if (slider_flags().is_set(SliderFlag::square_handle) ||
788 slider_flags().is_set(SliderFlag::round_handle))
789 {
790 if (m_orient == Orientation::horizontal)
791 return std::min<DefaultDim>(width / 6, height);
792 else
793 return std::min<DefaultDim>(height / 6, width);
794 }
795 else
796 {
797 if (m_orient == Orientation::horizontal)
798 return std::min<DefaultDim>(width / 6, height);
799 else
800 return std::min<DefaultDim>(height / 6, width) * 2;
801 }
802}
803
804template <class T>
806 Rect* background,
807 Rect* handle) const
808{
809 const auto b = this->content_area();
810 const auto dimw = handle_width();
811 const auto dimh = handle_height();
812 const auto offset = to_offset(value);
813 Rect bg, hndl;
814
815 auto* image_bg = this->background(Palette::GroupId::normal);
816 bg.size(image_bg ? image_bg->size() : b.size());
817
818 auto* image_hndl = handle_image(Palette::GroupId::normal);
819 hndl.width(dimw);
820 hndl.height(dimh);
821
822 if (m_orient == Orientation::horizontal)
823 {
824 auto deltah = (bg.height() - dimh) / 2 + m_handle_offset;
825
826 bg.x(b.x() + (b.width() - bg.width()) / 2);
827 bg.y(b.y() - std::min(0, deltah));
828
829 if (slider_flags().is_set(SliderFlag::inverted))
830 hndl.x(b.x() + b.width() - offset - dimw);
831 else
832 hndl.x(b.x() + offset);
833
834 if (image_hndl)
835 hndl.y(b.y() + std::max(0, deltah));
836 else if (slider_flags().is_set(SliderFlag::show_labels) ||
837 slider_flags().is_set(SliderFlag::show_label))
838 hndl.y(b.y() + b.height() * 3 / 4 - dimh / 2 + m_handle_offset);
839 else
840 hndl.y(b.y() + b.height() / 2 - dimh / 2 + m_handle_offset);
841 }
842 else
843 {
844 auto deltaw = (bg.width() - dimw) / 2 + m_handle_offset;
845
846 bg.y(b.y() + (b.height() - bg.height()) / 2);
847 bg.x(b.x() - std::min(0, deltaw));
848
849 if (slider_flags().is_set(SliderFlag::inverted))
850 hndl.y(b.y() + offset);
851 else
852 hndl.y(b.y() + b.height() - offset - dimh);
853
854 if (image_hndl)
855 hndl.x(b.x() + std::max(0, deltaw));
856 else if (slider_flags().is_set(SliderFlag::show_labels) ||
857 slider_flags().is_set(SliderFlag::show_label))
858 hndl.x(b.x() + b.width() * 3 / 4 - dimw / 2 + m_handle_offset);
859 else
860 hndl.x(b.x() + b.width() / 2 - dimw / 2 + m_handle_offset);
861 }
862
863 if (background)
864 *background = bg;
865
866 if (handle)
867 *handle = hndl;
868}
869
870template <class T>
872{
873 Rect handle;
874 compute_boxes(value, nullptr, &handle);
875 return handle;
876}
877
878template <class T>
879void SliderType<T>::draw_handle(Painter& painter, const Rect& handle_rect)
880{
881 auto* image = handle_image(this->group(), true);
882 if (image)
883 {
884 painter.draw(*image, handle_rect.point(), handle_rect);
885 }
886 else if (slider_flags().is_set(SliderFlag::round_handle))
887 {
888 this->theme().draw_circle(painter,
890 handle_rect,
891 this->color(Palette::ColorId::border),
892 this->color(Palette::ColorId::button_bg),
893 this->border());
894 }
895 else
896 {
897 this->theme().draw_box(painter,
899 handle_rect,
900 this->color(Palette::ColorId::border),
901 this->color(Palette::ColorId::button_bg),
902 this->border(),
903 0,
904 this->border_radius());
905 }
906}
907
908template <class T>
909void SliderType<T>::draw_line(Painter& painter, const Rect& handle_rect)
910{
911 if (slider_flags().is_set(SliderFlag::hide_line))
912 return;
913
914 const auto inverted = !!slider_flags().is_set(SliderFlag::inverted);
915 const auto b = this->content_area();
916 const auto center = handle_rect.center();
917 Point p1, p2;
918 Size s1, s2, s;
919
920 if (m_orient == Orientation::horizontal)
921 {
922 const auto w = handle_rect.width() / 2;
923 auto transition_x = center.x();
924 switch (line_transition())
925 {
926 case SliderLineTransition::to_end:
927 transition_x += inverted ? -w : w;
928 break;
929 case SliderLineTransition::to_begin:
930 transition_x -= inverted ? -w : w;
931 break;
932 default:
933 break;
934 }
935
936 p1.x(b.x() + m_handle_margin);
937 s1.width(transition_x - p1.x());
938 s1.height(handle_rect.height() / 5);
939 p1.y(center.y() - s1.height() / 2);
940
941 p2.x(transition_x);
942 s2.width(b.x() + b.width() - m_handle_margin - p2.x());
943 s2.height(s1.height());
944 p2.y(p1.y());
945
946 s.width(s1.width() + s2.width());
947 s.height(s1.height());
948 }
949 else
950 {
951 const auto h = handle_rect.height() / 2;
952 auto transition_y = center.y();
953 switch (line_transition())
954 {
955 case SliderLineTransition::to_end:
956 transition_y -= inverted ? -h : h;
957 break;
958 case SliderLineTransition::to_begin:
959 transition_y += inverted ? -h : h;
960 break;
961 default:
962 break;
963 }
964
965 p1.y(b.y() + m_handle_margin);
966 s1.height(transition_y - p1.y());
967 s1.width(handle_rect.width() / 5);
968 p1.x(center.x() - s1.width() / 2);
969
970 p2.y(transition_y);
971 s2.height(b.y() + b.height() - m_handle_margin - p2.y());
972 s2.width(s1.width());
973 p2.x(p1.x());
974
975 s.height(s1.height() + s2.height());
976 s.width(s1.width());
977 }
978
979 if (slider_flags().is_set(SliderFlag::consistent_line))
980 {
981 painter.draw(this->color(Palette::ColorId::button_fg,
983 Rect(p1, s));
984 }
985 else
986 {
987 auto c1 = this->color(Palette::ColorId::button_fg);
988 auto c2 = this->color(Palette::ColorId::button_fg,
990
991 if (inverted ^ (m_orient == Orientation::vertical))
992 std::swap(c1, c2);
993
994 const Rect r1(p1, s1);
995 if (!r1.empty())
996 painter.draw(c1, r1);
997
998 const Rect r2(p2, s2);
999 if (!r2.empty())
1000 painter.draw(c2, r2);
1001 }
1002}
1003
1005template<>
1006EGT_API std::string SliderType<float>::format_label(float value);
1007
1009template<>
1010EGT_API std::string SliderType<double>::format_label(double value);
1011
1012template <class T>
1014{
1016
1017 serializer.add_property("sliderflags", m_slider_flags.to_string());
1018 serializer.add_property("line_transition", detail::enum_to_string(line_transition()));
1019 serializer.add_property("orient", detail::enum_to_string(orient()));
1020 serializer.add_property("label_offset", label_offset());
1021 serializer.add_property("handle_offset", handle_offset());
1022 serializer.add_property("handle_margin", handle_margin());
1023 m_handles.serialize(serializer);
1024}
1025
1026template <class T>
1028{
1029 props.erase(std::remove_if(props.begin(), props.end(), [&](auto & p)
1030 {
1031 if (std::get<0>(p) == "sliderflags")
1032 {
1033 m_slider_flags.from_string(std::get<1>(p));
1034 return true;
1035 }
1036 else if (std::get<0>(p) == "line_transition")
1037 {
1038 line_transition(detail::enum_from_string<SliderLineTransition>(std::get<1>(p)));
1039 return true;
1040 }
1041 else if (std::get<0>(p) == "orient")
1042 {
1043 orient(detail::enum_from_string<Orientation>(std::get<1>(p)));
1044 return true;
1045 }
1046 else if (std::get<0>(p) == "label_offset")
1047 {
1048 label_offset(std::stoi(std::get<1>(p)));
1049 return true;
1050 }
1051 else if (std::get<0>(p) == "handle_offset")
1052 {
1053 handle_offset(std::stoi(std::get<1>(p)));
1054 return true;
1055 }
1056 else if (std::get<0>(p) == "handle_margin")
1057 {
1058 handle_margin(std::stoi(std::get<1>(p)));
1059 return true;
1060 }
1061 else if (m_handles.deserialize(std::get<0>(p), std::get<1>(p)))
1062 {
1063 return true;
1064 }
1065 return false;
1066 }), props.end());
1067}
1068
1069template <class T>
1070Image* SliderType<T>::handle_image(Palette::GroupId group, bool allow_fallback) const
1071{
1072 return m_handles.get(group, allow_fallback);
1073}
1074
1075template <class T>
1077{
1078 m_handles.set(group, image);
1079 this->damage();
1080 this->layout();
1081}
1082
1083template <class T>
1085{
1086 if (m_handles.reset(group))
1087 {
1088 this->damage();
1089 this->layout();
1090 }
1091}
1092
1094template<>
1095EGT_API const std::pair<SliderBase::SliderFlag, char const*> detail::EnumStrings<SliderBase::SliderFlag>::data[8];
1096
1097template<>
1098EGT_API const std::pair<SliderBase::SliderLineTransition, char const*> detail::EnumStrings<SliderBase::SliderLineTransition>::data[3];
1099
1100}
1101}
1102
1103#endif
static constexpr HVBitField center
Definition widgetflags.h:297
EGT_NODISCARD Screen * screen() const
Get a pointer to the Screen instance.
Definition app.h:119
Utility class for managing a set of flags with the ability to observe changes to the flags.
Definition flags.h:40
EGT_NODISCARD egt::Size text_size(const std::string &text) const
Get the size of a rectangle containing the text, based on a default context.
A Frame is a Widget that has children widgets.
Definition frame.h:45
Definition imagegroup.h:25
Raster image resource used for drawing or displaying.
Definition image.h:38
Drawing interface for 2D graphics.
Definition painter.h:54
Painter & set(const Pattern &pattern)
Set the current color.
Painter & draw(const PointType< T, detail::Compatible::normal > &point)
Move to a point.
Definition painter.h:304
Painter & alpha_blending(bool enabled)
Set the alpha blending state either enabled or disabled.
Painter & clip()
GroupId
Used to define a category of patterns that usually relate to the state of a widget.
Definition palette.h:219
@ disabled
Color group usually associated with the Widget::Flag::disabled flag.
@ normal
Default color group associated with a normal Widget state.
@ button_bg
Button background color.
@ button_fg
Button foreground color.
@ label_text
Label text color.
EGT_NODISCARD constexpr Dim x() const noexcept
Get the x value.
Definition geometry.h:192
EGT_NODISCARD constexpr Dim y() const noexcept
Get the y value.
Definition geometry.h:194
EGT_NODISCARD constexpr Dim width() const noexcept
Get the width value.
Definition geometry.h:926
EGT_NODISCARD constexpr Dim x() const noexcept
Get the x value.
Definition geometry.h:916
static constexpr RectType merge(const RectType &lhs, const RectType &rhs) noexcept
Merge two rectangles together into one super rectangle that contains them both.
Definition geometry.h:871
EGT_NODISCARD constexpr bool empty() const noexcept
Returns true if the rectangle has no width or height.
Definition geometry.h:829
constexpr void move_to_center(const PointType< Dim, DimCompat > &center) noexcept
Move the rectangle's center to the specified point.
Definition geometry.h:689
EGT_NODISCARD constexpr const SizeType< Dim, DimCompat > & size() const noexcept
Get the SizeType of the rectangle.
Definition geometry.h:738
EGT_NODISCARD constexpr const PointType< Dim, DimCompat > & point() const noexcept
Get the PointType of the rectangle.
Definition geometry.h:722
EGT_NODISCARD constexpr Dim height() const noexcept
Get the height value.
Definition geometry.h:928
EGT_NODISCARD constexpr PointType< Dim, DimCompat > center() const noexcept
Return the center point of the rectangle.
Definition geometry.h:681
EGT_NODISCARD constexpr Dim y() const noexcept
Get the y value.
Definition geometry.h:918
EGT_NODISCARD Size size() const
Size of the screen.
Definition screen.h:80
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
Signal class used for defining a signal and dispatching events.
Definition signal.h:30
@ INVALID_HANDLE
Definition signal.h:35
void invoke(Args... args)
Invoke all handlers with the specified args.
Definition signal.h:85
uint32_t RegisterHandle
Handle type.
Definition signal.h:46
EGT_NODISCARD constexpr Dim width() const noexcept
Get the width value.
Definition geometry.h:457
EGT_NODISCARD constexpr bool empty() const noexcept
Returns true if the size has no width or height.
Definition geometry.h:372
EGT_NODISCARD constexpr Dim height() const noexcept
Get the height value.
Definition geometry.h:459
This is a slider that can be used to select floating value from a range.
Definition slider.h:607
EGT_NODISCARD std::string type() const override
Returns a string representation of the type of this widget.
Definition slider.h:611
This is a slider that can be used to select value from a range.
Definition slider.h:95
void orient(Orientation orient)
Set the Orientation.
Definition slider.h:338
SliderLineTransition m_line_transition
Line transition.
Definition slider.h:563
EGT_NODISCARD Size min_size_hint() const override
Get a minimum size hint for the Widget.
Definition slider.h:376
SliderFlags & slider_flags()
Get the current slider flags.
Definition slider.h:367
void compute_boxes(T value, Rect *background, Rect *handle) const
Definition slider.h:805
SliderType(Frame &parent, T start=0, T end=100, T value=0, Orientation orient=Orientation::horizontal) noexcept
Definition slider.h:145
void live_update(bool enable)
Enable or disable the live update feature.
Definition slider.h:318
void update_value(T value)
Update the value without notifying the handlers.
Definition slider.h:436
static Size default_size()
Default Slider size.
Definition slider.h:643
void draw(Painter &painter, const Rect &rect) override
Draw the widget.
Definition slider.h:689
EGT_NODISCARD int handle_width() const
Get the calculated handle width.
Definition slider.h:731
EGT_NODISCARD bool live_update() const
get live update value.
Definition slider.h:326
void label_offset(DefaultDim offset)
Set the offset the label.
Definition slider.h:241
static void default_size(const Size &size)
Change default Slider size.
Definition slider.h:656
void handle_image(const Image &image, Palette::GroupId group=Palette::GroupId::normal)
Set the image used to draw the slider's handle.
Definition slider.h:1076
void handle_offset(DefaultDim offset)
Set the offset for the handle.
Definition slider.h:260
void draw_line(Painter &painter, const Rect &handle_rect)
Draw the line.
Definition slider.h:909
void reset_handle_image(Palette::GroupId group=Palette::GroupId::normal)
Remove the image, if any, used to draw the slider's handle.
Definition slider.h:1084
EGT_NODISCARD Image * handle_image(Palette::GroupId group, bool allow_fallback=false) const
Get the image, if any, to draw the slider's handle for the given group.
Definition slider.h:1070
EGT_NODISCARD Orientation orient() const
Get the Orientation.
Definition slider.h:331
EGT_NODISCARD SliderLineTransition line_transition() const
Get the line transition.
Definition slider.h:350
void draw_label(Painter &painter, T value)
Draw the value label.
Definition slider.h:529
EGT_NODISCARD DefaultDim label_offset() const
Get the offset for the label.
Definition slider.h:250
SliderType(Serializer::Properties &props, bool is_derived) noexcept
Definition slider.h:678
EGT_NODISCARD Rect handle_box() const
Get the handle box for the current value.
Definition slider.h:470
EGT_NODISCARD Rect handle_box(T value) const
Get the handle box for the specified value.
Definition slider.h:871
Orientation m_orient
Orientation of the slider.
Definition slider.h:551
SliderType(T start=0, T end=100, T value=0, Orientation orient=Orientation::horizontal) noexcept
Definition slider.h:117
EGT_NODISCARD int handle_height() const
Get the calculated handle height.
Definition slider.h:768
T value(T value) override
Set value.
Definition slider.h:295
static std::string format_label(T value)
Format the label text.
Definition slider.h:545
SliderType(const Rect &rect, T start=0, T end=100, T value=0, Orientation orient=Orientation::horizontal) noexcept
Definition slider.h:665
int m_start_offset
When dragging, the offset at the drag start.
Definition slider.h:566
bool internal_drag() const override
Definition slider.h:403
void serialize(Serializer &serializer) const override
Serialize the widget to the specified serializer.
Definition slider.h:1013
SliderType(Serializer::Properties &props) noexcept
Definition slider.h:155
void draw_handle(Painter &painter, const Rect &handle_rect)
Draw the handle.
Definition slider.h:879
bool internal_track_drag() const override
Definition slider.h:404
EGT_NODISCARD T to_value(int offset) const
Convert an offset to value.
Definition slider.h:423
EGT_NODISCARD int to_offset(T value) const
Convert a value to an offset.
Definition slider.h:407
EGT_NODISCARD DefaultDim handle_margin() const
Get the margin for the handle image.
Definition slider.h:291
void handle(Event &event) override
Handle an event.
Definition slider.h:166
EGT_NODISCARD Rect label_box(T value, std::string &text) const
Get the label box and text for the specified value.
Definition slider.h:479
bool m_live_update
When true, notify handlers even during drag.
Definition slider.h:557
EGT_NODISCARD DefaultDim handle_offset() const
Get the offset for the handle.
Definition slider.h:272
void line_transition(SliderLineTransition transition)
Set the line transition.
Definition slider.h:357
SliderType(Frame &parent, const Rect &rect, T start=0, T end=100, T value=0, Orientation orient=Orientation::horizontal) noexcept
Definition slider.h:131
void handle_margin(DefaultDim margin)
Set the margin for the handle image.
Definition slider.h:282
EGT_NODISCARD const SliderFlags & slider_flags() const
Get the current slider flags.
Definition slider.h:364
SliderFlags m_slider_flags
Slider flags.
Definition slider.h:560
bool m_invoke_pending
When true, an invoke of events has been queued to occur.
Definition slider.h:554
This is a slider that can be used to select integer value from a range.
Definition slider.h:591
EGT_NODISCARD std::string type() const override
Returns a string representation of the type of this widget.
Definition slider.h:595
@ blend
perform a blend
Manages a value in a range.
Definition valuewidget.h:93
T m_start
The start value.
Definition valuewidget.h:258
bool set_value(T v)
Definition valuewidget.h:242
void serialize(Serializer &serializer) const override
Serialize the widget to the specified serializer.
Definition valuewidget.h:275
Signal on_value_changed
Event signal.
Definition valuewidget.h:103
EGT_NODISCARD T value() const
Get the current value.
Definition valuewidget.h:233
T m_end
The end value.
Definition valuewidget.h:261
T m_value
The current value.
Definition valuewidget.h:264
virtual void handle(Event &event)
Handle an event.
EGT_NODISCARD DefaultDim margin() const
Get the margin width.
Definition widget.h:971
EGT_NODISCARD Image * background(bool allow_fallback=false) const
Get the background image, if any, for the current group.
virtual void layout()
Perform layout of the Widget.
void enable()
Set the disabled state to false.
EGT_NODISCARD const Size & size() const
Get the size of the widget's box().
Definition widget.h:739
Widget * parent()
Get a pointer to the parent Widget, or nullptr if none exists.
EGT_NODISCARD Palette::GroupId group() const
Get the current Palette::GroupId depending on the widget's state.
Size m_min_size
Minimum size of the widget when not an empty value.
Definition widget.h:1815
EGT_NODISCARD const Font & font() const
Get the widget Font.
virtual EGT_NODISCARD Rect content_area() const
Return the area that content is allowed to be positioned into.
EGT_NODISCARD const Pattern & color(Palette::ColorId id) const
Get a Widget color.
virtual EGT_NODISCARD Size min_size_hint() const
Get a minimum size hint for the Widget.
virtual void damage()
Damage the box() of the widget and cause a redraw.
static Signal ::RegisterHandle register_screen_resize_hook(const Signal<>::EventCallback &handler)
Register a handler to manage screen size changes.
static void unregister_screen_resize_hook(Signal<>::RegisterHandle handle)
Unregister a handler that managed screen size changes.
@ raw_pointer_up
Raw pointer event.
@ pointer_drag
Pointer event.
@ pointer_drag_start
Pointer event.
SizeType< DefaultDim, detail::Compatible::normal > Size
Helper type alias.
Definition geometry.h:573
RectType< DefaultDim, detail::Compatible::normal > Rect
Helper type alias.
Definition geometry.h:1036
PointType< DefaultDim, detail::Compatible::normal > Point
Helper type alias.
Definition geometry.h:314
constexpr T bit(T n)
Utility to create a bit mask for the specified bit.
Definition meta.h:306
constexpr bool float_equal(const float f1, const float f2)
Safe equal comparison of float values.
Definition math.h:107
constexpr const char * enum_to_string(T const &e)
Convert an enum to a string.
Definition enum.h:55
EGT_API Rect align_algorithm(const Rect &orig, const Rect &bounding, const AlignFlags &align, DefaultDim padding=0, DefaultDim horizontal_ratio=0, DefaultDim vertical_ratio=0, DefaultDim xratio=0, DefaultDim yratio=0)
Given an item size, and a bounding box, and an alignment parameter, return the rectangle the item box...
T & center(T &widget)
Helper to set alignment of a widget.
Definition widgetflags.h:417
Orientation
Generic orientation flags.
Definition widgetflags.h:679
int DefaultDim
Define the default dimension type used for geometry.
Definition geometry.h:34
EGT framework namespace.
Definition animation.h:24
A single event that has information about the event and state for the event.
Definition event.h:255
EGT_NODISCARD const EventId & id() const noexcept
Get the id of the event.
Definition event.h:284
Scoped save() and restore() for a Painter.
Definition painter.h:104
Base class for SliderType.
Definition slider.h:38
SliderFlag
Slider flags.
Definition slider.h:41
@ inverted
Horizontal slider origin (value start()), is to the left.
@ round_handle
Draw a round handle.
@ consistent_line
Solid color line.
@ square_handle
Draw a square handle.
@ show_labels
Show range labels.
@ rectangle_handle
Draw a rectangle handle.
@ show_label
Show value label.
SliderLineTransition
Definition slider.h:74
When using enum_to_string() and enum_from_string(), this type needs to be defined and specialized to ...
Definition enum.h:48