1#![deny(missing_docs)]
2use std::{any::Any, cell::RefCell, rc::Rc};
8
9use floem_winit::window::WindowId;
10use peniko::kurbo::{Insets, Point, Rect, Size};
11use slotmap::new_key_type;
12use taffy::{Display, Layout, NodeId, TaffyTree};
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(&self, children: Vec<impl IntoView>) {
123 VIEW_STORAGE.with_borrow_mut(|s| {
124 let mut children_ids = Vec::new();
125 for child in children {
126 let child_view = child.into_view();
127 let child_view_id = child_view.id();
128 children_ids.push(child_view_id);
129 s.parent.insert(child_view_id, Some(*self));
130 s.views
131 .insert(child_view_id, Rc::new(RefCell::new(child_view.into_any())));
132 }
133 s.children.insert(*self, children_ids);
134 });
135 }
136
137 pub fn set_view(&self, view: Box<dyn View>) {
139 VIEW_STORAGE.with_borrow_mut(|s| {
140 if s.view_ids.contains_key(*self) {
141 s.views.insert(*self, Rc::new(RefCell::new(view)));
142 }
143 });
144 }
145
146 pub fn set_parent(&self, parent: ViewId) {
148 VIEW_STORAGE.with_borrow_mut(|s| {
149 if s.view_ids.contains_key(*self) {
150 s.parent.insert(*self, Some(parent));
151 }
152 });
153 }
154
155 pub fn set_children_ids(&self, children: Vec<ViewId>) {
157 VIEW_STORAGE.with_borrow_mut(|s| {
158 if s.view_ids.contains_key(*self) {
159 s.children.insert(*self, children);
160 }
161 });
162 }
163
164 pub fn children(&self) -> Vec<ViewId> {
166 VIEW_STORAGE.with_borrow(|s| s.children.get(*self).cloned().unwrap_or_default())
167 }
168
169 pub fn parent(&self) -> Option<ViewId> {
171 VIEW_STORAGE.with_borrow(|s| s.parent.get(*self).cloned().flatten())
172 }
173
174 pub(crate) fn root(&self) -> Option<ViewId> {
175 VIEW_STORAGE.with_borrow_mut(|s| {
176 if let Some(root) = s.root.get(*self) {
177 return *root;
179 }
180 let root_view_id = s.root_view_id(*self);
181 if let Some(root) = root_view_id {
185 if is_known_root(&root) {
186 s.root.insert(*self, root_view_id);
187 return Some(root);
188 }
189 }
190 None
191 })
192 }
193
194 pub fn layout_rect(&self) -> Rect {
196 self.state().borrow().layout_rect
197 }
198
199 pub fn get_size(&self) -> Option<Size> {
201 self.get_layout()
202 .map(|l| Size::new(l.size.width as f64, l.size.height as f64))
203 }
204
205 pub fn parent_size(&self) -> Option<Size> {
207 let parent_id = self.parent()?;
208 parent_id.get_size()
209 }
210
211 pub fn get_content_rect(&self) -> Rect {
214 let size = self
215 .get_layout()
216 .map(|layout| layout.size)
217 .unwrap_or_default();
218 let rect = Size::new(size.width as f64, size.height as f64).to_rect();
219 let view_state = self.state();
220 let props = &view_state.borrow().layout_props;
221 let pixels = |px_pct, abs| match px_pct {
222 PxPct::Px(v) => v,
223 PxPct::Pct(pct) => pct * abs,
224 };
225 rect.inset(-Insets {
226 x0: props.border_left().0.width + pixels(props.padding_left(), rect.width()),
227 x1: props.border_right().0.width + pixels(props.padding_right(), rect.width()),
228 y0: props.border_top().0.width + pixels(props.padding_top(), rect.height()),
229 y1: props.border_bottom().0.width + pixels(props.padding_bottom(), rect.height()),
230 })
231 }
232
233 pub fn get_layout(&self) -> Option<Layout> {
235 let widget_parent = self.parent().map(|id| id.state().borrow().node);
236
237 let taffy = self.taffy();
238 let mut node = self.state().borrow().node;
239 let mut layout = *taffy.borrow().layout(node).ok()?;
240
241 loop {
242 let parent = taffy.borrow().parent(node);
243
244 if parent == widget_parent {
245 break;
246 }
247
248 node = parent?;
249
250 layout.location = layout.location + taffy.borrow().layout(node).ok()?.location;
251 }
252
253 Some(layout)
254 }
255
256 pub fn style_has_hidden(&self) -> bool {
258 let state = self.state();
259 let state = state.borrow();
260 state.combined_style.get(DisplayProp) == Display::None
261 }
262
263 pub fn is_hidden_recursive(&self) -> bool {
265 if self.style_has_hidden() {
266 return true;
267 }
268
269 let mut parent = self.parent();
270 while let Some(id) = parent {
271 if id.style_has_hidden() {
272 return true;
273 }
274 parent = id.parent();
275 }
276
277 false
278 }
279
280 pub fn request_all(&self) {
283 self.request_changes(ChangeFlags::all());
284 }
285
286 pub fn request_layout(&self) {
288 self.request_changes(ChangeFlags::LAYOUT)
289 }
290
291 pub fn window_id(&self) -> Option<WindowId> {
293 self.root().and_then(window_id_for_root)
294 }
295
296 pub fn request_paint(&self) {
298 self.add_update_message(UpdateMessage::RequestPaint);
299 }
300
301 pub fn request_style(&self) {
304 self.request_changes(ChangeFlags::STYLE)
305 }
306
307 pub(crate) fn request_changes(&self, flags: ChangeFlags) {
308 let state = self.state();
309 if state.borrow().requested_changes.contains(flags) {
310 return;
311 }
312 state.borrow_mut().requested_changes.insert(flags);
313 if let Some(parent) = self.parent() {
314 parent.request_changes(flags);
315 }
316 }
317
318 pub(crate) fn request_style_recursive(&self) {
320 let state = self.state();
321 state.borrow_mut().request_style_recursive = true;
322 self.request_style();
323 }
324
325 pub fn request_focus(&self) {
327 self.add_update_message(UpdateMessage::Focus(*self));
328 }
329
330 pub fn clear_focus(&self) {
332 self.add_update_message(UpdateMessage::ClearFocus(*self));
333 }
334
335 pub fn update_context_menu(&self, menu: impl Fn() -> Menu + 'static) {
337 self.state().borrow_mut().context_menu = Some(Rc::new(menu));
338 }
339
340 pub fn update_popout_menu(&self, menu: impl Fn() -> Menu + 'static) {
344 self.state().borrow_mut().popout_menu = Some(Rc::new(menu));
345 }
346
347 pub fn request_active(&self) {
353 self.add_update_message(UpdateMessage::Active(*self));
354 }
355
356 pub fn clear_active(&self) {
358 self.add_update_message(UpdateMessage::ClearActive(*self));
359 }
360
361 pub fn inspect(&self) {
363 self.add_update_message(UpdateMessage::Inspect);
364 }
365
366 pub fn scroll_to(&self, rect: Option<Rect>) {
369 self.add_update_message(UpdateMessage::ScrollTo { id: *self, rect });
370 }
371
372 pub(crate) fn transition_anim_complete(&self) {
373 self.add_update_message(UpdateMessage::ViewTransitionAnimComplete(*self));
374 }
375
376 pub(crate) fn update_animation(&self, offset: StackOffset<Animation>, animation: Animation) {
377 let state = self.state();
378 state.borrow_mut().animations.set(offset, animation);
379 self.request_style();
380 }
381
382 pub(crate) fn update_animation_state(
383 &self,
384 offset: StackOffset<Animation>,
385 command: AnimStateCommand,
386 ) {
387 let view_state = self.state();
388 view_state
389 .borrow_mut()
390 .animations
391 .update(offset, move |anim| anim.transition(command));
392 self.request_style();
393 }
394
395 pub fn update_state(&self, state: impl Any) {
397 self.add_update_message(UpdateMessage::State {
398 id: *self,
399 state: Box::new(state),
400 });
401 }
402
403 pub(crate) fn set_viewport(&self, viewport: Rect) {
405 let state = self.state();
406 state.borrow_mut().viewport = Some(viewport);
407 }
408
409 pub fn add_event_listener(&self, listener: EventListener, action: Box<EventCallback>) {
411 let state = self.state();
412 state.borrow_mut().add_event_listener(listener, action);
413 }
414
415 pub fn update_resize_listener(&self, action: Box<ResizeCallback>) {
417 let state = self.state();
418 state.borrow_mut().update_resize_listener(action);
419 }
420
421 pub fn update_move_listener(&self, action: Box<dyn Fn(Point)>) {
423 let state = self.state();
424 state.borrow_mut().update_move_listener(action);
425 }
426
427 pub fn update_cleanup_listener(&self, action: Box<dyn Fn()>) {
429 let state = self.state();
430 state.borrow_mut().update_cleanup_listener(action);
431 }
432
433 pub fn get_combined_style(&self) -> Style {
442 self.state().borrow().combined_style.clone()
443 }
444
445 pub fn add_class(&self, class: StyleClassRef) {
447 let state = self.state();
448 state.borrow_mut().classes.push(class);
449 self.request_style_recursive();
450 }
451
452 pub fn remove_class(&self, class: StyleClassRef) {
454 let state = self.state();
455 state.borrow_mut().classes.retain_mut(|c| *c != class);
456 self.request_style_recursive();
457 }
458
459 pub(crate) fn update_style_selector(&self, selector: StyleSelector, style: Style) {
460 if let StyleSelector::Dragging = selector {
461 let state = self.state();
462 state.borrow_mut().dragging_style = Some(style);
463 }
464 self.request_style();
465 }
466
467 pub(crate) fn update_style(&self, offset: StackOffset<Style>, style: Style) {
468 let state = self.state();
469 let old_any_inherited = state.borrow().style().any_inherited();
470 state.borrow_mut().style.set(offset, style);
471 if state.borrow().style().any_inherited() || old_any_inherited {
472 self.request_style_recursive();
473 } else {
474 self.request_style();
475 }
476 }
477
478 pub(crate) fn apply_event(
479 &self,
480 listener: &EventListener,
481 event: &crate::event::Event,
482 ) -> Option<EventPropagation> {
483 let mut handled = false;
484 let event_listeners = self.state().borrow().event_listeners.clone();
485 if let Some(handlers) = event_listeners.get(listener) {
486 for handler in handlers {
487 handled |= (handler.borrow_mut())(event).is_processed();
488 }
489 } else {
490 return None;
491 }
492 if handled {
493 Some(EventPropagation::Stop)
494 } else {
495 Some(EventPropagation::Continue)
496 }
497 }
498
499 pub fn update_disabled(&self, is_disabled: bool) {
503 self.add_update_message(UpdateMessage::Disabled {
504 id: *self,
505 is_disabled,
506 });
507 }
508
509 pub fn keyboard_navigable(&self) {
511 self.add_update_message(UpdateMessage::KeyboardNavigable { id: *self });
512 }
513
514 pub fn remove_keyboard_navigatable(&self) {
516 self.add_update_message(UpdateMessage::RemoveKeyboardNavigable { id: *self });
517 }
518
519 pub fn disable_default_event(&self, event: EventListener) {
523 self.state()
524 .borrow_mut()
525 .disable_default_events
526 .insert(event);
527 }
528
529 pub fn remove_disable_default_event(&self, event: EventListener) {
531 self.state()
532 .borrow_mut()
533 .disable_default_events
534 .remove(&event);
535 }
536
537 pub fn pointer_events(&self, pointer_events: bool) {
539 self.state().borrow_mut().pointer_events = pointer_events;
540 }
541
542 pub fn draggable(&self) {
546 self.add_update_message(UpdateMessage::Draggable { id: *self });
547 }
548
549 pub fn window_visible(&self, visible: bool) {
552 self.add_update_message(UpdateMessage::WindowVisible(visible));
553 }
554
555 fn add_update_message(&self, msg: UpdateMessage) {
556 CENTRAL_UPDATE_MESSAGES.with_borrow_mut(|msgs| {
557 msgs.push((*self, msg));
558 });
559 }
560
561 pub fn update_state_deferred(&self, state: impl Any) {
564 CENTRAL_DEFERRED_UPDATE_MESSAGES.with_borrow_mut(|msgs| {
565 msgs.push((*self, Box::new(state)));
566 });
567 }
568
569 pub fn screen_layout(&self) -> Option<ScreenLayout> {
571 crate::screen_layout::try_create_screen_layout(self)
572 }
573}