ferroui_base/input/gesture_recognizers/
gesture_recognizer.rs1use crate::input::{
2 IPointer, InputElement, Pointer, PointerEventArgs, PointerPressedEventArgs, PointerReleasedEventArgs,
3};
4use crate::{ferro_class, ferro_impl_classes, FerroObjectImpl, Ref, StyledElement, StyledElementImpl, WeakRef};
5use std::cell::RefCell;
6use std::rc::Rc;
7
8#[repr(C)]
15pub struct GestureRecognizer {
16 base: StyledElement,
17 current_pointer: RefCell<Option<Rc<dyn IPointer>>>,
19 target: RefCell<Option<WeakRef<InputElement>>>,
20}
21
22ferro_class! {
23 GestureRecognizer: StyledElement, virtuals GestureRecognizerImpl: StyledElementImpl {
24 fn pointer_pressed(this, e: &PointerPressedEventArgs);
26 fn pointer_released(this, e: &PointerReleasedEventArgs);
28 fn pointer_moved(this, e: &PointerEventArgs);
30 fn pointer_capture_lost(this, pointer: &Rc<dyn IPointer>);
32 }
33}
34
35ferro_impl_classes!(GestureRecognizer: FerroObjectImpl, StyledElementImpl);
36
37impl GestureRecognizerImpl for GestureRecognizer {
40 fn pointer_pressed(_this: &Self, _e: &PointerPressedEventArgs) {}
41
42 fn pointer_released(_this: &Self, _e: &PointerReleasedEventArgs) {}
43
44 fn pointer_moved(_this: &Self, _e: &PointerEventArgs) {}
45
46 fn pointer_capture_lost(_this: &Self, _pointer: &Rc<dyn IPointer>) {}
47}
48
49impl GestureRecognizer {
50 pub fn construct() -> Self {
52 Self { base: StyledElement::construct(), current_pointer: RefCell::new(None), target: RefCell::new(None) }
53 }
54
55 pub fn target(&self) -> Option<Ref<InputElement>> {
57 self.target.borrow().as_ref().and_then(WeakRef::upgrade)
58 }
59
60 pub(crate) fn set_target(&self, value: Option<&Ref<InputElement>>) {
61 *self.target.borrow_mut() = value.map(Ref::downgrade);
62 }
63
64 fn set_current_pointer(&self, value: Option<Rc<dyn IPointer>>) {
65 let old = self.current_pointer.replace(value);
66 drop(old);
67 }
68
69 pub(crate) fn pointer_pressed_internal(&self, e: &PointerPressedEventArgs) {
70 self.set_current_pointer(Some(e.pointer().clone()));
71 self.pointer_pressed(e);
72 self.set_current_pointer(None);
73 }
74
75 pub(crate) fn pointer_released_internal(&self, e: &PointerReleasedEventArgs) {
76 self.set_current_pointer(Some(e.pointer().clone()));
77 self.pointer_released(e);
78 self.set_current_pointer(None);
79 }
80
81 pub(crate) fn pointer_moved_internal(&self, e: &PointerEventArgs) {
82 self.set_current_pointer(Some(e.pointer().clone()));
83 self.pointer_moved(e);
84 self.set_current_pointer(None);
85 }
86
87 #[cfg(any(test, feature = "testing"))]
91 pub fn pointer_moved_for_testing(&self, e: &PointerEventArgs) {
92 self.pointer_moved_internal(e);
93 }
94
95 #[cfg(any(test, feature = "testing"))]
99 pub fn pointer_released_for_testing(&self, e: &PointerReleasedEventArgs) {
100 self.pointer_released_internal(e);
101 }
102
103 pub(crate) fn pointer_capture_lost_internal(&self, pointer: &Rc<dyn IPointer>) {
104 self.pointer_capture_lost(pointer);
105 }
106
107 pub fn capture(&self, pointer: &Rc<dyn IPointer>) {
110 if let Some(pointer) = pointer.as_any().downcast_ref::<Pointer>() {
111 pointer.capture_gesture_recognizer(Some(&self.to_ref()));
112 }
113
114 let current = self.current_pointer.borrow().clone();
116 if let Some(current) = current {
117 if let Some(current) = current.as_any().downcast_ref::<Pointer>() {
118 current.set_is_gesture_recognition_skipped(true);
119 }
120 }
121 }
122}