14#include "../observer.hpp"
22namespace hi {
inline namespace v1 {
41 observer<int> aperture;
42 observer<int> content;
46 forward_of<observer<int>>
auto&& content,
47 forward_of<observer<int>>
auto&& aperture,
48 forward_of<observer<int>>
auto&& offset) noexcept :
51 _content_cbt = this->content.subscribe([&](
auto...) {
52 ++global_counter<
"scroll_bar_widget:content:relayout">;
55 _aperture_cbt = this->aperture.subscribe([&](
auto...) {
56 ++global_counter<
"scroll_bar_widget:aperture:relayout">;
59 _offset_cbt = this->offset.subscribe([&](
auto...) {
60 ++global_counter<
"scroll_bar_widget:offset:relayout">;
76 if constexpr (
axis == axis::vertical) {
78 extent2i{theme().icon_size, theme().size * 4},
79 extent2i{theme().icon_size, theme().size * 4},
80 extent2i{theme().icon_size, large_number_v<int>}};
83 extent2i{theme().size * 4, theme().icon_size},
84 extent2i{theme().size * 4, theme().icon_size},
85 extent2i{large_number_v<int>, theme().icon_size}};
94 _slider_rectangle = {};
99 hilet slider_offset = narrow_cast<int>(
std::round(*offset * travel_vs_hidden_content_ratio()));
100 if constexpr (
axis == axis::vertical) {
101 _slider_rectangle =
aarectanglei{0, slider_offset, context.width(), slider_length()};
103 _slider_rectangle =
aarectanglei{slider_offset, 0, slider_length(), context.height()};
107 [[nodiscard]]
bool visible() const noexcept
109 return *aperture < *content;
112 void draw(draw_context
const& context)
noexcept override
116 draw_slider(context);
125 _slider_rectangle.
contains(position)) {
126 return {
this, _layout.elevation, hitbox_type::scroll_bar};
134 switch (event.type()) {
135 case gui_event_type::mouse_down:
136 if (event.mouse().cause.left_button) {
138 _offset_before_drag = *offset;
143 case gui_event_type::mouse_drag:
144 if (event.mouse().cause.left_button) {
147 hilet slider_movement =
148 narrow_cast<int>(
axis == axis::vertical ? event.drag_delta().y() :
event.drag_delta().x());
149 hilet content_movement = narrow_cast<int>(
std::round(slider_movement * hidden_content_vs_travel_ratio()));
150 hilet new_offset = _offset_before_drag + content_movement;
151 offset = clamp_offset(new_offset);
167 [[nodiscard]] color background_color() const noexcept
override
172 [[nodiscard]] color foreground_color() const noexcept
override
182 aarectanglei _slider_rectangle;
184 int _offset_before_drag;
186 typename decltype(content)::callback_token _content_cbt;
187 typename decltype(aperture)::callback_token _aperture_cbt;
188 typename decltype(offset)::callback_token _offset_cbt;
194 [[nodiscard]]
int clamp_offset(
int new_offset)
const noexcept
196 hilet scrollable_distance =
std::max(0, *content - *aperture);
197 return std::clamp(new_offset, 0, scrollable_distance);
200 [[nodiscard]]
int rail_length() const noexcept
206 [[nodiscard]]
int slider_length() const noexcept
210 hilet preferred_length = [&] {
212 return rail_length();
214 return *aperture * rail_length() / *content;
218 return std::clamp(preferred_length, narrow_cast<int>(theme().size) * 2, rail_length());
223 [[nodiscard]]
int slider_travel_range() const noexcept
226 return rail_length() - slider_length();
231 [[nodiscard]]
int hidden_content() const noexcept
234 return *content - *aperture;
241 [[nodiscard]]
float hidden_content_vs_travel_ratio() const noexcept
245 hilet _slider_travel_range = slider_travel_range();
246 return _slider_travel_range != 0 ? narrow_cast<float>(hidden_content()) / _slider_travel_range : 0.0f;
253 [[nodiscard]]
float travel_vs_hidden_content_ratio() const noexcept
257 hilet _hidden_content = hidden_content();
258 return _hidden_content != 0 ? narrow_cast<float>(slider_travel_range()) / _hidden_content : 0.0f;
261 void draw_rails(draw_context
const& context)
noexcept
268 void draw_slider(draw_context
const& context)
noexcept
274 layout(), translate_z(0.1f) * narrow_cast<aarectangle>(_slider_rectangle), foreground_color(), corner_radii);
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition utility.hpp:29
This file contains constants and conversion functions.
Definition of GUI event types.
axis
An enumeration of the 3 axis for 3D geometry.
Definition axis.hpp:18
@ window_relayout
Request that widgets get laid out on the next frame.
@ rectangle
The gui_event has rectangle data.
@ partial
A widget is partially enabled.
@ collapse
The widget is collapsed.
@ invisible
The widget is invisible.
DOXYGEN BUG.
Definition algorithm.hpp:15
geometry/margins.hpp
Definition assert.hpp:18
constexpr bool contains(point< value_type, 2 > const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition axis_aligned_rectangle.hpp:266
The 4 radiuses of the corners of a quad or rectangle.
Definition corner_radii.hpp:17
A user interface event.
Definition gui_event.hpp:77
2D constraints.
Definition box_constraints.hpp:25
Scroll bar widget This widget is used in a pair of a vertical and horizontal scrollbar as a child of ...
Definition scroll_bar_widget.hpp:34
void draw(draw_context const &context) noexcept override
Draw the widget.
Definition scroll_bar_widget.hpp:112
void set_layout(widget_layout const &context) noexcept override
Update the internal layout of the widget.
Definition scroll_bar_widget.hpp:89
hitbox hitbox_test(point2i position) const noexcept override
Find the widget that is under the mouse cursor.
Definition scroll_bar_widget.hpp:120
box_constraints update_constraints() noexcept override
Update the constraints of the widget.
Definition scroll_bar_widget.hpp:67
bool handle_event(gui_event const &event) noexcept
Handle command.
Definition scroll_bar_widget.hpp:132
bool accepts_keyboard_focus(keyboard_focus_group group) const noexcept override
Check if the widget will accept keyboard focus.
Definition scroll_bar_widget.hpp:162
An interactive graphical object as part of the user-interface.
Definition widget.hpp:46
widget_layout const & layout() const noexcept
Get the current layout for this widget.
Definition widget.hpp:194
int semantic_layer
The draw layer of the widget.
Definition widget.hpp:86
observer< bool > hover
Mouse cursor is hovering over the widget.
Definition widget.hpp:66
widget(widget *parent) noexcept
virtual bool handle_event(gui_event const &event) noexcept
Handle command.
widget * parent
Pointer to the parent widget.
Definition widget.hpp:51
observer< widget_mode > mode
The widget mode.
Definition widget.hpp:62
The layout of a widget.
Definition widget_layout.hpp:41