1use crate::{
17 core::{algebra::Vector2, pool::Handle},
18 UiNode,
19};
20use std::{
21 any::Any,
22 cell::Cell,
23 fmt::Debug,
24 ops::{Deref, DerefMut},
25 rc::Rc,
26};
27
28#[macro_export]
29macro_rules! define_constructor {
30 ($inner:ident : $inner_var:tt => fn $name:ident(), layout: $perform_layout:expr) => {
31 pub fn $name(destination: Handle<UiNode>, direction: MessageDirection) -> UiMessage {
32 UiMessage {
33 handled: std::cell::Cell::new(false),
34 data: std::rc::Rc::new($inner::$inner_var),
35 destination,
36 direction,
37 perform_layout: std::cell::Cell::new($perform_layout),
38 flags: 0
39 }
40 }
41 };
42
43 ($inner:ident : $inner_var:tt => fn $name:ident($typ:ty), layout: $perform_layout:expr) => {
44 pub fn $name(destination: Handle<UiNode>, direction: MessageDirection, value:$typ) -> UiMessage {
45 UiMessage {
46 handled: std::cell::Cell::new(false),
47 data: std::rc::Rc::new($inner::$inner_var(value)),
48 destination,
49 direction,
50 perform_layout: std::cell::Cell::new($perform_layout),
51 flags: 0
52 }
53 }
54 };
55
56 ($inner:ident : $inner_var:tt => fn $name:ident( $($params:ident : $types:ty),+ ), layout: $perform_layout:expr) => {
57 pub fn $name(destination: Handle<UiNode>, direction: MessageDirection, $($params : $types),+) -> UiMessage {
58 UiMessage {
59 handled: std::cell::Cell::new(false),
60 data: std::rc::Rc::new($inner::$inner_var { $($params),+ }),
61 destination,
62 direction,
63 perform_layout: std::cell::Cell::new($perform_layout),
64 flags: 0
65 }
66 }
67 }
68}
69
70#[derive(Debug)]
71pub struct UserMessageData(pub Box<dyn MessageData>);
72
73impl Deref for UserMessageData {
74 type Target = dyn MessageData;
75
76 fn deref(&self) -> &Self::Target {
77 &*self.0
78 }
79}
80
81impl DerefMut for UserMessageData {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut *self.0
84 }
85}
86
87impl PartialEq for UserMessageData {
88 fn eq(&self, other: &Self) -> bool {
89 self.0.compare(&*other.0)
90 }
91}
92
93#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Hash)]
109pub enum MessageDirection {
110 ToWidget,
112
113 FromWidget,
115}
116
117impl MessageDirection {
118 pub fn reverse(self) -> Self {
120 match self {
121 Self::ToWidget => Self::FromWidget,
122 Self::FromWidget => Self::ToWidget,
123 }
124 }
125}
126
127pub trait MessageData: 'static + Debug + Any {
128 fn as_any(&self) -> &dyn Any;
129
130 fn compare(&self, other: &dyn MessageData) -> bool;
131}
132
133impl<T> MessageData for T
134where
135 T: 'static + Debug + PartialEq + Any,
136{
137 fn as_any(&self) -> &dyn Any {
138 self
139 }
140
141 fn compare(&self, other: &dyn MessageData) -> bool {
142 other
143 .as_any()
144 .downcast_ref::<T>()
145 .map(|other| other == self)
146 .unwrap_or_default()
147 }
148}
149
150#[derive(Debug, Clone)]
157pub struct UiMessage {
158 pub handled: Cell<bool>,
160
161 pub data: Rc<dyn MessageData>,
163
164 pub destination: Handle<UiNode>,
167
168 pub direction: MessageDirection,
172
173 pub perform_layout: Cell<bool>,
182
183 pub flags: u64,
185}
186
187impl PartialEq for UiMessage {
188 fn eq(&self, other: &Self) -> bool {
189 self.handled == other.handled
190 && self.data.compare(&*other.data)
191 && self.destination == other.destination
192 && self.direction == other.direction
193 && self.perform_layout == other.perform_layout
194 && self.flags == other.flags
195 }
196}
197
198impl UiMessage {
199 pub fn with_data<T: MessageData>(data: T) -> Self {
200 Self {
201 handled: Cell::new(false),
202 data: Rc::new(data),
203 destination: Default::default(),
204 direction: MessageDirection::ToWidget,
205 perform_layout: Cell::new(false),
206 flags: 0,
207 }
208 }
209
210 pub fn with_destination(mut self, destination: Handle<UiNode>) -> Self {
211 self.destination = destination;
212 self
213 }
214
215 pub fn with_direction(mut self, direction: MessageDirection) -> Self {
216 self.direction = direction;
217 self
218 }
219
220 pub fn with_perform_layout(self, perform_layout: bool) -> Self {
221 self.perform_layout.set(perform_layout);
222 self
223 }
224
225 #[must_use = "method creates new value which must be used"]
235 pub fn reverse(&self) -> Self {
236 Self {
237 handled: self.handled.clone(),
238 data: self.data.clone(),
239 destination: self.destination,
240 direction: self.direction.reverse(),
241 perform_layout: self.perform_layout.clone(),
242 flags: self.flags,
243 }
244 }
245
246 pub fn destination(&self) -> Handle<UiNode> {
247 self.destination
248 }
249
250 pub fn data<T: MessageData>(&self) -> Option<&T> {
251 (*self.data).as_any().downcast_ref::<T>()
252 }
253
254 pub fn set_handled(&self, handled: bool) {
255 self.handled.set(handled);
256 }
257
258 pub fn handled(&self) -> bool {
259 self.handled.get()
260 }
261
262 pub fn direction(&self) -> MessageDirection {
263 self.direction
264 }
265
266 pub fn set_perform_layout(&self, value: bool) {
267 self.perform_layout.set(value);
268 }
269
270 pub fn need_perform_layout(&self) -> bool {
271 self.perform_layout.get()
272 }
273
274 pub fn has_flags(&self, flags: u64) -> bool {
275 self.flags & flags != 0
276 }
277}
278
279#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
280pub enum ButtonState {
281 Pressed,
282 Released,
283}
284
285#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
286pub enum MouseButton {
287 Left,
288 Right,
289 Middle,
290 Other(u16),
291}
292
293pub enum OsEvent {
294 MouseInput {
295 button: MouseButton,
296 state: ButtonState,
297 },
298 CursorMoved {
299 position: Vector2<f32>,
300 },
301 KeyboardInput {
302 button: KeyCode,
303 state: ButtonState,
304 },
305 Character(char),
306 KeyboardModifiers(KeyboardModifiers),
307 MouseWheel(f32, f32),
308}
309
310#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Default)]
311pub struct KeyboardModifiers {
312 pub alt: bool,
313 pub shift: bool,
314 pub control: bool,
315 pub system: bool,
316}
317
318impl KeyboardModifiers {
319 pub fn is_none(self) -> bool {
320 !self.shift && !self.control && !self.alt && !self.system
321 }
322}
323
324#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
325#[repr(u32)]
326pub enum KeyCode {
327 Key1,
328 Key2,
329 Key3,
330 Key4,
331 Key5,
332 Key6,
333 Key7,
334 Key8,
335 Key9,
336 Key0,
337 A,
338 B,
339 C,
340 D,
341 E,
342 F,
343 G,
344 H,
345 I,
346 J,
347 K,
348 L,
349 M,
350 N,
351 O,
352 P,
353 Q,
354 R,
355 S,
356 T,
357 U,
358 V,
359 W,
360 X,
361 Y,
362 Z,
363
364 Escape,
365
366 F1,
367 F2,
368 F3,
369 F4,
370 F5,
371 F6,
372 F7,
373 F8,
374 F9,
375 F10,
376 F11,
377 F12,
378 F13,
379 F14,
380 F15,
381 F16,
382 F17,
383 F18,
384 F19,
385 F20,
386 F21,
387 F22,
388 F23,
389 F24,
390
391 Snapshot,
392 Scroll,
393 Pause,
394
395 Insert,
396 Home,
397 Delete,
398 End,
399 PageDown,
400 PageUp,
401
402 Left,
403 Up,
404 Right,
405 Down,
406
407 Backspace,
408 Return,
409 Space,
410
411 Compose,
412
413 Caret,
414
415 Numlock,
416 Numpad0,
417 Numpad1,
418 Numpad2,
419 Numpad3,
420 Numpad4,
421 Numpad5,
422 Numpad6,
423 Numpad7,
424 Numpad8,
425 Numpad9,
426
427 AbntC1,
428 AbntC2,
429 NumpadAdd,
430 Apostrophe,
431 Apps,
432 At,
433 Ax,
434 Backslash,
435 Calculator,
436 Capital,
437 Colon,
438 Comma,
439 Convert,
440 NumpadDecimal,
441 NumpadDivide,
442 Equals,
443 Grave,
444 Kana,
445 Kanji,
446 LAlt,
447 LBracket,
448 LControl,
449 LShift,
450 LWin,
451 Mail,
452 MediaSelect,
453 MediaStop,
454 Minus,
455 NumpadMultiply,
456 Mute,
457 MyComputer,
458 NavigateForward,
459 NavigateBackward,
460 NextTrack,
461 NoConvert,
462 NumpadComma,
463 NumpadEnter,
464 NumpadEquals,
465 OEM102,
466 Period,
467 PlayPause,
468 Power,
469 PrevTrack,
470 RAlt,
471 RBracket,
472 RControl,
473 RShift,
474 RWin,
475 Semicolon,
476 Slash,
477 Sleep,
478 Stop,
479 NumpadSubtract,
480 Sysrq,
481 Tab,
482 Underline,
483 Unlabeled,
484 VolumeDown,
485 VolumeUp,
486 Wake,
487 WebBack,
488 WebFavorites,
489 WebForward,
490 WebHome,
491 WebRefresh,
492 WebSearch,
493 WebStop,
494 Yen,
495 Copy,
496 Paste,
497 Cut,
498 Asterisk,
499 Plus,
500}
501
502#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
503pub enum CursorIcon {
504 Default,
505 Crosshair,
506 Hand,
507 Arrow,
508 Move,
509 Text,
510 Wait,
511 Help,
512 Progress,
513 NotAllowed,
514 ContextMenu,
515 Cell,
516 VerticalText,
517 Alias,
518 Copy,
519 NoDrop,
520 Grab,
521 Grabbing,
522 AllScroll,
523 ZoomIn,
524 ZoomOut,
525 EResize,
526 NResize,
527 NeResize,
528 NwResize,
529 SResize,
530 SeResize,
531 SwResize,
532 WResize,
533 EwResize,
534 NsResize,
535 NeswResize,
536 NwseResize,
537 ColResize,
538 RowResize,
539}
540
541impl Default for CursorIcon {
542 fn default() -> Self {
543 CursorIcon::Default
544 }
545}