1use crate::widget::{EventPhase, WidgetId};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum PointerButton {
5 Primary,
6 Secondary,
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum PointerState {
11 Pressed,
12 Released,
13 Moved,
14}
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum InputEvent {
18 Up,
19 Down,
20 Left,
21 Right,
22 SelectLeft,
23 SelectRight,
24 Home,
25 End,
26 SelectHome,
27 SelectEnd,
28 WordLeft,
29 WordRight,
30 SelectWordLeft,
31 SelectWordRight,
32 Undo,
33 Redo,
34 Select,
35 SelectPressed,
36 SelectReleased,
37 Back,
38 BackPressed,
39 BackReleased,
40 Encoder {
41 delta: i8,
42 },
43 Pointer {
44 x: i32,
45 y: i32,
46 state: PointerState,
47 button: PointerButton,
48 },
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub enum UiEvent {
53 FocusChanged {
54 old: Option<WidgetId>,
55 new: Option<WidgetId>,
56 },
57 Activate(WidgetId),
58 Back,
59 Pressed(WidgetId),
60 Released(WidgetId),
61 Clicked(WidgetId),
62 DoubleClicked(WidgetId),
63 LongPressed(WidgetId),
64 Opened(WidgetId),
65 Closed(WidgetId),
66 PointerPressed(WidgetId),
67 PointerReleased(WidgetId),
68 Gesture(WidgetId),
69 ValueChanged(WidgetId),
70 TextInput {
71 id: WidgetId,
72 ch: char,
73 },
74 Focused(WidgetId),
75 Defocused(WidgetId),
76 Scroll {
77 id: WidgetId,
78 delta: i32,
79 },
80 LayoutChanged(WidgetId),
81 StyleChanged(WidgetId),
82}
83
84#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
85pub struct UiEventFilter(u16);
86
87impl UiEventFilter {
88 pub const FOCUS: Self = Self(1 << 0);
89 pub const ACTIVATE: Self = Self(1 << 1);
90 pub const BACK: Self = Self(1 << 2);
91 pub const POINTER: Self = Self(1 << 3);
92 pub const VALUE: Self = Self(1 << 4);
93 pub const SCROLL: Self = Self(1 << 5);
94 pub const LAYOUT: Self = Self(1 << 6);
95 pub const STYLE: Self = Self(1 << 7);
96
97 pub const ALL: Self = Self(
98 Self::FOCUS.0
99 | Self::ACTIVATE.0
100 | Self::BACK.0
101 | Self::POINTER.0
102 | Self::VALUE.0
103 | Self::SCROLL.0
104 | Self::LAYOUT.0
105 | Self::STYLE.0,
106 );
107
108 pub const fn empty() -> Self {
109 Self(0)
110 }
111
112 pub const fn contains(self, other: Self) -> bool {
113 self.0 & other.0 == other.0
114 }
115
116 pub fn insert(&mut self, other: Self) {
117 self.0 |= other.0;
118 }
119
120 pub fn remove(&mut self, other: Self) {
121 self.0 &= !other.0;
122 }
123}
124
125impl core::ops::BitOr for UiEventFilter {
126 type Output = Self;
127
128 fn bitor(self, rhs: Self) -> Self::Output {
129 Self(self.0 | rhs.0)
130 }
131}
132
133impl UiEvent {
134 pub const fn target(self) -> Option<WidgetId> {
135 match self {
136 Self::FocusChanged { new, .. } => new,
137 Self::Activate(id)
138 | Self::Pressed(id)
139 | Self::Released(id)
140 | Self::Clicked(id)
141 | Self::DoubleClicked(id)
142 | Self::LongPressed(id)
143 | Self::Opened(id)
144 | Self::Closed(id)
145 | Self::PointerPressed(id)
146 | Self::PointerReleased(id)
147 | Self::Gesture(id)
148 | Self::ValueChanged(id)
149 | Self::TextInput { id, .. }
150 | Self::Focused(id)
151 | Self::Defocused(id)
152 | Self::LayoutChanged(id)
153 | Self::StyleChanged(id) => Some(id),
154 Self::Scroll { id, .. } => Some(id),
155 Self::Back => None,
156 }
157 }
158
159 pub const fn filter(self) -> UiEventFilter {
160 match self {
161 Self::FocusChanged { .. } | Self::Focused(_) | Self::Defocused(_) => {
162 UiEventFilter::FOCUS
163 }
164 Self::Activate(_)
165 | Self::Pressed(_)
166 | Self::Released(_)
167 | Self::Clicked(_)
168 | Self::DoubleClicked(_)
169 | Self::LongPressed(_)
170 | Self::Opened(_)
171 | Self::Closed(_) => UiEventFilter::ACTIVATE,
172 Self::Back => UiEventFilter::BACK,
173 Self::PointerPressed(_) | Self::PointerReleased(_) | Self::Gesture(_) => {
174 UiEventFilter::POINTER
175 }
176 Self::ValueChanged(_) | Self::TextInput { .. } => UiEventFilter::VALUE,
177 Self::Scroll { .. } => UiEventFilter::SCROLL,
178 Self::LayoutChanged(_) => UiEventFilter::LAYOUT,
179 Self::StyleChanged(_) => UiEventFilter::STYLE,
180 }
181 }
182}
183
184#[derive(Clone, Copy, Debug, PartialEq, Eq)]
185pub enum WidgetEventKind {
186 Pressed,
187 Released,
188 Clicked,
189 DoubleClicked,
190 LongPressed,
191 Opened,
192 Closed,
193 ValueChanged,
194 Focused,
195 Defocused,
196 Scroll { delta: i32 },
197 Gesture,
198 LayoutChanged,
199 StyleChanged,
200}
201
202#[derive(Clone, Copy, Debug, PartialEq, Eq)]
203pub struct WidgetEvent {
204 pub target: WidgetId,
205 pub current: WidgetId,
206 pub phase: EventPhase,
207 pub kind: WidgetEventKind,
208}
209
210#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
211pub struct WidgetEventFilter(u16);
212
213impl WidgetEventFilter {
214 pub const POINTER: Self = Self(1 << 0);
215 pub const ACTIVATE: Self = Self(1 << 1);
216 pub const VALUE: Self = Self(1 << 2);
217 pub const FOCUS: Self = Self(1 << 3);
218 pub const SCROLL: Self = Self(1 << 4);
219 pub const LAYOUT: Self = Self(1 << 5);
220 pub const STYLE: Self = Self(1 << 6);
221
222 pub const ALL: Self = Self(
223 Self::POINTER.0
224 | Self::ACTIVATE.0
225 | Self::VALUE.0
226 | Self::FOCUS.0
227 | Self::SCROLL.0
228 | Self::LAYOUT.0
229 | Self::STYLE.0,
230 );
231
232 pub const fn contains(self, other: Self) -> bool {
233 self.0 & other.0 == other.0
234 }
235}
236
237impl core::ops::BitOr for WidgetEventFilter {
238 type Output = Self;
239
240 fn bitor(self, rhs: Self) -> Self::Output {
241 Self(self.0 | rhs.0)
242 }
243}
244
245impl WidgetEventKind {
246 pub const fn filter(self) -> WidgetEventFilter {
247 match self {
248 Self::Pressed | Self::Released | Self::Gesture => WidgetEventFilter::POINTER,
249 Self::Clicked
250 | Self::DoubleClicked
251 | Self::LongPressed
252 | Self::Opened
253 | Self::Closed => WidgetEventFilter::ACTIVATE,
254 Self::ValueChanged => WidgetEventFilter::VALUE,
255 Self::Focused | Self::Defocused => WidgetEventFilter::FOCUS,
256 Self::Scroll { .. } => WidgetEventFilter::SCROLL,
257 Self::LayoutChanged => WidgetEventFilter::LAYOUT,
258 Self::StyleChanged => WidgetEventFilter::STYLE,
259 }
260 }
261}
262
263#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
264pub struct EventPhaseMask(u8);
265
266impl EventPhaseMask {
267 pub const CAPTURE: Self = Self(1 << 0);
268 pub const TARGET: Self = Self(1 << 1);
269 pub const BUBBLE: Self = Self(1 << 2);
270 pub const ALL: Self = Self(Self::CAPTURE.0 | Self::TARGET.0 | Self::BUBBLE.0);
271
272 pub const fn contains(self, phase: EventPhase) -> bool {
273 let bit = match phase {
274 EventPhase::Capture => Self::CAPTURE.0,
275 EventPhase::Target => Self::TARGET.0,
276 EventPhase::Bubble => Self::BUBBLE.0,
277 };
278 self.0 & bit == bit
279 }
280}
281
282#[derive(Clone, Copy, Debug, PartialEq, Eq)]
283pub struct WidgetDispatchPolicy {
284 pub kinds: WidgetEventFilter,
285 pub phases: EventPhaseMask,
286 pub stop: bool,
287}
288
289impl WidgetDispatchPolicy {
290 pub const fn stop(kinds: WidgetEventFilter, phases: EventPhaseMask) -> Self {
291 Self {
292 kinds,
293 phases,
294 stop: true,
295 }
296 }
297
298 pub const fn allows(self, kind: WidgetEventKind, phase: EventPhase) -> bool {
299 self.kinds.contains(kind.filter()) && self.phases.contains(phase)
300 }
301}