orbit/events/
delegation.rs

1//! Event delegation system for Orbit UI framework
2//!
3//! This module provides an enhanced event handling system with:
4//! - Event bubbling and capturing
5//! - Event delegation up and down the component tree
6//! - Stop propagation and prevent default functionality
7
8use std::any::TypeId;
9use std::collections::HashMap;
10use std::fmt::Debug;
11use std::sync::{Arc, Mutex, RwLock};
12
13use crate::component_single::Node;
14use crate::events::Event;
15
16/// Type alias for event handler function
17type EventHandler = Box<dyn Fn(&mut dyn Event, &EventPropagation) + Send + Sync>;
18
19/// Type alias for handler storage map
20type HandlerMap = Arc<RwLock<HashMap<TypeId, Vec<EventHandler>>>>;
21
22/// Specifies the event propagation phase
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum PropagationPhase {
25    /// Event is traveling down from parent to target (DOM capturing phase)
26    Capturing,
27
28    /// Event is at the target component
29    Target,
30
31    /// Event is traveling up from target to parent (DOM bubbling phase)
32    Bubbling,
33}
34
35/// Controls how an event propagates through the component tree
36#[derive(Debug, Clone)]
37pub struct EventPropagation {
38    /// Whether the event should continue propagating
39    pub stopped: bool,
40
41    /// Whether the default action should be prevented
42    pub default_prevented: bool,
43
44    /// The current propagation phase
45    pub phase: PropagationPhase,
46
47    /// The component that is the original target of the event
48    pub target_id: Option<usize>,
49
50    /// The component that is currently handling the event
51    pub current_target_id: Option<usize>,
52}
53
54impl EventPropagation {
55    /// Create a new event propagation
56    pub fn new(phase: PropagationPhase) -> Self {
57        Self {
58            stopped: false,
59            default_prevented: false,
60            phase,
61            target_id: None,
62            current_target_id: None,
63        }
64    }
65
66    /// Stop event propagation
67    pub fn stop_propagation(&mut self) {
68        self.stopped = true;
69    }
70
71    /// Prevent the default action
72    pub fn prevent_default(&mut self) {
73        self.default_prevented = true;
74    }
75
76    /// Check if propagation is stopped
77    pub fn is_propagation_stopped(&self) -> bool {
78        self.stopped
79    }
80
81    /// Check if default is prevented
82    pub fn is_default_prevented(&self) -> bool {
83        self.default_prevented
84    }
85}
86
87/// An enhanced event that includes propagation information
88pub struct DelegatedEvent<E: Event> {
89    /// The original event
90    pub event: E,
91
92    /// Propagation control
93    pub propagation: EventPropagation,
94}
95
96impl<E: Event> DelegatedEvent<E> {
97    /// Create a new delegated event
98    pub fn new(event: E, phase: PropagationPhase) -> Self {
99        Self {
100            event,
101            propagation: EventPropagation::new(phase),
102        }
103    }
104
105    /// Stop propagation of this event
106    pub fn stop_propagation(&mut self) {
107        self.propagation.stop_propagation();
108    }
109
110    /// Prevent the default action for this event
111    pub fn prevent_default(&mut self) {
112        self.propagation.prevent_default();
113    }
114}
115
116/// Type of callback for delegated events
117#[allow(dead_code)]
118type DelegatedEventCallback<E> = Box<dyn Fn(&mut DelegatedEvent<E>) + Send + Sync>;
119
120/// Event delegate manages capturing, targeting, and bubbling of events
121#[derive(Default)]
122pub struct EventDelegate {
123    /// Map of event type to callbacks registered for capturing phase
124    capturing_handlers: HandlerMap,
125
126    /// Map of event type to callbacks registered for bubbling phase
127    bubbling_handlers: HandlerMap,
128
129    /// Map of event type to callbacks registered for just that target
130    target_handlers: HandlerMap,
131
132    /// Component ID for identification during propagation
133    component_id: Option<usize>,
134
135    /// Parent delegate for bubbling events up
136    parent: Option<Arc<Mutex<EventDelegate>>>,
137
138    /// Child delegates for capturing events down
139    children: Vec<Arc<Mutex<EventDelegate>>>,
140}
141
142impl std::fmt::Debug for EventDelegate {
143    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144        f.debug_struct("EventDelegate")
145            .field("component_id", &self.component_id)
146            .field("capturing_handlers", &"<handlers>")
147            .field("bubbling_handlers", &"<handlers>")
148            .field("target_handlers", &"<handlers>")
149            .field("parent", &self.parent.as_ref().map(|_| "<delegate>"))
150            .field("children", &format!("<{} children>", self.children.len()))
151            .finish()
152    }
153}
154
155impl EventDelegate {
156    /// Create a new event delegate
157    pub fn new(component_id: Option<usize>) -> Self {
158        Self {
159            capturing_handlers: Arc::new(RwLock::new(HashMap::new())),
160            bubbling_handlers: Arc::new(RwLock::new(HashMap::new())),
161            target_handlers: Arc::new(RwLock::new(HashMap::new())),
162            component_id,
163            parent: None,
164            children: Vec::new(),
165        }
166    }
167
168    /// Set the parent delegate for bubbling events
169    pub fn set_parent(&mut self, parent: Arc<Mutex<EventDelegate>>) {
170        self.parent = Some(parent);
171    }
172
173    /// Add a child delegate for capturing events
174    pub fn add_child(&mut self, child: Arc<Mutex<EventDelegate>>) {
175        self.children.push(child);
176    }
177
178    /// Register a handler for an event type in the capturing phase
179    pub fn capture<E: Event + 'static>(
180        &self,
181        handler: impl Fn(&E, &EventPropagation) + Send + Sync + 'static,
182    ) {
183        let type_id = TypeId::of::<E>();
184        let mut handlers = self.capturing_handlers.write().unwrap();
185
186        let boxed_handler: EventHandler = Box::new(move |e, prop| {
187            if let Some(event) = e.as_any().downcast_ref::<E>() {
188                handler(event, prop);
189            }
190        });
191
192        handlers.entry(type_id).or_default().push(boxed_handler);
193    }
194
195    /// Register a handler for an event type in the bubbling phase
196    pub fn bubble<E: Event + 'static>(
197        &self,
198        handler: impl Fn(&E, &EventPropagation) + Send + Sync + 'static,
199    ) {
200        let type_id = TypeId::of::<E>();
201        let mut handlers = self.bubbling_handlers.write().unwrap();
202
203        let boxed_handler: EventHandler = Box::new(move |e, prop| {
204            if let Some(event) = e.as_any().downcast_ref::<E>() {
205                handler(event, prop);
206            }
207        });
208
209        handlers.entry(type_id).or_default().push(boxed_handler);
210    }
211
212    /// Register a handler for an event type for this target only
213    pub fn on<E: Event + 'static>(
214        &self,
215        handler: impl Fn(&E, &EventPropagation) + Send + Sync + 'static,
216    ) {
217        let type_id = TypeId::of::<E>();
218        let mut handlers = self.target_handlers.write().unwrap();
219
220        let boxed_handler: EventHandler = Box::new(move |e, prop| {
221            if let Some(event) = e.as_any().downcast_ref::<E>() {
222                handler(event, prop);
223            }
224        });
225
226        handlers.entry(type_id).or_default().push(boxed_handler);
227    }
228
229    /// Dispatch an event starting from this delegate
230    pub fn dispatch<E: Event + 'static>(&self, event: &E, target_id: Option<usize>) {
231        // First, we do the capturing phase from the root down to the target
232        let mut propagation = EventPropagation {
233            stopped: false,
234            default_prevented: false,
235            phase: PropagationPhase::Capturing,
236            target_id,
237            current_target_id: self.component_id,
238        };
239
240        self.dispatch_capturing(event, &mut propagation, target_id);
241
242        // Next, we handle the target phase
243        if !propagation.is_propagation_stopped() && self.component_id == target_id {
244            propagation.phase = PropagationPhase::Target;
245            propagation.current_target_id = self.component_id;
246            self.handle_event(event, &propagation);
247        }
248
249        // Finally, we do the bubbling phase from the target up to the root
250        if !propagation.is_propagation_stopped() {
251            propagation.phase = PropagationPhase::Bubbling;
252            self.dispatch_bubbling(event, &mut propagation, target_id);
253        }
254    }
255
256    // Internal method to handle capturing phase
257    fn dispatch_capturing<E: Event + 'static>(
258        &self,
259        event: &E,
260        propagation: &mut EventPropagation,
261        target_id: Option<usize>,
262    ) {
263        // Handle this component's capturing handlers
264        if !propagation.is_propagation_stopped() {
265            propagation.current_target_id = self.component_id;
266            self.handle_capturing_event(event, propagation);
267        }
268
269        // If this is the target, stop capturing phase
270        if self.component_id == target_id {
271            return;
272        }
273
274        // Otherwise, continue capturing phase down to children
275        for child in &self.children {
276            if let Ok(child) = child.lock() {
277                if !propagation.is_propagation_stopped() {
278                    child.dispatch_capturing(event, propagation, target_id);
279                }
280            }
281        }
282    }
283
284    // Internal method to handle bubbling phase
285    fn dispatch_bubbling<E: Event + 'static>(
286        &self,
287        event: &E,
288        propagation: &mut EventPropagation,
289        _target_id: Option<usize>,
290    ) {
291        // Handle this component's bubbling handlers
292        if !propagation.is_propagation_stopped() {
293            propagation.current_target_id = self.component_id;
294            self.handle_bubbling_event(event, propagation);
295        }
296
297        // Continue bubbling up to parent
298        if !propagation.is_propagation_stopped() {
299            if let Some(parent) = &self.parent {
300                if let Ok(parent) = parent.lock() {
301                    parent.dispatch_bubbling(event, propagation, _target_id);
302                }
303            }
304        }
305    }
306
307    // Internal method to handle events during capturing phase
308    fn handle_capturing_event<E: Event + 'static>(
309        &self,
310        event: &E,
311        propagation: &EventPropagation,
312    ) {
313        let type_id = TypeId::of::<E>();
314        if let Ok(handlers) = self.capturing_handlers.read() {
315            if let Some(handlers) = handlers.get(&type_id) {
316                let mut boxed_event = event.box_clone();
317                for handler in handlers {
318                    handler(boxed_event.as_mut(), propagation);
319                    if propagation.is_propagation_stopped() {
320                        break;
321                    }
322                }
323            }
324        }
325    }
326
327    // Internal method to handle events during bubbling phase
328    fn handle_bubbling_event<E: Event + 'static>(&self, event: &E, propagation: &EventPropagation) {
329        let type_id = TypeId::of::<E>();
330        if let Ok(handlers) = self.bubbling_handlers.read() {
331            if let Some(handlers) = handlers.get(&type_id) {
332                let mut boxed_event = event.box_clone();
333                for handler in handlers {
334                    handler(boxed_event.as_mut(), propagation);
335                    if propagation.is_propagation_stopped() {
336                        break;
337                    }
338                }
339            }
340        }
341    }
342
343    // Internal method to handle events at the target
344    fn handle_event<E: Event + 'static>(&self, event: &E, propagation: &EventPropagation) {
345        let type_id = TypeId::of::<E>();
346        if let Ok(handlers) = self.target_handlers.read() {
347            if let Some(handlers) = handlers.get(&type_id) {
348                let mut boxed_event = event.box_clone();
349                for handler in handlers {
350                    handler(boxed_event.as_mut(), propagation);
351                    if propagation.is_propagation_stopped() {
352                        break;
353                    }
354                }
355            }
356        }
357    }
358}
359
360/// Helper to build an event delegation tree from a component tree
361pub fn build_delegation_tree(
362    node: &Node,
363    parent_delegate: Option<Arc<Mutex<EventDelegate>>>,
364) -> Arc<Mutex<EventDelegate>> {
365    let delegate = Arc::new(Mutex::new(EventDelegate::new(Some(node.id_value()))));
366
367    // Set parent relationship
368    if let Some(parent) = parent_delegate {
369        if let Ok(mut delegate_mut) = delegate.lock() {
370            delegate_mut.set_parent(parent.clone());
371        }
372
373        if let Ok(mut parent_mut) = parent.lock() {
374            parent_mut.add_child(delegate.clone());
375        }
376    }
377
378    // Build delegation tree for children
379    for child in node.children() {
380        let child_delegate = build_delegation_tree(child, Some(delegate.clone()));
381
382        if let Ok(mut delegate_mut) = delegate.lock() {
383            delegate_mut.add_child(child_delegate);
384        }
385    }
386
387    delegate
388}