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>
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>
185 const auto diff =
event.pointer().point -
event.pointer().drag_start;
193 const auto diff =
event.pointer().point -
event.pointer().drag_start;
215 bool allow_fallback =
false)
const;
243 if (detail::change_if_diff<>(m_label_offset, offset))
262 if (detail::change_if_diff<>(m_handle_offset, offset))
284 if (detail::change_if_diff<>(m_handle_margin,
margin))
297 T orig = this->
value();
387 Rect r(image->size());
390 r.
y(r.
y() + m_handle_offset);
392 r.
x(r.
x() + m_handle_offset);
410 return m_handle_margin;
412 const auto m = m_handle_margin;
425 const auto m = m_handle_margin;
428 return egt::detail::normalize<float>(offset, m, b.width() - m -
handle_width(),
431 return egt::detail::normalize<float>(offset, m, b.height() - m -
handle_height(),
447 auto label_rect =
label_box(prev_value, text);
487 auto shift = image ? 0 : (b.height() / 2);
488 handle_rect +=
Point(0, m_label_offset - shift);
492 auto shift = image ? 0 : (b.width() / 2);
493 handle_rect +=
Point(m_label_offset - shift, 0);
505 if (target.width() <= b.width())
507 if (target.x() < b.x())
510 if (target.x() + target.width() > b.x() + b.width())
511 target.x(b.x() + b.width() - target.width());
514 if (target.height() <= b.height())
516 if (target.y() < b.y())
519 if (target.y() + target.height() > b.y() + b.height())
520 target.y(b.y() + b.height() - target.height());
533 painter.
draw(target.point());
547 return std::to_string(
value);
570 static Size m_default_size;
572 static void register_handler();
573 static void unregister_handler();
595 EGT_NODISCARD std::string
type()
const override
611 EGT_NODISCARD std::string
type()
const override
630 m_default_size.clear();
636void SliderType<T>::unregister_handler()
648 auto ss = egt::Application::instance().
screen()->
size();
659 unregister_handler();
670 this->name(
"Slider" + std::to_string(this->m_widgetid));
672 this->grab_mouse(
true);
673 this->slider_flags().set(SliderFlag::rectangle_handle);
674 this->border_radius(4.0);
684 this->deserialize_leaf(props);
701 Rect background, handle;
702 compute_boxes(this->value(), &background, &handle);
704 auto* bg = this->background(
true);
706 painter.
draw(*bg, background.
point(), background);
709 draw_line(painter, handle);
712 draw_handle(painter, handle);
718 if (slider_flags().is_set(SliderFlag::show_label))
720 draw_label(painter, this->value());
722 else if (slider_flags().is_set(SliderFlag::show_labels))
724 draw_label(painter, this->starting());
725 draw_label(painter, this->starting() + ((this->
ending() - this->starting()) / 2));
726 draw_label(painter, this->
ending());
735 return image->width();
737 const auto b = this->content_area();
738 auto width = b.width();
739 auto height = b.height();
741 if (slider_flags().is_set(SliderFlag::show_labels) ||
742 slider_flags().is_set(SliderFlag::show_label))
750 if (slider_flags().is_set(SliderFlag::square_handle) ||
751 slider_flags().is_set(SliderFlag::round_handle))
754 return std::min<DefaultDim>(width / 6, height);
756 return std::min<DefaultDim>(height / 6, width);
761 return std::min<DefaultDim>(width / 6, height) * 2;
763 return std::min<DefaultDim>(height / 6, width);
772 return image->height();
774 const auto b = this->content_area();
775 auto width = b.width();
776 auto height = b.height();
778 if (slider_flags().is_set(SliderFlag::show_labels) ||
779 slider_flags().is_set(SliderFlag::show_label))
787 if (slider_flags().is_set(SliderFlag::square_handle) ||
788 slider_flags().is_set(SliderFlag::round_handle))
791 return std::min<DefaultDim>(width / 6, height);
793 return std::min<DefaultDim>(height / 6, width);
798 return std::min<DefaultDim>(width / 6, height);
800 return std::min<DefaultDim>(height / 6, width) * 2;
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);
816 bg.
size(image_bg ? image_bg->size() : b.size());
824 auto deltah = (bg.
height() - dimh) / 2 + m_handle_offset;
826 bg.
x(b.x() + (b.width() - bg.
width()) / 2);
827 bg.
y(b.y() - std::min(0, deltah));
829 if (slider_flags().is_set(SliderFlag::inverted))
830 hndl.
x(b.x() + b.width() - offset - dimw);
832 hndl.
x(b.x() + offset);
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);
840 hndl.
y(b.y() + b.height() / 2 - dimh / 2 + m_handle_offset);
844 auto deltaw = (bg.
width() - dimw) / 2 + m_handle_offset;
846 bg.
y(b.y() + (b.height() - bg.
height()) / 2);
847 bg.
x(b.x() - std::min(0, deltaw));
849 if (slider_flags().is_set(SliderFlag::inverted))
850 hndl.
y(b.y() + offset);
852 hndl.
y(b.y() + b.height() - offset - dimh);
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);
860 hndl.
x(b.x() + b.width() / 2 - dimw / 2 + m_handle_offset);
874 compute_boxes(value,
nullptr, &handle);
881 auto* image = handle_image(this->group(),
true);
884 painter.
draw(*image, handle_rect.
point(), handle_rect);
886 else if (slider_flags().is_set(SliderFlag::round_handle))
888 this->theme().draw_circle(painter,
897 this->theme().draw_box(painter,
904 this->border_radius());
911 if (slider_flags().is_set(SliderFlag::hide_line))
914 const auto inverted = !!slider_flags().is_set(SliderFlag::inverted);
915 const auto b = this->content_area();
922 const auto w = handle_rect.
width() / 2;
923 auto transition_x =
center.x();
924 switch (line_transition())
926 case SliderLineTransition::to_end:
927 transition_x += inverted ? -w : w;
929 case SliderLineTransition::to_begin:
930 transition_x -= inverted ? -w : w;
936 p1.
x(b.x() + m_handle_margin);
937 s1.
width(transition_x - p1.
x());
942 s2.
width(b.x() + b.width() - m_handle_margin - p2.
x());
951 const auto h = handle_rect.
height() / 2;
952 auto transition_y =
center.y();
953 switch (line_transition())
955 case SliderLineTransition::to_end:
956 transition_y -= inverted ? -h : h;
958 case SliderLineTransition::to_begin:
959 transition_y += inverted ? -h : h;
965 p1.
y(b.y() + m_handle_margin);
966 s1.
height(transition_y - p1.
y());
971 s2.
height(b.y() + b.height() - m_handle_margin - p2.
y());
979 if (slider_flags().is_set(SliderFlag::consistent_line))
994 const Rect r1(p1, s1);
996 painter.
draw(c1, r1);
998 const Rect r2(p2, s2);
1000 painter.
draw(c2, r2);
1017 serializer.
add_property(
"sliderflags", m_slider_flags.to_string());
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);
1029 props.erase(std::remove_if(props.begin(), props.end(), [&](
auto & p)
1031 if (std::get<0>(p) ==
"sliderflags")
1033 m_slider_flags.from_string(std::get<1>(p));
1036 else if (std::get<0>(p) ==
"line_transition")
1038 line_transition(detail::enum_from_string<SliderLineTransition>(std::get<1>(p)));
1041 else if (std::get<0>(p) ==
"orient")
1043 orient(detail::enum_from_string<Orientation>(std::get<1>(p)));
1046 else if (std::get<0>(p) ==
"label_offset")
1048 label_offset(std::stoi(std::get<1>(p)));
1051 else if (std::get<0>(p) ==
"handle_offset")
1053 handle_offset(std::stoi(std::get<1>(p)));
1056 else if (std::get<0>(p) ==
"handle_margin")
1058 handle_margin(std::stoi(std::get<1>(p)));
1061 else if (m_handles.deserialize(std::get<0>(p), std::get<1>(p)))
1072 return m_handles.get(group, allow_fallback);
1078 m_handles.set(group, image);
1086 if (m_handles.reset(group))
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.
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 > ¢er) 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
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