12#include "../macros.hpp"
15hi_export_module(hikogui.widgets.scroll_aperture_widget);
17hi_export
namespace hi {
inline namespace v1 {
39 hi_axiom(loop::main().on_thread());
41 _content_width_cbt = content_width.
subscribe([&](
auto...) {
42 ++global_counter<
"scroll_aperture_widget:content_width:relayout">;
45 _content_height_cbt = content_height.
subscribe([&](
auto...) {
46 ++global_counter<
"scroll_aperture_widget:content_height:relayout">;
49 _aperture_width_cbt = aperture_width.
subscribe([&](
auto...) {
50 ++global_counter<
"scroll_aperture_widget:aperture_width:relayout">;
53 _aperture_height_cbt = aperture_height.
subscribe([&](
auto...) {
54 ++global_counter<
"scroll_aperture_widget:aperture_height:relayout">;
57 _offset_x_cbt = offset_x.
subscribe([&](
auto...) {
58 ++global_counter<
"scroll_aperture_widget:offset_x:relayout">;
61 _offset_y_cbt = offset_y.
subscribe([&](
auto...) {
62 ++global_counter<
"scroll_aperture_widget:offset_y:relayout">;
65 _minimum_cbt =
minimum.subscribe([&](
auto...) {
66 ++global_counter<
"scroll_aperture_widget:minimum:reconstrain">;
71 template<
typename Widget,
typename... Args>
72 Widget& emplace(Args&&...args)
noexcept
74 hi_axiom(loop::main().on_thread());
75 hi_axiom(_content ==
nullptr);
77 auto tmp = std::make_unique<Widget>(
this, std::forward<Args>(args)...);
83 [[nodiscard]]
bool x_axis_scrolls()
const noexcept
85 return *content_width > *aperture_width;
88 [[nodiscard]]
bool y_axis_scrolls()
const noexcept
90 return *content_height > *aperture_height;
94 [[nodiscard]] generator<widget_intf &> children(
bool include_invisible)
noexcept override
102 _content_constraints = _content->update_constraints();
105 auto aperture_constraints = _content_constraints;
106 aperture_constraints.minimum =
extent2{0, 0};
108 aperture_constraints = aperture_constraints.constrain(*
minimum, *
maximum);
109 aperture_constraints +=
extent2{
110 _content_constraints.margins.left() + _content_constraints.margins.right(),
111 _content_constraints.margins.top() + _content_constraints.margins.bottom()};
112 aperture_constraints.margins = {};
113 return aperture_constraints;
116 void set_layout(
widget_layout const& context)
noexcept override
119 aperture_width = context.width() - _content_constraints.margins.left() - _content_constraints.margins.right();
120 aperture_height = context.height() - _content_constraints.margins.bottom() - _content_constraints.margins.top();
124 content_width = *aperture_width < _content_constraints.preferred.
width() ? _content_constraints.preferred.
width() :
126 content_height = *aperture_height < _content_constraints.preferred.
height() ?
127 _content_constraints.preferred.
height() :
132 auto const offset_x_max =
std::max(*content_width - *aperture_width, 0.0f);
133 auto const offset_y_max =
std::max(*content_height - *aperture_height, 0.0f);
134 offset_x = std::clamp(*offset_x, 0.0f, offset_x_max);
135 offset_y = std::clamp(*offset_y, 0.0f, offset_y_max);
140 _content_constraints,
142 -*offset_x + _content_constraints.margins.left(),
143 -*offset_y + _content_constraints.margins.bottom(),
146 theme().baseline_adjustment()};
153 void draw(
draw_context const& context)
noexcept override
156 _content->draw(context);
160 [[nodiscard]] hitbox hitbox_test(point2 position)
const noexcept override
162 hi_axiom(loop::main().on_thread());
165 auto r = _content->hitbox_test_from_parent(position);
167 if (
layout().contains(position)) {
168 r =
std::max(r, hitbox{
id, _layout.elevation});
177 bool handle_event(
gui_event const& event)
noexcept override
179 hi_axiom(loop::main().on_thread());
181 if (event == gui_event_type::mouse_wheel) {
184 auto const max_offset_x =
std::max(0.0f, *content_width - *aperture_width);
185 auto const max_offset_y =
std::max(0.0f, *content_height - *aperture_height);
187 offset_x = std::clamp(new_offset_x, 0.0f, max_offset_x);
188 offset_y = std::clamp(new_offset_y, 0.0f, max_offset_y);
189 ++global_counter<
"scroll_aperture_widget:mouse_wheel:relayout">;
200 auto safe_rectangle = intersect(_layout.rectangle(), _layout.clipping_rectangle);
208 safe_rectangle = safe_rectangle - theme().margin<
float>();
210 if (to_show.right() > safe_rectangle.right()) {
211 delta_x = to_show.right() - safe_rectangle.right();
212 }
else if (to_show.left() < safe_rectangle.left()) {
213 delta_x = to_show.left() - safe_rectangle.left();
216 if (to_show.top() > safe_rectangle.top()) {
217 delta_y = to_show.top() - safe_rectangle.top();
218 }
else if (to_show.bottom() < safe_rectangle.bottom()) {
219 delta_y = to_show.bottom() - safe_rectangle.bottom();
241 callback<void(
float)> _content_width_cbt;
242 callback<void(
float)> _content_height_cbt;
243 callback<void(
float)> _aperture_width_cbt;
244 callback<void(
float)> _aperture_height_cbt;
245 callback<void(
float)> _offset_x_cbt;
246 callback<void(
float)> _offset_y_cbt;
@ window_relayout
Request that widgets get laid out on the next frame.
@ window_reconstrain
Request that widget get constraint on the next frame.
@ partial
A widget is partially enabled.
@ invisible
The widget is invisible.
The HikoGUI namespace.
Definition array_generic.hpp:20
bool compare_store(T &lhs, U &&rhs) noexcept
Compare then store if there was a change.
Definition misc.hpp:53
@ level
The child widget stays at the same elevation and layer.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition callback.hpp:77
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
A high-level geometric extent.
Definition extent2.hpp:32
constexpr float & width() noexcept
Access the x-as-width element from the extent.
Definition extent2.hpp:107
constexpr float & height() noexcept
Access the y-as-height element from the extent.
Definition extent2.hpp:118
Definition translate2.hpp:18
constexpr float & x() noexcept
Access the x element from the vector.
Definition vector2.hpp:65
constexpr float & y() noexcept
Access the y element from the vector.
Definition vector2.hpp:73
Draw context for drawing using the HikoGUI shaders.
Definition draw_context_intf.hpp:209
vector2 wheel_delta
Change in wheel rotation, in points (pt).
Definition gui_event.hpp:58
A user interface event.
Definition gui_event.hpp:82
mouse_event_data & mouse() noexcept
Get the mouse event information.
Definition gui_event.hpp:264
Definition widget_intf.hpp:24
widget_id id
The numeric identifier of a widget.
Definition widget_intf.hpp:30
widget_layout const & layout() const noexcept
Get the current layout for this widget.
Definition widget_intf.hpp:206
widget_intf * parent
Pointer to the parent widget.
Definition widget_intf.hpp:35
virtual void scroll_to_show(hi::aarectangle rectangle) noexcept=0
Scroll to show the given rectangle on the window.
The layout of a widget.
Definition widget_layout.hpp:56
constexpr widget_layout transform(box_shape const &child_shape, transform_command command, aarectangle new_clipping_rectangle) const noexcept
Create a new widget_layout for the child widget.
Definition widget_layout.hpp:236
2D constraints.
Definition box_constraints.hpp:25
Definition box_shape.hpp:18
A observer pointing to the whole or part of a observed_base.
Definition observer_intf.hpp:32
callback< void(value_type)> subscribe(Func &&func, callback_flags flags=callback_flags::synchronous) noexcept
Subscribe a callback to this observer.
Definition observer_intf.hpp:456
Definition theme_value.hpp:11
Definition pixel_density.hpp:16
A scroll aperture widget.
Definition scroll_aperture_widget.hpp:26
An interactive graphical object as part of the user-interface.
Definition widget.hpp:37
observer< extent2 > minimum
The minimum size this widget is allowed to be.
Definition widget.hpp:41
void scroll_to_show() noexcept
Scroll to show the important part of the widget.
Definition widget_intf.hpp:312
widget() noexcept
Constructor for creating sub views.
Definition widget.hpp:55
bool process_event(gui_event const &event) const noexcept override
Send a event to the window.
Definition widget.hpp:130
bool handle_event(gui_event const &event) noexcept override
Handle command.
Definition widget.hpp:150
observer< extent2 > maximum
The maximum size this widget is allowed to be.
Definition widget.hpp:45