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