1use super::{Component, Element, Key, Manager, Platform};
2use std::any::{Any, TypeId};
3use std::cell::RefCell;
4use std::collections::HashMap;
5use std::rc::{Rc, Weak};
6
7pub struct ContextTree {
8 parent: Option<Rc<ContextTree>>,
9 values: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
10}
11
12impl ContextTree {
13 pub fn new() -> ContextTree {
15 ContextTree {
16 parent: None,
17 values: RefCell::new(HashMap::new()),
18 }
19 }
20
21 pub fn enter(self: &Rc<Self>) -> ContextTree {
23 ContextTree {
24 parent: Some(self.clone()),
25 values: RefCell::new(HashMap::new()),
26 }
27 }
28
29 pub fn insert<T>(&self, value: Rc<T>)
30 where
31 T: 'static,
32 {
33 self.insert_raw(value);
34 }
35
36 pub fn insert_raw(&self, value: Rc<dyn Any>) {
37 self.values
38 .borrow_mut()
39 .insert(value.as_ref().type_id(), value);
40 }
41
42 pub fn get_flat<T>(&self) -> Option<Rc<T>>
43 where
44 T: 'static,
45 {
46 let id = TypeId::of::<T>();
47 let values = self.values.borrow();
48 let value = values.get(&id)?;
49 value.clone().downcast::<T>().ok()
50 }
51
52 pub fn get<T>(&self) -> Option<Rc<T>>
53 where
54 T: 'static,
55 {
56 self.get_flat()
57 .or_else(|| self.parent.as_ref().and_then(|parent| parent.get()))
58 }
59}
60
61impl Default for ContextTree {
62 fn default() -> Self {
63 ContextTree::new()
64 }
65}
66
67pub struct Context<T> {
68 current: Weak<T>,
69}
70
71impl<T> Context<T> {
72 pub fn new(value: &Rc<T>) -> Context<T> {
73 Context {
74 current: Rc::downgrade(value),
75 }
76 }
77
78 pub fn is_none(&self) -> bool {
79 !self.is_some()
80 }
81
82 pub fn is_some(&self) -> bool {
83 self.current.upgrade().is_some()
84 }
85
86 pub fn upgrade(&self) -> Option<Rc<T>> {
87 self.current.upgrade()
88 }
89
90 pub fn to_owned(&self) -> Option<T>
91 where
92 T: Clone,
93 {
94 Some(self.upgrade()?.as_ref().to_owned())
95 }
96}
97
98impl<T> Clone for Context<T> {
99 fn clone(&self) -> Self {
100 Context {
101 current: self.current.clone(),
102 }
103 }
104}
105
106pub struct ContextProvider<T>
107where
108 T: 'static,
109{
110 pub value: Rc<T>,
111}
112
113impl<T> Clone for ContextProvider<T>
114where
115 T: 'static,
116{
117 fn clone(&self) -> ContextProvider<T> {
118 ContextProvider {
119 value: self.value.clone(),
120 }
121 }
122}
123
124impl<T, P> Component<P> for ContextProvider<T>
125where
126 T: 'static,
127 P: Platform + ?Sized,
128{
129 fn render(&self, manager: &mut Manager<P>) -> Element<P> {
130 Element::context(Key::new(()), self.value.clone(), manager.children())
131 }
132}