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 animate::{AnimStateCommand, Animation},
16 context::{EventCallback, ResizeCallback},
17 event::{EventListener, EventPropagation},
18 menu::Menu,
19 style::{DisplayProp, Style, StyleClassRef, StyleSelector},
20 unit::PxPct,
21 update::{UpdateMessage, CENTRAL_DEFERRED_UPDATE_MESSAGES, CENTRAL_UPDATE_MESSAGES},
22 view::{IntoView, View},
23 view_state::{ChangeFlags, StackOffset, ViewState},
24 view_storage::VIEW_STORAGE,
25 window_tracking::{is_known_root, window_id_for_root},
26 ScreenLayout,
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(crate) fn taffy(&self) -> Rc<RefCell<TaffyTree>> {
58 VIEW_STORAGE.with_borrow(|s| s.taffy.clone())
59 }
60
61 pub fn new_taffy_node(&self) -> NodeId {
63 self.taffy()
64 .borrow_mut()
65 .new_leaf(taffy::style::Style::DEFAULT)
66 .unwrap()
67 }
68
69 pub fn set_taffy_style(&self, node: NodeId, style: taffy::Style) {
71 let _ = self.taffy().borrow_mut().set_style(node, style);
72 }
73
74 pub fn taffy_layout(&self, node: NodeId) -> Option<taffy::Layout> {
76 self.taffy().borrow().layout(node).cloned().ok()
77 }
78
79 pub fn taffy_node(&self) -> NodeId {
81 self.state().borrow().node
82 }
83
84 pub(crate) fn state(&self) -> Rc<RefCell<ViewState>> {
85 VIEW_STORAGE.with_borrow_mut(|s| {
86 if !s.view_ids.contains_key(*self) {
87 s.stale_view_state.clone()
90 } else {
91 s.states
92 .entry(*self)
93 .unwrap()
94 .or_insert_with(|| {
95 Rc::new(RefCell::new(ViewState::new(&mut s.taffy.borrow_mut())))
96 })
97 .clone()
98 }
99 })
100 }
101
102 pub(crate) fn view(&self) -> Rc<RefCell<Box<dyn View>>> {
103 VIEW_STORAGE.with_borrow(|s| {
104 s.views
105 .get(*self)
106 .cloned()
107 .unwrap_or_else(|| s.stale_view.clone())
108 })
109 }
110
111 pub fn add_child(&self, child: Box<dyn View>) {
113 VIEW_STORAGE.with_borrow_mut(|s| {
114 let child_id = child.id();
115 s.children.entry(*self).unwrap().or_default().push(child_id);
116 s.parent.insert(child_id, Some(*self));
117 s.views.insert(child_id, Rc::new(RefCell::new(child)));
118 });
119 }
120
121 pub fn set_children<const N: usize, V: IntoView>(&self, children: [V; N]) {
124 VIEW_STORAGE.with_borrow_mut(|s| {
125 let mut children_ids = Vec::new();
126 for child in children {
127 let child_view = child.into_view();
128 let child_view_id = child_view.id();
129 children_ids.push(child_view_id);
130 s.parent.insert(child_view_id, Some(*self));
131 s.views
132 .insert(child_view_id, Rc::new(RefCell::new(child_view.into_any())));
133 }
134 s.children.insert(*self, children_ids);
135 });
136 }
137
138 pub fn set_children_vec(&self, children: Vec<impl IntoView>) {
141 VIEW_STORAGE.with_borrow_mut(|s| {
142 let mut children_ids = Vec::new();
143 for child in children {
144 let child_view = child.into_view();
145 let child_view_id = child_view.id();
146 children_ids.push(child_view_id);
147 s.parent.insert(child_view_id, Some(*self));
148 s.views
149 .insert(child_view_id, Rc::new(RefCell::new(child_view.into_any())));
150 }
151 s.children.insert(*self, children_ids);
152 });
153 }
154
155 pub fn set_view(&self, view: Box<dyn View>) {
157 VIEW_STORAGE.with_borrow_mut(|s| {
158 if s.view_ids.contains_key(*self) {
159 s.views.insert(*self, Rc::new(RefCell::new(view)));
160 }
161 });
162 }
163
164 pub fn set_parent(&self, parent: ViewId) {
166 VIEW_STORAGE.with_borrow_mut(|s| {
167 if s.view_ids.contains_key(*self) {
168 s.parent.insert(*self, Some(parent));
169 }
170 });
171 }
172
173 pub fn set_children_ids(&self, children: Vec<ViewId>) {
175 VIEW_STORAGE.with_borrow_mut(|s| {
176 if s.view_ids.contains_key(*self) {
177 s.children.insert(*self, children);
178 }
179 });
180 }
181
182 pub fn children(&self) -> Vec<ViewId> {
184 VIEW_STORAGE.with_borrow(|s| s.children.get(*self).cloned().unwrap_or_default())
185 }
186
187 pub fn with_children<R>(&self, children: impl Fn(&[ViewId]) -> R) -> R {
189 VIEW_STORAGE.with_borrow(|s| children(s.children.get(*self).map_or(&[], |v| v)))
190 }
191
192 pub fn parent(&self) -> Option<ViewId> {
194 VIEW_STORAGE.with_borrow(|s| s.parent.get(*self).cloned().flatten())
195 }
196
197 pub(crate) fn root(&self) -> Option<ViewId> {
198 VIEW_STORAGE.with_borrow_mut(|s| {
199 if let Some(root) = s.root.get(*self) {
200 return *root;
202 }
203 let root_view_id = s.root_view_id(*self);
204 if let Some(root) = root_view_id {
208 if is_known_root(&root) {
209 s.root.insert(*self, root_view_id);
210 return Some(root);
211 }
212 }
213 None
214 })
215 }
216
217 pub fn layout_rect(&self) -> Rect {
219 self.state().borrow().layout_rect
220 }
221
222 pub fn get_size(&self) -> Option<Size> {
224 self.get_layout()
225 .map(|l| Size::new(l.size.width as f64, l.size.height as f64))
226 }
227
228 pub fn parent_size(&self) -> Option<Size> {
230 let parent_id = self.parent()?;
231 parent_id.get_size()
232 }
233
234 pub fn get_content_rect(&self) -> Rect {
237 let size = self
238 .get_layout()
239 .map(|layout| layout.size)
240 .unwrap_or_default();
241 let rect = Size::new(size.width as f64, size.height as f64).to_rect();
242 let view_state = self.state();
243 let props = &view_state.borrow().layout_props;
244 let pixels = |px_pct, abs| match px_pct {
245 PxPct::Px(v) => v,
246 PxPct::Pct(pct) => pct * abs,
247 };
248 rect.inset(-Insets {
249 x0: props.border_left().0.width + pixels(props.padding_left(), rect.width()),
250 x1: props.border_right().0.width + pixels(props.padding_right(), rect.width()),
251 y0: props.border_top().0.width + pixels(props.padding_top(), rect.height()),
252 y1: props.border_bottom().0.width + pixels(props.padding_bottom(), rect.height()),
253 })
254 }
255
256 pub fn get_layout(&self) -> Option<Layout> {
258 let widget_parent = self.parent().map(|id| id.state().borrow().node);
259
260 let taffy = self.taffy();
261 let mut node = self.state().borrow().node;
262 let mut layout = *taffy.borrow().layout(node).ok()?;
263
264 loop {
265 let parent = taffy.borrow().parent(node);
266
267 if parent == widget_parent {
268 break;
269 }
270
271 node = parent?;
272
273 layout.location = layout.location + taffy.borrow().layout(node).ok()?.location;
274 }
275
276 Some(layout)
277 }
278
279 pub fn style_has_hidden(&self) -> bool {
281 let state = self.state();
282 let state = state.borrow();
283 state.combined_style.get(DisplayProp) == Display::None
284 }
285
286 pub fn is_hidden_recursive(&self) -> bool {
288 if self.style_has_hidden() {
289 return true;
290 }
291
292 let mut parent = self.parent();
293 while let Some(id) = parent {
294 if id.style_has_hidden() {
295 return true;
296 }
297 parent = id.parent();
298 }
299
300 false
301 }
302
303 pub fn request_all(&self) {
306 self.request_changes(ChangeFlags::all());
307 }
308
309 pub fn request_layout(&self) {
311 self.request_changes(ChangeFlags::LAYOUT)
312 }
313
314 pub fn window_id(&self) -> Option<WindowId> {
316 self.root().and_then(window_id_for_root)
317 }
318
319 pub fn request_paint(&self) {
321 self.add_update_message(UpdateMessage::RequestPaint);
322 }
323
324 pub fn request_style(&self) {
327 self.request_changes(ChangeFlags::STYLE)
328 }
329
330 pub(crate) fn request_changes(&self, flags: ChangeFlags) {
331 let state = self.state();
332 if state.borrow().requested_changes.contains(flags) {
333 return;
334 }
335 state.borrow_mut().requested_changes.insert(flags);
336 if let Some(parent) = self.parent() {
337 parent.request_changes(flags);
338 }
339 }
340
341 pub fn request_style_recursive(&self) {
343 let state = self.state();
344 state.borrow_mut().request_style_recursive = true;
345 self.request_style();
346 }
347
348 pub fn request_focus(&self) {
350 self.add_update_message(UpdateMessage::Focus(*self));
351 }
352
353 pub fn clear_focus(&self) {
355 self.add_update_message(UpdateMessage::ClearFocus(*self));
356 }
357
358 pub fn update_context_menu(&self, menu: impl Fn() -> Menu + 'static) {
360 self.state().borrow_mut().context_menu = Some(Rc::new(menu));
361 }
362
363 pub fn update_popout_menu(&self, menu: impl Fn() -> Menu + 'static) {
367 self.state().borrow_mut().popout_menu = Some(Rc::new(menu));
368 }
369
370 pub fn request_active(&self) {
376 self.add_update_message(UpdateMessage::Active(*self));
377 }
378
379 pub fn clear_active(&self) {
381 self.add_update_message(UpdateMessage::ClearActive(*self));
382 }
383
384 pub fn inspect(&self) {
386 self.add_update_message(UpdateMessage::Inspect);
387 }
388
389 pub fn scroll_to(&self, rect: Option<Rect>) {
392 self.add_update_message(UpdateMessage::ScrollTo { id: *self, rect });
393 }
394
395 pub(crate) fn transition_anim_complete(&self) {
396 self.add_update_message(UpdateMessage::ViewTransitionAnimComplete(*self));
397 }
398
399 pub(crate) fn update_animation(&self, offset: StackOffset<Animation>, animation: Animation) {
400 let state = self.state();
401 state.borrow_mut().animations.set(offset, animation);
402 self.request_style();
403 }
404
405 pub(crate) fn update_animation_state(
406 &self,
407 offset: StackOffset<Animation>,
408 command: AnimStateCommand,
409 ) {
410 let view_state = self.state();
411 view_state
412 .borrow_mut()
413 .animations
414 .update(offset, move |anim| anim.transition(command));
415 self.request_style();
416 }
417
418 pub fn update_state(&self, state: impl Any) {
420 self.add_update_message(UpdateMessage::State {
421 id: *self,
422 state: Box::new(state),
423 });
424 }
425
426 pub(crate) fn set_viewport(&self, viewport: Rect) {
428 let state = self.state();
429 state.borrow_mut().viewport = Some(viewport);
430 }
431
432 pub fn add_event_listener(&self, listener: EventListener, action: Box<EventCallback>) {
434 let state = self.state();
435 state.borrow_mut().add_event_listener(listener, action);
436 }
437
438 pub fn update_resize_listener(&self, action: Box<ResizeCallback>) {
440 let state = self.state();
441 state.borrow_mut().update_resize_listener(action);
442 }
443
444 pub fn update_move_listener(&self, action: Box<dyn Fn(Point)>) {
446 let state = self.state();
447 state.borrow_mut().update_move_listener(action);
448 }
449
450 pub fn update_cleanup_listener(&self, action: Box<dyn Fn()>) {
452 let state = self.state();
453 state.borrow_mut().update_cleanup_listener(action);
454 }
455
456 pub fn get_combined_style(&self) -> Style {
465 self.state().borrow().combined_style.clone()
466 }
467
468 pub fn add_class(&self, class: StyleClassRef) {
470 let state = self.state();
471 state.borrow_mut().classes.push(class);
472 self.request_style_recursive();
473 }
474
475 pub fn remove_class(&self, class: StyleClassRef) {
477 let state = self.state();
478 state.borrow_mut().classes.retain_mut(|c| *c != class);
479 self.request_style_recursive();
480 }
481
482 pub(crate) fn update_style_selector(&self, selector: StyleSelector, style: Style) {
483 if let StyleSelector::Dragging = selector {
484 let state = self.state();
485 state.borrow_mut().dragging_style = Some(style);
486 }
487 self.request_style();
488 }
489
490 pub(crate) fn update_style(&self, offset: StackOffset<Style>, style: Style) {
491 let state = self.state();
492 let old_any_inherited = state.borrow().style().any_inherited();
493 state.borrow_mut().style.set(offset, style);
494 if state.borrow().style().any_inherited() || old_any_inherited {
495 self.request_style_recursive();
496 } else {
497 self.request_style();
498 }
499 }
500
501 pub(crate) fn apply_event(
502 &self,
503 listener: &EventListener,
504 event: &crate::event::Event,
505 ) -> Option<EventPropagation> {
506 let mut handled = false;
507 let event_listeners = self.state().borrow().event_listeners.clone();
508 if let Some(handlers) = event_listeners.get(listener) {
509 for handler in handlers {
510 handled |= (handler.borrow_mut())(event).is_processed();
511 }
512 } else {
513 return None;
514 }
515 if handled {
516 Some(EventPropagation::Stop)
517 } else {
518 Some(EventPropagation::Continue)
519 }
520 }
521
522 pub fn update_disabled(&self, is_disabled: bool) {
526 self.add_update_message(UpdateMessage::Disabled {
527 id: *self,
528 is_disabled,
529 });
530 }
531
532 pub fn keyboard_navigable(&self) {
534 self.add_update_message(UpdateMessage::KeyboardNavigable { id: *self });
535 }
536
537 pub fn remove_keyboard_navigatable(&self) {
539 self.add_update_message(UpdateMessage::RemoveKeyboardNavigable { id: *self });
540 }
541
542 pub fn disable_default_event(&self, event: EventListener) {
546 self.state()
547 .borrow_mut()
548 .disable_default_events
549 .insert(event);
550 }
551
552 pub fn remove_disable_default_event(&self, event: EventListener) {
554 self.state()
555 .borrow_mut()
556 .disable_default_events
557 .remove(&event);
558 }
559
560 pub fn draggable(&self) {
564 self.add_update_message(UpdateMessage::Draggable { id: *self });
565 }
566
567 pub fn window_visible(&self, visible: bool) {
570 self.add_update_message(UpdateMessage::WindowVisible(visible));
571 }
572
573 fn add_update_message(&self, msg: UpdateMessage) {
574 CENTRAL_UPDATE_MESSAGES.with_borrow_mut(|msgs| {
575 msgs.push((*self, msg));
576 });
577 }
578
579 pub fn update_state_deferred(&self, state: impl Any) {
582 CENTRAL_DEFERRED_UPDATE_MESSAGES.with_borrow_mut(|msgs| {
583 msgs.push((*self, Box::new(state)));
584 });
585 }
586
587 pub fn screen_layout(&self) -> Option<ScreenLayout> {
589 crate::screen_layout::try_create_screen_layout(self)
590 }
591}