29class window_controls_win32_widget :
public widget {
33 window_controls_win32_widget() noexcept : super() {}
40 auto const size =
extent2{theme().large_size() * 3.0f, theme().large_size()};
41 return {size, size, size};
44 void set_layout(
widget_layout const& context)
noexcept override
47 auto extent = context.size();
48 if (extent.height() > floor_cast<int>(theme().large_size() * 1.2f)) {
49 extent =
extent2{extent.width(), theme().large_size()};
51 auto y = context.height() - extent.height();
54 aarectangle{point2(extent.width() * 2.0f / 3.0f, y),
extent2{extent.width() * 1.0f / 3.0f, extent.height()}};
57 aarectangle{point2(extent.width() * 1.0f / 3.0f, y),
extent2{extent.width() * 1.0f / 3.0f, extent.height()}};
59 minimizeRectangle =
aarectangle{point2(0.0f, y),
extent2{extent.width() * 1.0f / 3.0f, extent.height()}};
61 closeWindowGlyph = find_glyph(hikogui_icon::CloseWindow);
62 minimizeWindowGlyph = find_glyph(hikogui_icon::MinimizeWindow);
63 maximizeWindowGlyph = find_glyph(hikogui_icon::MaximizeWindowMS);
64 restoreWindowGlyph = find_glyph(hikogui_icon::RestoreWindowMS);
65 auto const glyph_size = theme().icon_size();
67 auto const closeWindowGlyphBB = closeWindowGlyph.front_glyph_metrics().bounding_rectangle * glyph_size;
68 auto const minimizeWindowGlyphBB = minimizeWindowGlyph.front_glyph_metrics().bounding_rectangle * glyph_size;
69 auto const maximizeWindowGlyphBB = maximizeWindowGlyph.front_glyph_metrics().bounding_rectangle * glyph_size;
70 auto const restoreWindowGlyphBB = restoreWindowGlyph.front_glyph_metrics().bounding_rectangle * glyph_size;
72 closeWindowGlyphRectangle = align(closeRectangle, closeWindowGlyphBB, alignment::middle_center());
73 minimizeWindowGlyphRectangle = align(minimizeRectangle, minimizeWindowGlyphBB, alignment::middle_center());
74 maximizeWindowGlyphRectangle = align(maximizeRectangle, maximizeWindowGlyphBB, alignment::middle_center());
75 restoreWindowGlyphRectangle = align(maximizeRectangle, restoreWindowGlyphBB, alignment::middle_center());
83 context.draw_box(
layout(), closeRectangle,
color{1.0f, 0.0f, 0.0f});
84 }
else if (hoverClose) {
85 context.draw_box(
layout(), closeRectangle,
color{0.5f, 0.0f, 0.0f});
87 context.draw_box(
layout(), closeRectangle, theme().fill_color(_layout.layer));
90 if (pressedMinimize) {
91 context.draw_box(
layout(), minimizeRectangle, theme().fill_color(_layout.layer + 2));
92 }
else if (hoverMinimize) {
93 context.draw_box(
layout(), minimizeRectangle, theme().fill_color(_layout.layer + 1));
95 context.draw_box(
layout(), minimizeRectangle, theme().fill_color(_layout.layer));
98 if (pressedMaximize) {
99 context.draw_box(
layout(), maximizeRectangle, theme().fill_color(_layout.layer + 2));
100 }
else if (hoverMaximize) {
101 context.draw_box(
layout(), maximizeRectangle, theme().fill_color(_layout.layer + 1));
103 context.draw_box(
layout(), maximizeRectangle, theme().fill_color(_layout.layer));
106 auto const glyph_color = foreground_color();
108 context.draw_glyph(
layout(), translate_z(0.1f) * closeWindowGlyphRectangle, closeWindowGlyph, glyph_color);
109 context.draw_glyph(
layout(), translate_z(0.1f) * minimizeWindowGlyphRectangle, minimizeWindowGlyph, glyph_color);
110 if (
layout().window_size_state == gui_window_size::maximized) {
111 context.draw_glyph(
layout(), translate_z(0.1f) * restoreWindowGlyphRectangle, restoreWindowGlyph, glyph_color);
113 context.draw_glyph(
layout(), translate_z(0.1f) * maximizeWindowGlyphRectangle, maximizeWindowGlyph, glyph_color);
118 bool handle_event(
gui_event const& event)
noexcept override
120 switch (event.
type()) {
121 case gui_event_type::mouse_move:
122 case gui_event_type::mouse_drag:
125 auto state_has_changed =
false;
129 if (state_has_changed) {
135 case gui_event_type::mouse_exit:
137 hoverMinimize =
false;
138 hoverMaximize =
false;
142 case gui_event_type::mouse_down:
147 }
else if (minimizeRectangle.contains(event.
mouse().
position)) {
148 pressedMinimize =
true;
150 }
else if (maximizeRectangle.contains(event.
mouse().
position)) {
151 pressedMaximize =
true;
158 case gui_event_type::mouse_up:
160 pressedClose =
false;
161 pressedMinimize =
false;
162 pressedMaximize =
false;
168 }
else if (minimizeRectangle.contains(event.
mouse().
position)) {
171 }
else if (maximizeRectangle.contains(event.
mouse().
position)) {
172 switch (
layout().window_size_state) {
173 case gui_window_size::normal:
176 case gui_window_size::maximized:
192 [[nodiscard]] hitbox hitbox_test(point2 position)
const noexcept override
194 hi_axiom(loop::main().on_thread());
197 (closeRectangle.contains(position) or minimizeRectangle.contains(position) or maximizeRectangle.contains(position))) {
198 return hitbox{
id, _layout.elevation, hitbox_type::button};
219 bool hoverClose =
false;
220 bool hoverMinimize =
false;
221 bool hoverMaximize =
false;
223 bool pressedClose =
false;
224 bool pressedMinimize =
false;
225 bool pressedMaximize =
false;