39 static_assert(Axis == axis::horizontal or Axis == axis::vertical);
43 static constexpr hi::axis axis = Axis;
47 if (
auto delegate = _delegate.lock()) {
48 delegate->deinit(*
this);
60 super(window, parent), _delegate(
std::move(delegate))
62 hi_axiom(is_gui_thread());
67 if (
auto d = _delegate.lock()) {
84 template<
typename Widget,
typename... Args>
87 auto tmp = std::make_unique<Widget>(window,
this, std::forward<Args>(args)...);
90 request_reconstrain();
98 hi_axiom(is_gui_thread());
100 request_reconstrain();
106 for (
hilet& child : _children) {
107 co_yield child.get();
111 widget_constraints
const& set_constraints() noexcept
override
117 auto minimum_thickness = 0.0f;
118 auto preferred_thickness = 0.0f;
119 auto maximum_thickness = 0.0f;
120 float margin_before_thickness = 0.0f;
121 float margin_after_thickness = 0.0f;
122 widget_baseline baseline = {};
124 _grid_layout.clear();
125 for (
hilet& child : _children) {
126 update_constraints_for_child(
132 margin_before_thickness,
133 margin_after_thickness,
136 _grid_layout.commit_constraints();
138 hi_axiom(index == ssize(_children));
140 if constexpr (axis == axis::row) {
141 return _constraints = {
142 {_grid_layout.minimum(), minimum_thickness},
143 {_grid_layout.preferred(), preferred_thickness},
144 {_grid_layout.maximum(), maximum_thickness},
145 {_grid_layout.margin_before(),
146 margin_before_thickness,
147 _grid_layout.margin_after(),
148 margin_after_thickness},
151 return _constraints = {
152 {minimum_thickness, _grid_layout.minimum()},
153 {preferred_thickness, _grid_layout.preferred()},
154 {maximum_thickness, _grid_layout.maximum()},
155 {margin_before_thickness,
156 _grid_layout.margin_before(),
157 margin_after_thickness,
158 _grid_layout.margin_after()}};
162 void set_layout(widget_layout
const& layout)
noexcept override
164 if (compare_store(_layout, layout)) {
165 _grid_layout.layout(axis == axis::row ? layout.width() : layout.height());
169 for (
hilet& child : _children) {
170 update_layout_for_child(*child, index++, layout);
173 hi_axiom(index == ssize(_children));
176 void draw(draw_context
const& context)
noexcept override
178 if (*mode > widget_mode::invisible) {
179 for (
hilet& child : _children) {
180 child->draw(context);
185 hitbox hitbox_test(point3 position)
const noexcept override
187 hi_axiom(is_gui_thread());
189 if (*mode >= widget_mode::partial) {
191 for (
hilet& child : _children) {
192 r = child->hitbox_test_from_parent(position, r);
203 grid_layout _grid_layout;
205 void update_constraints_for_child(
208 float& minimum_thickness,
209 float& preferred_thickness,
210 float& maximum_thickness,
211 float& margin_before_thickness,
212 float& margin_after_thickness,
213 widget_baseline& baseline)
noexcept
215 hi_axiom(is_gui_thread());
217 hilet& child_constraints = child.set_constraints();
218 if (axis == axis::row) {
219 _grid_layout.add_constraint(
221 child_constraints.minimum.width(),
222 child_constraints.preferred.width(),
223 child_constraints.maximum.width(),
224 child_constraints.margins.left(),
225 child_constraints.margins.right());
227 inplace_max(minimum_thickness, child_constraints.minimum.height());
228 inplace_max(preferred_thickness, child_constraints.preferred.height());
229 inplace_max(maximum_thickness, child_constraints.maximum.height());
230 inplace_max(margin_before_thickness, child_constraints.margins.top());
231 inplace_max(margin_after_thickness, child_constraints.margins.bottom());
232 inplace_max(baseline, child_constraints.baseline);
235 _grid_layout.add_constraint(
237 child_constraints.minimum.height(),
238 child_constraints.preferred.height(),
239 child_constraints.maximum.height(),
240 child_constraints.margins.top(),
241 child_constraints.margins.bottom(),
242 child_constraints.baseline);
244 inplace_max(minimum_thickness, child_constraints.minimum.width());
245 inplace_max(preferred_thickness, child_constraints.preferred.width());
246 inplace_max(maximum_thickness, child_constraints.maximum.width());
247 inplace_max(margin_before_thickness, child_constraints.margins.left());
248 inplace_max(margin_after_thickness, child_constraints.margins.right());
252 void update_layout_for_child(widget& child, ssize_t index, widget_layout
const& context)
const noexcept
254 hi_axiom(is_gui_thread());
256 hilet[child_position, child_length] = _grid_layout.get_position_and_size(index);
258 if (axis == axis::row) {
259 hilet child_rectangle = aarectangle{child_position, 0.0f, child_length, layout().height()};
261 child.set_layout(context.transform(child_rectangle, 0.0f));
264 hilet child_rectangle =
265 aarectangle{0.0f, layout().height() - child_position - child_length, layout().width(), child_length};
266 child.set_layout(context.transform(child_rectangle, 0.0f, _grid_layout.get_baseline(index)));