8#include "../GUI/draw_context.hpp"
9#include "../observable.hpp"
18template<
bool IsVertical>
23 static constexpr bool is_vertical = IsVertical;
25 template<
typename Content,
typename Aperture,
typename Offset>
31 Offset &&offset) noexcept :
33 content(std::forward<Content>(content)),
34 aperture(std::forward<Aperture>(aperture)),
35 offset(std::forward<Offset>(offset))
37 _content_callback = this->content.subscribe([
this](
auto...) {
40 _aperture_callback = this->aperture.subscribe([
this](
auto...) {
43 _offset_callback = this->offset.subscribe([
this](
auto...) {
55 ttlet minimum_length = theme::global->width;
57 if constexpr (is_vertical) {
59 extent2{theme::global->scroll_bar_thickness, minimum_length},
63 extent2{minimum_length, theme::global->scroll_bar_thickness},
77 need_layout |= std::exchange(_request_relayout,
false);
79 tt_axiom(*content != 0.0f);
82 ttlet slider_offset = *offset * travel_vs_hidden_content_ratio();
84 if constexpr (is_vertical) {
99 if (overlaps(context, this->_clipping_rectangle) &&
visible()) {
101 draw_slider(context);
110 if (
visible() && _visible_rectangle.contains(position) && slider_rectangle.
contains(position)) {
111 return hit_box{weak_from_this(), _draw_layer};
119 ttlet lock = std::scoped_lock(gui_system_mutex);
122 if (event.cause.leftButton) {
125 switch (event.type) {
126 using enum mouse_event::Type;
129 offset_before_drag = *offset;
135 ttlet slider_movement = is_vertical ?
event.delta().y() :
event.delta().x();
136 ttlet content_movement = slider_movement * hidden_content_vs_travel_ratio();
137 offset = offset_before_drag + content_movement;
158 return hidden_content() >= 1.0f;
161 [[nodiscard]]
color background_color() const noexcept
override
163 return theme::global->fillColor(_semantic_layer);
166 [[nodiscard]] color foreground_color() const noexcept
override
169 return theme::global->fillColor(_semantic_layer + 2);
171 return theme::global->fillColor(_semantic_layer + 1);
176 observable<float> offset;
177 observable<float> aperture;
178 observable<float> content;
180 typename decltype(offset)::callback_ptr_type _offset_callback;
181 typename decltype(aperture)::callback_ptr_type _aperture_callback;
182 typename decltype(content)::callback_ptr_type _content_callback;
184 aarectangle slider_rectangle;
186 float offset_before_drag;
188 [[nodiscard]]
float rail_length() const noexcept
194 [[nodiscard]]
float slider_length() const noexcept
198 ttlet content_aperture_ratio = *aperture / *content;
199 return std::max(rail_length() * content_aperture_ratio, theme::global->smallSize * 2.0f);
204 [[nodiscard]]
float slider_travel_range() const noexcept
207 return rail_length() - slider_length();
212 [[nodiscard]]
float hidden_content() const noexcept
215 return *content - *aperture;
222 [[nodiscard]]
float hidden_content_vs_travel_ratio() const noexcept
226 ttlet _slider_travel_range = slider_travel_range();
227 return _slider_travel_range != 0.0f ? hidden_content() / _slider_travel_range : 0.0f;
234 [[nodiscard]]
float travel_vs_hidden_content_ratio() const noexcept
238 ttlet _hidden_content = hidden_content();
239 return _hidden_content != 0.0f ? slider_travel_range() / _hidden_content : 0.0f;
242 void draw_rails(draw_context context)
noexcept
246 ttlet corner_shapes =
248 context.draw_box(
rectangle(), background_color(), corner_shapes);
251 void draw_slider(draw_context context)
noexcept
255 ttlet corner_shapes = is_vertical ?
tt::corner_shapes{slider_rectangle.width() * 0.5f} :
258 context.draw_box(translate_z(0.1f) * slider_rectangle, foreground_color(), corner_shapes);
This is a RGBA floating point color.
Definition color.hpp:39
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:18
bool contains(point2 const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition axis_aligned_rectangle.hpp:222
Definition corner_shapes.hpp:9
Draw context for drawing using the TTauri shaders.
Definition draw_context.hpp:33
Definition gui_window.hpp:37
std::atomic< bool > requestLayout
When set to true the widgets will be layed out.
Definition gui_window.hpp:54
Definition hit_box.hpp:15
Definition mouse_event.hpp:15
A 2D vector using interval arithmetic.
Definition interval_extent2.hpp:18
int recurse_lock_count() const noexcept
This function should be used in tt_axiom() to check if the lock is held by current thread.
Definition unfair_recursive_mutex.hpp:60
Definition scroll_bar_widget.hpp:19
bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept override
Check if the widget will accept keyboard focus.
Definition scroll_bar_widget.hpp:146
hit_box hitbox_test(point2 position) const noexcept override
Find the widget that is under the mouse cursor.
Definition scroll_bar_widget.hpp:106
void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept override
Draw the widget.
Definition scroll_bar_widget.hpp:95
bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept override
Update the constraints of the widget.
Definition scroll_bar_widget.hpp:50
void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept override
Update the internal layout of the widget.
Definition scroll_bar_widget.hpp:73
bool visible() const noexcept
Is the scrollbar visible.
Definition scroll_bar_widget.hpp:155
bool handle_event(mouse_event const &event) noexcept
Definition scroll_bar_widget.hpp:117
virtual void update_layout(hires_utc_clock::time_point display_time_point, bool need_layout) noexcept
Update the internal layout of the widget.
widget(gui_window &window, std::shared_ptr< abstract_container_widget > parent) noexcept
aarectangle rectangle() const noexcept
Get the rectangle in local coordinates.
Definition widget.hpp:342
virtual bool handle_event(command command) noexcept
Handle command.
gui_window & window
Convenient reference to the Window.
Definition widget.hpp:101
virtual void draw(draw_context context, hires_utc_clock::time_point display_time_point) noexcept
Draw the widget.
Definition widget.hpp:462
virtual bool update_constraints(hires_utc_clock::time_point display_time_point, bool need_reconstrain) noexcept
Update the constraints of the widget.
abstract_container_widget const & parent() const noexcept
Get a reference to the parent.