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
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<Rc<ContextTree>>,
    values: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
}

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<Self>) -> ContextTree {
        ContextTree {
            parent: Some(self.clone()),
            values: RefCell::new(HashMap::new()),
        }
    }

    pub fn insert<T>(&self, value: Rc<T>)
    where
        T: 'static,
    {
        self.insert_raw(value);
    }

    pub fn insert_raw(&self, value: Rc<dyn Any>) {
        self.values
            .borrow_mut()
            .insert(value.as_ref().type_id(), value);
    }

    pub fn get_flat<T>(&self) -> Option<Rc<T>>
    where
        T: 'static,
    {
        let id = TypeId::of::<T>();
        let values = self.values.borrow();
        let value = values.get(&id)?;
        value.clone().downcast::<T>().ok()
    }

    pub fn get<T>(&self) -> Option<Rc<T>>
    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<T> {
    current: Weak<T>,
}

impl<T> Context<T> {
    pub fn new(value: &Rc<T>) -> Context<T> {
        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<Rc<T>> {
        self.current.upgrade()
    }

    pub fn to_owned(&self) -> Option<T>
    where
        T: Clone,
    {
        Some(self.upgrade()?.as_ref().to_owned())
    }
}

impl<T> Clone for Context<T> {
    fn clone(&self) -> Self {
        Context {
            current: self.current.clone(),
        }
    }
}

pub struct ContextProvider<T>
where
    T: 'static,
{
    pub value: Rc<T>,
}

impl<T> Clone for ContextProvider<T>
where
    T: 'static,
{
    fn clone(&self) -> ContextProvider<T> {
        ContextProvider {
            value: self.value.clone(),
        }
    }
}

impl<T, P> Component<P> for ContextProvider<T>
where
    T: 'static,
    P: Platform + ?Sized,
{
    fn render(&self, manager: &mut Manager<P>) -> Element<P> {
        Element::context(Key::new(()), self.value.clone(), manager.children())
    }
}