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
1683pub 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 fn on_pointer_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2040 where
2041 Self: Sized,
2042 {
2043 let node_ref = self.node_ref();
2044 node_ref.inner.borrow_mut().handlers.pointer_click = Some(Rc::new(handler));
2045 node_ref.require_interactive();
2046 self
2047 }
2048
2049 fn on_pointer_double_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2051 where
2052 Self: Sized,
2053 {
2054 let node_ref = self.node_ref();
2055 node_ref.inner.borrow_mut().handlers.pointer_double_click = Some(Rc::new(handler));
2056 node_ref.require_interactive();
2057 self
2058 }
2059
2060 fn on_pointer_triple_click(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2062 where
2063 Self: Sized,
2064 {
2065 let node_ref = self.node_ref();
2066 node_ref.inner.borrow_mut().handlers.pointer_triple_click = Some(Rc::new(handler));
2067 node_ref.require_interactive();
2068 self
2069 }
2070
2071 fn on_pointer_down(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2072 where
2073 Self: Sized,
2074 {
2075 let node_ref = self.node_ref();
2076 node_ref.inner.borrow_mut().handlers.pointer_down = Some(Rc::new(handler));
2077 node_ref.require_interactive();
2078 self
2079 }
2080
2081 fn on_pointer_move(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2082 where
2083 Self: Sized,
2084 {
2085 let node_ref = self.node_ref();
2086 node_ref.inner.borrow_mut().handlers.pointer_move = Some(Rc::new(handler));
2087 node_ref.require_interactive();
2088 self
2089 }
2090
2091 fn on_pointer_up(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2092 where
2093 Self: Sized,
2094 {
2095 let node_ref = self.node_ref();
2096 node_ref.inner.borrow_mut().handlers.pointer_up = Some(Rc::new(handler));
2097 node_ref.require_interactive();
2098 self
2099 }
2100
2101 fn on_pointer_enter(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2102 where
2103 Self: Sized,
2104 {
2105 let node_ref = self.node_ref();
2106 node_ref.inner.borrow_mut().handlers.pointer_enter = Some(Rc::new(handler));
2107 node_ref.require_interactive();
2108 self
2109 }
2110
2111 fn on_pointer_leave(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2112 where
2113 Self: Sized,
2114 {
2115 let node_ref = self.node_ref();
2116 node_ref.inner.borrow_mut().handlers.pointer_leave = Some(Rc::new(handler));
2117 node_ref.require_interactive();
2118 self
2119 }
2120
2121 fn on_pointer_cancel(&self, handler: impl Fn(&mut PointerEventArgs) + 'static) -> &Self
2122 where
2123 Self: Sized,
2124 {
2125 let node_ref = self.node_ref();
2126 node_ref.inner.borrow_mut().handlers.pointer_cancel = Some(Rc::new(handler));
2127 node_ref.require_interactive();
2128 self
2129 }
2130
2131 fn on_wheel(&self, handler: impl Fn(&mut WheelEventArgs) + 'static) -> &Self
2132 where
2133 Self: Sized,
2134 {
2135 let node_ref = self.node_ref();
2136 node_ref.inner.borrow_mut().handlers.wheel = Some(Rc::new(handler));
2137 node_ref.require_interactive();
2138 self
2139 }
2140
2141 fn on_pan_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2142 where
2143 Self: Sized,
2144 {
2145 self.node_ref().inner.borrow_mut().handlers.pan_gesture = Some(Rc::new(handler));
2146 self
2147 }
2148
2149 fn on_pinch_gesture(&self, handler: impl Fn(&mut GestureEventArgs) + 'static) -> &Self
2150 where
2151 Self: Sized,
2152 {
2153 self.node_ref().inner.borrow_mut().handlers.pinch_gesture = Some(Rc::new(handler));
2154 self
2155 }
2156
2157 fn long_press_options(&self, minimum_duration_ms: i32, movement_tolerance: f32) -> &Self
2158 where
2159 Self: Sized,
2160 {
2161 let node_ref = self.node_ref();
2162 let mut core = node_ref.inner.borrow_mut();
2163 let handlers = &mut core.handlers;
2164 handlers.long_press_minimum_duration_ms = minimum_duration_ms.max(0);
2165 handlers.long_press_movement_tolerance = movement_tolerance.max(0.0);
2166 self
2167 }
2168
2169 fn on_long_press(&self, handler: impl Fn(&mut LongPressEventArgs) + 'static) -> &Self
2170 where
2171 Self: Sized,
2172 {
2173 let node_ref = self.node_ref();
2174 node_ref.inner.borrow_mut().handlers.long_press = Some(Rc::new(handler));
2175 node_ref.require_interactive();
2176 self
2177 }
2178
2179 fn focusable(&self, enabled: bool, tab_index: i32) -> &Self
2180 where
2181 Self: Sized,
2182 {
2183 self.apply_focusable(enabled, tab_index);
2184 self
2185 }
2186
2187 fn focus_now(&self) -> &Self
2188 where
2189 Self: Sized,
2190 {
2191 self.apply_focus_now();
2192 self
2193 }
2194
2195 fn enabled(&self, enabled: bool) -> &Self
2196 where
2197 Self: Sized,
2198 {
2199 self.apply_enabled(enabled);
2200 self
2201 }
2202
2203 fn visibility(&self, visibility: Visibility) -> &Self
2204 where
2205 Self: Sized,
2206 {
2207 self.node_ref().set_own_visibility(visibility);
2208 if self.has_built_handle() {
2209 self.notify_retained_layout_mutation();
2210 }
2211 self
2212 }
2213
2214 fn cursor(&self, style: CursorStyle) -> &Self
2215 where
2216 Self: Sized,
2217 {
2218 self.node_ref().inner.borrow_mut().behavior.cursor = Some(style);
2219 crate::event::handle_cursor_style_changed(self.handle());
2220 self
2221 }
2222
2223 fn clear_cursor(&self) -> &Self
2224 where
2225 Self: Sized,
2226 {
2227 self.node_ref().inner.borrow_mut().behavior.cursor = None;
2228 crate::event::handle_cursor_style_changed(self.handle());
2229 self
2230 }
2231
2232 fn on_key_down(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2233 where
2234 Self: Sized,
2235 {
2236 self.node_ref().inner.borrow_mut().handlers.key_down = Some(Rc::new(handler));
2237 self
2238 }
2239
2240 fn on_key_up(&self, handler: impl Fn(&mut KeyEventArgs) + 'static) -> &Self
2241 where
2242 Self: Sized,
2243 {
2244 self.node_ref().inner.borrow_mut().handlers.key_up = Some(Rc::new(handler));
2245 self
2246 }
2247
2248 fn on_focus_changed(&self, handler: impl Fn(FocusChangedEventArgs) + 'static) -> &Self
2249 where
2250 Self: Sized,
2251 {
2252 self.apply_focus_changed_handler(Rc::new(handler));
2253 self
2254 }
2255
2256 fn drag_allowed_effects(&self, effects: DragDropEffects) -> &Self
2257 where
2258 Self: Sized,
2259 {
2260 self.node_ref().inner.borrow_mut().drag_allowed_effects = effects;
2261 self
2262 }
2263
2264 fn drag_data(&self, handler: impl Fn() -> Option<DragDataObject> + 'static) -> &Self
2265 where
2266 Self: Sized,
2267 {
2268 let node_ref = self.node_ref();
2269 node_ref.inner.borrow_mut().drag_data_callback = Some(Rc::new(handler));
2270 node_ref.require_interactive();
2271 node_ref.ensure_drag_gesture();
2272 self
2273 }
2274
2275 fn clear_drag_data(&self) -> &Self
2276 where
2277 Self: Sized,
2278 {
2279 self.node_ref().inner.borrow_mut().drag_data_callback = None;
2280 self
2281 }
2282
2283 fn allow_drop(&self, flag: bool) -> &Self
2284 where
2285 Self: Sized,
2286 {
2287 let node_ref = self.node_ref();
2288 node_ref.inner.borrow_mut().drop_allowed = flag;
2289 if flag {
2290 node_ref.require_interactive();
2291 }
2292 self
2293 }
2294
2295 fn on_drag_completed(&self, handler: impl Fn(DragCompletedEventArgs) + 'static) -> &Self
2296 where
2297 Self: Sized,
2298 {
2299 self.node_ref().inner.borrow_mut().drag_completed_callback = Some(Rc::new(handler));
2300 self
2301 }
2302
2303 fn on_drag_enter(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2304 where
2305 Self: Sized,
2306 {
2307 let node_ref = self.node_ref();
2308 node_ref.inner.borrow_mut().drag_enter_callback = Some(Rc::new(handler));
2309 self.allow_drop(true);
2310 node_ref.require_interactive();
2311 self
2312 }
2313
2314 fn on_drag_over(&self, handler: impl Fn(DragEventArgs) -> DropProposal + 'static) -> &Self
2315 where
2316 Self: Sized,
2317 {
2318 let node_ref = self.node_ref();
2319 node_ref.inner.borrow_mut().drag_over_callback = Some(Rc::new(handler));
2320 self.allow_drop(true);
2321 node_ref.require_interactive();
2322 self
2323 }
2324
2325 fn on_drag_leave(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2326 where
2327 Self: Sized,
2328 {
2329 let node_ref = self.node_ref();
2330 node_ref.inner.borrow_mut().drag_leave_callback = Some(Rc::new(handler));
2331 self.allow_drop(true);
2332 node_ref.require_interactive();
2333 self
2334 }
2335
2336 fn on_drop(&self, handler: impl Fn(DragEventArgs) + 'static) -> &Self
2337 where
2338 Self: Sized,
2339 {
2340 let node_ref = self.node_ref();
2341 node_ref.inner.borrow_mut().drop_callback = Some(Rc::new(handler));
2342 self.allow_drop(true);
2343 node_ref.require_interactive();
2344 self
2345 }
2346
2347 fn allow_external_drop(&self, flag: bool) -> &Self
2348 where
2349 Self: Sized,
2350 {
2351 let node_ref = self.node_ref();
2352 node_ref.inner.borrow_mut().behavior.external_drop_allowed = flag;
2353 if flag {
2354 node_ref.require_interactive();
2355 }
2356 self
2357 }
2358
2359 fn on_external_drag_enter(
2360 &self,
2361 handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2362 ) -> &Self
2363 where
2364 Self: Sized,
2365 {
2366 let node_ref = self.node_ref();
2367 node_ref.inner.borrow_mut().external_drag_enter_callback = Some(Rc::new(handler));
2368 self.allow_external_drop(true);
2369 node_ref.require_interactive();
2370 self
2371 }
2372
2373 fn on_external_drag_over(
2374 &self,
2375 handler: impl Fn(ExternalDropEventArgs) -> DropProposal + 'static,
2376 ) -> &Self
2377 where
2378 Self: Sized,
2379 {
2380 let node_ref = self.node_ref();
2381 node_ref.inner.borrow_mut().external_drag_over_callback = Some(Rc::new(handler));
2382 self.allow_external_drop(true);
2383 node_ref.require_interactive();
2384 self
2385 }
2386
2387 fn on_external_drag_leave(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2388 where
2389 Self: Sized,
2390 {
2391 let node_ref = self.node_ref();
2392 node_ref.inner.borrow_mut().external_drag_leave_callback = Some(Rc::new(handler));
2393 self.allow_external_drop(true);
2394 node_ref.require_interactive();
2395 self
2396 }
2397
2398 fn on_external_drop(&self, handler: impl Fn(ExternalDropEventArgs) + 'static) -> &Self
2399 where
2400 Self: Sized,
2401 {
2402 let node_ref = self.node_ref();
2403 node_ref.inner.borrow_mut().external_drop_callback = Some(Rc::new(handler));
2404 self.allow_external_drop(true);
2405 node_ref.require_interactive();
2406 self
2407 }
2408
2409 fn get_bounds(&self) -> [f32; 4] {
2410 if !self.has_built_handle() {
2411 return [0.0; 4];
2412 }
2413 ui::get_bounds(self.handle().raw()).unwrap_or([0.0; 4])
2414 }
2415
2416 fn absolute_to_local_position(&self, absolute_x: f32, absolute_y: f32) -> [f32; 2] {
2417 let bounds = self.get_bounds();
2418 [absolute_x - bounds[0], absolute_y - bounds[1]]
2419 }
2420
2421 fn local_to_absolute_position(&self, local_x: f32, local_y: f32) -> [f32; 2] {
2422 let bounds = self.get_bounds();
2423 [bounds[0] + local_x, bounds[1] + local_y]
2424 }
2425
2426 fn ensure_handle(&self) {
2427 if self.has_built_handle() {
2428 return;
2429 }
2430 let node_ref = self.node_ref();
2431 let node_type = node_ref.inner.borrow().kind.node_type();
2432 let handle = NodeHandle(ui::create_node(node_type as u32));
2433 {
2434 let mut core = node_ref.inner.borrow_mut();
2435 core.handle = handle;
2436 core.mounted = true;
2437 }
2438 crate::event::register_node(&node_ref);
2439 }
2440
2441 fn build(&self) {
2442 self.ensure_handle();
2443 self.build_self();
2444 self.build_children();
2445 }
2446
2447 fn dispose(&self) {
2448 self.node_ref().dispose();
2449 }
2450
2451 fn build_children(&self) {
2452 let node_ref = self.node_ref();
2453 {
2454 let mut core = node_ref.inner.borrow_mut();
2455 if core.children_built {
2456 return;
2457 }
2458 core.children_built = true;
2459 }
2460 let children = node_ref.inner.borrow().children.clone();
2461 for child in children {
2462 child.build();
2463 ui::add_child(self.handle().raw(), child.handle().raw());
2464 }
2465 }
2466
2467 fn append_child<T: Node>(&self, child: &T) {
2468 let self_node_ref = self.node_ref();
2469 let child_node_ref = child.node_ref();
2470 if Rc::ptr_eq(&self_node_ref.inner, &child_node_ref.inner) {
2471 return;
2472 }
2473 if self_node_ref
2474 .inner
2475 .borrow()
2476 .children
2477 .iter()
2478 .any(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2479 {
2480 return;
2481 }
2482 if let Some(previous_parent) = child_node_ref.inner.borrow().parent.upgrade() {
2483 if Rc::ptr_eq(&previous_parent, &self_node_ref.inner) {
2484 return;
2485 }
2486 let child_handle = child.handle();
2487 {
2488 let mut previous_parent_core = previous_parent.borrow_mut();
2489 previous_parent_core
2490 .children
2491 .retain(|candidate| !Rc::ptr_eq(&candidate.inner, &child_node_ref.inner));
2492 }
2493 if previous_parent.borrow().handle != NodeHandle::INVALID
2494 && child_handle != NodeHandle::INVALID
2495 {
2496 ui::remove_child(previous_parent.borrow().handle.raw(), child_handle.raw());
2497 }
2498 }
2499
2500 {
2501 let mut child_core = child_node_ref.inner.borrow_mut();
2502 child_core.parent = Rc::downgrade(&self_node_ref.inner);
2503 }
2504 child_node_ref.set_inherited_enabled(self_node_ref.is_enabled_for_routing());
2505 self_node_ref
2506 .inner
2507 .borrow_mut()
2508 .children
2509 .push(child_node_ref.clone());
2510 if let Some(owner) = child.retained_owner_attachment() {
2511 self_node_ref
2512 .inner
2513 .borrow_mut()
2514 .retained_attachments
2515 .push(owner);
2516 }
2517 self_node_ref.inner.borrow_mut().children_built = false;
2518 if self.has_built_handle() {
2519 child.build();
2520 ui::add_child(self.handle().raw(), child.handle().raw());
2521 self_node_ref.inner.borrow_mut().children_built = true;
2522 self.notify_retained_mutation();
2523 self.notify_retained_child_layout_changed();
2524 }
2525 }
2526
2527 fn remove_child<T: Node>(&self, child: &T) -> bool {
2528 let child_handle = child.handle();
2529 let child_node_ref = child.node_ref();
2530 let removed = {
2531 let self_node_ref = self.node_ref();
2532 let mut core = self_node_ref.inner.borrow_mut();
2533 let Some(index) = core
2534 .children
2535 .iter()
2536 .position(|candidate| Rc::ptr_eq(&candidate.inner, &child_node_ref.inner))
2537 else {
2538 return false;
2539 };
2540 core.children.remove(index)
2541 };
2542 removed.inner.borrow_mut().parent = Weak::new();
2543 removed.set_inherited_enabled(true);
2544 self.node_ref().inner.borrow_mut().children_built = false;
2545 if self.has_built_handle() && child.has_built_handle() {
2546 ui::remove_child(self.handle().raw(), child_handle.raw());
2547 self.node_ref().inner.borrow_mut().children_built = true;
2548 self.notify_retained_mutation();
2549 self.notify_retained_child_layout_changed();
2550 }
2551 true
2552 }
2553
2554 fn parent_handle(&self) -> Option<NodeHandle> {
2555 self.node_ref()
2556 .inner
2557 .borrow()
2558 .parent
2559 .upgrade()
2560 .map(|parent| parent.borrow().handle)
2561 }
2562
2563 fn notify_retained_layout_mutation(&self) {
2564 self.notify_retained_mutation();
2565 }
2566
2567 fn notify_retained_mutation(&self) {
2568 crate::frame_scheduler::mark_needs_commit();
2569 }
2570
2571 fn notify_retained_child_layout_changed(&self) {}
2572
2573 #[doc(hidden)]
2574 fn bind_scroll_proxy_target_handle(&self, scroll_handle: u64) -> &Self
2575 where
2576 Self: Sized,
2577 {
2578 let node_ref = self.node_ref();
2579 node_ref.inner.borrow_mut().behavior.scroll_proxy_target = Some(scroll_handle);
2580 if self.has_built_handle() {
2581 ui::set_scroll_proxy_target(self.handle().raw(), scroll_handle);
2582 self.notify_retained_mutation();
2583 }
2584 self
2585 }
2586
2587 fn preserve_selection_on_pointer_down(&self, preserve: bool) -> &Self
2588 where
2589 Self: Sized,
2590 {
2591 let node_ref = self.node_ref();
2592 node_ref
2593 .inner
2594 .borrow_mut()
2595 .behavior
2596 .preserve_selection_on_pointer_down = preserve;
2597 if self.has_built_handle() {
2598 ui::set_preserve_selection_on_pointer_down(self.handle().raw(), preserve);
2599 self.notify_retained_mutation();
2600 }
2601 self
2602 }
2603
2604 fn tool_tip(&self, tool_tip: ToolTip) -> &Self
2605 where
2606 Self: Sized,
2607 {
2608 let node_ref = self.node_ref();
2609 node_ref.inner.borrow_mut().behavior.tool_tip = Some(tool_tip.clone());
2610 node_ref.require_interactive();
2611 if self.has_built_handle()
2612 && node_ref.is_enabled_for_routing()
2613 && node_ref.is_visible_for_routing()
2614 {
2615 ui::set_interactive(self.handle().raw(), true);
2616 self.notify_retained_mutation();
2617 }
2618 crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, Some(tool_tip));
2619 self
2620 }
2621
2622 fn tool_tip_text(&self, text: impl Into<String>) -> &Self
2623 where
2624 Self: Sized,
2625 {
2626 self.tool_tip(ToolTip::text(text))
2627 }
2628
2629 fn clear_tool_tip(&self) -> &Self
2630 where
2631 Self: Sized,
2632 {
2633 let node_ref = self.node_ref();
2634 node_ref.inner.borrow_mut().behavior.tool_tip = None;
2635 crate::tool_tip_manager::ToolTipManager::handle_tool_tip_changed(&node_ref, None);
2636 self
2637 }
2638}
2639
2640impl<T: Node> Node for &T {
2641 fn retained_node_ref(&self) -> NodeRef {
2642 (*self).retained_node_ref()
2643 }
2644
2645 fn retained_owner_attachment(&self) -> Option<Rc<dyn Any>> {
2646 (*self).retained_owner_attachment()
2647 }
2648
2649 fn build_self(&self) {
2650 (*self).build_self();
2651 }
2652}