1#![deny(missing_docs)]
2use std::{any::Any, cell::RefCell, rc::Rc};
8
9use peniko::kurbo::{Insets, Point, Rect, Size};
10use slotmap::new_key_type;
11use taffy::{Display, Layout, NodeId, TaffyTree};
12use winit::window::WindowId;
13
14use crate::{
15 ScreenLayout,
16 animate::{AnimStateCommand, Animation},
17 context::{EventCallback, ResizeCallback},
18 event::{EventListener, EventPropagation},
19 menu::Menu,
20 style::{Disabled, DisplayProp, Draggable, Focusable, Hidden, Style, StyleClassRef},
21 unit::PxPct,
22 update::{CENTRAL_DEFERRED_UPDATE_MESSAGES, CENTRAL_UPDATE_MESSAGES, UpdateMessage},
23 view::{IntoView, View},
24 view_state::{ChangeFlags, StackOffset, ViewState},
25 view_storage::VIEW_STORAGE,
26 window_tracking::{is_known_root, window_id_for_root},
27};
28
29new_key_type! {
30 pub struct ViewId;
34}
35
36impl ViewId {
37 pub fn new() -> ViewId {
39 VIEW_STORAGE.with_borrow_mut(|s| s.view_ids.insert(()))
40 }
41
42 pub fn remove(&self) {
44 VIEW_STORAGE.with_borrow_mut(|s| {
45 s.root.remove(*self);
48 if let Some(Some(parent)) = s.parent.get(*self) {
49 if let Some(children) = s.children.get_mut(*parent) {
50 children.retain(|c| c != self);
51 }
52 }
53 s.view_ids.remove(*self);
54 });
55 }
56
57 pub fn taffy(&self) -> Rc<RefCell<TaffyTree>> {
59 VIEW_STORAGE.with_borrow(|s| s.taffy.clone())
60 }
61
62 pub fn new_taffy_node(&self) -> NodeId {
64 self.taffy()
65 .borrow_mut()
66 .new_leaf(taffy::style::Style::DEFAULT)
67 .unwrap()
68 }
69
70 pub fn set_taffy_style(&self, node: NodeId, style: taffy::Style) {
72 let _ = self.taffy().borrow_mut().set_style(node, style);
73 }
74
75 pub fn taffy_layout(&self, node: NodeId) -> Option<taffy::Layout> {
77 self.taffy().borrow().layout(node).cloned().ok()
78 }
79
80 pub fn taffy_node(&self) -> NodeId {
82 self.state().borrow().node
83 }
84
85 pub(crate) fn state(&self) -> Rc<RefCell<ViewState>> {
86 VIEW_STORAGE.with_borrow_mut(|s| {
87 if !s.view_ids.contains_key(*self) {
88 s.stale_view_state.clone()
91 } else {
92 s.states
93 .entry(*self)
94 .unwrap()
95 .or_insert_with(|| {
96 Rc::new(RefCell::new(ViewState::new(&mut s.taffy.borrow_mut())))
97 })
98 .clone()
99 }
100 })
101 }
102
103 pub(crate) fn view(&self) -> Rc<RefCell<Box<dyn View>>> {
105 VIEW_STORAGE.with_borrow(|s| {
106 s.views
107 .get(*self)
108 .cloned()
109 .unwrap_or_else(|| s.stale_view.clone())
110 })
111 }
112
113 pub fn add_child(&self, child: Box<dyn View>) {
115 VIEW_STORAGE.with_borrow_mut(|s| {
116 let child_id = child.id();
117 s.children.entry(*self).unwrap().or_default().push(child_id);
118 s.parent.insert(child_id, Some(*self));
119 s.views.insert(child_id, Rc::new(RefCell::new(child)));
120 });
121 }
122
123 pub fn set_children<const N: usize, V: IntoView>(&self, children: [V; N]) {
126 VIEW_STORAGE.with_borrow_mut(|s| {
127 let mut children_ids = Vec::new();
128 for child in children {
129 let child_view = child.into_view();
130 let child_view_id = child_view.id();
131 children_ids.push(child_view_id);
132 s.parent.insert(child_view_id, Some(*self));
133 s.views
134 .insert(child_view_id, Rc::new(RefCell::new(child_view.into_any())));
135 }
136 s.children.insert(*self, children_ids);
137 });
138 }
139
140 pub fn set_children_vec(&self, children: Vec<impl IntoView>) {
143 VIEW_STORAGE.with_borrow_mut(|s| {
144 let mut children_ids = Vec::new();
145 for child in children {
146 let child_view = child.into_view();
147 let child_view_id = child_view.id();
148 children_ids.push(child_view_id);
149 s.parent.insert(child_view_id, Some(*self));
150 s.views
151 .insert(child_view_id, Rc::new(RefCell::new(child_view.into_any())));
152 }
153 s.children.insert(*self, children_ids);
154 });
155 }
156
157 pub fn set_view(&self, view: Box<dyn View>) {
159 VIEW_STORAGE.with_borrow_mut(|s| {
160 if s.view_ids.contains_key(*self) {
161 s.views.insert(*self, Rc::new(RefCell::new(view)));
162 }
163 });
164 }
165
166 pub fn set_parent(&self, parent: ViewId) {
168 VIEW_STORAGE.with_borrow_mut(|s| {
169 if s.view_ids.contains_key(*self) {
170 s.parent.insert(*self, Some(parent));
171 }
172 });
173 }
174
175 pub fn set_children_ids(&self, children: Vec<ViewId>) {
177 VIEW_STORAGE.with_borrow_mut(|s| {
178 if s.view_ids.contains_key(*self) {
179 s.children.insert(*self, children);
180 }
181 });
182 }
183
184 pub fn children(&self) -> Vec<ViewId> {
186 VIEW_STORAGE.with_borrow(|s| s.children.get(*self).cloned().unwrap_or_default())
187 }
188
189 pub fn with_children<R>(&self, children: impl Fn(&[ViewId]) -> R) -> R {
191 VIEW_STORAGE.with_borrow(|s| children(s.children.get(*self).map_or(&[], |v| v)))
192 }
193
194 pub fn parent(&self) -> Option<ViewId> {
196 VIEW_STORAGE.with_borrow(|s| s.parent.get(*self).cloned().flatten())
197 }
198
199 pub fn root(&self) -> Option<ViewId> {
201 VIEW_STORAGE.with_borrow_mut(|s| {
202 if let Some(root) = s.root.get(*self) {
203 return *root;
205 }
206 let root_view_id = s.root_view_id(*self);
207 if let Some(root) = root_view_id {
211 if is_known_root(&root) {
212 s.root.insert(*self, root_view_id);
213 return Some(root);
214 }
215 }
216 None
217 })
218 }
219
220 pub fn layout_rect(&self) -> Rect {
222 self.state().borrow().layout_rect
223 }
224
225 pub fn get_size(&self) -> Option<Size> {
227 self.get_layout()
228 .map(|l| Size::new(l.size.width as f64, l.size.height as f64))
229 }
230
231 pub fn parent_size(&self) -> Option<Size> {
233 let parent_id = self.parent()?;
234 parent_id.get_size()
235 }
236
237 pub fn get_content_rect(&self) -> Rect {
240 let size = self
241 .get_layout()
242 .map(|layout| layout.size)
243 .unwrap_or_default();
244 let rect = Size::new(size.width as f64, size.height as f64).to_rect();
245 let view_state = self.state();
246 let props = &view_state.borrow().layout_props;
247 let pixels = |px_pct, abs| match px_pct {
248 PxPct::Px(v) => v,
249 PxPct::Pct(pct) => pct * abs,
250 };
251 let border = props.border();
252 let padding = props.padding();
253 rect.inset(-Insets {
254 x0: border.left.map_or(0.0, |b| b.0.width)
255 + pixels(padding.left.unwrap_or(PxPct::Px(0.0)), rect.width()),
256 x1: border.right.map_or(0.0, |b| b.0.width)
257 + pixels(padding.right.unwrap_or(PxPct::Px(0.0)), rect.width()),
258 y0: border.top.map_or(0.0, |b| b.0.width)
259 + pixels(padding.top.unwrap_or(PxPct::Px(0.0)), rect.height()),
260 y1: border.bottom.map_or(0.0, |b| b.0.width)
261 + pixels(padding.bottom.unwrap_or(PxPct::Px(0.0)), rect.height()),
262 })
263 }
264
265 pub fn get_layout(&self) -> Option<Layout> {
267 let widget_parent = self.parent().map(|id| id.state().borrow().node);
268
269 let taffy = self.taffy();
270 let mut node = self.state().borrow().node;
271 let mut layout = *taffy.borrow().layout(node).ok()?;
272
273 loop {
274 let parent = taffy.borrow().parent(node);
275
276 if parent == widget_parent {
277 break;
278 }
279
280 node = parent?;
281
282 layout.location = layout.location + taffy.borrow().layout(node).ok()?.location;
283 }
284
285 Some(layout)
286 }
287
288 pub fn get_layout_relative_to(&self, relative_to: ViewId) -> Option<Layout> {
290 let taffy = self.taffy();
291 let target_node = relative_to.state().borrow().node;
292 let mut node = self.state().borrow().node;
293 let mut layout = *taffy.borrow().layout(node).ok()?;
294
295 loop {
296 let parent = taffy.borrow().parent(node);
297 if parent == Some(target_node) {
298 break;
299 }
300
301 node = parent?;
303 layout.location = layout.location + taffy.borrow().layout(node).ok()?.location;
304 }
305
306 Some(layout)
307 }
308
309 pub fn get_layout_relative_to_root(&self) -> Option<Layout> {
311 let taffy = self.taffy();
312 let node = self.state().borrow().node;
313 let layout = *taffy.borrow().layout(node).ok()?;
314
315 Some(layout)
316 }
317
318 pub fn is_hidden(&self) -> bool {
320 let state = self.state();
321 let state = state.borrow();
322 state.computed_style.get(Hidden) || state.computed_style.get(DisplayProp) == Display::None
323 }
324
325 pub fn is_disabled(&self) -> bool {
329 let state = self.state();
330 let state = state.borrow();
331 state.computed_style.get(Disabled)
332 }
333
334 pub fn is_selected(&self) -> bool {
338 let state = self.state();
339 let state = state.borrow();
340 state.computed_style.get(Disabled)
341 }
342
343 pub fn can_focus(&self) -> bool {
347 self.state().borrow().computed_style.get(Focusable)
348 }
349
350 pub fn can_drag(&self) -> bool {
354 self.state().borrow().computed_style.get(Draggable)
355 }
356
357 pub fn request_all(&self) {
360 self.request_changes(ChangeFlags::all());
361 }
362
363 pub fn request_layout(&self) {
365 self.request_changes(ChangeFlags::LAYOUT)
366 }
367
368 pub fn window_id(&self) -> Option<WindowId> {
370 self.root().and_then(window_id_for_root)
371 }
372
373 pub fn request_paint(&self) {
375 self.add_update_message(UpdateMessage::RequestPaint);
376 }
377
378 pub fn request_style(&self) {
381 self.request_changes(ChangeFlags::STYLE)
382 }
383
384 pub(crate) fn request_changes(&self, flags: ChangeFlags) {
385 let state = self.state();
386 if state.borrow().requested_changes.contains(flags) {
387 return;
388 }
389 state.borrow_mut().requested_changes.insert(flags);
390 if let Some(parent) = self.parent() {
391 parent.request_changes(flags);
392 }
393 }
394
395 pub fn request_style_recursive(&self) {
397 let state = self.state();
398 state.borrow_mut().request_style_recursive = true;
399 self.request_style();
400 }
401
402 pub fn request_focus(&self) {
404 self.add_update_message(UpdateMessage::Focus(*self));
405 }
406
407 pub fn clear_focus(&self) {
409 self.add_update_message(UpdateMessage::ClearFocus(*self));
410 }
411
412 pub fn update_context_menu(&self, menu: impl Fn() -> Menu + 'static) {
414 self.state().borrow_mut().context_menu = Some(Rc::new(menu));
415 }
416
417 pub fn update_popout_menu(&self, menu: impl Fn() -> Menu + 'static) {
421 self.state().borrow_mut().popout_menu = Some(Rc::new(menu));
422 }
423
424 pub fn request_active(&self) {
430 self.add_update_message(UpdateMessage::Active(*self));
431 }
432
433 pub fn clear_active(&self) {
435 self.add_update_message(UpdateMessage::ClearActive(*self));
436 }
437
438 pub fn inspect(&self) {
440 self.add_update_message(UpdateMessage::Inspect);
441 }
442
443 pub fn scroll_to(&self, rect: Option<Rect>) {
446 self.add_update_message(UpdateMessage::ScrollTo { id: *self, rect });
447 }
448
449 pub(crate) fn transition_anim_complete(&self) {
450 self.add_update_message(UpdateMessage::ViewTransitionAnimComplete(*self));
451 }
452
453 pub(crate) fn update_animation(&self, offset: StackOffset<Animation>, animation: Animation) {
454 let state = self.state();
455 state.borrow_mut().animations.set(offset, animation);
456 self.request_style();
457 }
458
459 pub(crate) fn update_animation_state(
460 &self,
461 offset: StackOffset<Animation>,
462 command: AnimStateCommand,
463 ) {
464 let view_state = self.state();
465 view_state
466 .borrow_mut()
467 .animations
468 .update(offset, move |anim| anim.transition(command));
469 self.request_style();
470 }
471
472 pub fn update_state(&self, state: impl Any) {
474 self.add_update_message(UpdateMessage::State {
475 id: *self,
476 state: Box::new(state),
477 });
478 }
479
480 pub(crate) fn set_viewport(&self, viewport: Rect) {
482 let state = self.state();
483 state.borrow_mut().viewport = Some(viewport);
484 }
485
486 pub fn add_event_listener(&self, listener: EventListener, action: Box<EventCallback>) {
488 let state = self.state();
489 state.borrow_mut().add_event_listener(listener, action);
490 }
491
492 pub fn add_resize_listener(&self, action: Rc<ResizeCallback>) {
494 let state = self.state();
495 state.borrow_mut().add_resize_listener(action);
496 }
497
498 pub fn add_move_listener(&self, action: Rc<dyn Fn(Point)>) {
500 let state = self.state();
501 state.borrow_mut().add_move_listener(action);
502 }
503
504 pub fn add_cleanup_listener(&self, action: Rc<dyn Fn()>) {
506 let state = self.state();
507 state.borrow_mut().add_cleanup_listener(action);
508 }
509
510 pub fn get_combined_style(&self) -> Style {
519 self.state().borrow().combined_style.clone()
520 }
521
522 pub fn add_class(&self, class: StyleClassRef) {
524 let state = self.state();
525 state.borrow_mut().classes.push(class);
526 self.request_style_recursive();
527 }
528
529 pub fn remove_class(&self, class: StyleClassRef) {
531 let state = self.state();
532 state.borrow_mut().classes.retain_mut(|c| *c != class);
533 self.request_style_recursive();
534 }
535
536 pub(crate) fn update_style(&self, offset: StackOffset<Style>, style: Style) {
537 let state = self.state();
538 let old_any_inherited = state.borrow().style().any_inherited();
539 state.borrow_mut().style.set(offset, style);
540 if state.borrow().style().any_inherited() || old_any_inherited {
541 self.request_style_recursive();
542 } else {
543 self.request_style();
544 }
545 }
546
547 pub(crate) fn apply_event(
548 &self,
549 listener: &EventListener,
550 event: &crate::event::Event,
551 ) -> Option<EventPropagation> {
552 let mut handled = false;
553 let event_listeners = self.state().borrow().event_listeners.clone();
554 if let Some(handlers) = event_listeners.get(listener) {
555 for handler in handlers {
556 handled |= (handler.borrow_mut())(event).is_processed();
557 }
558 } else {
559 return None;
560 }
561 if handled {
562 Some(EventPropagation::Stop)
563 } else {
564 Some(EventPropagation::Continue)
565 }
566 }
567
568 pub fn disable_default_event(&self, event: EventListener) {
572 self.state()
573 .borrow_mut()
574 .disable_default_events
575 .insert(event);
576 }
577
578 pub fn remove_disable_default_event(&self, event: EventListener) {
580 self.state()
581 .borrow_mut()
582 .disable_default_events
583 .remove(&event);
584 }
585
586 pub fn window_visible(&self, visible: bool) {
589 self.add_update_message(UpdateMessage::WindowVisible(visible));
590 }
591
592 fn add_update_message(&self, msg: UpdateMessage) {
593 let _ = CENTRAL_UPDATE_MESSAGES.try_with(|msgs| {
594 let mut msgs = msgs.borrow_mut();
595 msgs.push((*self, msg));
596 });
597 }
598
599 pub fn update_state_deferred(&self, state: impl Any) {
602 CENTRAL_DEFERRED_UPDATE_MESSAGES.with_borrow_mut(|msgs| {
603 msgs.push((*self, Box::new(state)));
604 });
605 }
606
607 pub fn screen_layout(&self) -> Option<ScreenLayout> {
609 crate::screen_layout::try_create_screen_layout(self)
610 }
611}