use super::{Component, Element, Key, Manager, Platform}; use std::any::{Any, TypeId}; use std::cell::RefCell; use std::collections::HashMap; use std::rc::{Rc, Weak}; pub struct ContextTree { parent: Option>, values: RefCell>>, } impl ContextTree { /// This function creates a new context tree root. pub fn new() -> ContextTree { ContextTree { parent: None, values: RefCell::new(HashMap::new()), } } /// This function enters a new branch of a given context tree. pub fn enter(self: &Rc) -> ContextTree { ContextTree { parent: Some(self.clone()), values: RefCell::new(HashMap::new()), } } pub fn insert(&self, value: Rc) where T: 'static, { self.insert_raw(value); } pub fn insert_raw(&self, value: Rc) { self.values .borrow_mut() .insert(value.as_ref().type_id(), value); } pub fn get_flat(&self) -> Option> where T: 'static, { let id = TypeId::of::(); let values = self.values.borrow(); let value = values.get(&id)?; value.clone().downcast::().ok() } pub fn get(&self) -> Option> where T: 'static, { self.get_flat() .or_else(|| self.parent.as_ref().and_then(|parent| parent.get())) } } impl Default for ContextTree { fn default() -> Self { ContextTree::new() } } pub struct Context { current: Weak, } impl Context { pub fn new(value: &Rc) -> Context { Context { current: Rc::downgrade(value), } } pub fn is_none(&self) -> bool { !self.is_some() } pub fn is_some(&self) -> bool { self.current.upgrade().is_some() } pub fn upgrade(&self) -> Option> { self.current.upgrade() } pub fn to_owned(&self) -> Option where T: Clone, { Some(self.upgrade()?.as_ref().to_owned()) } } impl Clone for Context { fn clone(&self) -> Self { Context { current: self.current.clone(), } } } pub struct ContextProvider where T: 'static, { pub value: Rc, } impl Clone for ContextProvider where T: 'static, { fn clone(&self) -> ContextProvider { ContextProvider { value: self.value.clone(), } } } impl Component

for ContextProvider where T: 'static, P: Platform + ?Sized, { fn render(&self, manager: &mut Manager

) -> Element

{ Element::context(Key::new(()), self.value.clone(), manager.children()) } }