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