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                        return;
1212                    }
1213                }
1214                let mut core = self.inner.borrow_mut();
1215                core.drag_click_pending = false;
1216                core.drag_click_pending_count = 0;
1217                core.click_pending =
1218                    handlers.has_pointer_click_handler() && is_primary_activation_pointer(event);
1219                core.click_pending_count = event.click_count;
1220            }
1221            crate::ffi::PointerEventType::Move => {
1222                crate::tool_tip_manager::ToolTipManager::handle_pointer_move(
1223                    self,
1224                    event.scene_x,
1225                    event.scene_y,
1226                );
1227                if let Some(handler) = handlers.pointer_move {
1228                    handler(event);
1229                }
1230                if event.handled {
1231                    return;
1232                }
1233                let drag_gesture = self.inner.borrow().drag_gesture.clone();
1234                if let Some(drag_gesture) = drag_gesture {
1235                    let has_drag_source = self.has_drag_source();
1236                    let is_dragging = drag_gesture
1237                        .try_borrow()
1238                        .map(|gesture| gesture.is_dragging())
1239                        .unwrap_or(true);
1240                    if has_drag_source || is_dragging {
1241                        if let Ok(mut gesture) = drag_gesture.try_borrow_mut() {
1242                            gesture.handle_pointer_move(event.x, event.y, event.modifiers);
1243                        }
1244                    }
1245                }
1246            }
1247            crate::ffi::PointerEventType::Up => {
1248                if let Some(handler) = handlers.pointer_up.as_ref() {
1249                    handler(event);
1250                }
1251                if event.handled {
1252                    self.cancel_drag_state();
1253                    return;
1254                }
1255                let drag_gesture = self.inner.borrow().drag_gesture.clone();
1256                let has_drag_source = self.has_drag_source();
1257                let drag_gesture_is_dragging = drag_gesture
1258                    .as_ref()
1259                    .map(|gesture| {
1260                        gesture
1261                            .try_borrow()
1262                            .map(|gesture| gesture.is_dragging())
1263                            .unwrap_or(true)
1264                    })
1265                    .unwrap_or(false);
1266                let drag_gesture_active = drag_gesture
1267                    .as_ref()
1268                    .map(|_| has_drag_source || drag_gesture_is_dragging)
1269                    .unwrap_or(false);
1270                let (can_fire_pending_click, pending_click_count, can_fire_click, click_count) = {
1271                    let core = self.inner.borrow();
1272                    let can_fire_pending_click = core.drag_click_pending
1273                        && (!drag_gesture_active || !drag_gesture_is_dragging);
1274                    (
1275                        can_fire_pending_click,
1276                        core.drag_click_pending_count,
1277                        core.click_pending,
1278                        core.click_pending_count,
1279                    )
1280                };
1281                if let Some(drag_gesture) = drag_gesture.as_ref() {
1282                    if drag_gesture_active {
1283                        if let Ok(mut gesture) = drag_gesture.try_borrow_mut() {
1284                            gesture.handle_pointer_up(event.x, event.y, event.modifiers);
1285                        }
1286                    }
1287                }
1288                if can_fire_click {
1289                    handlers.dispatch_pointer_click(event, click_count);
1290                }
1291                self.clear_click_pending_state();
1292                if can_fire_pending_click {
1293                    handlers.dispatch_pointer_click(event, pending_click_count);
1294                }
1295                self.clear_drag_click_pending_state();
1296            }
1297            crate::ffi::PointerEventType::Enter => {
1298                if let Some(handler) = handlers.pointer_enter {
1299                    handler(event);
1300                }
1301                if !event.handled {
1302                    crate::tool_tip_manager::ToolTipManager::handle_pointer_enter(
1303                        self,
1304                        self.tool_tip_for_routing(),
1305                        event.scene_x,
1306                        event.scene_y,
1307                    );
1308                }
1309            }
1310            crate::ffi::PointerEventType::Leave => {
1311                self.clear_pending_pointer_state();
1312                if let Some(handler) = handlers.pointer_leave {
1313                    handler(event);
1314                }
1315                crate::tool_tip_manager::ToolTipManager::handle_pointer_leave(self);
1316            }
1317            crate::ffi::PointerEventType::Cancel => {
1318                self.cancel_drag_state();
1319                if let Some(handler) = handlers.pointer_cancel {
1320                    handler(event);
1321                }
1322                crate::tool_tip_manager::ToolTipManager::handle_pointer_leave(self);
1323            }
1324        }
1325    }
1326
1327    fn cancel_drag_state(&self) {
1328        let gesture = {
1329            let mut core = self.inner.borrow_mut();
1330            core.drag_click_pending = false;
1331            core.drag_click_pending_count = 0;
1332            core.click_pending = false;
1333            core.click_pending_count = 0;
1334            core.drag_gesture.clone()
1335        };
1336        if let Some(gesture) = gesture {
1337            gesture.borrow_mut().cancel();
1338        }
1339    }
1340
1341    fn clear_pending_pointer_state(&self) {
1342        let Ok(mut core) = self.inner.try_borrow_mut() else {
1343            return;
1344        };
1345        core.drag_click_pending = false;
1346        core.drag_click_pending_count = 0;
1347        core.click_pending = false;
1348        core.click_pending_count = 0;
1349    }
1350
1351    fn clear_click_pending_state(&self) {
1352        let Ok(mut core) = self.inner.try_borrow_mut() else {
1353            return;
1354        };
1355        core.click_pending = false;
1356        core.click_pending_count = 0;
1357    }
1358
1359    fn clear_drag_click_pending_state(&self) {
1360        let Ok(mut core) = self.inner.try_borrow_mut() else {
1361            return;
1362        };
1363        core.drag_click_pending = false;
1364        core.drag_click_pending_count = 0;
1365    }
1366
1367    pub(crate) fn handle_bubbled_pointer_event(&self, event: &mut PointerEventArgs) {
1368        self.handle_pointer_event(event);
1369    }
1370
1371    pub(crate) fn handle_wheel_event(&self, event: &mut WheelEventArgs) {
1372        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1373            return;
1374        }
1375        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1376        if let Some(handler) = self.inner.borrow().handlers.wheel.clone() {
1377            handler(event);
1378        }
1379    }
1380
1381    pub(crate) fn handle_key_event(&self, event: &mut KeyEventArgs) {
1382        if !self.is_enabled_for_routing() {
1383            return;
1384        }
1385        let handlers = self.inner.borrow().handlers.clone();
1386        match event.event_type {
1387            crate::ffi::KeyEventType::Down => {
1388                if let Some(handler) = handlers.key_down {
1389                    handler(event);
1390                }
1391            }
1392            crate::ffi::KeyEventType::Up => {
1393                if let Some(handler) = handlers.key_up {
1394                    handler(event);
1395                }
1396            }
1397        }
1398    }
1399
1400    pub(crate) fn handle_focus_changed(&self, event: FocusChangedEventArgs) {
1401        let handler = self.inner.borrow().handlers.focus_changed.clone();
1402        if let Some(handler) = handler {
1403            handler(event);
1404        }
1405        crate::tool_tip_manager::ToolTipManager::handle_focus_changed(
1406            self,
1407            self.tool_tip_for_routing(),
1408            event.focused,
1409        );
1410    }
1411
1412    pub(crate) fn handle_scroll_changed(
1413        &self,
1414        offset_x: f32,
1415        offset_y: f32,
1416        content_width: f32,
1417        content_height: f32,
1418        viewport_width: f32,
1419        viewport_height: f32,
1420    ) {
1421        self.set_scroll_routing_metrics(
1422            offset_x,
1423            offset_y,
1424            content_width,
1425            content_height,
1426            viewport_width,
1427            viewport_height,
1428        );
1429        let handler = self.inner.borrow().handlers.scroll_changed.clone();
1430        if let Some(handler) = handler {
1431            handler(
1432                offset_x,
1433                offset_y,
1434                content_width,
1435                content_height,
1436                viewport_width,
1437                viewport_height,
1438            );
1439        }
1440    }
1441
1442    pub(crate) fn handle_selection_changed(&self, start: u32, end: u32) {
1443        let handler = self.inner.borrow().handlers.selection_changed.clone();
1444        if let Some(handler) = handler {
1445            handler(SelectionChangedEventArgs { start, end });
1446        }
1447    }
1448
1449    pub(crate) fn handle_text_changed(&self, text: String) {
1450        let handler = self.inner.borrow().handlers.text_changed.clone();
1451        if let Some(handler) = handler {
1452            handler(TextChangedEventArgs { text });
1453        }
1454    }
1455
1456    pub(crate) fn handle_text_replaced(&self, start: u32, end: u32, text: String) {
1457        let handler = self.inner.borrow().handlers.text_replaced.clone();
1458        if let Some(handler) = handler {
1459            handler(start, end, text);
1460        }
1461    }
1462
1463    pub(crate) fn handle_cross_selection_changed(&self, text: String) {
1464        let handler = self.inner.borrow().handlers.cross_selection_changed.clone();
1465        if let Some(handler) = handler {
1466            handler(text);
1467        }
1468    }
1469
1470    pub(crate) fn handle_gesture_event(&self, event: &mut GestureEventArgs) {
1471        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1472            return;
1473        }
1474        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1475        let handlers = self.inner.borrow().handlers.clone();
1476        match event.kind {
1477            crate::event::GestureEventKind::Pan => {
1478                if let Some(handler) = handlers.pan_gesture {
1479                    handler(event);
1480                }
1481            }
1482            crate::event::GestureEventKind::Pinch => {
1483                if let Some(handler) = handlers.pinch_gesture {
1484                    handler(event);
1485                }
1486            }
1487            crate::event::GestureEventKind::None => {}
1488        }
1489    }
1490
1491    pub(crate) fn handle_bubbled_gesture_event(&self, event: &mut GestureEventArgs) {
1492        self.handle_gesture_event(event);
1493    }
1494
1495    pub(crate) fn handle_long_press_event(&self, event: &mut LongPressEventArgs) {
1496        if !self.is_enabled_for_routing() || !self.is_visible_for_routing() {
1497            return;
1498        }
1499        [event.x, event.y] = self.absolute_to_local_position(event.scene_x, event.scene_y);
1500        if let Some(handler) = self.inner.borrow().handlers.long_press.clone() {
1501            handler(event);
1502        }
1503        if !event.handled
1504            && matches!(event.pointer_type, PointerType::Touch | PointerType::Pen)
1505            && self.has_drag_source()
1506        {
1507            event.handled = self.ensure_drag_gesture().borrow_mut().handle_long_press(
1508                event.x,
1509                event.y,
1510                event.modifiers,
1511            );
1512        }
1513    }
1514
1515    pub(crate) fn handle_bubbled_long_press_event(&self, event: &mut LongPressEventArgs) {
1516        self.handle_long_press_event(event);
1517    }
1518
1519    pub(crate) fn handle_custom_draw(&self, canvas_ptr: usize) {
1520        if let Some(callback) = self.inner.borrow().draw_callback.clone() {
1521            let mut context = DrawContext::new(canvas_ptr);
1522            callback(&mut context);
1523        }
1524    }
1525
1526    pub(crate) fn build(&self) {
1527        if let Some(callback) = self.build_callback.as_ref() {
1528            callback();
1529        }
1530    }
1531
1532    pub(crate) fn downgrade(&self) -> WeakNodeRef {
1533        WeakNodeRef {
1534            inner: Rc::downgrade(&self.inner),
1535        }
1536    }
1537
1538    pub(crate) fn ensure_drag_gesture(&self) -> Rc<RefCell<DragGesture>> {
1539        if let Some(gesture) = self.inner.borrow().drag_gesture.clone() {
1540            return gesture;
1541        }
1542        let weak = self.downgrade();
1543        let gesture = Rc::new(RefCell::new(DragGesture::new(self)));
1544        gesture.borrow_mut().threshold(4.0);
1545        gesture.borrow_mut().set_started({
1546            let weak = weak.clone();
1547            move |_event: DragStartedEvent| {
1548                if let Some(node) = weak.upgrade() {
1549                    node.handle_drag_gesture_started();
1550                }
1551            }
1552        });
1553        gesture
1554            .borrow_mut()
1555            .set_completed(move |event: DragCompletedEvent| {
1556                if let Some(node) = weak.upgrade() {
1557                    node.handle_drag_gesture_completed(event);
1558                }
1559            });
1560        self.inner.borrow_mut().drag_gesture = Some(gesture.clone());
1561        gesture
1562    }
1563
1564    fn handle_drag_gesture_started(&self) {
1565        if !crate::event::begin_drag_session(self.clone()) {
1566            if let Some(gesture) = self.inner.borrow().drag_gesture.clone() {
1567                gesture.borrow_mut().cancel();
1568            }
1569        }
1570    }
1571
1572    fn handle_drag_gesture_completed(&self, event: DragCompletedEvent) {
1573        let mut core = self.inner.borrow_mut();
1574        core.drag_click_pending = false;
1575        core.drag_click_pending_count = 0;
1576        drop(core);
1577        if event.cancelled {
1578            crate::event::cancel_drag_session_for_source(self);
1579        }
1580    }
1581
1582    pub(crate) fn has_drag_source(&self) -> bool {
1583        self.inner.borrow().drag_data_callback.is_some()
1584    }
1585
1586    pub(crate) fn create_drag_data_object(&self) -> Option<DragDataObject> {
1587        let callback = self.inner.borrow().drag_data_callback.clone();
1588        callback.and_then(|callback| callback())
1589    }
1590
1591    pub(crate) fn get_drag_allowed_effects(&self) -> DragDropEffects {
1592        self.inner.borrow().drag_allowed_effects
1593    }
1594
1595    pub(crate) fn notify_drag_completed(&self, effect: DragDropEffects) {
1596        let callback = self.inner.borrow().drag_completed_callback.clone();
1597        if let Some(callback) = callback {
1598            callback(DragCompletedEventArgs { effect });
1599        }
1600    }
1601
1602    pub(crate) fn allows_drop(&self) -> bool {
1603        self.inner.borrow().drop_allowed
1604    }
1605
1606    pub(crate) fn has_drag_enter_handler(&self) -> bool {
1607        self.inner.borrow().drag_enter_callback.is_some()
1608    }
1609
1610    pub(crate) fn has_drag_over_handler(&self) -> bool {
1611        self.inner.borrow().drag_over_callback.is_some()
1612    }
1613
1614    pub(crate) fn handle_drag_enter(&self, args: DragEventArgs) -> DropProposal {
1615        let callback = self.inner.borrow().drag_enter_callback.clone();
1616        callback
1617            .map(|callback| callback(args))
1618            .unwrap_or_else(DropProposal::none)
1619    }
1620
1621    pub(crate) fn handle_drag_over(&self, args: DragEventArgs) -> DropProposal {
1622        let callback = self.inner.borrow().drag_over_callback.clone();
1623        callback
1624            .map(|callback| callback(args))
1625            .unwrap_or_else(DropProposal::none)
1626    }
1627
1628    pub(crate) fn handle_drag_leave(&self, args: DragEventArgs) {
1629        let callback = self.inner.borrow().drag_leave_callback.clone();
1630        if let Some(callback) = callback {
1631            callback(args);
1632        }
1633    }
1634
1635    pub(crate) fn handle_drop_event(&self, args: DragEventArgs) {
1636        let callback = self.inner.borrow().drop_callback.clone();
1637        if let Some(callback) = callback {
1638            callback(args);
1639        }
1640    }
1641
1642    pub(crate) fn allows_external_drop(&self) -> bool {
1643        self.inner.borrow().behavior.external_drop_allowed
1644    }
1645
1646    pub(crate) fn has_external_drag_enter_handler(&self) -> bool {
1647        self.inner.borrow().external_drag_enter_callback.is_some()
1648    }
1649
1650    pub(crate) fn has_external_drag_over_handler(&self) -> bool {
1651        self.inner.borrow().external_drag_over_callback.is_some()
1652    }
1653
1654    pub(crate) fn handle_external_drag_enter(&self, args: ExternalDropEventArgs) -> DropProposal {
1655        let callback = self.inner.borrow().external_drag_enter_callback.clone();
1656        callback
1657            .map(|callback| callback(args))
1658            .unwrap_or_else(DropProposal::none)
1659    }
1660
1661    pub(crate) fn handle_external_drag_over(&self, args: ExternalDropEventArgs) -> DropProposal {
1662        let callback = self.inner.borrow().external_drag_over_callback.clone();
1663        callback
1664            .map(|callback| callback(args))
1665            .unwrap_or_else(DropProposal::none)
1666    }
1667
1668    pub(crate) fn handle_external_drag_leave(&self, args: ExternalDropEventArgs) {
1669        let callback = self.inner.borrow().external_drag_leave_callback.clone();
1670        if let Some(callback) = callback {
1671            callback(args);
1672        }
1673    }
1674
1675    pub(crate) fn handle_external_drop_event(&self, args: ExternalDropEventArgs) {
1676        let callback = self.inner.borrow().external_drop_callback.clone();
1677        if let Some(callback) = callback {
1678            callback(args);
1679        }
1680    }
1681}
1682
1683/// Universal retained-node capabilities shared by every visual node and control.
1684///
1685/// Rust controls use composition rather than FUI-AS class inheritance, but this
1686/// trait preserves the common retained identity, state, semantics, focus,
1687/// routed-input, gesture, geometry, and child-inspection contract. Layout and
1688/// appearance are exposed separately through the cohesive surface traits.
1689pub trait Node: Clone {
1690    #[doc(hidden)]
1691    fn node_ref(&self) -> NodeRef {
1692        self.retained_node_ref()
1693    }
1694    #[doc(hidden)]
1695    fn retained_node_ref(&self) -> NodeRef;
1696    #[doc(hidden)]
1697    fn retained_owner_attachment(&self) -> Option<Rc<dyn Any>> {
1698        None
1699    }
1700    #[doc(hidden)]
1701    fn build_self(&self);
1702
1703    #[doc(hidden)]
1704    fn required_font_ids_for_preparation(&self) -> Vec<u32> {
1705        Vec::new()
1706    }
1707
1708    #[doc(hidden)]
1709    fn apply_node_id(&self, node_id: String) {
1710        let node_ref = self.node_ref();
1711        node_ref.set_node_id(node_id);
1712        if self.has_built_handle() {
1713            self.notify_retained_mutation();
1714        }
1715    }
1716
1717    #[doc(hidden)]
1718    fn apply_semantic_label(&self, label: String) {
1719        let node_ref = self.node_ref();
1720        node_ref.inner.borrow_mut().behavior.semantic_label = Some(label.clone());
1721        let handle = node_ref.handle();
1722        if handle != NodeHandle::INVALID {
1723            ui::set_semantic_label(handle.raw(), &label);
1724            self.notify_retained_mutation();
1725        }
1726    }
1727
1728    #[doc(hidden)]
1729    fn apply_focusable(&self, enabled: bool, tab_index: i32) {
1730        let node_ref = self.node_ref();
1731        if enabled {
1732            node_ref.require_interactive();
1733        }
1734        let visible = node_ref.is_effectively_visible_for_routing();
1735        let mut core = node_ref.inner.borrow_mut();
1736        core.behavior.focusable = Some((enabled, tab_index));
1737        let interactive = core.behavior.enabled && core.behavior.inherited_enabled && visible;
1738        let handle = core.handle;
1739        drop(core);
1740        if handle != NodeHandle::INVALID {
1741            ui::set_focusable(handle.raw(), interactive && enabled, tab_index);
1742            self.notify_retained_mutation();
1743        }
1744    }
1745
1746    #[doc(hidden)]
1747    fn apply_focus_now(&self) {
1748        let handle = self.node_ref().handle();
1749        if handle != NodeHandle::INVALID {
1750            ui::request_focus(handle.raw());
1751        }
1752    }
1753
1754    #[doc(hidden)]
1755    fn apply_enabled(&self, enabled: bool) {
1756        self.node_ref().set_own_enabled(enabled);
1757    }
1758
1759    #[doc(hidden)]
1760    fn apply_focus_changed_handler(&self, handler: Rc<dyn Fn(FocusChangedEventArgs)>) {
1761        self.node_ref().inner.borrow_mut().handlers.focus_changed = Some(handler);
1762    }
1763
1764    fn node_id(&self, node_id: impl Into<String>) -> &Self
1765    where
1766        Self: Sized,
1767    {
1768        self.apply_node_id(node_id.into());
1769        self
1770    }
1771
1772    fn semantic_role(&self, role: SemanticRole) -> &Self
1773    where
1774        Self: Sized,
1775    {
1776        let node_ref = self.node_ref();
1777        node_ref.inner.borrow_mut().behavior.semantic_role = Some(role);
1778        if self.has_built_handle() {
1779            ui::set_semantic_role(self.handle().raw(), role as u32);
1780            self.notify_retained_mutation();
1781        }
1782        self
1783    }
1784
1785    fn semantic_label(&self, label: impl Into<String>) -> &Self
1786    where
1787        Self: Sized,
1788    {
1789        self.apply_semantic_label(label.into());
1790        self
1791    }
1792
1793    fn semantic_checked(&self, state: SemanticCheckedState) -> &Self
1794    where
1795        Self: Sized,
1796    {
1797        let node_ref = self.node_ref();
1798        node_ref.inner.borrow_mut().behavior.semantic_checked = Some(state);
1799        if self.has_built_handle() {
1800            ui::set_semantic_checked(self.handle().raw(), state as u32);
1801            self.notify_retained_mutation();
1802        }
1803        self
1804    }
1805
1806    fn semantic_disabled(&self, disabled: bool) -> &Self
1807    where
1808        Self: Sized,
1809    {
1810        let node_ref = self.node_ref();
1811        let mut core = node_ref.inner.borrow_mut();
1812        core.behavior.track_semantic_disabled_from_enabled = false;
1813        core.behavior.semantic_disabled = Some(disabled);
1814        drop(core);
1815        if self.has_built_handle() {
1816            ui::set_semantic_disabled(self.handle().raw(), true, disabled);
1817            self.notify_retained_mutation();
1818        }
1819        self
1820    }
1821
1822    fn clear_semantic_disabled(&self) -> &Self
1823    where
1824        Self: Sized,
1825    {
1826        let node_ref = self.node_ref();
1827        let mut core = node_ref.inner.borrow_mut();
1828        core.behavior.track_semantic_disabled_from_enabled = false;
1829        core.behavior.semantic_disabled = None;
1830        drop(core);
1831        if self.has_built_handle() {
1832            ui::set_semantic_disabled(self.handle().raw(), false, false);
1833            self.notify_retained_mutation();
1834        }
1835        self
1836    }
1837
1838    fn semantic_selected(&self, selected: bool) -> &Self
1839    where
1840        Self: Sized,
1841    {
1842        self.node_ref()
1843            .inner
1844            .borrow_mut()
1845            .behavior
1846            .semantic_selected = Some(selected);
1847        if self.has_built_handle() {
1848            ui::set_semantic_selected(self.handle().raw(), true, selected);
1849            self.notify_retained_mutation();
1850        }
1851        self
1852    }
1853
1854    fn clear_semantic_selected(&self) -> &Self
1855    where
1856        Self: Sized,
1857    {
1858        self.node_ref()
1859            .inner
1860            .borrow_mut()
1861            .behavior
1862            .semantic_selected = None;
1863        if self.has_built_handle() {
1864            ui::set_semantic_selected(self.handle().raw(), false, false);
1865            self.notify_retained_mutation();
1866        }
1867        self
1868    }
1869
1870    fn semantic_expanded(&self, expanded: bool) -> &Self
1871    where
1872        Self: Sized,
1873    {
1874        self.node_ref()
1875            .inner
1876            .borrow_mut()
1877            .behavior
1878            .semantic_expanded = Some(expanded);
1879        if self.has_built_handle() {
1880            ui::set_semantic_expanded(self.handle().raw(), true, expanded);
1881            self.notify_retained_mutation();
1882        }
1883        self
1884    }
1885
1886    fn clear_semantic_expanded(&self) -> &Self
1887    where
1888        Self: Sized,
1889    {
1890        self.node_ref()
1891            .inner
1892            .borrow_mut()
1893            .behavior
1894            .semantic_expanded = None;
1895        if self.has_built_handle() {
1896            ui::set_semantic_expanded(self.handle().raw(), false, false);
1897            self.notify_retained_mutation();
1898        }
1899        self
1900    }
1901
1902    fn semantic_value_range(&self, value_now: f32, value_min: f32, value_max: f32) -> &Self
1903    where
1904        Self: Sized,
1905    {
1906        self.node_ref()
1907            .inner
1908            .borrow_mut()
1909            .behavior
1910            .semantic_value_range = Some((value_now, value_min, value_max));
1911        if self.has_built_handle() {
1912            ui::set_semantic_value_range(
1913                self.handle().raw(),
1914                true,
1915                value_now,
1916                value_min,
1917                value_max,
1918            );
1919            self.notify_retained_mutation();
1920        }
1921        self
1922    }
1923
1924    fn clear_semantic_value_range(&self) -> &Self
1925    where
1926        Self: Sized,
1927    {
1928        self.node_ref()
1929            .inner
1930            .borrow_mut()
1931            .behavior
1932            .semantic_value_range = None;
1933        if self.has_built_handle() {
1934            ui::set_semantic_value_range(self.handle().raw(), false, 0.0, 0.0, 0.0);
1935            self.notify_retained_mutation();
1936        }
1937        self
1938    }
1939
1940    fn semantic_orientation(&self, orientation: Orientation) -> &Self
1941    where
1942        Self: Sized,
1943    {
1944        self.node_ref()
1945            .inner
1946            .borrow_mut()
1947            .behavior
1948            .semantic_orientation = Some(orientation);
1949        if self.has_built_handle() {
1950            ui::set_semantic_orientation(self.handle().raw(), orientation as u32);
1951            self.notify_retained_mutation();
1952        }
1953        self
1954    }
1955
1956    fn request_semantic_announcement(&self) -> &Self
1957    where
1958        Self: Sized,
1959    {
1960        if self.has_built_handle() {
1961            ui::request_semantic_announcement(self.handle().raw());
1962        }
1963        self
1964    }
1965
1966    fn child_count(&self) -> usize {
1967        self.node_ref().children().len()
1968    }
1969
1970    fn is_enabled(&self) -> bool {
1971        self.node_ref().is_enabled_for_routing()
1972    }
1973
1974    fn is_visible(&self) -> bool {
1975        self.node_ref().is_effectively_visible_for_routing()
1976    }
1977
1978    fn cursor_style(&self) -> CursorStyle {
1979        self.node_ref().cursor_style_for_routing()
1980    }
1981
1982    fn persist_state(&self, adapter: Rc<dyn PersistedStateAdapter>) -> &Self
1983    where
1984        Self: Sized,
1985    {
1986        self.node_ref().register_persisted_state_adapter(adapter);
1987        self
1988    }
1989
1990    fn handle(&self) -> NodeHandle {
1991        self.node_ref().inner.borrow().handle
1992    }
1993
1994    fn has_built_handle(&self) -> bool {
1995        self.handle() != NodeHandle::INVALID
1996    }
1997
1998    fn on_context_menu(&self, handler: impl Fn(ContextMenuEventArgs) + 'static) -> &Self
1999    where
2000        Self: Sized,
2001    {
2002        self.node_ref()
2003            .inner
2004            .borrow_mut()
2005            .behavior
2006            .context_menu_handler = Some(Rc::new(handler));
2007        self
2008    }
2009
2010    fn clear_context_menu(&self) -> &Self
2011    where
2012        Self: Sized,
2013    {
2014        self.node_ref()
2015            .inner
2016            .borrow_mut()
2017            .behavior
2018            .context_menu_handler = None;
2019        self
2020    }
2021
2022    fn disable_context_menu(&self, flag: bool) -> &Self
2023    where
2024        Self: Sized,
2025    {
2026        self.node_ref()
2027            .inner
2028            .borrow_mut()
2029            .behavior
2030            .context_menu_disabled = flag;
2031        self
2032    }
2033
2034    /// Handles the low-level routed pointer-click event.
2035    ///
2036    /// This is not control activation. Use [`Button::on_click`](crate::Button::on_click)
2037    /// for a button action that also supports keyboard activation.
2038    fn on_pointer_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2039    where
2040        Self: Sized,
2041    {
2042        let node_ref = self.node_ref();
2043        node_ref.inner.borrow_mut().handlers.pointer_click = Some(Rc::new(handler));
2044        node_ref.require_interactive();
2045        self
2046    }
2047
2048    /// Handles a low-level routed pointer double-click after the ordinary pointer-click callback.
2049    fn on_pointer_double_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2050    where
2051        Self: Sized,
2052    {
2053        let node_ref = self.node_ref();
2054        node_ref.inner.borrow_mut().handlers.pointer_double_click = Some(Rc::new(handler));
2055        node_ref.require_interactive();
2056        self
2057    }
2058
2059    /// Handles a low-level routed pointer triple-click after the ordinary pointer-click callback.
2060    fn on_pointer_triple_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2061    where
2062        Self: Sized,
2063    {
2064        let node_ref = self.node_ref();
2065        node_ref.inner.borrow_mut().handlers.pointer_triple_click = Some(Rc::new(handler));
2066        node_ref.require_interactive();
2067        self
2068    }
2069
2070    fn on_pointer_down(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2071    where
2072        Self: Sized,
2073    {
2074        let node_ref = self.node_ref();
2075        node_ref.inner.borrow_mut().handlers.pointer_down = Some(Rc::new(handler));
2076        node_ref.require_interactive();
2077        self
2078    }
2079
2080    fn on_pointer_move(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2081    where
2082        Self: Sized,
2083    {
2084        let node_ref = self.node_ref();
2085        node_ref.inner.borrow_mut().handlers.pointer_move = Some(Rc::new(handler));
2086        node_ref.require_interactive();
2087        self
2088    }
2089
2090    fn on_pointer_up(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2091    where
2092        Self: Sized,
2093    {
2094        let node_ref = self.node_ref();
2095        node_ref.inner.borrow_mut().handlers.pointer_up = Some(Rc::new(handler));
2096        node_ref.require_interactive();
2097        self
2098    }
2099
2100    fn on_pointer_enter(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2101    where
2102        Self: Sized,
2103    {
2104        let node_ref = self.node_ref();
2105        node_ref.inner.borrow_mut().handlers.pointer_enter = Some(Rc::new(handler));
2106        node_ref.require_interactive();
2107        self
2108    }
2109
2110    fn on_pointer_leave(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2111    where
2112        Self: Sized,
2113    {
2114        let node_ref = self.node_ref();
2115        node_ref.inner.borrow_mut().handlers.pointer_leave = Some(Rc::new(handler));
2116        node_ref.require_interactive();
2117        self
2118    }
2119
2120    fn on_pointer_cancel(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2121    where
2122        Self: Sized,
2123    {
2124        let node_ref = self.node_ref();
2125        node_ref.inner.borrow_mut().handlers.pointer_cancel = Some(Rc::new(handler));
2126        node_ref.require_interactive();
2127        self
2128    }
2129
2130    fn on_wheel(&self, handler: impl Fn(&mut WheelEventArgs) + 'static) -> &Self
2131    where
2132        Self: Sized,
2133    {
2134        let node_ref = self.node_ref();
2135        node_ref.inner.borrow_mut().handlers.wheel = Some(Rc::new(handler));
2136        node_ref.require_interactive();
2137        self
2138    }
2139
2140    fn on_pan_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2141    where
2142        Self: Sized,
2143    {
2144        self.node_ref().inner.borrow_mut().handlers.pan_gesture = Some(Rc::new(handler));
2145        self
2146    }
2147
2148    fn on_pinch_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2149    where
2150        Self: Sized,
2151    {
2152        self.node_ref().inner.borrow_mut().handlers.pinch_gesture = Some(Rc::new(handler));
2153        self
2154    }
2155
2156    fn long_press_options(&self, minimum_duration_ms: i32, movement_tolerance: f32) -> &Self
2157    where
2158        Self: Sized,
2159    {
2160        let node_ref = self.node_ref();
2161        let mut core = node_ref.inner.borrow_mut();
2162        let handlers = &mut core.handlers;
2163        handlers.long_press_minimum_duration_ms = minimum_duration_ms.max(0);
2164        handlers.long_press_movement_tolerance = movement_tolerance.max(0.0);
2165        self
2166    }
2167
2168    fn on_long_press(&self, handler: impl Fn(&mut LongPressEventArgs) + 'static) -> &Self
2169    where
2170        Self: Sized,
2171    {
2172        let node_ref = self.node_ref();
2173        node_ref.inner.borrow_mut().handlers.long_press = Some(Rc::new(handler));
2174        node_ref.require_interactive();
2175        self
2176    }
2177
2178    fn focusable(&self, enabled: bool, tab_index: i32) -> &Self
2179    where
2180        Self: Sized,
2181    {
2182        self.apply_focusable(enabled, tab_index);
2183        self
2184    }
2185
2186    fn focus_now(&self) -> &Self
2187    where
2188        Self: Sized,
2189    {
2190        self.apply_focus_now();
2191        self
2192    }
2193
2194    fn enabled(&self, enabled: bool) -> &Self
2195    where
2196        Self: Sized,
2197    {
2198        self.apply_enabled(enabled);
2199        self
2200    }
2201
2202    fn visibility(&self, visibility: Visibility) -> &Self
2203    where
2204        Self: Sized,
2205    {
2206        self.node_ref().set_own_visibility(visibility);
2207        if self.has_built_handle() {
2208            self.notify_retained_layout_mutation();
2209        }
2210        self
2211    }
2212
2213    fn cursor(&self, style: CursorStyle) -> &Self
2214    where
2215        Self: Sized,
2216    {
2217        self.node_ref().inner.borrow_mut().behavior.cursor = Some(style);
2218        crate::event::handle_cursor_style_changed(self.handle());
2219        self
2220    }
2221
2222    fn clear_cursor(&self) -> &Self
2223    where
2224        Self: Sized,
2225    {
2226        self.node_ref().inner.borrow_mut().behavior.cursor = None;
2227        crate::event::handle_cursor_style_changed(self.handle());
2228        self
2229    }
2230
2231    fn on_key_down(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2232    where
2233        Self: Sized,
2234    {
2235        self.node_ref().inner.borrow_mut().handlers.key_down = Some(Rc::new(handler));
2236        self
2237    }
2238
2239    fn on_key_up(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2240    where
2241        Self: Sized,
2242    {
2243        self.node_ref().inner.borrow_mut().handlers.key_up = Some(Rc::new(handler));
2244        self
2245    }
2246
2247    fn on_focus_changed(&self, handler: impl Fn(FocusChangedEventArgs) + 'static) -> &Self
2248    where
2249        Self: Sized,
2250    {
2251        self.apply_focus_changed_handler(Rc::new(handler));
2252        self
2253    }
2254
2255    fn drag_allowed_effects(&self, effects: DragDropEffects) -> &Self
2256    where
2257        Self: Sized,
2258    {
2259        self.node_ref().inner.borrow_mut().drag_allowed_effects = effects;
2260        self
2261    }
2262
2263    fn drag_data(&self, handler: impl Fn() -> Option<DragDataObject> + 'static) -> &Self
2264    where
2265        Self: Sized,
2266    {
2267        let node_ref = self.node_ref();
2268        node_ref.inner.borrow_mut().drag_data_callback = Some(Rc::new(handler));
2269        node_ref.require_interactive();
2270        node_ref.ensure_drag_gesture();
2271        self
2272    }
2273
2274    fn clear_drag_data(&self) -> &Self
2275    where
2276        Self: Sized,
2277    {
2278        self.node_ref().inner.borrow_mut().drag_data_callback = None;
2279        self
2280    }
2281
2282    fn allow_drop(&self, flag: bool) -> &Self
2283    where
2284        Self: Sized,
2285    {
2286        let node_ref = self.node_ref();
2287        node_ref.inner.borrow_mut().drop_allowed = flag;
2288        if flag {
2289            node_ref.require_interactive();
2290        }
2291        self
2292    }
2293
2294    fn on_drag_completed(&self, handler: impl Fn(DragCompletedEventArgs) + 'static) -> &Self
2295    where
2296        Self: Sized,
2297    {
2298        self.node_ref().inner.borrow_mut().drag_completed_callback = Some(Rc::new(handler));
2299        self
2300    }
2301
2302    fn on_drag_enter(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2303    where
2304        Self: Sized,
2305    {
2306        let node_ref = self.node_ref();
2307        node_ref.inner.borrow_mut().drag_enter_callback = Some(Rc::new(handler));
2308        self.allow_drop(true);
2309        node_ref.require_interactive();
2310        self
2311    }
2312
2313    fn on_drag_over(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2314    where
2315        Self: Sized,
2316    {
2317        let node_ref = self.node_ref();
2318        node_ref.inner.borrow_mut().drag_over_callback = Some(Rc::new(handler));
2319        self.allow_drop(true);
2320        node_ref.require_interactive();
2321        self
2322    }
2323
2324    fn on_drag_leave(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2325    where
2326        Self: Sized,
2327    {
2328        let node_ref = self.node_ref();
2329        node_ref.inner.borrow_mut().drag_leave_callback = Some(Rc::new(handler));
2330        self.allow_drop(true);
2331        node_ref.require_interactive();
2332        self
2333    }
2334
2335    fn on_drop(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2336    where
2337        Self: Sized,
2338    {
2339        let node_ref = self.node_ref();
2340        node_ref.inner.borrow_mut().drop_callback = Some(Rc::new(handler));
2341        self.allow_drop(true);
2342        node_ref.require_interactive();
2343        self
2344    }
2345
2346    fn allow_external_drop(&self, flag: bool) -> &Self
2347    where
2348        Self: Sized,
2349    {
2350        let node_ref = self.node_ref();
2351        node_ref.inner.borrow_mut().behavior.external_drop_allowed = flag;
2352        if flag {
2353            node_ref.require_interactive();
2354        }
2355        self
2356    }
2357
2358    fn on_external_drag_enter(
2359        &self,
2360        handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2361    ) -> &Self
2362    where
2363        Self: Sized,
2364    {
2365        let node_ref = self.node_ref();
2366        node_ref.inner.borrow_mut().external_drag_enter_callback = Some(Rc::new(handler));
2367        self.allow_external_drop(true);
2368        node_ref.require_interactive();
2369        self
2370    }
2371
2372    fn on_external_drag_over(
2373        &self,
2374        handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2375    ) -> &Self
2376    where
2377        Self: Sized,
2378    {
2379        let node_ref = self.node_ref();
2380        node_ref.inner.borrow_mut().external_drag_over_callback = Some(Rc::new(handler));
2381        self.allow_external_drop(true);
2382        node_ref.require_interactive();
2383        self
2384    }
2385
2386    fn on_external_drag_leave(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2387    where
2388        Self: Sized,
2389    {
2390        let node_ref = self.node_ref();
2391        node_ref.inner.borrow_mut().external_drag_leave_callback = Some(Rc::new(handler));
2392        self.allow_external_drop(true);
2393        node_ref.require_interactive();
2394        self
2395    }
2396
2397    fn on_external_drop(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2398    where
2399        Self: Sized,
2400    {
2401        let node_ref = self.node_ref();
2402        node_ref.inner.borrow_mut().external_drop_callback = Some(Rc::new(handler));
2403        self.allow_external_drop(true);
2404        node_ref.require_interactive();
2405        self
2406    }
2407
2408    fn get_bounds(&self) -> [f32; 4] {
2409        if !self.has_built_handle() {
2410            return [0.0; 4];
2411        }
2412        ui::get_bounds(self.handle().raw()).unwrap_or([0.0; 4])
2413    }
2414
2415    fn absolute_to_local_position(&self, absolute_x: f32, absolute_y: f32) -> [f32; 2] {
2416        let bounds = self.get_bounds();
2417        [absolute_x - bounds[0], absolute_y - bounds[1]]
2418    }
2419
2420    fn local_to_absolute_position(&self, local_x: f32, local_y: f32) -> [f32; 2] {
2421        let bounds = self.get_bounds();
2422        [bounds[0] + local_x, bounds[1] + local_y]
2423    }
2424
2425    fn ensure_handle(&self) {
2426        if self.has_built_handle() {
2427            return;
2428        }
2429        let node_ref = self.node_ref();
2430        let node_type = node_ref.inner.borrow().kind.node_type();
2431        let handle = NodeHandle(ui::create_node(node_type as u32));
2432        {
2433            let mut core = node_ref.inner.borrow_mut();
2434            core.handle = handle;
2435            core.mounted = true;
2436        }
2437        crate::event::register_node(&node_ref);
2438    }
2439
2440    fn build(&self) {
2441        self.ensure_handle();
2442        self.build_self();
2443        self.build_children();
2444    }
2445
2446    fn dispose(&self) {
2447        self.node_ref().dispose();
2448    }
2449
2450    fn build_children(&self) {
2451        let node_ref = self.node_ref();
2452        {
2453            let mut core = node_ref.inner.borrow_mut();
2454            if core.children_built {
2455                return;
2456            }
2457            core.children_built = true;
2458        }
2459        let children = node_ref.inner.borrow().children.clone();
2460        for child in children {
2461            child.build();
2462            ui::add_child(self.handle().raw(), child.handle().raw());
2463        }
2464    }
2465
2466    fn append_child<T: Node>(&self, child: &T) {
2467        let self_node_ref = self.node_ref();
2468        let child_node_ref = child.node_ref();
2469        if Rc::ptr_eq(&self_node_ref.inner, &child_node_ref.inner) {
2470            return;
2471        }
2472        if self_node_ref
2473            .inner
2474            .borrow()
2475            .children
2476            .iter()
2477            .any(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2478        {
2479            return;
2480        }
2481        if let Some(previous_parent) = child_node_ref.inner.borrow().parent.upgrade() {
2482            if Rc::ptr_eq(&previous_parent, &self_node_ref.inner) {
2483                return;
2484            }
2485            let child_handle = child.handle();
2486            {
2487                let mut previous_parent_core = previous_parent.borrow_mut();
2488                previous_parent_core
2489                    .children
2490                    .retain(|candidate| !Rc::ptr_eq(&candidate.inner, &child_node_ref.inner));
2491            }
2492            if previous_parent.borrow().handle != NodeHandle::INVALID
2493                && child_handle != NodeHandle::INVALID
2494            {
2495                ui::remove_child(previous_parent.borrow().handle.raw(), child_handle.raw());
2496            }
2497        }
2498
2499        {
2500            let mut child_core = child_node_ref.inner.borrow_mut();
2501            child_core.parent = Rc::downgrade(&self_node_ref.inner);
2502        }
2503        child_node_ref.set_inherited_enabled(self_node_ref.is_enabled_for_routing());
2504        self_node_ref
2505            .inner
2506            .borrow_mut()
2507            .children
2508            .push(child_node_ref.clone());
2509        if let Some(owner) = child.retained_owner_attachment() {
2510            self_node_ref
2511                .inner
2512                .borrow_mut()
2513                .retained_attachments
2514                .push(owner);
2515        }
2516        self_node_ref.inner.borrow_mut().children_built = false;
2517        if self.has_built_handle() {
2518            child.build();
2519            ui::add_child(self.handle().raw(), child.handle().raw());
2520            self_node_ref.inner.borrow_mut().children_built = true;
2521            self.notify_retained_mutation();
2522            self.notify_retained_child_layout_changed();
2523        }
2524    }
2525
2526    fn remove_child<T: Node>(&self, child: &T) -> bool {
2527        let child_handle = child.handle();
2528        let child_node_ref = child.node_ref();
2529        let removed = {
2530            let self_node_ref = self.node_ref();
2531            let mut core = self_node_ref.inner.borrow_mut();
2532            let Some(index) = core
2533                .children
2534                .iter()
2535                .position(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2536            else {
2537                return false;
2538            };
2539            core.children.remove(index)
2540        };
2541        removed.inner.borrow_mut().parent = Weak::new();
2542        removed.set_inherited_enabled(true);
2543        self.node_ref().inner.borrow_mut().children_built = false;
2544        if self.has_built_handle() && child.has_built_handle() {
2545            ui::remove_child(self.handle().raw(), child_handle.raw());
2546            self.node_ref().inner.borrow_mut().children_built = true;
2547            self.notify_retained_mutation();
2548            self.notify_retained_child_layout_changed();
2549        }
2550        true
2551    }
2552
2553    fn parent_handle(&self) -> Option<NodeHandle> {
2554        self.node_ref()
2555            .inner
2556            .borrow()
2557            .parent
2558            .upgrade()
2559            .map(|parent| parent.borrow().handle)
2560    }
2561
2562    fn notify_retained_layout_mutation(&self) {
2563        self.notify_retained_mutation();
2564    }
2565
2566    fn notify_retained_mutation(&self) {
2567        crate::frame_scheduler::mark_needs_commit();
2568    }
2569
2570    fn notify_retained_child_layout_changed(&self) {}
2571
2572    #[doc(hidden)]
2573    fn bind_scroll_proxy_target_handle(&self, scroll_handle: u64) -> &Self
2574    where
2575        Self: Sized,
2576    {
2577        let node_ref = self.node_ref();
2578        node_ref.inner.borrow_mut().behavior.scroll_proxy_target = Some(scroll_handle);
2579        if self.has_built_handle() {
2580            ui::set_scroll_proxy_target(self.handle().raw(), scroll_handle);
2581            self.notify_retained_mutation();
2582        }
2583        self
2584    }
2585
2586    fn preserve_selection_on_pointer_down(&self, preserve: bool) -> &Self
2587    where
2588        Self: Sized,
2589    {
2590        let node_ref = self.node_ref();
2591        node_ref
2592            .inner
2593            .borrow_mut()
2594            .behavior
2595            .preserve_selection_on_pointer_down = preserve;
2596        if self.has_built_handle() {
2597            ui::set_preserve_selection_on_pointer_down(self.handle().raw(), preserve);
2598            self.notify_retained_mutation();
2599        }
2600        self
2601    }
2602
2603    fn tool_tip(&self, tool_tip: ToolTip) -> &Self
2604    where
2605        Self: Sized,
2606    {
2607        let node_ref = self.node_ref();
2608        node_ref.inner.borrow_mut().behavior.tool_tip = Some(tool_tip.clone());
2609        node_ref.require_interactive();
2610        if self.has_built_handle()
2611            && node_ref.is_enabled_for_routing()
2612            && node_ref.is_visible_for_routing()
2613        {
2614            ui::set_interactive(self.handle().raw(), true);
2615            self.notify_retained_mutation();
2616        }
2617        crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, Some(tool_tip));
2618        self
2619    }
2620
2621    fn tool_tip_text(&self, text: impl Into<String>) -> &Self
2622    where
2623        Self: Sized,
2624    {
2625        self.tool_tip(ToolTip::text(text))
2626    }
2627
2628    fn clear_tool_tip(&self) -> &Self
2629    where
2630        Self: Sized,
2631    {
2632        let node_ref = self.node_ref();
2633        node_ref.inner.borrow_mut().behavior.tool_tip = None;
2634        crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, None);
2635        self
2636    }
2637}
2638
2639impl<T: Node> Node for &T {
2640    fn retained_node_ref(&self) -> NodeRef {
2641        (*self).retained_node_ref()
2642    }
2643
2644    fn retained_owner_attachment(&self) -> Option<Rc<dyn Any>> {
2645        (*self).retained_owner_attachment()
2646    }
2647
2648    fn build_self(&self) {
2649        (*self).build_self();
2650    }
2651}