49 static constexpr hi::axis axis = Axis;
50 static constexpr bool controls_window = ControlsWindow;
54 if (
auto delegate = _delegate.lock()) {
55 delegate->deinit(*
this);
67 super(window, parent), _delegate(
std::move(delegate))
69 hi_axiom(is_gui_thread());
75 _aperture = std::make_unique<scroll_aperture_widget>(window,
this);
76 _horizontal_scroll_bar = std::make_unique<horizontal_scroll_bar_widget>(
77 window,
this, _aperture->content_width, _aperture->aperture_width, _aperture->offset_x);
78 _vertical_scroll_bar = std::make_unique<vertical_scroll_bar_widget>(
79 window,
this, _aperture->content_height, _aperture->aperture_height, _aperture->offset_y);
81 if (
auto d = _delegate.lock()) {
95 template<
typename Widget,
typename... Args>
98 return _aperture->make_widget<Widget>(std::forward<Args>(args)...);
104 co_yield _aperture.get();
105 co_yield _vertical_scroll_bar.get();
106 co_yield _horizontal_scroll_bar.get();
109 widget_constraints
const &set_constraints() noexcept
override
112 hilet aperture_constraints = _aperture->set_constraints();
113 hilet horizontal_constraints = _horizontal_scroll_bar->set_constraints();
114 hilet vertical_constraints = _vertical_scroll_bar->set_constraints();
116 _constraints = aperture_constraints;
120 if constexpr (any(axis & axis::horizontal)) {
121 _constraints.minimum.width() = horizontal_constraints.minimum.width();
122 inplace_max(_constraints.preferred.width(), horizontal_constraints.minimum.width());
123 inplace_max(_constraints.maximum.width(), horizontal_constraints.minimum.width());
125 if constexpr (any(axis & axis::vertical)) {
126 _constraints.minimum.height() = vertical_constraints.minimum.height();
127 inplace_max(_constraints.preferred.height(), vertical_constraints.minimum.height());
128 inplace_max(_constraints.maximum.height(), vertical_constraints.minimum.height());
132 if constexpr (any(axis & axis::horizontal)) {
133 _constraints.minimum.height() += horizontal_constraints.preferred.height();
134 _constraints.preferred.height() += horizontal_constraints.preferred.height();
135 _constraints.maximum.height() += horizontal_constraints.preferred.height();
137 if constexpr (any(axis & axis::vertical)) {
138 _constraints.minimum.width() += vertical_constraints.preferred.width();
139 _constraints.preferred.width() += vertical_constraints.preferred.width();
140 _constraints.maximum.width() += vertical_constraints.preferred.width();
145 void set_layout(widget_layout
const &layout)
noexcept override
147 if (compare_store(_layout, layout)) {
148 _horizontal_scroll_bar->visible = _aperture->x_axis_scrolls() and any(axis & axis::horizontal);
149 _vertical_scroll_bar->visible = _aperture->y_axis_scrolls() and any(axis & axis::vertical);
150 hilet both_bars_visible = *_horizontal_scroll_bar->visible and *_vertical_scroll_bar->visible;
152 hilet vertical_scroll_bar_width = _vertical_scroll_bar->constraints().preferred.width();
153 hilet horizontal_scroll_bar_height = _horizontal_scroll_bar->constraints().preferred.height();
156 hilet aperture_size = extent2{
157 *_vertical_scroll_bar->visible ? layout.
width() - vertical_scroll_bar_width : layout.width(),
158 *_horizontal_scroll_bar->visible ? layout.height() - horizontal_scroll_bar_height : layout.height()};
159 hilet aperture_offset = point2{0.0f, *_horizontal_scroll_bar->visible ? horizontal_scroll_bar_height : 0.0f};
160 _aperture_rectangle = aarectangle{aperture_offset, aperture_size};
164 hilet horizontal_scroll_bar_size =
165 extent2{both_bars_visible ? aperture_size.
width() : layout.width(), horizontal_scroll_bar_height};
166 hilet vertical_scroll_bar_size =
167 extent2{vertical_scroll_bar_width, both_bars_visible ? aperture_size.
height() : layout.height()};
169 _vertical_scroll_bar_rectangle = aarectangle{
170 point2{layout.width() - vertical_scroll_bar_size.width(), layout.height() - vertical_scroll_bar_size.height()},
171 vertical_scroll_bar_size};
173 _horizontal_scroll_bar_rectangle = aarectangle{point2{0.0f, 0.0f}, horizontal_scroll_bar_size};
175 if constexpr (controls_window) {
176 window.set_resize_border_priority(
177 true, not *_vertical_scroll_bar->visible, not *_horizontal_scroll_bar->visible,
true);
181 _aperture->set_layout(layout.transform(_aperture_rectangle));
182 if (*_vertical_scroll_bar->visible) {
183 _vertical_scroll_bar->set_layout(layout.transform(_vertical_scroll_bar_rectangle));
185 if (*_horizontal_scroll_bar->visible) {
186 _horizontal_scroll_bar->set_layout(layout.transform(_horizontal_scroll_bar_rectangle));
190 void draw(draw_context
const &context)
noexcept
193 _vertical_scroll_bar->draw(context);
194 _horizontal_scroll_bar->draw(context);
195 _aperture->draw(context);
199 [[nodiscard]] hitbox hitbox_test(point3 position)
const noexcept override
201 hi_axiom(is_gui_thread());
203 if (*visible and *enabled) {
204 auto r = _aperture->hitbox_test_from_parent(position);
205 r = _horizontal_scroll_bar->hitbox_test_from_parent(position, r);
206 r = _vertical_scroll_bar->hitbox_test_from_parent(position, r);
208 if (layout().contains(position)) {
209 r =
std::max(r, hitbox{
this, position});
221 aarectangle _aperture_rectangle;
224 aarectangle _horizontal_scroll_bar_rectangle;
227 aarectangle _vertical_scroll_bar_rectangle;