1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use crate::context::LocalizationContext;
use crate::prelude::*;
use std::{
    any::{Any, TypeId},
    marker::PhantomData,
};

/// A handle to a view which has been built into the tree.
pub struct Handle<'a, V> {
    pub(crate) current: Entity,
    pub(crate) entity: Entity,
    pub(crate) p: PhantomData<V>,
    pub(crate) cx: &'a mut Context,
}

impl<'a, V> DataContext for Handle<'a, V> {
    fn data<T: 'static>(&self) -> Option<&T> {
        // Return data for the static model.
        if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
            return Some(t);
        }

        for entity in self.entity.parent_iter(&self.cx.tree) {
            // Return any model data.
            if let Some(model_data_store) = self.cx.data.get(&entity) {
                if let Some(model) = model_data_store.models.get(&TypeId::of::<T>()) {
                    return model.downcast_ref::<T>();
                }
            }

            // Return any view data.
            if let Some(view_handler) = self.cx.views.get(&entity) {
                if let Some(data) = view_handler.downcast_ref::<T>() {
                    return Some(data);
                }
            }
        }

        None
    }

    fn as_context(&self) -> Option<LocalizationContext<'_>> {
        Some(LocalizationContext::from_context(self.cx))
    }
}

impl<'a, V> Handle<'a, V> {
    /// Returns the [`Entity`] id of the view.
    pub fn entity(&self) -> Entity {
        self.entity
    }

    pub(crate) fn current(&self) -> Entity {
        self.current
    }

    /// Returns a mutable reference to the context.
    pub fn context(&mut self) -> &mut Context {
        self.cx
    }

    pub fn parent(&self) -> Entity {
        self.cx.tree.get_parent(self.entity).unwrap_or(Entity::root())
    }

    /// Marks the view as being ignored.
    pub(crate) fn ignore(self) -> Self {
        self.cx.tree.set_ignored(self.entity, true);
        self.focusable(false)
    }

    /// Stop the user from tabbing out of a subtree, which is useful for modal dialogs.
    pub fn lock_focus_to_within(self) -> Self {
        self.cx.tree.set_lock_focus_within(self.entity, true);
        self.cx.focus_stack.push(self.cx.focused);
        if !self.cx.focused.is_descendant_of(&self.cx.tree, self.entity) {
            let new_focus = vizia_storage::TreeIterator::subtree(&self.cx.tree, self.entity)
                .find(|node| {
                    crate::tree::is_navigatable(
                        &self.cx.tree,
                        &self.cx.style,
                        *node,
                        Entity::root(),
                    )
                })
                .unwrap_or(self.cx.focus_stack.pop().unwrap());
            self.cx.with_current(new_focus, |cx| cx.focus());
        }
        self
    }

    /// Mody the internal data of the view.
    pub fn modify<F>(self, f: F) -> Self
    where
        F: FnOnce(&mut V),
        V: 'static,
    {
        if let Some(view) = self
            .cx
            .views
            .get_mut(&self.entity)
            .and_then(|view_handler| view_handler.downcast_mut::<V>())
        {
            (f)(view);
        }

        self
    }

    /// Callback which is run when the view is built/rebuilt.
    pub fn on_build<F>(self, callback: F) -> Self
    where
        F: Fn(&mut EventContext),
    {
        let mut event_context = EventContext::new(self.cx);
        event_context.current = self.entity;
        (callback)(&mut event_context);

        self
    }

    pub fn bind<R, T, F>(self, res: R, closure: F) -> Self
    where
        R: Res<T>,
        F: 'static + Clone + Fn(Handle<'_, V>, R),
    {
        let entity = self.entity();
        let current = self.current();
        self.cx.with_current(current, |cx| {
            res.set_or_bind(cx, entity, move |cx, r| {
                let new_handle = Handle { entity, current: cx.current, p: Default::default(), cx };
                // new_handle.cx.set_current(new_handle.entity);
                (closure)(new_handle, r);
            });
        });
        self
    }

    /// Marks the view as needing a relayout.
    pub fn needs_relayout(&mut self) {
        self.cx.needs_relayout();
    }

    /// Marks the view as needing a restyle.
    pub fn needs_restyle(&mut self) {
        self.cx.needs_restyle(self.entity);
    }

    /// Marks the view as needing a redraw.
    pub fn needs_redraw(&mut self) {
        self.cx.needs_redraw(self.entity);
    }

    /// Returns the bounding box of the view.
    pub fn bounds(&self) -> BoundingBox {
        self.cx.cache.get_bounds(self.entity)
    }

    /// Returns the scale factor of the device.
    pub fn scale_factor(&self) -> f32 {
        self.cx.scale_factor()
    }
}

impl<'a, V> AsMut<Context> for Handle<'a, V> {
    fn as_mut(&mut self) -> &mut Context {
        self.context()
    }
}