HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gui_event.hpp
1// Copyright Take Vos 2022.
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 "gui_event_type.hpp"
8#include "gui_event_variant.hpp"
9#include "keyboard_virtual_key.hpp"
10#include "keyboard_state.hpp"
11#include "keyboard_modifiers.hpp"
12#include "mouse_buttons.hpp"
13#include "../unicode/grapheme.hpp"
14#include "../geometry/vector.hpp"
15#include "../geometry/point.hpp"
16#include "../geometry/transform.hpp"
17#include "../chrono.hpp"
18#include <chrono>
19
20namespace hi::inline v1 {
21
27 point2 position = {};
28
35 point2 down_position = {};
36
41 vector2 wheel_delta = {};
42
45 mouse_buttons cause = {};
46
49 mouse_buttons down = {};
50
53 uint8_t click_count = 0;
54};
55
58class gui_event {
59public:
62 utc_nanoseconds time_point;
63
68 keyboard_modifiers keyboard_modifiers;
69
72 keyboard_state keyboard_state;
73
74 constexpr gui_event(
75 gui_event_type type,
76 utc_nanoseconds time_point,
77 hi::keyboard_modifiers keyboard_modifiers,
78 hi::keyboard_state keyboard_state) noexcept :
79 _type(gui_event_type::none), time_point(time_point), keyboard_modifiers(keyboard_modifiers), keyboard_state(keyboard_state)
80 {
81 set_type(type);
82 }
83
84 constexpr gui_event() noexcept :
85 gui_event(gui_event_type::none, utc_nanoseconds{}, keyboard_modifiers::none, keyboard_state::idle)
86 {
87 }
88
89 gui_event(gui_event_type type) noexcept :
90 gui_event(type, std::chrono::utc_clock::now(), keyboard_modifiers::none, keyboard_state::idle)
91 {
92 }
93
94 gui_event(gui_event_type type, hi::grapheme grapheme) noexcept :
95 gui_event(type, std::chrono::utc_clock::now(), keyboard_modifiers::none, keyboard_state::idle)
96 {
97 hi_axiom(variant() == gui_event_variant::grapheme);
98 this->grapheme() = grapheme;
99 }
100
101 gui_event(
102 gui_event_type type,
103 keyboard_virtual_key key,
104 hi::keyboard_modifiers keyboard_modifiers = keyboard_modifiers::none,
105 hi::keyboard_state keyboard_state = keyboard_state::idle) noexcept :
106 gui_event(type, std::chrono::utc_clock::now(), keyboard_modifiers, keyboard_state)
107 {
108 hi_axiom(variant() == gui_event_variant::keyboard);
109 this->key() = key;
110 }
111
112 constexpr gui_event(gui_event const&) noexcept = default;
113 constexpr gui_event(gui_event&&) noexcept = default;
114 constexpr gui_event& operator=(gui_event const&) noexcept = default;
115 constexpr gui_event& operator=(gui_event&&) noexcept = default;
116
117 [[nodiscard]] static gui_event make_mouse_enter(point2 position) noexcept
118 {
119 auto r = gui_event{gui_event_type::mouse_enter};
120 r.mouse().position = position;
121 return r;
122 }
123
124 [[nodiscard]] constexpr gui_event_type type() const noexcept
125 {
126 return _type;
127 }
128
134 [[nodiscard]] constexpr void set_type(gui_event_type type) noexcept
135 {
136 hilet previous_variant = variant();
137
138 _type = type;
139 if (previous_variant != variant()) {
140 switch (variant()) {
141 case gui_event_variant::mouse:
142 _mouse = {};
143 break;
144 case gui_event_variant::grapheme:
145 _grapheme = hi::grapheme{};
146 break;
147 case gui_event_variant::keyboard:
148 _key = {};
149 break;
150 default:;
151 }
152 }
153 }
154
155 [[nodiscard]] mouse_event_data& mouse() noexcept
156 {
157 hi_axiom(variant() == gui_event_variant::mouse);
158 return _mouse;
159 }
160
161 [[nodiscard]] mouse_event_data const& mouse() const noexcept
162 {
163 hi_axiom(variant() == gui_event_variant::mouse);
164 return _mouse;
165 }
166
167 [[nodiscard]] keyboard_virtual_key& key() noexcept
168 {
169 hi_axiom(variant() == gui_event_variant::keyboard);
170 return _key;
171 }
172
173 [[nodiscard]] keyboard_virtual_key const& key() const noexcept
174 {
175 hi_axiom(variant() == gui_event_variant::keyboard);
176 return _key;
177 }
178
179 [[nodiscard]] hi::grapheme& grapheme() noexcept
180 {
181 hi_axiom(variant() == gui_event_variant::grapheme);
182 return _grapheme;
183 }
184
185 [[nodiscard]] hi::grapheme const& grapheme() const noexcept
186 {
187 hi_axiom(variant() == gui_event_variant::grapheme);
188 return _grapheme;
189 }
190
191 [[nodiscard]] constexpr bool operator==(gui_event_type event_type) const noexcept
192 {
193 return type() == event_type;
194 }
195
196 [[nodiscard]] constexpr bool operator==(gui_event_variant event_variant) const noexcept
197 {
198 return variant() == event_variant;
199 }
200
201 [[nodiscard]] constexpr bool empty() const noexcept
202 {
203 return type() == gui_event_type::none;
204 }
205
206 constexpr operator bool() const noexcept
207 {
208 return not empty();
209 }
210
211 [[nodiscard]] constexpr gui_event_variant variant() const noexcept
212 {
213 return to_gui_event_variant(type());
214 }
215
218 [[nodiscard]] constexpr bool is_left_button_up(aarectangle active_area) const noexcept
219 {
220 using enum gui_event_type;
221 return type() == mouse_up and mouse().cause.left_button and active_area.contains(mouse().position);
222 }
223
226 [[nodiscard]] constexpr vector2 drag_delta() const noexcept
227 {
228 using enum gui_event_type;
229 return type() == mouse_drag ? mouse().position - mouse().down_position : vector2{};
230 }
231
232 [[nodiscard]] constexpr friend gui_event operator*(geo::transformer auto const& transform, gui_event const& rhs) noexcept
233 {
234 auto r = rhs;
235 if (rhs == gui_event_variant::mouse) {
236 r.mouse().position = point2{transform * rhs.mouse().position};
237 r.mouse().down_position = point2{transform * rhs.mouse().down_position};
238 r.mouse().wheel_delta = vector2{transform * rhs.mouse().wheel_delta};
239 }
240 return r;
241 }
242
243private:
244 gui_event_type _type;
245
246 union {
247 mouse_event_data _mouse;
248 keyboard_virtual_key _key;
249 hi::grapheme _grapheme;
250 };
251};
252
253} // namespace hi::inline v1
254
255template<typename CharT>
256struct std::formatter<hi::gui_event, CharT> : std::formatter<std::string_view, CharT> {
257 auto format(hi::gui_event const& t, auto& fc)
258 {
259 return std::formatter<std::string_view, CharT>::format(hi::gui_event_type_metadata[t.type()], fc);
260 }
261};
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
Definition gui_event.hpp:22
A user interface event.
Definition gui_event.hpp:58
constexpr void set_type(gui_event_type type) noexcept
Change the type of the gui_event.
Definition gui_event.hpp:134
constexpr bool is_left_button_up(aarectangle active_area) const noexcept
Check if this event is for a left-button-up event while the mouse pointer is in the given area.
Definition gui_event.hpp:218
keyboard_state keyboard_state
State of the keyboard; caps-lock, num-lock, scroll-lock.
Definition gui_event.hpp:72
keyboard_modifiers keyboard_modifiers
Keyboard modifiers: shift, ctrl, alt, etc.
Definition gui_event.hpp:68
utc_nanoseconds time_point
The time when the event was created.
Definition gui_event.hpp:62
constexpr vector2 drag_delta() const noexcept
Get the location of the mouse relative to the start of a drag.
Definition gui_event.hpp:226
Definition mouse_buttons.hpp:11
Definition transform.hpp:82
T transform(T... args)