ferroui_base/input/gesture_recognizers/
gesture_recognizer_collection.rs1use super::GestureRecognizer;
2use crate::input::{
3 IPointer, InputElement, Pointer, PointerEventArgs, PointerPressedEventArgs, PointerReleasedEventArgs,
4};
5use crate::{FerroObject, Ref, StyledElement, WeakRef};
6use std::cell::RefCell;
7use std::rc::Rc;
8
9#[derive(Clone)]
14pub struct GestureRecognizerCollection(Rc<GestureRecognizerCollectionData>);
15
16struct GestureRecognizerCollectionData {
17 input_element: WeakRef<InputElement>,
18 recognizers: RefCell<Vec<Ref<GestureRecognizer>>>,
19}
20
21impl PartialEq for GestureRecognizerCollection {
22 fn eq(&self, other: &Self) -> bool {
23 Rc::ptr_eq(&self.0, &other.0)
24 }
25}
26
27impl std::fmt::Debug for GestureRecognizerCollection {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "GestureRecognizerCollection({})", self.count())
30 }
31}
32
33impl GestureRecognizerCollection {
34 pub fn new(input_element: &Ref<InputElement>) -> Self {
36 Self(Rc::new(GestureRecognizerCollectionData {
37 input_element: input_element.downgrade(),
38 recognizers: RefCell::new(Vec::new()),
39 }))
40 }
41
42 fn snapshot(&self) -> Vec<Ref<GestureRecognizer>> {
43 self.0.recognizers.borrow().clone()
44 }
45
46 pub fn add(&self, recognizer: impl crate::IntoRef<GestureRecognizer>) {
48 let recognizer = recognizer.into_ref();
49 self.0.recognizers.borrow_mut().push(recognizer.clone());
50
51 let Some(input_element) = self.0.input_element.upgrade() else { return };
52 recognizer.set_target(Some(&input_element));
53
54 recognizer.set_parent(input_element.clone().upcast::<StyledElement>());
58 recognizer.set_templated_parent(input_element.templated_parent());
59
60 let weak = recognizer.downgrade();
61 input_element.property_changed(move |e| {
62 if e.property() == StyledElement::templated_parent_property().as_property() {
63 if let Some(recognizer) = weak.upgrade() {
64 recognizer.set_templated_parent(e.get_new_value::<Option<Ref<FerroObject>>>());
65 }
66 }
67 });
68 }
69
70 pub fn remove(&self, recognizer: &GestureRecognizer) -> bool {
73 let removed = {
74 let mut recognizers = self.0.recognizers.borrow_mut();
75 recognizers
76 .iter()
77 .position(|r| std::ptr::eq::<GestureRecognizer>(&**r, recognizer))
78 .map(|index| recognizers.remove(index))
79 };
80
81 match removed {
82 Some(removed) => {
83 removed.set_target(None);
84 removed.set_parent(None);
85 true
86 }
87 None => false,
88 }
89 }
90
91 pub fn to_vec(&self) -> Vec<Ref<GestureRecognizer>> {
93 self.snapshot()
94 }
95
96 pub fn count(&self) -> usize {
98 self.0.recognizers.borrow().len()
99 }
100
101 fn captured_recognizer(pointer: &Rc<dyn IPointer>) -> Option<Ref<GestureRecognizer>> {
102 pointer.as_any().downcast_ref::<Pointer>().and_then(Pointer::captured_gesture_recognizer)
103 }
104
105 pub(crate) fn handle_pointer_pressed(&self, e: &PointerPressedEventArgs) -> bool {
106 if self.0.recognizers.borrow().is_empty() {
107 return false;
108 }
109
110 for r in self.snapshot() {
111 r.pointer_pressed_internal(e);
112 }
113
114 e.handled()
115 }
116
117 pub(crate) fn handle_capture_lost(&self, pointer: &Rc<dyn IPointer>) {
118 if self.0.recognizers.borrow().is_empty() || pointer.as_any().downcast_ref::<Pointer>().is_none() {
119 return;
120 }
121
122 for r in self.snapshot() {
123 if Self::captured_recognizer(pointer).as_ref() == Some(&r) {
124 continue;
125 }
126
127 r.pointer_capture_lost_internal(pointer);
128 }
129 }
130
131 pub(crate) fn handle_pointer_released(&self, e: &PointerReleasedEventArgs) -> bool {
132 if self.0.recognizers.borrow().is_empty() {
133 return false;
134 }
135
136 for r in self.snapshot() {
137 if Self::captured_recognizer(e.pointer()).is_some() {
138 break;
139 }
140
141 r.pointer_released_internal(e);
142 }
143
144 e.handled()
145 }
146
147 pub(crate) fn handle_pointer_moved(&self, e: &PointerEventArgs) -> bool {
148 if self.0.recognizers.borrow().is_empty() {
149 return false;
150 }
151
152 for r in self.snapshot() {
153 if Self::captured_recognizer(e.pointer()).is_some() {
154 break;
155 }
156
157 r.pointer_moved_internal(e);
158 }
159
160 e.handled()
161 }
162}