HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
widget_state.hpp
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../concurrency/concurrency.hpp"
8#include "../theme/theme.hpp"
9#include "../macros.hpp"
10#include <cstdint>
11#include <utility>
12#include <concepts>
13#include <compare>
14
15hi_export_module(hikogui.GUI : widget_state);
16
17hi_export namespace hi { inline namespace v1 {
18
26enum class widget_mode {
35
42
48 disabled = 2,
49
56
63 select = 4,
64
74
82};
83
84enum class widget_value {
85 off = 0,
86 on = 1,
87 other = 2,
88};
89
90enum class widget_phase {
91 inactive = 0,
92 normal = 1,
93 hover = 2,
94 pressed = 3,
95};
96
97constexpr auto widget_state_mode_shift = 0;
98constexpr auto widget_state_value_shift = 5;
99
105class widget_state {
106public:
107 constexpr widget_state(widget_state const &) noexcept = default;
108 constexpr widget_state(widget_state &&) noexcept = default;
109 constexpr widget_state &operator=(widget_state const &) noexcept = default;
110 constexpr widget_state &operator=(widget_state &&) noexcept = default;
111
112 constexpr widget_state() noexcept = default;
113
116 constexpr static widget_state begin() noexcept
117 {
118 auto r = widget_state{};
120 r.set_layer(0);
121 r.set_value(widget_value::off);
122 r.set_pressed(false);
123 r.set_hover(false);
124 r.set_active(false);
125 r.set_focus(false);
126 return r;
127 }
128
131 constexpr static widget_state end() noexcept
132 {
133 auto r = begin();
134 r._end = true;
135 return r;
136 }
137
140 constexpr static size_t size() noexcept
141 {
142 return static_cast<size_t>(end());
143 }
144
149 [[nodiscard]] constexpr widget_mode mode() const noexcept
150 {
151 return static_cast<widget_mode>(_mode);
152 }
153
158 constexpr widget_state &set_mode(widget_mode mode) noexcept
159 {
160 _mode = static_cast<uint16_t>(mode);
161 return *this;
162 }
163
169 [[nodiscard]] constexpr size_t layer() const noexcept
170 {
171 return _layer;
172 }
173
178 constexpr widget_state &set_layer(size_t layer) noexcept
179 {
180 _layer = static_cast<uint16_t>(layer % 4);
181 return *this;
182 }
183
188 [[nodiscard]] constexpr widget_value value() const noexcept
189 {
190 return static_cast<widget_value>(_value);
191 }
192
197 constexpr widget_state &set_value(widget_value value) noexcept
198 {
199 _value = static_cast<uint16_t>(value);
200 return *this;
201 }
202
207 [[nodiscard]] constexpr widget_phase phase() const noexcept
208 {
209 if (_pressed) {
210 return widget_phase::pressed;
211 } else if (_hover) {
212 return widget_phase::hover;
213 } else if (_active) {
214 return widget_phase::normal;
215 } else {
216 return widget_phase::inactive;
217 }
218 }
219
220 [[nodiscard]] constexpr bool pressed() const noexcept
221 {
222 return _pressed;
223 }
224
229 constexpr widget_state &set_pressed(bool pressed) noexcept
230 {
231 _pressed = static_cast<bool>(pressed);
232 return *this;
233 }
234
235 [[nodiscard]] constexpr bool hover() const noexcept
236 {
237 return _hover;
238 }
239
244 constexpr widget_state &set_hover(bool hover) noexcept
245 {
246 _hover = static_cast<bool>(hover);
247 return *this;
248 }
249
250 [[nodiscard]] constexpr bool active() const noexcept
251 {
252 return _active;
253 }
254
259 constexpr widget_state &set_active(bool active) noexcept
260 {
261 _active = static_cast<bool>(active);
262 return *this;
263 }
264
267 [[nodiscard]] constexpr bool focus() const noexcept
268 {
269 return static_cast<bool>(_focus);
270 }
271
274 constexpr widget_state &set_focus(bool focus) noexcept
275 {
276 _focus = static_cast<uint16_t>(focus);
277 return *this;
278 }
279
280 constexpr style_pseudo_class pseudo_class() const noexcept
281 {
282 auto r = style_pseudo_class{};
283
284 if (pressed()) {
286 } else if (hover()) {
288 } else if (active()) {
290 } else {
292 }
293
294 if (focus()) {
296 }
297
298 if (value() != widget_value::off) {
300 } else {
302 }
303
304 return r;
305 }
306
313 template<std::integral T>
314 constexpr explicit operator T() const noexcept
315 requires(sizeof(T) >= 2)
316 {
317 auto r = T{0};
318
319 r += static_cast<T>(_end);
320
321 r *= 2;
322 r += static_cast<T>(focus());
323
324 r *= 4;
325 r += static_cast<T>(phase());
326
327 r *= 3;
328 r += static_cast<T>(value());
329
330 r *= 4;
331 r += static_cast<T>(layer());
332
333 r *= 7;
334 r += static_cast<T>(mode());
335 return r;
336 }
337
338 [[nodiscard]] constexpr friend bool operator==(widget_state const &lhs, widget_state const &rhs) noexcept
339 {
340 return static_cast<uint16_t>(lhs) == static_cast<uint16_t>(rhs);
341 }
342
348 constexpr widget_state& operator++() noexcept
349 {
350 if (mode() < widget_mode::enabled) {
351 set_mode(static_cast<widget_mode>(std::to_underlying(mode()) + 1));
352 return *this;
353 }
355
356 if (layer() < 3) {
357 set_layer(layer() + 1);
358 return *this;
359 }
360 set_layer(0);
361
362 if (value() < widget_value::other) {
363 set_value(static_cast<widget_value>(std::to_underlying(value()) + 1));
364 return *this;
365 }
366 set_value(widget_value::off);
367
368 switch (phase()) {
369 case widget_phase::inactive:
370 set_pressed(false);
371 set_hover(false);
372 set_active(true);
373 return *this;
374 case widget_phase::normal:
375 set_pressed(false);
376 set_hover(true);
377 set_active(true);
378 return *this;
379 case widget_phase::hover:
380 set_pressed(true);
381 set_hover(true);
382 set_active(true);
383 return *this;
384 case widget_phase::pressed:
385 set_pressed(false);
386 set_hover(false);
387 set_active(false);
388 break;
389 default:
390 hi_no_default();
391 }
392
393 if (focus() == false) {
394 set_focus(true);
395 return *this;
396 }
397 set_focus(false);
398
399 _end = true;
400 return *this;
401 }
402
405 [[nodiscard]] constexpr friend bool need_reconstrain(widget_state const &lhs, widget_state const &rhs) noexcept
406 {
407 return lhs._mode != rhs._mode;
408 }
409
412 [[nodiscard]] constexpr friend bool need_relayout(widget_state const &lhs, widget_state const &rhs) noexcept
413 {
414 return need_reconstrain(lhs, rhs) or lhs._layer != rhs._layer;
415 }
416
419 [[nodiscard]] constexpr friend bool need_redraw(widget_state const &lhs, widget_state const &rhs) noexcept
420 {
421 return lhs != rhs;
422 }
423
424private:
427 uint16_t _mode : 3 = static_cast<uint16_t>(widget_mode::enabled);
428
431 uint16_t _layer : 2 = 0;
432
435 uint16_t _value : 2 = static_cast<uint16_t>(widget_value::off);
436
439 uint16_t _active: 1 = 1;
440
443 uint16_t _hover : 1 = 0;
444
447 uint16_t _pressed : 1 = 0;
448
451 uint16_t _focus : 1 = 0;
452
455 uint16_t _end : 1 = 0;
456};
457
458}}
@ other
The gui_event does not have associated data.
Definition gui_event_variant.hpp:24
widget_mode
The mode that the widget is operating at.
Definition widget_state.hpp:26
@ partial
A widget is partially enabled.
Definition widget_state.hpp:73
@ collapse
The widget is collapsed.
Definition widget_state.hpp:34
@ invisible
The widget is invisible.
Definition widget_state.hpp:41
@ select
The widget is selectable.
Definition widget_state.hpp:63
@ enabled
The widget is fully enabled.
Definition widget_state.hpp:81
@ display
The widget is in display-only mode.
Definition widget_state.hpp:55
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
style_pseudo_class
The different dynamic states of a widget from the point of view of styles.
Definition style_pseudo_class.hpp:18
@ disabled
The widget is disabled, often shown in gray.
Definition style_pseudo_class.hpp:23
@ focus
The widget has keyboard focus.
Definition style_pseudo_class.hpp:45
@ enabled
The widget is enabled, the normal idle state.
Definition style_pseudo_class.hpp:29
@ active
The widget was clicked by the mouse or otherwise activated.
Definition style_pseudo_class.hpp:41
@ hover
The mouse hovers over the widget.
Definition style_pseudo_class.hpp:35
@ _false
The value that the widget represent is 'false'.
Definition style_pseudo_class.hpp:49
@ _true
The value that the widget represent is 'true'.
Definition style_pseudo_class.hpp:53
@ on
The border is drawn on the edge of a quad.
Definition draw_context_intf.hpp:31
The state the widget is in.
Definition widget_state.hpp:105
constexpr widget_state & set_layer(size_t layer) noexcept
Set the layer of the widget.
Definition widget_state.hpp:178
constexpr widget_state & set_hover(bool hover) noexcept
Set if the mouse hovers over the widget.
Definition widget_state.hpp:244
constexpr widget_state & set_mode(widget_mode mode) noexcept
Set the mode of a widget.
Definition widget_state.hpp:158
static constexpr widget_state end() noexcept
End of the iteration of all possible widget states.
Definition widget_state.hpp:131
constexpr size_t layer() const noexcept
Get the layer of a widget.
Definition widget_state.hpp:169
constexpr widget_state & set_active(bool active) noexcept
Set if the window is active widget.
Definition widget_state.hpp:259
constexpr bool focus() const noexcept
Get if the window has keyboard focus.
Definition widget_state.hpp:267
constexpr widget_phase phase() const noexcept
Get the phase of the widget.
Definition widget_state.hpp:207
constexpr widget_state & set_value(widget_value value) noexcept
Set the value of the widget.
Definition widget_state.hpp:197
constexpr widget_state & set_pressed(bool pressed) noexcept
Set if the mouse/finger presses the widget.
Definition widget_state.hpp:229
constexpr friend bool need_reconstrain(widget_state const &lhs, widget_state const &rhs) noexcept
Check if the change in widget-state requires the widget to reconstrain.
Definition widget_state.hpp:405
static constexpr size_t size() noexcept
The number if possible widget states.
Definition widget_state.hpp:140
static constexpr widget_state begin() noexcept
Start of the iteration of all possible widget states.
Definition widget_state.hpp:116
constexpr widget_state & operator++() noexcept
Increment the widget-state.
Definition widget_state.hpp:348
constexpr widget_state & set_focus(bool focus) noexcept
Set if the window has keyboard focus.
Definition widget_state.hpp:274
constexpr friend bool need_relayout(widget_state const &lhs, widget_state const &rhs) noexcept
Check if the change in widget-state requires the widget to relayout.
Definition widget_state.hpp:412
constexpr widget_value value() const noexcept
Get the value of the widget.
Definition widget_state.hpp:188
constexpr widget_mode mode() const noexcept
Get the mode of a widget.
Definition widget_state.hpp:149
constexpr friend bool need_redraw(widget_state const &lhs, widget_state const &rhs) noexcept
Check if the change in widget-state requires the widget to redraw.
Definition widget_state.hpp:419