Skip to main content

fui/node/
core.rs

1use super::*;
2use crate::drag_drop::{
3    DragCompletedEventArgs, DragDataObject, DragDropEffects, DragEventArgs, DropProposal,
4};
5use crate::drag_gesture::{DragCompletedEvent, DragGesture, DragStartedEvent};
6use crate::event::{PointerButton, SelectionChangedEventArgs, TextChangedEventArgs};
7use crate::external_drop::ExternalDropEventArgs;
8use crate::persisted::PersistedStateAdapter;
9use crate::tool_tip::ToolTip;
10use crate::transitions::NodeTransitions;
11
12pub(crate) type PointerCallback = Rc<dyn Fn(&mut PointerEventArgs)>;
13pub(crate) type WheelCallback = Rc<dyn Fn(&mut WheelEventArgs)>;
14pub(crate) type GestureCallback = Rc<dyn Fn(&mut GestureEventArgs)>;
15pub(crate) type KeyCallback = Rc<dyn Fn(&mut KeyEventArgs)>;
16pub(crate) type LongPressCallback = Rc<dyn Fn(&mut LongPressEventArgs)>;
17pub(crate) type FocusChangedCallback = Rc<dyn Fn(FocusChangedEventArgs)>;
18pub(crate) type TextChangedCallback = Rc<dyn Fn(TextChangedEventArgs)>;
19pub(crate) type TextReplacedCallback = Rc<dyn Fn(u32, u32, String)>;
20pub(crate) type ScrollChangedCallback = Rc<dyn Fn(f32, f32, f32, f32, f32, f32)>;
21pub(crate) type SelectionChangedCallback = Rc<dyn Fn(SelectionChangedEventArgs)>;
22pub(crate) type CrossSelectionChangedCallback = Rc<dyn Fn(String)>;
23pub(crate) type DrawCallback = Rc<dyn Fn(&mut DrawContext)>;
24pub(crate) type ContextMenuCallback = Rc<dyn Fn(ContextMenuEventArgs)>;
25pub(crate) type DragDataCallback = Rc<dyn Fn() -> Option<DragDataObject>>;
26pub(crate) type DragCompletedCallback = Rc<dyn Fn(DragCompletedEventArgs)>;
27pub(crate) type DragProposalCallback = Rc<dyn Fn(DragEventArgs) -> DropProposal>;
28pub(crate) type DragEventCallback = Rc<dyn Fn(DragEventArgs)>;
29pub(crate) type ExternalDragProposalCallback = Rc<dyn Fn(ExternalDropEventArgs) -> DropProposal>;
30pub(crate) type ExternalDragEventCallback = Rc<dyn Fn(ExternalDropEventArgs)>;
31pub(crate) type EffectiveEnabledChangedCallback = Rc<dyn Fn(bool)>;
32
33pub(crate) fn is_primary_activation_pointer(event: &PointerEventArgs) -> bool {
34    event.button == PointerButton::Primary
35        || event.pointer_type == PointerType::Touch
36        || event.pointer_type == PointerType::Pen
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
40pub struct NodeHandle(u64);
41
42impl NodeHandle {
43    pub const INVALID: Self = Self(HandleValue::Invalid as u64);
44
45    pub(crate) fn from_raw(raw: u64) -> Self {
46        Self(raw)
47    }
48
49    pub fn raw(self) -> u64 {
50        self.0
51    }
52}
53
54#[derive(Clone, Copy, Debug, PartialEq)]
55pub struct ContextMenuEventArgs {
56    pub target: NodeHandle,
57    pub x: f32,
58    pub y: f32,
59    pub host: crate::platform::HostContext,
60}
61
62#[derive(Clone, Copy, Debug, PartialEq, Eq)]
63pub(crate) enum NodeKind {
64    FlexBox,
65    Text,
66    Grid,
67    Image,
68    Svg,
69    ScrollView,
70}
71
72impl NodeKind {
73    pub(crate) fn node_type(self) -> NodeType {
74        match self {
75            Self::FlexBox => NodeType::FlexBox,
76            Self::Text => NodeType::Text,
77            Self::Grid => NodeType::Grid,
78            Self::Image => NodeType::Image,
79            Self::Svg => NodeType::Svg,
80            Self::ScrollView => NodeType::ScrollView,
81        }
82    }
83}
84
85#[derive(Clone, Default)]
86pub(crate) struct EventHandlers {
87    pub(crate) pointer_click: Option<PointerCallback>,
88    pub(crate) pointer_double_click: Option<PointerCallback>,
89    pub(crate) pointer_triple_click: Option<PointerCallback>,
90    pub(crate) pointer_down: Option<PointerCallback>,
91    pub(crate) pointer_move: Option<PointerCallback>,
92    pub(crate) pointer_up: Option<PointerCallback>,
93    pub(crate) pointer_enter: Option<PointerCallback>,
94    pub(crate) pointer_leave: Option<PointerCallback>,
95    pub(crate) pointer_cancel: Option<PointerCallback>,
96    pub(crate) wheel: Option<WheelCallback>,
97    pub(crate) pan_gesture: Option<GestureCallback>,
98    pub(crate) pinch_gesture: Option<GestureCallback>,
99    pub(crate) long_press: Option<LongPressCallback>,
100    pub(crate) long_press_minimum_duration_ms: i32,
101    pub(crate) long_press_movement_tolerance: f32,
102    pub(crate) key_down: Option<KeyCallback>,
103    pub(crate) key_up: Option<KeyCallback>,
104    pub(crate) focus_changed: Option<FocusChangedCallback>,
105    pub(crate) text_changed: Option<TextChangedCallback>,
106    pub(crate) text_replaced: Option<TextReplacedCallback>,
107    pub(crate) scroll_changed: Option<ScrollChangedCallback>,
108    pub(crate) selection_changed: Option<SelectionChangedCallback>,
109    pub(crate) cross_selection_changed: Option<CrossSelectionChangedCallback>,
110}
111
112impl EventHandlers {
113    pub(crate) fn new() -> Self {
114        Self {
115            long_press_minimum_duration_ms: DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS,
116            long_press_movement_tolerance: DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE,
117            ..Self::default()
118        }
119    }
120
121    fn has_pointer_click_handler(&self) -> bool {
122        self.pointer_click.is_some()
123            || self.pointer_double_click.is_some()
124            || self.pointer_triple_click.is_some()
125    }
126
127    fn dispatch_pointer_click(&self, event: &mut PointerEventArgs, click_count: i32) {
128        let click_count = click_count.max(1);
129        event.click_count = click_count;
130        if let Some(handler) = self.pointer_click.as_ref() {
131            handler(event);
132        }
133        if click_count == 2 {
134            if let Some(handler) = self.pointer_double_click.as_ref() {
135                handler(event);
136            }
137        } else if click_count == 3 {
138            if let Some(handler) = self.pointer_triple_click.as_ref() {
139                handler(event);
140            }
141        }
142    }
143}
144#[derive(Clone)]
145pub(crate) struct NodeBehavior {
146    pub(crate) enabled: bool,
147    pub(crate) inherited_enabled: bool,
148    pub(crate) last_effective_enabled: bool,
149    pub(crate) interactive: bool,
150    pub(crate) focusable: Option<(bool, i32)>,
151    pub(crate) cursor: Option<CursorStyle>,
152    pub(crate) node_id: Option<String>,
153    pub(crate) semantic_role: Option<SemanticRole>,
154    pub(crate) semantic_label: Option<String>,
155    pub(crate) default_semantic_label: Option<String>,
156    pub(crate) semantic_disabled: Option<bool>,
157    pub(crate) semantic_checked: Option<SemanticCheckedState>,
158    pub(crate) semantic_selected: Option<bool>,
159    pub(crate) semantic_expanded: Option<bool>,
160    pub(crate) semantic_value_range: Option<(f32, f32, f32)>,
161    pub(crate) semantic_orientation: Option<Orientation>,
162    pub(crate) selectable_text: bool,
163    pub(crate) editable_text: bool,
164    pub(crate) text_content: Option<String>,
165    pub(crate) text_selection_range_bytes: Option<Rc<dyn Fn() -> (u32, u32)>>,
166    pub(crate) text_input_editor: Option<Weak<RefCell<NodeCore>>>,
167    pub(crate) link_url: Option<String>,
168    pub(crate) image_url: Option<String>,
169    pub(crate) link_preview_pin: Option<Rc<dyn Fn()>>,
170    pub(crate) link_preview_release: Option<Rc<dyn Fn()>>,
171    pub(crate) context_menu_disabled: bool,
172    pub(crate) context_menu_handler: Option<ContextMenuCallback>,
173    pub(crate) tool_tip: Option<ToolTip>,
174    pub(crate) track_semantic_disabled_from_enabled: bool,
175    pub(crate) visibility: Option<Visibility>,
176    pub(crate) is_portal: bool,
177    pub(crate) fill_width: bool,
178    pub(crate) fill_height: bool,
179    pub(crate) fill_width_percent: Option<f32>,
180    pub(crate) fill_height_percent: Option<f32>,
181    pub(crate) min_width: Option<(f32, Unit)>,
182    pub(crate) max_width: Option<(f32, Unit)>,
183    pub(crate) min_height: Option<(f32, Unit)>,
184    pub(crate) max_height: Option<(f32, Unit)>,
185    pub(crate) flex_basis: Option<f32>,
186    pub(crate) justify_content: Option<JustifyContent>,
187    pub(crate) align_items: Option<AlignItems>,
188    pub(crate) align_self: Option<AlignSelf>,
189    pub(crate) margin: Option<(f32, f32, f32, f32)>,
190    pub(crate) position_type: Option<PositionType>,
191    pub(crate) position: Option<(f32, f32, f32, f32)>,
192    pub(crate) is_shared_size_scope: bool,
193    pub(crate) custom_drawable: bool,
194    pub(crate) flex_wrap: Option<FlexWrap>,
195    pub(crate) clip_to_bounds: Option<bool>,
196    pub(crate) selection_area: bool,
197    pub(crate) selection_area_barrier: bool,
198    pub(crate) preserve_selection_on_pointer_down: bool,
199    pub(crate) scroll_proxy_target: Option<u64>,
200    pub(crate) external_drop_allowed: bool,
201}
202
203impl Default for NodeBehavior {
204    fn default() -> Self {
205        Self {
206            enabled: true,
207            inherited_enabled: true,
208            last_effective_enabled: true,
209            interactive: false,
210            focusable: None,
211            cursor: None,
212            node_id: None,
213            semantic_role: None,
214            semantic_label: None,
215            default_semantic_label: None,
216            semantic_disabled: None,
217            semantic_checked: None,
218            semantic_selected: None,
219            semantic_expanded: None,
220            semantic_value_range: None,
221            semantic_orientation: None,
222            selectable_text: false,
223            editable_text: false,
224            text_content: None,
225            text_selection_range_bytes: None,
226            text_input_editor: None,
227            link_url: None,
228            image_url: None,
229            link_preview_pin: None,
230            link_preview_release: None,
231            context_menu_disabled: false,
232            context_menu_handler: None,
233            tool_tip: None,
234            track_semantic_disabled_from_enabled: false,
235            visibility: None,
236            is_portal: false,
237            fill_width: false,
238            fill_height: false,
239            fill_width_percent: None,
240            fill_height_percent: None,
241            min_width: None,
242            max_width: None,
243            min_height: None,
244            max_height: None,
245            flex_basis: None,
246            justify_content: None,
247            align_items: None,
248            align_self: None,
249            margin: None,
250            position_type: None,
251            position: None,
252            is_shared_size_scope: false,
253            custom_drawable: false,
254            flex_wrap: None,
255            clip_to_bounds: None,
256            selection_area: false,
257            selection_area_barrier: false,
258            preserve_selection_on_pointer_down: false,
259            scroll_proxy_target: None,
260            external_drop_allowed: false,
261        }
262    }
263}
264
265#[derive(Clone, Copy)]
266pub(crate) struct BoxStyle {
267    pub(crate) radius_tl: f32,
268    pub(crate) radius_tr: f32,
269    pub(crate) radius_br: f32,
270    pub(crate) radius_bl: f32,
271    pub(crate) border_width: f32,
272    pub(crate) border_color: u32,
273    pub(crate) border_style: BorderStyle,
274    pub(crate) border_dash_on: f32,
275    pub(crate) border_dash_off: f32,
276}
277
278#[derive(Clone, Copy)]
279pub(crate) struct DropShadow {
280    pub(crate) color: u32,
281    pub(crate) offset_x: f32,
282    pub(crate) offset_y: f32,
283    pub(crate) blur_sigma: f32,
284    pub(crate) spread: f32,
285}
286#[derive(Clone)]
287pub(crate) struct LinearGradient {
288    pub(crate) sx: f32,
289    pub(crate) sy: f32,
290    pub(crate) ex: f32,
291    pub(crate) ey: f32,
292    pub(crate) offsets: Vec<f32>,
293    pub(crate) colors: Vec<u32>,
294}
295#[derive(Clone, Default)]
296pub(crate) struct FlexBoxProps {
297    pub(crate) width: Option<(f32, Unit)>,
298    pub(crate) height: Option<(f32, Unit)>,
299    pub(crate) min_width: Option<(f32, Unit)>,
300    pub(crate) max_width: Option<(f32, Unit)>,
301    pub(crate) min_height: Option<(f32, Unit)>,
302    pub(crate) max_height: Option<(f32, Unit)>,
303    pub(crate) bg_color: Option<u32>,
304    pub(crate) padding: Option<(f32, f32, f32, f32)>,
305    pub(crate) flex_direction: Option<FlexDirection>,
306    pub(crate) box_style: Option<BoxStyle>,
307    pub(crate) opacity: Option<f32>,
308    pub(crate) blur_sigma: Option<f32>,
309    pub(crate) drop_shadow: Option<DropShadow>,
310    pub(crate) background_blur_sigma: Option<f32>,
311    pub(crate) linear_gradient: Option<LinearGradient>,
312    pub(crate) transitions: Option<NodeTransitions>,
313}
314
315#[derive(Clone, Default)]
316pub(crate) struct TextProps {
317    pub(crate) content: String,
318    pub(crate) width: Option<(f32, Unit)>,
319    pub(crate) height: Option<(f32, Unit)>,
320    pub(crate) min_width: Option<(f32, Unit)>,
321    pub(crate) max_width: Option<(f32, Unit)>,
322    pub(crate) min_height: Option<(f32, Unit)>,
323    pub(crate) max_height: Option<(f32, Unit)>,
324    pub(crate) font_id: u32,
325    pub(crate) font_size: f32,
326    pub(crate) has_font: bool,
327    pub(crate) font_family: Option<FontFamily>,
328    pub(crate) font_weight: FontWeight,
329    pub(crate) font_style: FontStyle,
330    pub(crate) uses_direct_font_id: bool,
331    pub(crate) text_color: Option<u32>,
332    pub(crate) style_runs: Vec<u32>,
333    pub(crate) has_style_runs: bool,
334    pub(crate) line_height: Option<f32>,
335    pub(crate) text_align: Option<TextAlign>,
336    pub(crate) text_vertical_align: Option<TextVerticalAlign>,
337    pub(crate) text_limits: Option<(i32, i32)>,
338    pub(crate) wrapping: Option<bool>,
339    pub(crate) overflow: Option<TextOverflow>,
340    pub(crate) overflow_fade: Option<(bool, bool)>,
341    pub(crate) selectable: Option<(bool, u32)>,
342    pub(crate) uses_theme_selection_color: bool,
343    pub(crate) editable: Option<bool>,
344    pub(crate) editor_command_keys: Option<bool>,
345    pub(crate) editor_accepts_tab: Option<bool>,
346    pub(crate) obscured: Option<bool>,
347    pub(crate) caret_color: Option<u32>,
348    pub(crate) selection_range_bytes: Option<(u32, u32)>,
349    pub(crate) selection_start: u32,
350    pub(crate) selection_end: u32,
351}
352
353#[derive(Clone, Default)]
354pub(crate) struct GridProps {
355    pub(crate) columns: Vec<f32>,
356    pub(crate) column_types: Vec<GridUnit>,
357    pub(crate) rows: Vec<f32>,
358    pub(crate) row_types: Vec<GridUnit>,
359    pub(crate) column_shared_size_groups: Vec<(u32, String)>,
360    pub(crate) row_shared_size_groups: Vec<(u32, String)>,
361}
362#[derive(Clone)]
363pub(crate) struct ImageProps {
364    pub(crate) texture_id: u32,
365    pub(crate) source_url: Option<String>,
366    pub(crate) object_fit: ObjectFit,
367    pub(crate) sampling_kind: ImageSamplingKind,
368    pub(crate) max_aniso: u32,
369    pub(crate) image_nine: Option<(f32, f32, f32, f32)>,
370}
371
372#[derive(Clone)]
373pub(crate) struct SvgProps {
374    pub(crate) svg_id: u32,
375    pub(crate) source_url: Option<String>,
376    pub(crate) tint_color: u32,
377    pub(crate) sampling_kind: ImageSamplingKind,
378    pub(crate) max_aniso: u32,
379}
380
381#[derive(Clone)]
382pub(crate) struct ScrollViewProps {
383    pub(crate) width: Option<(f32, Unit)>,
384    pub(crate) height: Option<(f32, Unit)>,
385    pub(crate) enable_scroll_x: bool,
386    pub(crate) enable_scroll_y: bool,
387    pub(crate) friction: Option<f32>,
388    pub(crate) smooth_scrolling: bool,
389    pub(crate) scroll_offset: Option<(f32, f32)>,
390    pub(crate) content_size: Option<(f32, f32)>,
391    pub(crate) persist_scroll: bool,
392    pub(crate) transitions: Option<NodeTransitions>,
393}
394
395#[derive(Clone, Copy, Debug, Default)]
396pub(crate) struct ScrollRoutingState {
397    pub(crate) enabled_x: bool,
398    pub(crate) enabled_y: bool,
399    pub(crate) offset_x: f32,
400    pub(crate) offset_y: f32,
401    pub(crate) content_width: f32,
402    pub(crate) content_height: f32,
403    pub(crate) viewport_width: f32,
404    pub(crate) viewport_height: f32,
405}
406
407#[derive(Clone, Copy, Debug, PartialEq, Eq)]
408pub(crate) struct GridPlacement {
409    pub(crate) row: u32,
410    pub(crate) col: u32,
411    pub(crate) row_span: u32,
412    pub(crate) col_span: u32,
413}
414
415pub(crate) struct NodeCore {
416    pub(crate) handle: NodeHandle,
417    pub(crate) kind: NodeKind,
418    pub(crate) parent: Weak<RefCell<NodeCore>>,
419    pub(crate) children: Vec<NodeRef>,
420    pub(crate) mounted: bool,
421    pub(crate) children_built: bool,
422    pub(crate) behavior: NodeBehavior,
423    pub(crate) handlers: EventHandlers,
424    pub(crate) draw_callback: Option<DrawCallback>,
425    pub(crate) retained_attachments: Vec<Rc<dyn Any>>,
426    pub(crate) persisted_state_adapters: Vec<Rc<dyn PersistedStateAdapter>>,
427    pub(crate) drag_data_callback: Option<DragDataCallback>,
428    pub(crate) drag_allowed_effects: DragDropEffects,
429    pub(crate) drag_completed_callback: Option<DragCompletedCallback>,
430    pub(crate) drop_allowed: bool,
431    pub(crate) drag_enter_callback: Option<DragProposalCallback>,
432    pub(crate) drag_over_callback: Option<DragProposalCallback>,
433    pub(crate) drag_leave_callback: Option<DragEventCallback>,
434    pub(crate) drop_callback: Option<DragEventCallback>,
435    pub(crate) external_drag_enter_callback: Option<ExternalDragProposalCallback>,
436    pub(crate) external_drag_over_callback: Option<ExternalDragProposalCallback>,
437    pub(crate) external_drag_leave_callback: Option<ExternalDragEventCallback>,
438    pub(crate) external_drop_callback: Option<ExternalDragEventCallback>,
439    pub(crate) drag_gesture: Option<Rc<RefCell<DragGesture>>>,
440    pub(crate) drag_click_pending: bool,
441    pub(crate) drag_click_pending_count: i32,
442    pub(crate) click_pending: bool,
443    pub(crate) click_pending_count: i32,
444    pub(crate) scroll_routing: Option<ScrollRoutingState>,
445    pub(crate) effective_enabled_changed_callbacks: Vec<EffectiveEnabledChangedCallback>,
446}
447
448impl NodeCore {
449    pub(crate) fn new(kind: NodeKind) -> Self {
450        Self {
451            handle: NodeHandle::INVALID,
452            kind,
453            parent: Weak::new(),
454            children: Vec::new(),
455            mounted: false,
456            children_built: false,
457            behavior: NodeBehavior::default(),
458            handlers: EventHandlers::new(),
459            draw_callback: None,
460            retained_attachments: Vec::new(),
461            persisted_state_adapters: Vec::new(),
462            drag_data_callback: None,
463            drag_allowed_effects: DragDropEffects::Copy,
464            drag_completed_callback: None,
465            drop_allowed: false,
466            drag_enter_callback: None,
467            drag_over_callback: None,
468            drag_leave_callback: None,
469            drop_callback: None,
470            external_drag_enter_callback: None,
471            external_drag_over_callback: None,
472            external_drag_leave_callback: None,
473            external_drop_callback: None,
474            drag_gesture: None,
475            drag_click_pending: false,
476            drag_click_pending_count: 0,
477            click_pending: false,
478            click_pending_count: 0,
479            scroll_routing: None,
480            effective_enabled_changed_callbacks: Vec::new(),
481        }
482    }
483}
484
485#[derive(Clone)]
486#[doc(hidden)]
487pub struct NodeRef {
488    inner: Rc<RefCell<NodeCore>>,
489    build_callback: Option<Rc<dyn Fn()>>,
490}
491
492#[derive(Clone)]
493pub(crate) struct WeakNodeRef {
494    inner: Weak<RefCell<NodeCore>>,
495}
496
497impl WeakNodeRef {
498    pub(crate) fn upgrade(&self) -> Option<NodeRef> {
499        self.inner.upgrade().map(NodeRef::from_core)
500    }
501}
502
503#[derive(Clone)]
504pub(crate) struct WeakFlexBox {
505    pub(crate) core: Weak<RefCell<NodeCore>>,
506    pub(crate) props: Weak<RefCell<FlexBoxProps>>,
507    pub(crate) active_animations: Weak<RefCell<crate::node::flex_box::FlexBoxAnimations>>,
508    pub(crate) host_style_layers: Weak<RefCell<crate::node::HostStyleLayers>>,
509}
510
511impl WeakFlexBox {
512    pub(crate) fn upgrade(&self) -> Option<FlexBox> {
513        Some(FlexBox {
514            core: self.core.upgrade()?,
515            props: self.props.upgrade()?,
516            active_animations: self.active_animations.upgrade()?,
517            host_style_layers: self.host_style_layers.upgrade()?,
518        })
519    }
520}
521
522impl NodeRef {
523    pub(crate) fn set_shared_size_scope(&self, enabled: bool) {
524        let handle = {
525            let mut core = self.inner.borrow_mut();
526            core.behavior.is_shared_size_scope = enabled;
527            core.handle
528        };
529        if handle != NodeHandle::INVALID {
530            ui::set_is_shared_size_scope(handle.raw(), enabled);
531            crate::frame_scheduler::mark_needs_commit();
532        }
533    }
534
535    pub(crate) fn from_core(inner: Rc<RefCell<NodeCore>>) -> Self {
536        Self {
537            inner,
538            build_callback: None,
539        }
540    }
541
542    pub(crate) fn from_node<T: Node + 'static>(inner: Rc<RefCell<NodeCore>>, node: T) -> Self {
543        Self {
544            inner,
545            build_callback: Some(Rc::new(move || node.build())),
546        }
547    }
548
549    pub(crate) fn with_build_callback(mut self, callback: impl Fn() + 'static) -> Self {
550        self.build_callback = Some(Rc::new(callback));
551        self
552    }
553
554    pub(crate) fn handle(&self) -> NodeHandle {
555        self.inner.borrow().handle
556    }
557
558    pub(crate) fn set_semantic_checked(&self, state: SemanticCheckedState, announce: bool) {
559        let handle = {
560            let mut core = self.inner.borrow_mut();
561            core.behavior.semantic_checked = Some(state);
562            core.handle
563        };
564        if handle == NodeHandle::INVALID {
565            return;
566        }
567        ui::set_semantic_checked(handle.raw(), state as u32);
568        if announce {
569            ui::request_semantic_announcement(handle.raw());
570        }
571        crate::frame_scheduler::mark_needs_commit();
572    }
573
574    pub(crate) fn ptr_eq(&self, other: &Self) -> bool {
575        Rc::ptr_eq(&self.inner, &other.inner)
576    }
577
578    pub(crate) fn parent(&self) -> Option<Self> {
579        self.inner.borrow().parent.upgrade().map(Self::from_core)
580    }
581
582    pub(crate) fn node_type(&self) -> NodeType {
583        self.inner.borrow().kind.node_type()
584    }
585
586    pub(crate) fn children(&self) -> Vec<Self> {
587        self.inner.borrow().children.clone()
588    }
589
590    pub(crate) fn append_child_ref(&self, child: &NodeRef) {
591        if Rc::ptr_eq(&self.inner, &child.inner) {
592            return;
593        }
594        if self
595            .inner
596            .borrow()
597            .children
598            .iter()
599            .any(|candidate| Rc::ptr_eq(&candidate.inner, &child.inner))
600        {
601            return;
602        }
603        if let Some(previous_parent) = child.inner.borrow().parent.upgrade() {
604            if Rc::ptr_eq(&previous_parent, &self.inner) {
605                return;
606            }
607            let child_handle = child.handle();
608            {
609                let mut previous_parent_core = previous_parent.borrow_mut();
610                previous_parent_core
611                    .children
612                    .retain(|candidate| !Rc::ptr_eq(&candidate.inner, &child.inner));
613            }
614            if previous_parent.borrow().handle != NodeHandle::INVALID
615                && child_handle != NodeHandle::INVALID
616            {
617                ui::remove_child(previous_parent.borrow().handle.raw(), child_handle.raw());
618            }
619        }
620
621        child.inner.borrow_mut().parent = Rc::downgrade(&self.inner);
622        self.inner.borrow_mut().children.push(child.clone());
623        self.inner.borrow_mut().children_built = false;
624        child.set_inherited_enabled(self.is_enabled_for_routing());
625        child.refresh_effective_visibility();
626        if self.handle() != NodeHandle::INVALID {
627            child.build();
628            ui::add_child(self.handle().raw(), child.handle().raw());
629            self.inner.borrow_mut().children_built = true;
630            crate::frame_scheduler::mark_needs_commit();
631        }
632    }
633
634    pub(crate) fn dispose(&self) {
635        let children = self.inner.borrow().children.clone();
636        for child in children {
637            if child.handle() != NodeHandle::INVALID && self.handle() != NodeHandle::INVALID {
638                ui::remove_child(self.handle().raw(), child.handle().raw());
639            }
640            child.dispose();
641        }
642        let handle = self.handle();
643        if handle != NodeHandle::INVALID {
644            crate::focus_adorner::handle_owner_destroyed(handle);
645            crate::tool_tip_manager::ToolTipManager::handle_owner_destroyed(handle);
646            crate::event::unregister_node(handle);
647            ui::delete_node(handle.raw());
648        }
649        {
650            let mut core = self.inner.borrow_mut();
651            core.handle = NodeHandle::INVALID;
652            core.mounted = false;
653            core.children_built = false;
654        }
655    }
656
657    pub(crate) fn detach_from_parent(&self) {
658        let Some(parent) = self.parent() else {
659            return;
660        };
661        let removed = {
662            let mut core = parent.inner.borrow_mut();
663            let Some(index) = core
664                .children
665                .iter()
666                .position(|candidate| Rc::ptr_eq(&candidate.inner, &self.inner))
667            else {
668                return;
669            };
670            core.children.remove(index)
671        };
672        removed.inner.borrow_mut().parent = Weak::new();
673        removed.set_inherited_enabled(true);
674        removed.refresh_effective_visibility();
675        parent.inner.borrow_mut().children_built = false;
676        if parent.handle() != NodeHandle::INVALID && self.handle() != NodeHandle::INVALID {
677            ui::remove_child(parent.handle().raw(), self.handle().raw());
678            parent.inner.borrow_mut().children_built = true;
679            crate::frame_scheduler::mark_needs_commit();
680        }
681    }
682
683    pub(crate) fn is_visible_for_routing(&self) -> bool {
684        !matches!(
685            self.inner.borrow().behavior.visibility,
686            Some(Visibility::Hidden | Visibility::Collapsed)
687        )
688    }
689
690    pub(crate) fn is_effectively_visible_for_routing(&self) -> bool {
691        self.effective_visibility_for_routing() == Visibility::Normal
692    }
693
694    fn effective_visibility_for_routing(&self) -> Visibility {
695        let mut result = Visibility::Normal;
696        let mut node = Some(self.clone());
697        while let Some(current) = node {
698            match current
699                .inner
700                .borrow()
701                .behavior
702                .visibility
703                .unwrap_or(Visibility::Normal)
704            {
705                Visibility::Collapsed => return Visibility::Collapsed,
706                Visibility::Hidden => result = Visibility::Hidden,
707                Visibility::Normal => {}
708            }
709            node = current.parent();
710        }
711        result
712    }
713
714    pub(crate) fn is_enabled_for_routing(&self) -> bool {
715        let behavior = &self.inner.borrow().behavior;
716        behavior.enabled && behavior.inherited_enabled
717    }
718
719    pub(crate) fn is_effectively_enabled_for_routing(&self) -> bool {
720        let mut node = Some(self.clone());
721        while let Some(current) = node {
722            if !current.is_enabled_for_routing() {
723                return false;
724            }
725            node = current.parent();
726        }
727        true
728    }
729
730    pub(crate) fn set_own_enabled(&self, enabled: bool) {
731        {
732            let mut core = self.inner.borrow_mut();
733            if core.behavior.enabled == enabled {
734                return;
735            }
736            core.behavior.enabled = enabled;
737        }
738        self.apply_enabled_changed();
739    }
740
741    pub(crate) fn set_own_visibility(&self, visibility: Visibility) {
742        {
743            let mut core = self.inner.borrow_mut();
744            if core.behavior.visibility == Some(visibility) {
745                return;
746            }
747            core.behavior.visibility = Some(visibility);
748        }
749        if visibility != Visibility::Normal {
750            self.cancel_drag_state();
751        }
752        self.refresh_effective_visibility();
753    }
754
755    pub(crate) fn set_inherited_enabled(&self, enabled: bool) {
756        {
757            let mut core = self.inner.borrow_mut();
758            if core.behavior.inherited_enabled == enabled {
759                return;
760            }
761            core.behavior.inherited_enabled = enabled;
762        }
763        self.apply_enabled_changed();
764    }
765
766    pub(crate) fn on_effective_enabled_changed(&self, handler: EffectiveEnabledChangedCallback) {
767        self.inner
768            .borrow_mut()
769            .effective_enabled_changed_callbacks
770            .push(handler);
771    }
772
773    fn apply_enabled_changed(&self) {
774        let effectively_visible = self.is_effectively_visible_for_routing();
775        let (
776            effective,
777            handle,
778            interactive,
779            focusable,
780            visible,
781            track_semantic_disabled,
782            callbacks,
783            children,
784        ) = {
785            let mut core = self.inner.borrow_mut();
786            let effective = core.behavior.enabled && core.behavior.inherited_enabled;
787            if core.behavior.last_effective_enabled == effective {
788                return;
789            }
790            core.behavior.last_effective_enabled = effective;
791            (
792                effective,
793                core.handle,
794                core.behavior.interactive,
795                core.behavior.focusable,
796                effectively_visible,
797                core.behavior.track_semantic_disabled_from_enabled,
798                core.effective_enabled_changed_callbacks.clone(),
799                core.children.clone(),
800            )
801        };
802
803        if handle != NodeHandle::INVALID {
804            ui::set_interactive(handle.raw(), effective && visible && interactive);
805            if let Some((focusable, tab_index)) = focusable {
806                ui::set_focusable(handle.raw(), effective && visible && focusable, tab_index);
807            }
808            if track_semantic_disabled {
809                ui::set_semantic_disabled(handle.raw(), true, !effective);
810            }
811            crate::frame_scheduler::mark_needs_commit();
812        }
813
814        for callback in callbacks {
815            callback(effective);
816        }
817        if !effective {
818            self.cancel_drag_state();
819        }
820        for child in children {
821            child.set_inherited_enabled(effective);
822        }
823    }
824
825    pub(crate) fn semantic_role_for_routing(&self) -> Option<SemanticRole> {
826        self.inner.borrow().behavior.semantic_role
827    }
828
829    pub(crate) fn cursor_style_for_routing(&self) -> CursorStyle {
830        self.inner
831            .borrow()
832            .behavior
833            .cursor
834            .unwrap_or(CursorStyle::Default)
835    }
836
837    fn refresh_effective_visibility(&self) {
838        let effective_visibility = self.effective_visibility_for_routing();
839        let effective_visible = effective_visibility == Visibility::Normal;
840        let (handle, visibility, enabled, interactive, focusable, children) = {
841            let core = self.inner.borrow();
842            (
843                core.handle,
844                effective_visibility,
845                core.behavior.enabled && core.behavior.inherited_enabled,
846                core.behavior.interactive,
847                core.behavior.focusable,
848                core.children.clone(),
849            )
850        };
851        if handle != NodeHandle::INVALID {
852            ui::set_visibility(handle.raw(), visibility as u32);
853            ui::set_interactive(handle.raw(), enabled && effective_visible && interactive);
854            if let Some((focusable, tab_index)) = focusable {
855                ui::set_focusable(
856                    handle.raw(),
857                    enabled && effective_visible && focusable,
858                    tab_index,
859                );
860            }
861            crate::frame_scheduler::mark_needs_commit();
862        }
863        for child in children {
864            child.refresh_effective_visibility();
865        }
866    }
867
868    pub(crate) fn require_interactive(&self) {
869        let visible = self.is_effectively_visible_for_routing();
870        let (handle, enabled, visible, changed) = {
871            let mut inner = self.inner.borrow_mut();
872            let changed = !inner.behavior.interactive;
873            inner.behavior.interactive = true;
874            (
875                inner.handle,
876                inner.behavior.enabled && inner.behavior.inherited_enabled,
877                visible,
878                changed,
879            )
880        };
881        if handle != NodeHandle::INVALID {
882            ui::set_interactive(handle.raw(), enabled && visible);
883            if changed {
884                crate::frame_scheduler::mark_needs_commit();
885            }
886        }
887    }
888
889    pub(crate) fn is_selectable_text_for_routing(&self) -> bool {
890        self.inner.borrow().behavior.selectable_text
891    }
892
893    pub(crate) fn is_editable_text_for_routing(&self) -> bool {
894        self.inner.borrow().behavior.editable_text
895    }
896
897    pub(crate) fn preserves_selection_on_pointer_down_for_routing(&self) -> bool {
898        self.inner
899            .borrow()
900            .behavior
901            .preserve_selection_on_pointer_down
902    }
903
904    pub(crate) fn link_url_for_routing(&self) -> Option<String> {
905        self.inner.borrow().behavior.link_url.clone()
906    }
907
908    pub(crate) fn image_url_for_routing(&self) -> Option<String> {
909        self.inner.borrow().behavior.image_url.clone()
910    }
911
912    pub(crate) fn is_image_or_svg_for_routing(&self) -> bool {
913        matches!(self.inner.borrow().kind, NodeKind::Image | NodeKind::Svg)
914    }
915
916    pub(crate) fn text_content_for_routing(&self) -> Option<String> {
917        self.inner.borrow().behavior.text_content.clone()
918    }
919
920    pub(crate) fn text_selection_range_bytes_for_routing(&self) -> Option<(u32, u32)> {
921        let read_range = self
922            .inner
923            .borrow()
924            .behavior
925            .text_selection_range_bytes
926            .clone();
927        read_range.map(|read_range| read_range())
928    }
929
930    pub(crate) fn text_input_editor_for_routing(&self) -> Option<NodeRef> {
931        self.inner
932            .borrow()
933            .behavior
934            .text_input_editor
935            .as_ref()
936            .and_then(Weak::upgrade)
937            .map(NodeRef::from_core)
938    }
939
940    pub(crate) fn set_text_input_editor_for_routing(&self, editor: &NodeRef) {
941        self.inner.borrow_mut().behavior.text_input_editor = Some(Rc::downgrade(&editor.inner));
942    }
943
944    pub(crate) fn set_link_url_for_routing(&self, value: Option<String>) {
945        self.inner.borrow_mut().behavior.link_url = value;
946    }
947
948    pub(crate) fn set_text_content_for_routing(&self, value: Option<String>) {
949        self.inner.borrow_mut().behavior.text_content = value;
950    }
951
952    pub(crate) fn set_semantic_label_for_routing(&self, value: Option<String>) {
953        self.inner.borrow_mut().behavior.semantic_label = value;
954    }
955
956    pub(crate) fn set_image_url_for_routing(&self, value: Option<String>) {
957        self.inner.borrow_mut().behavior.image_url = value;
958    }
959
960    pub(crate) fn set_link_preview_handlers_for_routing(
961        &self,
962        pin: Option<Rc<dyn Fn()>>,
963        release: Option<Rc<dyn Fn()>>,
964    ) {
965        let mut inner = self.inner.borrow_mut();
966        inner.behavior.link_preview_pin = pin;
967        inner.behavior.link_preview_release = release;
968    }
969
970    pub(crate) fn pin_link_preview_for_routing(&self) {
971        let callback = self.inner.borrow().behavior.link_preview_pin.clone();
972        if let Some(callback) = callback {
973            callback();
974        }
975    }
976
977    pub(crate) fn release_link_preview_for_routing(&self) {
978        let callback = self.inner.borrow().behavior.link_preview_release.clone();
979        if let Some(callback) = callback {
980            callback();
981        }
982    }
983
984    pub(crate) fn is_context_menu_disabled_for_routing(&self) -> bool {
985        self.inner.borrow().behavior.context_menu_disabled
986    }
987
988    pub(crate) fn context_menu_handler_for_routing(&self) -> Option<ContextMenuCallback> {
989        self.inner.borrow().behavior.context_menu_handler.clone()
990    }
991
992    pub(crate) fn tool_tip_for_routing(&self) -> Option<ToolTip> {
993        self.inner.borrow().behavior.tool_tip.clone()
994    }
995
996    pub(crate) fn node_id(&self) -> Option<String> {
997        self.inner.borrow().behavior.node_id.clone()
998    }
999
1000    pub(crate) fn gesture_intent_for_routing(&self) -> crate::event::GestureIntent {
1001        let handlers = &self.inner.borrow().handlers;
1002        crate::event::GestureIntent::from_callbacks(
1003            handlers.pan_gesture.is_some(),
1004            handlers.pinch_gesture.is_some(),
1005        )
1006    }
1007
1008    pub(crate) fn is_scroll_view_for_routing(&self) -> bool {
1009        self.inner.borrow().kind == NodeKind::ScrollView
1010    }
1011
1012    pub(crate) fn has_long_press_for_routing(&self) -> bool {
1013        self.inner.borrow().handlers.long_press.is_some() || self.has_drag_source()
1014    }
1015
1016    pub(crate) fn scroll_routing_state(&self) -> Option<ScrollRoutingState> {
1017        self.inner.borrow().scroll_routing
1018    }
1019
1020    pub(crate) fn set_scroll_routing_enabled(&self, enabled_x: bool, enabled_y: bool) {
1021        let mut inner = self.inner.borrow_mut();
1022        let state = inner.scroll_routing.get_or_insert(ScrollRoutingState {
1023            enabled_x,
1024            enabled_y,
1025            ..ScrollRoutingState::default()
1026        });
1027        state.enabled_x = enabled_x;
1028        state.enabled_y = enabled_y;
1029    }
1030
1031    pub(crate) fn set_scroll_routing_offsets(&self, offset_x: f32, offset_y: f32) {
1032        if let Some(state) = self.inner.borrow_mut().scroll_routing.as_mut() {
1033            state.offset_x = offset_x;
1034            state.offset_y = offset_y;
1035        }
1036    }
1037
1038    pub(crate) fn set_scroll_routing_metrics(
1039        &self,
1040        offset_x: f32,
1041        offset_y: f32,
1042        content_width: f32,
1043        content_height: f32,
1044        viewport_width: f32,
1045        viewport_height: f32,
1046    ) {
1047        if let Some(state) = self.inner.borrow_mut().scroll_routing.as_mut() {
1048            state.offset_x = offset_x;
1049            state.offset_y = offset_y;
1050            state.content_width = content_width;
1051            state.content_height = content_height;
1052            state.viewport_width = viewport_width;
1053            state.viewport_height = viewport_height;
1054        }
1055    }
1056
1057    pub(crate) fn absolute_to_local_position(&self, absolute_x: f32, absolute_y: f32) -> [f32; 2] {
1058        let bounds = if self.handle() == NodeHandle::INVALID {
1059            [0.0; 4]
1060        } else {
1061            ui::get_bounds(self.handle().raw()).unwrap_or([0.0; 4])
1062        };
1063        [absolute_x - bounds[0], absolute_y - bounds[1]]
1064    }
1065
1066    pub(crate) fn retain_attachment<T: Any>(&self, attachment: Rc<T>) {
1067        let retained: Rc<dyn Any> = attachment;
1068        self.inner.borrow_mut().retained_attachments.push(retained);
1069    }
1070
1071    pub(crate) fn set_node_id(&self, node_id: impl Into<String>) {
1072        let node_id = node_id.into();
1073        self.inner.borrow_mut().behavior.node_id = Some(node_id.clone());
1074        if self.handle() != NodeHandle::INVALID {
1075            ui::set_node_id(self.handle().raw(), &node_id);
1076        }
1077    }
1078
1079    pub(crate) fn bind_scroll_proxy_target_handle(&self, scroll_handle: u64) {
1080        self.inner.borrow_mut().behavior.scroll_proxy_target = Some(scroll_handle);
1081        if self.handle() != NodeHandle::INVALID {
1082            ui::set_scroll_proxy_target(self.handle().raw(), scroll_handle);
1083        }
1084    }
1085
1086    pub(crate) fn register_persisted_state_adapter(&self, adapter: Rc<dyn PersistedStateAdapter>) {
1087        let mut core = self.inner.borrow_mut();
1088        if let Some(index) = core
1089            .persisted_state_adapters
1090            .iter()
1091            .position(|existing| existing.kind() == adapter.kind())
1092        {
1093            core.persisted_state_adapters[index] = adapter;
1094            return;
1095        }
1096        core.persisted_state_adapters.push(adapter);
1097    }
1098
1099    pub(crate) fn capture_persisted_state_tree(&self) {
1100        self.capture_persisted_state();
1101        let children = self.inner.borrow().children.clone();
1102        for child in children {
1103            child.capture_persisted_state_tree();
1104        }
1105    }
1106
1107    pub(crate) fn restore_persisted_state_tree(&self) {
1108        let children = self.inner.borrow().children.clone();
1109        for child in children {
1110            child.restore_persisted_state_tree();
1111        }
1112        self.restore_persisted_state();
1113    }
1114
1115    fn capture_persisted_state(&self) {
1116        let (node_id, adapters) = {
1117            let core = self.inner.borrow();
1118            (
1119                core.behavior.node_id.clone(),
1120                core.persisted_state_adapters.clone(),
1121            )
1122        };
1123        let Some(node_id) = node_id else {
1124            return;
1125        };
1126        if node_id.is_empty() {
1127            return;
1128        }
1129        for adapter in adapters {
1130            let Some(payload) = adapter.capture() else {
1131                continue;
1132            };
1133            crate::persisted::store_text_state(
1134                &node_id,
1135                adapter.kind(),
1136                adapter.version(),
1137                &payload,
1138            );
1139        }
1140    }
1141
1142    fn restore_persisted_state(&self) {
1143        let (node_id, adapters) = {
1144            let core = self.inner.borrow();
1145            (
1146                core.behavior.node_id.clone(),
1147                core.persisted_state_adapters.clone(),
1148            )
1149        };
1150        let Some(node_id) = node_id else {
1151            return;
1152        };
1153        if node_id.is_empty() {
1154            return;
1155        }
1156        for adapter in adapters {
1157            let Some(persisted) = crate::persisted::try_load_text_state(&node_id, adapter.kind())
1158            else {
1159                continue;
1160            };
1161            adapter.restore(&persisted.payload, persisted.version);
1162        }
1163    }
1164
1165    pub(crate) fn long_press_minimum_duration_ms_for_routing(&self) -> i32 {
1166        self.inner.borrow().handlers.long_press_minimum_duration_ms
1167    }
1168
1169    pub(crate) fn long_press_movement_tolerance_for_routing(&self) -> f32 {
1170        self.inner.borrow().handlers.long_press_movement_tolerance
1171    }
1172
1173    pub(crate) fn handle_pointer_event(&self, event: &mut PointerEventArgs) {
1174        if !self.is_enabled_for_routing() {
1175            self.cancel_drag_state();
1176            return;
1177        }
1178        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1179        let handlers = {
1180            let core = self.inner.borrow();
1181            core.handlers.clone()
1182        };
1183        match event.event_type {
1184            crate::ffi::PointerEventType::Down => {
1185                crate::tool_tip_manager::ToolTipManager::handle_pointer_down(self);
1186                if let Some(handler) = handlers.pointer_down.as_ref() {
1187                    handler(event);
1188                }
1189                if event.handled {
1190                    return;
1191                }
1192                let drag_gesture = if self.has_drag_source() {
1193                    Some(self.ensure_drag_gesture())
1194                } else {
1195                    None
1196                };
1197                let is_primary_button = is_primary_activation_pointer(event);
1198                if let Some(drag_gesture) = drag_gesture {
1199                    if is_primary_button {
1200                        drag_gesture.borrow_mut().handle_pointer_down(
1201                            event.x,
1202                            event.y,
1203                            event.modifiers,
1204                            matches!(event.pointer_type, PointerType::Touch | PointerType::Pen),
1205                        );
1206                        let mut core = self.inner.borrow_mut();
1207                        core.drag_click_pending = handlers.has_pointer_click_handler();
1208                        core.drag_click_pending_count = event.click_count;
1209                        core.click_pending = false;
1210                        core.click_pending_count = 0;
1211                        event.handled = true;
1212                        return;
1213                    }
1214                }
1215                let mut core = self.inner.borrow_mut();
1216                core.drag_click_pending = false;
1217                core.drag_click_pending_count = 0;
1218                core.click_pending =
1219                    handlers.has_pointer_click_handler() && is_primary_activation_pointer(event);
1220                core.click_pending_count = event.click_count;
1221            }
1222            crate::ffi::PointerEventType::Move => {
1223                crate::tool_tip_manager::ToolTipManager::handle_pointer_move(
1224                    self,
1225                    event.scene_x,
1226                    event.scene_y,
1227                );
1228                if let Some(handler) = handlers.pointer_move {
1229                    handler(event);
1230                }
1231                if event.handled {
1232                    return;
1233                }
1234                let drag_gesture = self.inner.borrow().drag_gesture.clone();
1235                if let Some(drag_gesture) = drag_gesture {
1236                    let has_drag_source = self.has_drag_source();
1237                    let is_dragging = drag_gesture
1238                        .try_borrow()
1239                        .map(|gesture| gesture.is_dragging())
1240                        .unwrap_or(true);
1241                    if has_drag_source || is_dragging {
1242                        if let Ok(mut gesture) = drag_gesture.try_borrow_mut() {
1243                            gesture.handle_pointer_move(event.x, event.y, event.modifiers);
1244                        }
1245                    }
1246                }
1247            }
1248            crate::ffi::PointerEventType::Up => {
1249                if let Some(handler) = handlers.pointer_up.as_ref() {
1250                    handler(event);
1251                }
1252                if event.handled {
1253                    self.cancel_drag_state();
1254                    return;
1255                }
1256                let drag_gesture = self.inner.borrow().drag_gesture.clone();
1257                let has_drag_source = self.has_drag_source();
1258                let drag_gesture_is_dragging = drag_gesture
1259                    .as_ref()
1260                    .map(|gesture| {
1261                        gesture
1262                            .try_borrow()
1263                            .map(|gesture| gesture.is_dragging())
1264                            .unwrap_or(true)
1265                    })
1266                    .unwrap_or(false);
1267                let drag_gesture_active = drag_gesture
1268                    .as_ref()
1269                    .map(|_| has_drag_source || drag_gesture_is_dragging)
1270                    .unwrap_or(false);
1271                let (can_fire_pending_click, pending_click_count, can_fire_click, click_count) = {
1272                    let core = self.inner.borrow();
1273                    let can_fire_pending_click = core.drag_click_pending
1274                        && (!drag_gesture_active || !drag_gesture_is_dragging);
1275                    (
1276                        can_fire_pending_click,
1277                        core.drag_click_pending_count,
1278                        core.click_pending,
1279                        core.click_pending_count,
1280                    )
1281                };
1282                if let Some(drag_gesture) = drag_gesture.as_ref() {
1283                    if drag_gesture_active {
1284                        if let Ok(mut gesture) = drag_gesture.try_borrow_mut() {
1285                            gesture.handle_pointer_up(event.x, event.y, event.modifiers);
1286                        }
1287                    }
1288                }
1289                if can_fire_click {
1290                    handlers.dispatch_pointer_click(event, click_count);
1291                }
1292                self.clear_click_pending_state();
1293                if can_fire_pending_click {
1294                    handlers.dispatch_pointer_click(event, pending_click_count);
1295                }
1296                self.clear_drag_click_pending_state();
1297            }
1298            crate::ffi::PointerEventType::Enter => {
1299                if let Some(handler) = handlers.pointer_enter {
1300                    handler(event);
1301                }
1302                if !event.handled {
1303                    crate::tool_tip_manager::ToolTipManager::handle_pointer_enter(
1304                        self,
1305                        self.tool_tip_for_routing(),
1306                        event.scene_x,
1307                        event.scene_y,
1308                    );
1309                }
1310            }
1311            crate::ffi::PointerEventType::Leave => {
1312                self.clear_pending_pointer_state();
1313                if let Some(handler) = handlers.pointer_leave {
1314                    handler(event);
1315                }
1316                crate::tool_tip_manager::ToolTipManager::handle_pointer_leave(self);
1317            }
1318            crate::ffi::PointerEventType::Cancel => {
1319                self.cancel_drag_state();
1320                if let Some(handler) = handlers.pointer_cancel {
1321                    handler(event);
1322                }
1323                crate::tool_tip_manager::ToolTipManager::handle_pointer_leave(self);
1324            }
1325        }
1326    }
1327
1328    fn cancel_drag_state(&self) {
1329        let gesture = {
1330            let mut core = self.inner.borrow_mut();
1331            core.drag_click_pending = false;
1332            core.drag_click_pending_count = 0;
1333            core.click_pending = false;
1334            core.click_pending_count = 0;
1335            core.drag_gesture.clone()
1336        };
1337        if let Some(gesture) = gesture {
1338            gesture.borrow_mut().cancel();
1339        }
1340    }
1341
1342    fn clear_pending_pointer_state(&self) {
1343        let Ok(mut core) = self.inner.try_borrow_mut() else {
1344            return;
1345        };
1346        core.drag_click_pending = false;
1347        core.drag_click_pending_count = 0;
1348        core.click_pending = false;
1349        core.click_pending_count = 0;
1350    }
1351
1352    fn clear_click_pending_state(&self) {
1353        let Ok(mut core) = self.inner.try_borrow_mut() else {
1354            return;
1355        };
1356        core.click_pending = false;
1357        core.click_pending_count = 0;
1358    }
1359
1360    fn clear_drag_click_pending_state(&self) {
1361        let Ok(mut core) = self.inner.try_borrow_mut() else {
1362            return;
1363        };
1364        core.drag_click_pending = false;
1365        core.drag_click_pending_count = 0;
1366    }
1367
1368    pub(crate) fn handle_bubbled_pointer_event(&self, event: &mut PointerEventArgs) {
1369        self.handle_pointer_event(event);
1370    }
1371
1372    pub(crate) fn handle_wheel_event(&self, event: &mut WheelEventArgs) {
1373        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1374            return;
1375        }
1376        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1377        if let Some(handler) = self.inner.borrow().handlers.wheel.clone() {
1378            handler(event);
1379        }
1380    }
1381
1382    pub(crate) fn handle_key_event(&self, event: &mut KeyEventArgs) {
1383        if !self.is_enabled_for_routing() {
1384            return;
1385        }
1386        let handlers = self.inner.borrow().handlers.clone();
1387        match event.event_type {
1388            crate::ffi::KeyEventType::Down => {
1389                if let Some(handler) = handlers.key_down {
1390                    handler(event);
1391                }
1392            }
1393            crate::ffi::KeyEventType::Up => {
1394                if let Some(handler) = handlers.key_up {
1395                    handler(event);
1396                }
1397            }
1398        }
1399    }
1400
1401    pub(crate) fn handle_focus_changed(&self, event: FocusChangedEventArgs) {
1402        let handler = self.inner.borrow().handlers.focus_changed.clone();
1403        if let Some(handler) = handler {
1404            handler(event);
1405        }
1406        crate::tool_tip_manager::ToolTipManager::handle_focus_changed(
1407            self,
1408            self.tool_tip_for_routing(),
1409            event.focused,
1410        );
1411    }
1412
1413    pub(crate) fn handle_scroll_changed(
1414        &self,
1415        offset_x: f32,
1416        offset_y: f32,
1417        content_width: f32,
1418        content_height: f32,
1419        viewport_width: f32,
1420        viewport_height: f32,
1421    ) {
1422        self.set_scroll_routing_metrics(
1423            offset_x,
1424            offset_y,
1425            content_width,
1426            content_height,
1427            viewport_width,
1428            viewport_height,
1429        );
1430        let handler = self.inner.borrow().handlers.scroll_changed.clone();
1431        if let Some(handler) = handler {
1432            handler(
1433                offset_x,
1434                offset_y,
1435                content_width,
1436                content_height,
1437                viewport_width,
1438                viewport_height,
1439            );
1440        }
1441    }
1442
1443    pub(crate) fn handle_selection_changed(&self, start: u32, end: u32) {
1444        let handler = self.inner.borrow().handlers.selection_changed.clone();
1445        if let Some(handler) = handler {
1446            handler(SelectionChangedEventArgs { start, end });
1447        }
1448    }
1449
1450    pub(crate) fn handle_text_changed(&self, text: String) {
1451        let handler = self.inner.borrow().handlers.text_changed.clone();
1452        if let Some(handler) = handler {
1453            handler(TextChangedEventArgs { text });
1454        }
1455    }
1456
1457    pub(crate) fn handle_text_replaced(&self, start: u32, end: u32, text: String) {
1458        let handler = self.inner.borrow().handlers.text_replaced.clone();
1459        if let Some(handler) = handler {
1460            handler(start, end, text);
1461        }
1462    }
1463
1464    pub(crate) fn handle_cross_selection_changed(&self, text: String) {
1465        let handler = self.inner.borrow().handlers.cross_selection_changed.clone();
1466        if let Some(handler) = handler {
1467            handler(text);
1468        }
1469    }
1470
1471    pub(crate) fn handle_gesture_event(&self, event: &mut GestureEventArgs) {
1472        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1473            return;
1474        }
1475        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1476        let handlers = self.inner.borrow().handlers.clone();
1477        match event.kind {
1478            crate::event::GestureEventKind::Pan => {
1479                if let Some(handler) = handlers.pan_gesture {
1480                    handler(event);
1481                }
1482            }
1483            crate::event::GestureEventKind::Pinch => {
1484                if let Some(handler) = handlers.pinch_gesture {
1485                    handler(event);
1486                }
1487            }
1488            crate::event::GestureEventKind::None => {}
1489        }
1490    }
1491
1492    pub(crate) fn handle_bubbled_gesture_event(&self, event: &mut GestureEventArgs) {
1493        self.handle_gesture_event(event);
1494    }
1495
1496    pub(crate) fn handle_long_press_event(&self, event: &mut LongPressEventArgs) {
1497        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1498            return;
1499        }
1500        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1501        if let Some(handler) = self.inner.borrow().handlers.long_press.clone() {
1502            handler(event);
1503        }
1504        if !event.handled
1505            && matches!(event.pointer_type, PointerType::Touch | PointerType::Pen)
1506            && self.has_drag_source()
1507        {
1508            event.handled = self.ensure_drag_gesture().borrow_mut().handle_long_press(
1509                event.x,
1510                event.y,
1511                event.modifiers,
1512            );
1513        }
1514    }
1515
1516    pub(crate) fn handle_bubbled_long_press_event(&self, event: &mut LongPressEventArgs) {
1517        self.handle_long_press_event(event);
1518    }
1519
1520    pub(crate) fn handle_custom_draw(&self, canvas_ptr: usize) {
1521        if let Some(callback) = self.inner.borrow().draw_callback.clone() {
1522            let mut context = DrawContext::new(canvas_ptr);
1523            callback(&mut context);
1524        }
1525    }
1526
1527    pub(crate) fn build(&self) {
1528        if let Some(callback) = self.build_callback.as_ref() {
1529            callback();
1530        }
1531    }
1532
1533    pub(crate) fn downgrade(&self) -> WeakNodeRef {
1534        WeakNodeRef {
1535            inner: Rc::downgrade(&self.inner),
1536        }
1537    }
1538
1539    pub(crate) fn ensure_drag_gesture(&self) -> Rc<RefCell<DragGesture>> {
1540        if let Some(gesture) = self.inner.borrow().drag_gesture.clone() {
1541            return gesture;
1542        }
1543        let weak = self.downgrade();
1544        let gesture = Rc::new(RefCell::new(DragGesture::new(self)));
1545        gesture.borrow_mut().threshold(4.0);
1546        gesture.borrow_mut().set_started({
1547            let weak = weak.clone();
1548            move |_event: DragStartedEvent| {
1549                if let Some(node) = weak.upgrade() {
1550                    node.handle_drag_gesture_started();
1551                }
1552            }
1553        });
1554        gesture
1555            .borrow_mut()
1556            .set_completed(move |event: DragCompletedEvent| {
1557                if let Some(node) = weak.upgrade() {
1558                    node.handle_drag_gesture_completed(event);
1559                }
1560            });
1561        self.inner.borrow_mut().drag_gesture = Some(gesture.clone());
1562        gesture
1563    }
1564
1565    fn handle_drag_gesture_started(&self) {
1566        if !crate::event::begin_drag_session(self.clone()) {
1567            if let Some(gesture) = self.inner.borrow().drag_gesture.clone() {
1568                gesture.borrow_mut().cancel();
1569            }
1570        }
1571    }
1572
1573    fn handle_drag_gesture_completed(&self, event: DragCompletedEvent) {
1574        let mut core = self.inner.borrow_mut();
1575        core.drag_click_pending = false;
1576        core.drag_click_pending_count = 0;
1577        drop(core);
1578        if event.cancelled {
1579            crate::event::cancel_drag_session_for_source(self);
1580        }
1581    }
1582
1583    pub(crate) fn has_drag_source(&self) -> bool {
1584        self.inner.borrow().drag_data_callback.is_some()
1585    }
1586
1587    pub(crate) fn create_drag_data_object(&self) -> Option<DragDataObject> {
1588        let callback = self.inner.borrow().drag_data_callback.clone();
1589        callback.and_then(|callback| callback())
1590    }
1591
1592    pub(crate) fn get_drag_allowed_effects(&self) -> DragDropEffects {
1593        self.inner.borrow().drag_allowed_effects
1594    }
1595
1596    pub(crate) fn notify_drag_completed(&self, effect: DragDropEffects) {
1597        let callback = self.inner.borrow().drag_completed_callback.clone();
1598        if let Some(callback) = callback {
1599            callback(DragCompletedEventArgs { effect });
1600        }
1601    }
1602
1603    pub(crate) fn allows_drop(&self) -> bool {
1604        self.inner.borrow().drop_allowed
1605    }
1606
1607    pub(crate) fn has_drag_enter_handler(&self) -> bool {
1608        self.inner.borrow().drag_enter_callback.is_some()
1609    }
1610
1611    pub(crate) fn has_drag_over_handler(&self) -> bool {
1612        self.inner.borrow().drag_over_callback.is_some()
1613    }
1614
1615    pub(crate) fn handle_drag_enter(&self, args: DragEventArgs) -> DropProposal {
1616        let callback = self.inner.borrow().drag_enter_callback.clone();
1617        callback
1618            .map(|callback| callback(args))
1619            .unwrap_or_else(DropProposal::none)
1620    }
1621
1622    pub(crate) fn handle_drag_over(&self, args: DragEventArgs) -> DropProposal {
1623        let callback = self.inner.borrow().drag_over_callback.clone();
1624        callback
1625            .map(|callback| callback(args))
1626            .unwrap_or_else(DropProposal::none)
1627    }
1628
1629    pub(crate) fn handle_drag_leave(&self, args: DragEventArgs) {
1630        let callback = self.inner.borrow().drag_leave_callback.clone();
1631        if let Some(callback) = callback {
1632            callback(args);
1633        }
1634    }
1635
1636    pub(crate) fn handle_drop_event(&self, args: DragEventArgs) {
1637        let callback = self.inner.borrow().drop_callback.clone();
1638        if let Some(callback) = callback {
1639            callback(args);
1640        }
1641    }
1642
1643    pub(crate) fn allows_external_drop(&self) -> bool {
1644        self.inner.borrow().behavior.external_drop_allowed
1645    }
1646
1647    pub(crate) fn has_external_drag_enter_handler(&self) -> bool {
1648        self.inner.borrow().external_drag_enter_callback.is_some()
1649    }
1650
1651    pub(crate) fn has_external_drag_over_handler(&self) -> bool {
1652        self.inner.borrow().external_drag_over_callback.is_some()
1653    }
1654
1655    pub(crate) fn handle_external_drag_enter(&self, args: ExternalDropEventArgs) -> DropProposal {
1656        let callback = self.inner.borrow().external_drag_enter_callback.clone();
1657        callback
1658            .map(|callback| callback(args))
1659            .unwrap_or_else(DropProposal::none)
1660    }
1661
1662    pub(crate) fn handle_external_drag_over(&self, args: ExternalDropEventArgs) -> DropProposal {
1663        let callback = self.inner.borrow().external_drag_over_callback.clone();
1664        callback
1665            .map(|callback| callback(args))
1666            .unwrap_or_else(DropProposal::none)
1667    }
1668
1669    pub(crate) fn handle_external_drag_leave(&self, args: ExternalDropEventArgs) {
1670        let callback = self.inner.borrow().external_drag_leave_callback.clone();
1671        if let Some(callback) = callback {
1672            callback(args);
1673        }
1674    }
1675
1676    pub(crate) fn handle_external_drop_event(&self, args: ExternalDropEventArgs) {
1677        let callback = self.inner.borrow().external_drop_callback.clone();
1678        if let Some(callback) = callback {
1679            callback(args);
1680        }
1681    }
1682}
1683
1684/// Universal retained-node capabilities shared by every visual node and control.
1685///
1686/// Rust controls use composition rather than FUI-AS class inheritance, but this
1687/// trait preserves the common retained identity, state, semantics, focus,
1688/// routed-input, gesture, geometry, and child-inspection contract. Layout and
1689/// appearance are exposed separately through the cohesive surface traits.
1690pub trait Node: Clone {
1691    #[doc(hidden)]
1692    fn node_ref(&self) -> NodeRef {
1693        self.retained_node_ref()
1694    }
1695    #[doc(hidden)]
1696    fn retained_node_ref(&self) -> NodeRef;
1697    #[doc(hidden)]
1698    fn retained_owner_attachment(&self) -> Option<Rc<dyn Any>> {
1699        None
1700    }
1701    #[doc(hidden)]
1702    fn build_self(&self);
1703
1704    #[doc(hidden)]
1705    fn required_font_ids_for_preparation(&self) -> Vec<u32> {
1706        Vec::new()
1707    }
1708
1709    #[doc(hidden)]
1710    fn apply_node_id(&self, node_id: String) {
1711        let node_ref = self.node_ref();
1712        node_ref.set_node_id(node_id);
1713        if self.has_built_handle() {
1714            self.notify_retained_mutation();
1715        }
1716    }
1717
1718    #[doc(hidden)]
1719    fn apply_semantic_label(&self, label: String) {
1720        let node_ref = self.node_ref();
1721        node_ref.inner.borrow_mut().behavior.semantic_label = Some(label.clone());
1722        let handle = node_ref.handle();
1723        if handle != NodeHandle::INVALID {
1724            ui::set_semantic_label(handle.raw(), &label);
1725            self.notify_retained_mutation();
1726        }
1727    }
1728
1729    #[doc(hidden)]
1730    fn apply_focusable(&self, enabled: bool, tab_index: i32) {
1731        let node_ref = self.node_ref();
1732        if enabled {
1733            node_ref.require_interactive();
1734        }
1735        let visible = node_ref.is_effectively_visible_for_routing();
1736        let mut core = node_ref.inner.borrow_mut();
1737        core.behavior.focusable = Some((enabled, tab_index));
1738        let interactive = core.behavior.enabled && core.behavior.inherited_enabled && visible;
1739        let handle = core.handle;
1740        drop(core);
1741        if handle != NodeHandle::INVALID {
1742            ui::set_focusable(handle.raw(), interactive && enabled, tab_index);
1743            self.notify_retained_mutation();
1744        }
1745    }
1746
1747    #[doc(hidden)]
1748    fn apply_focus_now(&self) {
1749        let handle = self.node_ref().handle();
1750        if handle != NodeHandle::INVALID {
1751            ui::request_focus(handle.raw());
1752        }
1753    }
1754
1755    #[doc(hidden)]
1756    fn apply_enabled(&self, enabled: bool) {
1757        self.node_ref().set_own_enabled(enabled);
1758    }
1759
1760    #[doc(hidden)]
1761    fn apply_focus_changed_handler(&self, handler: Rc<dyn Fn(FocusChangedEventArgs)>) {
1762        self.node_ref().inner.borrow_mut().handlers.focus_changed = Some(handler);
1763    }
1764
1765    fn node_id(&self, node_id: impl Into<String>) -> &Self
1766    where
1767        Self: Sized,
1768    {
1769        self.apply_node_id(node_id.into());
1770        self
1771    }
1772
1773    fn semantic_role(&self, role: SemanticRole) -> &Self
1774    where
1775        Self: Sized,
1776    {
1777        let node_ref = self.node_ref();
1778        node_ref.inner.borrow_mut().behavior.semantic_role = Some(role);
1779        if self.has_built_handle() {
1780            ui::set_semantic_role(self.handle().raw(), role as u32);
1781            self.notify_retained_mutation();
1782        }
1783        self
1784    }
1785
1786    fn semantic_label(&self, label: impl Into<String>) -> &Self
1787    where
1788        Self: Sized,
1789    {
1790        self.apply_semantic_label(label.into());
1791        self
1792    }
1793
1794    fn semantic_checked(&self, state: SemanticCheckedState) -> &Self
1795    where
1796        Self: Sized,
1797    {
1798        let node_ref = self.node_ref();
1799        node_ref.inner.borrow_mut().behavior.semantic_checked = Some(state);
1800        if self.has_built_handle() {
1801            ui::set_semantic_checked(self.handle().raw(), state as u32);
1802            self.notify_retained_mutation();
1803        }
1804        self
1805    }
1806
1807    fn semantic_disabled(&self, disabled: bool) -> &Self
1808    where
1809        Self: Sized,
1810    {
1811        let node_ref = self.node_ref();
1812        let mut core = node_ref.inner.borrow_mut();
1813        core.behavior.track_semantic_disabled_from_enabled = false;
1814        core.behavior.semantic_disabled = Some(disabled);
1815        drop(core);
1816        if self.has_built_handle() {
1817            ui::set_semantic_disabled(self.handle().raw(), true, disabled);
1818            self.notify_retained_mutation();
1819        }
1820        self
1821    }
1822
1823    fn clear_semantic_disabled(&self) -> &Self
1824    where
1825        Self: Sized,
1826    {
1827        let node_ref = self.node_ref();
1828        let mut core = node_ref.inner.borrow_mut();
1829        core.behavior.track_semantic_disabled_from_enabled = false;
1830        core.behavior.semantic_disabled = None;
1831        drop(core);
1832        if self.has_built_handle() {
1833            ui::set_semantic_disabled(self.handle().raw(), false, false);
1834            self.notify_retained_mutation();
1835        }
1836        self
1837    }
1838
1839    fn semantic_selected(&self, selected: bool) -> &Self
1840    where
1841        Self: Sized,
1842    {
1843        self.node_ref()
1844            .inner
1845            .borrow_mut()
1846            .behavior
1847            .semantic_selected = Some(selected);
1848        if self.has_built_handle() {
1849            ui::set_semantic_selected(self.handle().raw(), true, selected);
1850            self.notify_retained_mutation();
1851        }
1852        self
1853    }
1854
1855    fn clear_semantic_selected(&self) -> &Self
1856    where
1857        Self: Sized,
1858    {
1859        self.node_ref()
1860            .inner
1861            .borrow_mut()
1862            .behavior
1863            .semantic_selected = None;
1864        if self.has_built_handle() {
1865            ui::set_semantic_selected(self.handle().raw(), false, false);
1866            self.notify_retained_mutation();
1867        }
1868        self
1869    }
1870
1871    fn semantic_expanded(&self, expanded: bool) -> &Self
1872    where
1873        Self: Sized,
1874    {
1875        self.node_ref()
1876            .inner
1877            .borrow_mut()
1878            .behavior
1879            .semantic_expanded = Some(expanded);
1880        if self.has_built_handle() {
1881            ui::set_semantic_expanded(self.handle().raw(), true, expanded);
1882            self.notify_retained_mutation();
1883        }
1884        self
1885    }
1886
1887    fn clear_semantic_expanded(&self) -> &Self
1888    where
1889        Self: Sized,
1890    {
1891        self.node_ref()
1892            .inner
1893            .borrow_mut()
1894            .behavior
1895            .semantic_expanded = None;
1896        if self.has_built_handle() {
1897            ui::set_semantic_expanded(self.handle().raw(), false, false);
1898            self.notify_retained_mutation();
1899        }
1900        self
1901    }
1902
1903    fn semantic_value_range(&self, value_now: f32, value_min: f32, value_max: f32) -> &Self
1904    where
1905        Self: Sized,
1906    {
1907        self.node_ref()
1908            .inner
1909            .borrow_mut()
1910            .behavior
1911            .semantic_value_range = Some((value_now, value_min, value_max));
1912        if self.has_built_handle() {
1913            ui::set_semantic_value_range(
1914                self.handle().raw(),
1915                true,
1916                value_now,
1917                value_min,
1918                value_max,
1919            );
1920            self.notify_retained_mutation();
1921        }
1922        self
1923    }
1924
1925    fn clear_semantic_value_range(&self) -> &Self
1926    where
1927        Self: Sized,
1928    {
1929        self.node_ref()
1930            .inner
1931            .borrow_mut()
1932            .behavior
1933            .semantic_value_range = None;
1934        if self.has_built_handle() {
1935            ui::set_semantic_value_range(self.handle().raw(), false, 0.0, 0.0, 0.0);
1936            self.notify_retained_mutation();
1937        }
1938        self
1939    }
1940
1941    fn semantic_orientation(&self, orientation: Orientation) -> &Self
1942    where
1943        Self: Sized,
1944    {
1945        self.node_ref()
1946            .inner
1947            .borrow_mut()
1948            .behavior
1949            .semantic_orientation = Some(orientation);
1950        if self.has_built_handle() {
1951            ui::set_semantic_orientation(self.handle().raw(), orientation as u32);
1952            self.notify_retained_mutation();
1953        }
1954        self
1955    }
1956
1957    fn request_semantic_announcement(&self) -> &Self
1958    where
1959        Self: Sized,
1960    {
1961        if self.has_built_handle() {
1962            ui::request_semantic_announcement(self.handle().raw());
1963        }
1964        self
1965    }
1966
1967    fn child_count(&self) -> usize {
1968        self.node_ref().children().len()
1969    }
1970
1971    fn is_enabled(&self) -> bool {
1972        self.node_ref().is_enabled_for_routing()
1973    }
1974
1975    fn is_visible(&self) -> bool {
1976        self.node_ref().is_effectively_visible_for_routing()
1977    }
1978
1979    fn cursor_style(&self) -> CursorStyle {
1980        self.node_ref().cursor_style_for_routing()
1981    }
1982
1983    fn persist_state(&self, adapter: Rc<dyn PersistedStateAdapter>) -> &Self
1984    where
1985        Self: Sized,
1986    {
1987        self.node_ref().register_persisted_state_adapter(adapter);
1988        self
1989    }
1990
1991    fn handle(&self) -> NodeHandle {
1992        self.node_ref().inner.borrow().handle
1993    }
1994
1995    fn has_built_handle(&self) -> bool {
1996        self.handle() != NodeHandle::INVALID
1997    }
1998
1999    fn on_context_menu(&self, handler: impl Fn(ContextMenuEventArgs) + 'static) -> &Self
2000    where
2001        Self: Sized,
2002    {
2003        self.node_ref()
2004            .inner
2005            .borrow_mut()
2006            .behavior
2007            .context_menu_handler = Some(Rc::new(handler));
2008        self
2009    }
2010
2011    fn clear_context_menu(&self) -> &Self
2012    where
2013        Self: Sized,
2014    {
2015        self.node_ref()
2016            .inner
2017            .borrow_mut()
2018            .behavior
2019            .context_menu_handler = None;
2020        self
2021    }
2022
2023    fn disable_context_menu(&self, flag: bool) -> &Self
2024    where
2025        Self: Sized,
2026    {
2027        self.node_ref()
2028            .inner
2029            .borrow_mut()
2030            .behavior
2031            .context_menu_disabled = flag;
2032        self
2033    }
2034
2035    /// Handles the low-level routed pointer-click event.
2036    ///
2037    /// This is not control activation. Use
2038    /// [`Clickable::on_click`](crate::controls::Clickable::on_click) for a control action
2039    /// that also supports keyboard activation.
2040    fn on_pointer_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2041    where
2042        Self: Sized,
2043    {
2044        let node_ref = self.node_ref();
2045        node_ref.inner.borrow_mut().handlers.pointer_click = Some(Rc::new(handler));
2046        node_ref.require_interactive();
2047        self
2048    }
2049
2050    /// Handles a low-level routed pointer double-click after the ordinary pointer-click callback.
2051    fn on_pointer_double_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2052    where
2053        Self: Sized,
2054    {
2055        let node_ref = self.node_ref();
2056        node_ref.inner.borrow_mut().handlers.pointer_double_click = Some(Rc::new(handler));
2057        node_ref.require_interactive();
2058        self
2059    }
2060
2061    /// Handles a low-level routed pointer triple-click after the ordinary pointer-click callback.
2062    fn on_pointer_triple_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2063    where
2064        Self: Sized,
2065    {
2066        let node_ref = self.node_ref();
2067        node_ref.inner.borrow_mut().handlers.pointer_triple_click = Some(Rc::new(handler));
2068        node_ref.require_interactive();
2069        self
2070    }
2071
2072    fn on_pointer_down(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2073    where
2074        Self: Sized,
2075    {
2076        let node_ref = self.node_ref();
2077        node_ref.inner.borrow_mut().handlers.pointer_down = Some(Rc::new(handler));
2078        node_ref.require_interactive();
2079        self
2080    }
2081
2082    fn on_pointer_move(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2083    where
2084        Self: Sized,
2085    {
2086        let node_ref = self.node_ref();
2087        node_ref.inner.borrow_mut().handlers.pointer_move = Some(Rc::new(handler));
2088        node_ref.require_interactive();
2089        self
2090    }
2091
2092    fn on_pointer_up(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2093    where
2094        Self: Sized,
2095    {
2096        let node_ref = self.node_ref();
2097        node_ref.inner.borrow_mut().handlers.pointer_up = Some(Rc::new(handler));
2098        node_ref.require_interactive();
2099        self
2100    }
2101
2102    fn on_pointer_enter(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2103    where
2104        Self: Sized,
2105    {
2106        let node_ref = self.node_ref();
2107        node_ref.inner.borrow_mut().handlers.pointer_enter = Some(Rc::new(handler));
2108        node_ref.require_interactive();
2109        self
2110    }
2111
2112    fn on_pointer_leave(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2113    where
2114        Self: Sized,
2115    {
2116        let node_ref = self.node_ref();
2117        node_ref.inner.borrow_mut().handlers.pointer_leave = Some(Rc::new(handler));
2118        node_ref.require_interactive();
2119        self
2120    }
2121
2122    fn on_pointer_cancel(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2123    where
2124        Self: Sized,
2125    {
2126        let node_ref = self.node_ref();
2127        node_ref.inner.borrow_mut().handlers.pointer_cancel = Some(Rc::new(handler));
2128        node_ref.require_interactive();
2129        self
2130    }
2131
2132    fn on_wheel(&self, handler: impl Fn(&mut WheelEventArgs) + 'static) -> &Self
2133    where
2134        Self: Sized,
2135    {
2136        let node_ref = self.node_ref();
2137        node_ref.inner.borrow_mut().handlers.wheel = Some(Rc::new(handler));
2138        node_ref.require_interactive();
2139        self
2140    }
2141
2142    fn on_pan_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2143    where
2144        Self: Sized,
2145    {
2146        self.node_ref().inner.borrow_mut().handlers.pan_gesture = Some(Rc::new(handler));
2147        self
2148    }
2149
2150    fn on_pinch_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2151    where
2152        Self: Sized,
2153    {
2154        self.node_ref().inner.borrow_mut().handlers.pinch_gesture = Some(Rc::new(handler));
2155        self
2156    }
2157
2158    fn long_press_options(&self, minimum_duration_ms: i32, movement_tolerance: f32) -> &Self
2159    where
2160        Self: Sized,
2161    {
2162        let node_ref = self.node_ref();
2163        let mut core = node_ref.inner.borrow_mut();
2164        let handlers = &mut core.handlers;
2165        handlers.long_press_minimum_duration_ms = minimum_duration_ms.max(0);
2166        handlers.long_press_movement_tolerance = movement_tolerance.max(0.0);
2167        self
2168    }
2169
2170    fn on_long_press(&self, handler: impl Fn(&mut LongPressEventArgs) + 'static) -> &Self
2171    where
2172        Self: Sized,
2173    {
2174        let node_ref = self.node_ref();
2175        node_ref.inner.borrow_mut().handlers.long_press = Some(Rc::new(handler));
2176        node_ref.require_interactive();
2177        self
2178    }
2179
2180    fn focusable(&self, enabled: bool, tab_index: i32) -> &Self
2181    where
2182        Self: Sized,
2183    {
2184        self.apply_focusable(enabled, tab_index);
2185        self
2186    }
2187
2188    fn focus_now(&self) -> &Self
2189    where
2190        Self: Sized,
2191    {
2192        self.apply_focus_now();
2193        self
2194    }
2195
2196    fn enabled(&self, enabled: bool) -> &Self
2197    where
2198        Self: Sized,
2199    {
2200        self.apply_enabled(enabled);
2201        self
2202    }
2203
2204    fn visibility(&self, visibility: Visibility) -> &Self
2205    where
2206        Self: Sized,
2207    {
2208        self.node_ref().set_own_visibility(visibility);
2209        if self.has_built_handle() {
2210            self.notify_retained_layout_mutation();
2211        }
2212        self
2213    }
2214
2215    fn cursor(&self, style: CursorStyle) -> &Self
2216    where
2217        Self: Sized,
2218    {
2219        self.node_ref().inner.borrow_mut().behavior.cursor = Some(style);
2220        crate::event::handle_cursor_style_changed(self.handle());
2221        self
2222    }
2223
2224    fn clear_cursor(&self) -> &Self
2225    where
2226        Self: Sized,
2227    {
2228        self.node_ref().inner.borrow_mut().behavior.cursor = None;
2229        crate::event::handle_cursor_style_changed(self.handle());
2230        self
2231    }
2232
2233    fn on_key_down(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2234    where
2235        Self: Sized,
2236    {
2237        self.node_ref().inner.borrow_mut().handlers.key_down = Some(Rc::new(handler));
2238        self
2239    }
2240
2241    fn on_key_up(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2242    where
2243        Self: Sized,
2244    {
2245        self.node_ref().inner.borrow_mut().handlers.key_up = Some(Rc::new(handler));
2246        self
2247    }
2248
2249    fn on_focus_changed(&self, handler: impl Fn(FocusChangedEventArgs) + 'static) -> &Self
2250    where
2251        Self: Sized,
2252    {
2253        self.apply_focus_changed_handler(Rc::new(handler));
2254        self
2255    }
2256
2257    fn drag_allowed_effects(&self, effects: DragDropEffects) -> &Self
2258    where
2259        Self: Sized,
2260    {
2261        self.node_ref().inner.borrow_mut().drag_allowed_effects = effects;
2262        self
2263    }
2264
2265    fn drag_data(&self, handler: impl Fn() -> Option<DragDataObject> + 'static) -> &Self
2266    where
2267        Self: Sized,
2268    {
2269        let node_ref = self.node_ref();
2270        node_ref.inner.borrow_mut().drag_data_callback = Some(Rc::new(handler));
2271        node_ref.require_interactive();
2272        node_ref.ensure_drag_gesture();
2273        self
2274    }
2275
2276    fn clear_drag_data(&self) -> &Self
2277    where
2278        Self: Sized,
2279    {
2280        self.node_ref().inner.borrow_mut().drag_data_callback = None;
2281        self
2282    }
2283
2284    fn allow_drop(&self, flag: bool) -> &Self
2285    where
2286        Self: Sized,
2287    {
2288        let node_ref = self.node_ref();
2289        node_ref.inner.borrow_mut().drop_allowed = flag;
2290        if flag {
2291            node_ref.require_interactive();
2292        }
2293        self
2294    }
2295
2296    fn on_drag_completed(&self, handler: impl Fn(DragCompletedEventArgs) + 'static) -> &Self
2297    where
2298        Self: Sized,
2299    {
2300        self.node_ref().inner.borrow_mut().drag_completed_callback = Some(Rc::new(handler));
2301        self
2302    }
2303
2304    fn on_drag_enter(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2305    where
2306        Self: Sized,
2307    {
2308        let node_ref = self.node_ref();
2309        node_ref.inner.borrow_mut().drag_enter_callback = Some(Rc::new(handler));
2310        self.allow_drop(true);
2311        node_ref.require_interactive();
2312        self
2313    }
2314
2315    fn on_drag_over(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2316    where
2317        Self: Sized,
2318    {
2319        let node_ref = self.node_ref();
2320        node_ref.inner.borrow_mut().drag_over_callback = Some(Rc::new(handler));
2321        self.allow_drop(true);
2322        node_ref.require_interactive();
2323        self
2324    }
2325
2326    fn on_drag_leave(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2327    where
2328        Self: Sized,
2329    {
2330        let node_ref = self.node_ref();
2331        node_ref.inner.borrow_mut().drag_leave_callback = Some(Rc::new(handler));
2332        self.allow_drop(true);
2333        node_ref.require_interactive();
2334        self
2335    }
2336
2337    fn on_drop(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2338    where
2339        Self: Sized,
2340    {
2341        let node_ref = self.node_ref();
2342        node_ref.inner.borrow_mut().drop_callback = Some(Rc::new(handler));
2343        self.allow_drop(true);
2344        node_ref.require_interactive();
2345        self
2346    }
2347
2348    fn allow_external_drop(&self, flag: bool) -> &Self
2349    where
2350        Self: Sized,
2351    {
2352        let node_ref = self.node_ref();
2353        node_ref.inner.borrow_mut().behavior.external_drop_allowed = flag;
2354        if flag {
2355            node_ref.require_interactive();
2356        }
2357        self
2358    }
2359
2360    fn on_external_drag_enter(
2361        &self,
2362        handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2363    ) -> &Self
2364    where
2365        Self: Sized,
2366    {
2367        let node_ref = self.node_ref();
2368        node_ref.inner.borrow_mut().external_drag_enter_callback = Some(Rc::new(handler));
2369        self.allow_external_drop(true);
2370        node_ref.require_interactive();
2371        self
2372    }
2373
2374    fn on_external_drag_over(
2375        &self,
2376        handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2377    ) -> &Self
2378    where
2379        Self: Sized,
2380    {
2381        let node_ref = self.node_ref();
2382        node_ref.inner.borrow_mut().external_drag_over_callback = Some(Rc::new(handler));
2383        self.allow_external_drop(true);
2384        node_ref.require_interactive();
2385        self
2386    }
2387
2388    fn on_external_drag_leave(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2389    where
2390        Self: Sized,
2391    {
2392        let node_ref = self.node_ref();
2393        node_ref.inner.borrow_mut().external_drag_leave_callback = Some(Rc::new(handler));
2394        self.allow_external_drop(true);
2395        node_ref.require_interactive();
2396        self
2397    }
2398
2399    fn on_external_drop(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2400    where
2401        Self: Sized,
2402    {
2403        let node_ref = self.node_ref();
2404        node_ref.inner.borrow_mut().external_drop_callback = Some(Rc::new(handler));
2405        self.allow_external_drop(true);
2406        node_ref.require_interactive();
2407        self
2408    }
2409
2410    fn get_bounds(&self) -> [f32; 4] {
2411        if !self.has_built_handle() {
2412            return [0.0; 4];
2413        }
2414        ui::get_bounds(self.handle().raw()).unwrap_or([0.0; 4])
2415    }
2416
2417    fn absolute_to_local_position(&self, absolute_x: f32, absolute_y: f32) -> [f32; 2] {
2418        let bounds = self.get_bounds();
2419        [absolute_x - bounds[0], absolute_y - bounds[1]]
2420    }
2421
2422    fn local_to_absolute_position(&self, local_x: f32, local_y: f32) -> [f32; 2] {
2423        let bounds = self.get_bounds();
2424        [bounds[0] + local_x, bounds[1] + local_y]
2425    }
2426
2427    fn ensure_handle(&self) {
2428        if self.has_built_handle() {
2429            return;
2430        }
2431        let node_ref = self.node_ref();
2432        let node_type = node_ref.inner.borrow().kind.node_type();
2433        let handle = NodeHandle(ui::create_node(node_type as u32));
2434        {
2435            let mut core = node_ref.inner.borrow_mut();
2436            core.handle = handle;
2437            core.mounted = true;
2438        }
2439        crate::event::register_node(&node_ref);
2440    }
2441
2442    fn build(&self) {
2443        self.ensure_handle();
2444        self.build_self();
2445        self.build_children();
2446    }
2447
2448    fn dispose(&self) {
2449        self.node_ref().dispose();
2450    }
2451
2452    fn build_children(&self) {
2453        let node_ref = self.node_ref();
2454        {
2455            let mut core = node_ref.inner.borrow_mut();
2456            if core.children_built {
2457                return;
2458            }
2459            core.children_built = true;
2460        }
2461        let children = node_ref.inner.borrow().children.clone();
2462        for child in children {
2463            child.build();
2464            ui::add_child(self.handle().raw(), child.handle().raw());
2465        }
2466    }
2467
2468    fn append_child<T: Node>(&self, child: &T) {
2469        let self_node_ref = self.node_ref();
2470        let child_node_ref = child.node_ref();
2471        if Rc::ptr_eq(&self_node_ref.inner, &child_node_ref.inner) {
2472            return;
2473        }
2474        if self_node_ref
2475            .inner
2476            .borrow()
2477            .children
2478            .iter()
2479            .any(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2480        {
2481            return;
2482        }
2483        if let Some(previous_parent) = child_node_ref.inner.borrow().parent.upgrade() {
2484            if Rc::ptr_eq(&previous_parent, &self_node_ref.inner) {
2485                return;
2486            }
2487            let child_handle = child.handle();
2488            {
2489                let mut previous_parent_core = previous_parent.borrow_mut();
2490                previous_parent_core
2491                    .children
2492                    .retain(|candidate| !Rc::ptr_eq(&candidate.inner, &child_node_ref.inner));
2493            }
2494            if previous_parent.borrow().handle != NodeHandle::INVALID
2495                && child_handle != NodeHandle::INVALID
2496            {
2497                ui::remove_child(previous_parent.borrow().handle.raw(), child_handle.raw());
2498            }
2499        }
2500
2501        {
2502            let mut child_core = child_node_ref.inner.borrow_mut();
2503            child_core.parent = Rc::downgrade(&self_node_ref.inner);
2504        }
2505        child_node_ref.set_inherited_enabled(self_node_ref.is_enabled_for_routing());
2506        self_node_ref
2507            .inner
2508            .borrow_mut()
2509            .children
2510            .push(child_node_ref.clone());
2511        if let Some(owner) = child.retained_owner_attachment() {
2512            self_node_ref
2513                .inner
2514                .borrow_mut()
2515                .retained_attachments
2516                .push(owner);
2517        }
2518        self_node_ref.inner.borrow_mut().children_built = false;
2519        if self.has_built_handle() {
2520            child.build();
2521            ui::add_child(self.handle().raw(), child.handle().raw());
2522            self_node_ref.inner.borrow_mut().children_built = true;
2523            self.notify_retained_mutation();
2524            self.notify_retained_child_layout_changed();
2525        }
2526    }
2527
2528    fn remove_child<T: Node>(&self, child: &T) -> bool {
2529        let child_handle = child.handle();
2530        let child_node_ref = child.node_ref();
2531        let removed = {
2532            let self_node_ref = self.node_ref();
2533            let mut core = self_node_ref.inner.borrow_mut();
2534            let Some(index) = core
2535                .children
2536                .iter()
2537                .position(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2538            else {
2539                return false;
2540            };
2541            core.children.remove(index)
2542        };
2543        removed.inner.borrow_mut().parent = Weak::new();
2544        removed.set_inherited_enabled(true);
2545        self.node_ref().inner.borrow_mut().children_built = false;
2546        if self.has_built_handle() && child.has_built_handle() {
2547            ui::remove_child(self.handle().raw(), child_handle.raw());
2548            self.node_ref().inner.borrow_mut().children_built = true;
2549            self.notify_retained_mutation();
2550            self.notify_retained_child_layout_changed();
2551        }
2552        true
2553    }
2554
2555    fn parent_handle(&self) -> Option<NodeHandle> {
2556        self.node_ref()
2557            .inner
2558            .borrow()
2559            .parent
2560            .upgrade()
2561            .map(|parent| parent.borrow().handle)
2562    }
2563
2564    fn notify_retained_layout_mutation(&self) {
2565        self.notify_retained_mutation();
2566    }
2567
2568    fn notify_retained_mutation(&self) {
2569        crate::frame_scheduler::mark_needs_commit();
2570    }
2571
2572    fn notify_retained_child_layout_changed(&self) {}
2573
2574    #[doc(hidden)]
2575    fn bind_scroll_proxy_target_handle(&self, scroll_handle: u64) -> &Self
2576    where
2577        Self: Sized,
2578    {
2579        let node_ref = self.node_ref();
2580        node_ref.inner.borrow_mut().behavior.scroll_proxy_target = Some(scroll_handle);
2581        if self.has_built_handle() {
2582            ui::set_scroll_proxy_target(self.handle().raw(), scroll_handle);
2583            self.notify_retained_mutation();
2584        }
2585        self
2586    }
2587
2588    fn preserve_selection_on_pointer_down(&self, preserve: bool) -> &Self
2589    where
2590        Self: Sized,
2591    {
2592        let node_ref = self.node_ref();
2593        node_ref
2594            .inner
2595            .borrow_mut()
2596            .behavior
2597            .preserve_selection_on_pointer_down = preserve;
2598        if self.has_built_handle() {
2599            ui::set_preserve_selection_on_pointer_down(self.handle().raw(), preserve);
2600            self.notify_retained_mutation();
2601        }
2602        self
2603    }
2604
2605    fn tool_tip(&self, tool_tip: ToolTip) -> &Self
2606    where
2607        Self: Sized,
2608    {
2609        let node_ref = self.node_ref();
2610        node_ref.inner.borrow_mut().behavior.tool_tip = Some(tool_tip.clone());
2611        node_ref.require_interactive();
2612        if self.has_built_handle()
2613            && node_ref.is_enabled_for_routing()
2614            && node_ref.is_visible_for_routing()
2615        {
2616            ui::set_interactive(self.handle().raw(), true);
2617            self.notify_retained_mutation();
2618        }
2619        crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, Some(tool_tip));
2620        self
2621    }
2622
2623    fn tool_tip_text(&self, text: impl Into<String>) -> &Self
2624    where
2625        Self: Sized,
2626    {
2627        self.tool_tip(ToolTip::text(text))
2628    }
2629
2630    fn clear_tool_tip(&self) -> &Self
2631    where
2632        Self: Sized,
2633    {
2634        let node_ref = self.node_ref();
2635        node_ref.inner.borrow_mut().behavior.tool_tip = None;
2636        crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, None);
2637        self
2638    }
2639}
2640
2641impl<T: Node> Node for &T {
2642    fn retained_node_ref(&self) -> NodeRef {
2643        (*self).retained_node_ref()
2644    }
2645
2646    fn retained_owner_attachment(&self) -> Option<Rc<dyn Any>> {
2647        (*self).retained_owner_attachment()
2648    }
2649
2650    fn build_self(&self) {
2651        (*self).build_self();
2652    }
2653}