vizia_core/view/
handle.rs
1use crate::context::LocalizationContext;
2use crate::prelude::*;
3use std::{
4 any::{Any, TypeId},
5 marker::PhantomData,
6};
7
8pub struct Handle<'a, V> {
10 pub(crate) current: Entity,
11 pub(crate) entity: Entity,
12 pub(crate) p: PhantomData<V>,
13 pub(crate) cx: &'a mut Context,
14}
15
16impl<V> DataContext for Handle<'_, V> {
17 fn data<T: 'static>(&self) -> Option<&T> {
18 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
20 return Some(t);
21 }
22
23 for entity in self.entity.parent_iter(&self.cx.tree) {
24 if let Some(models) = self.cx.models.get(&entity) {
26 if let Some(model) = models.get(&TypeId::of::<T>()) {
27 return model.downcast_ref::<T>();
28 }
29 }
30
31 if let Some(view_handler) = self.cx.views.get(&entity) {
33 if let Some(data) = view_handler.downcast_ref::<T>() {
34 return Some(data);
35 }
36 }
37 }
38
39 None
40 }
41
42 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
43 Some(LocalizationContext::from_context(self.cx))
44 }
45}
46
47impl<V> Handle<'_, V> {
48 pub fn entity(&self) -> Entity {
50 self.entity
51 }
52
53 pub(crate) fn current(&self) -> Entity {
54 self.current
55 }
56
57 pub fn context(&mut self) -> &mut Context {
59 self.cx
60 }
61
62 pub fn parent(&self) -> Entity {
64 self.cx.tree.get_parent(self.entity).unwrap_or(Entity::root())
65 }
66
67 pub(crate) fn ignore(self) -> Self {
69 self.cx.tree.set_ignored(self.entity, true);
70 self.focusable(false)
71 }
72
73 pub fn lock_focus_to_within(self) -> Self {
75 self.cx.tree.set_lock_focus_within(self.entity, true);
76 self.cx.focus_stack.push(self.cx.focused);
77 if !self.cx.focused.is_descendant_of(&self.cx.tree, self.entity) {
78 let new_focus = vizia_storage::TreeIterator::subtree(&self.cx.tree, self.entity)
79 .find(|node| {
80 crate::tree::is_navigatable(
81 &self.cx.tree,
82 &self.cx.style,
83 *node,
84 Entity::root(),
85 )
86 })
87 .unwrap_or(self.cx.focus_stack.pop().unwrap());
88 self.cx.with_current(new_focus, |cx| cx.focus());
89 }
90 self
91 }
92
93 pub fn modify<F>(mut self, f: F) -> Self
95 where
96 F: FnOnce(&mut V),
97 V: 'static,
98 {
99 if let Some(view) = self
100 .cx
101 .views
102 .get_mut(&self.entity)
103 .and_then(|view_handler| view_handler.downcast_mut::<V>())
104 {
105 (f)(view);
106 }
107
108 self.context().emit(WindowEvent::Redraw);
110
111 self
112 }
113
114 pub fn on_build<F>(self, callback: F) -> Self
116 where
117 F: Fn(&mut EventContext),
118 {
119 let mut event_context = EventContext::new(self.cx);
120 event_context.current = self.entity;
121 (callback)(&mut event_context);
122
123 self
124 }
125
126 pub fn bind<R, T, F>(self, res: R, closure: F) -> Self
128 where
129 R: Res<T>,
130 F: 'static + Fn(Handle<'_, V>, R),
131 {
132 let entity = self.entity();
133 let current = self.current();
134 self.cx.with_current(current, |cx| {
135 res.set_or_bind(cx, entity, move |cx, r| {
136 let new_handle = Handle { entity, current: cx.current, p: Default::default(), cx };
137 (closure)(new_handle, r);
139 });
140 });
141 self
142 }
143
144 pub fn needs_relayout(&mut self) {
146 self.cx.needs_relayout();
147 }
148
149 pub fn needs_restyle(&mut self) {
151 self.cx.needs_restyle(self.entity);
152 }
153
154 pub fn needs_redraw(&mut self) {
156 self.cx.needs_redraw(self.entity);
157 }
158
159 pub fn bounds(&self) -> BoundingBox {
161 self.cx.cache.get_bounds(self.entity)
162 }
163
164 pub fn scale_factor(&self) -> f32 {
166 self.cx.scale_factor()
167 }
168}
169
170impl<V> AsMut<Context> for Handle<'_, V> {
171 fn as_mut(&mut self) -> &mut Context {
172 self.context()
173 }
174}