31 constexpr static auto prefix = Name /
"window";
33 observer<label> title;
35 window_widget(forward_of<observer<label>>
auto&& title) noexcept :
38 _toolbar = std::make_unique<toolbar_widget<prefix>>(
this);
40 if (operating_system::current == operating_system::windows) {
41#if HI_OPERATING_SYSTEM == HI_OS_WINDOWS
43 this->_system_menu->icon = this->title.get<
"icon">();
46 }
else if (operating_system::current == operating_system::macos) {
52 _content = std::make_unique<grid_widget<prefix>>(
this);
78 [[nodiscard]] generator<widget const&> children(
bool include_invisible)
const noexcept override
89 _content_constraints = _content->update_constraints();
90 _toolbar_constraints = _toolbar->update_constraints();
94 _toolbar_constraints.margins.left() + _toolbar_constraints.minimum.
width() + _toolbar_constraints.margins.right(),
95 _content_constraints.margins.left() + _content_constraints.minimum.
width() + _content_constraints.margins.right());
97 _toolbar_constraints.margins.left() + _toolbar_constraints.preferred.
width() + _toolbar_constraints.margins.right(),
98 _content_constraints.margins.left() + _content_constraints.preferred.
width() + _content_constraints.margins.right());
100 _toolbar_constraints.margins.left() + _toolbar_constraints.maximum.
width() + _toolbar_constraints.margins.right(),
101 _content_constraints.margins.left() + _content_constraints.maximum.
width() + _content_constraints.margins.right());
105 _toolbar_constraints.margins.top() +
106 _toolbar_constraints.preferred.
height() +
107 std::max(_toolbar_constraints.margins.bottom(), _content_constraints.margins.top()) +
108 _content_constraints.minimum.
height() +
109 _content_constraints.margins.bottom();
110 r.preferred.height() =
111 _toolbar_constraints.margins.top() +
112 _toolbar_constraints.preferred.
height() +
113 std::max(_toolbar_constraints.margins.bottom(), _content_constraints.margins.top()) +
114 _content_constraints.preferred.
height() +
115 _content_constraints.margins.bottom();
117 _toolbar_constraints.margins.top() +
118 _toolbar_constraints.preferred.
height() +
119 std::max(_toolbar_constraints.margins.bottom(), _content_constraints.margins.top()) +
120 _content_constraints.maximum.
height() +
121 _content_constraints.margins.bottom();
126 inplace_max(r.minimum.width(), os_settings::minimum_window_width());
127 inplace_max(r.minimum.height(), os_settings::minimum_window_height());
129 inplace_clamp(r.maximum.width(), r.minimum.width(), os_settings::maximum_window_width());
130 inplace_clamp(r.maximum.height(), r.minimum.height(), os_settings::maximum_window_height());
132 inplace_clamp(r.preferred.width(), r.minimum.width(), r.maximum.width());
133 inplace_clamp(r.preferred.height(), r.minimum.height(), r.maximum.height());
135 _can_resize_width = r.minimum.width() != r.maximum.width();
136 _can_resize_height = r.minimum.height() != r.maximum.height();
141 void set_layout(widget_layout
const& context)
noexcept override
144 hilet toolbar_height = _toolbar_constraints.preferred.
height();
145 hilet between_margin =
std::max(_toolbar_constraints.margins.bottom(), _content_constraints.margins.top());
147 hilet toolbar_rectangle = aarectanglei{
149 _toolbar_constraints.margins.left(), context.height() - toolbar_height - _toolbar_constraints.margins.top()},
151 context.width() - _toolbar_constraints.margins.right(),
152 context.height() - _toolbar_constraints.margins.top()}};
153 _toolbar_shape = box_shape{_toolbar_constraints, toolbar_rectangle, theme<prefix>.cap_height(
this)};
155 hilet content_rectangle = aarectanglei{
156 point2i{_content_constraints.margins.left(), _content_constraints.margins.bottom()},
157 point2i{context.width() - _content_constraints.margins.right(), toolbar_rectangle.bottom() - between_margin}};
158 _content_shape = box_shape{_content_constraints, content_rectangle, theme<prefix>.cap_height(
this)};
160 _toolbar->set_layout(context.transform(_toolbar_shape));
161 _content->set_layout(context.transform(_content_shape));
164 void draw(widget_draw_context
const& context)
noexcept override
167 _toolbar->draw(context);
168 _content->draw(context);
172 [[nodiscard]] hitbox hitbox_test(point2i position)
const noexcept override
174 constexpr float BORDER_WIDTH = 10.0f;
178 auto r = _toolbar->hitbox_test_from_parent(position);
179 r = _content->hitbox_test_from_parent(position, r);
181 hilet is_on_l_edge = position.x() <= BORDER_WIDTH;
182 hilet is_on_r_edge = position.x() >= (layout.width() - BORDER_WIDTH);
183 hilet is_on_b_edge = position.y() <= BORDER_WIDTH;
184 hilet is_on_t_edge = position.y() >= (layout.height() - BORDER_WIDTH);
187 if (is_on_l_edge and is_on_b_edge) {
188 if (_can_resize_width and _can_resize_height) {
189 return {
id, layout.
elevation, hitbox_type::bottom_left_resize_corner};
190 }
else if (_can_resize_width) {
191 return {
id, layout.
elevation, hitbox_type::left_resize_border};
192 }
else if (_can_resize_height) {
193 return {
id, layout.
elevation, hitbox_type::bottom_resize_border};
195 }
else if (is_on_r_edge and is_on_b_edge) {
196 if (_can_resize_width and _can_resize_height) {
197 return {
id, layout.
elevation, hitbox_type::bottom_right_resize_corner};
198 }
else if (_can_resize_width) {
199 return {
id, layout.
elevation, hitbox_type::right_resize_border};
200 }
else if (_can_resize_height) {
201 return {
id, layout.
elevation, hitbox_type::bottom_resize_border};
203 }
else if (is_on_l_edge and is_on_t_edge) {
204 if (_can_resize_width and _can_resize_height) {
205 return {
id, layout.
elevation, hitbox_type::top_left_resize_corner};
206 }
else if (_can_resize_width) {
207 return {
id, layout.
elevation, hitbox_type::left_resize_border};
208 }
else if (_can_resize_height) {
209 return {
id, layout.
elevation, hitbox_type::top_resize_border};
211 }
else if (is_on_r_edge and is_on_t_edge) {
212 if (_can_resize_width and _can_resize_height) {
213 return {
id, layout.
elevation, hitbox_type::top_right_resize_corner};
214 }
else if (_can_resize_width) {
215 return {
id, layout.
elevation, hitbox_type::right_resize_border};
216 }
else if (_can_resize_height) {
217 return {
id, layout.
elevation, hitbox_type::top_resize_border};
222 if (r.type != hitbox_type::scroll_bar) {
223 if (is_on_l_edge and _can_resize_width) {
224 return {
id, layout.
elevation, hitbox_type::left_resize_border};
225 }
else if (is_on_r_edge and _can_resize_width) {
226 return {
id, layout.
elevation, hitbox_type::right_resize_border};
227 }
else if (is_on_b_edge and _can_resize_height) {
228 return {
id, layout.
elevation, hitbox_type::bottom_resize_border};
229 }
else if (is_on_t_edge and _can_resize_height) {
230 return {
id, layout.
elevation, hitbox_type::top_resize_border};
237 bool handle_event(gui_event
const& event)
noexcept override
241 switch (event.type()) {
242 case gui_toolbar_open:
244 gui_event::window_set_keyboard_target(
id, keyboard_focus_group::toolbar, keyboard_focus_direction::forward));
250 bool process_event(gui_event
const& event)
const noexcept override
253 return window->process_event(event);
258 box_constraints _content_constraints;
259 box_shape _content_shape;
262 box_constraints _toolbar_constraints;
263 box_shape _toolbar_shape;
265 mutable bool _can_resize_width;
266 mutable bool _can_resize_height;
268#if HI_OPERATING_SYSTEM == HI_OS_WINDOWS
269 system_menu_widget<prefix> *_system_menu =
nullptr;