freya_core/
scope.rs

1use std::{
2    any::{
3        Any,
4        TypeId,
5    },
6    rc::Rc,
7};
8
9use generational_box::{
10    AnyStorage,
11    GenerationalBox,
12    Owner,
13    UnsyncStorage,
14};
15use pathgraph::PathGraph;
16use rustc_hash::FxHashMap;
17
18use crate::{
19    diff_key::DiffKey,
20    element::{
21        ComponentProps,
22        Element,
23    },
24    node_id::NodeId,
25    path_element::PathElement,
26    reactive_context::ReactiveContext,
27    scope_id::ScopeId,
28};
29
30pub struct Scope {
31    pub id: ScopeId,
32    pub parent_id: Option<ScopeId>,
33    pub height: usize,
34
35    pub parent_node_id_in_parent: NodeId,
36    pub path_in_parent: Box<[u32]>, // TODO: Maybe just store the index rather than the whole path?
37
38    pub nodes: PathGraph<PathNode>,
39
40    pub key: DiffKey,
41
42    pub comp: Rc<dyn Fn(Rc<dyn ComponentProps>) -> Element>,
43
44    pub props: Rc<dyn ComponentProps>,
45
46    pub element: Option<PathElement>,
47}
48
49impl Scope {
50    pub fn with_element<D>(&self, target_path: &[u32], with: D)
51    where
52        D: FnOnce(&PathElement),
53    {
54        if let Some(element) = &self.element {
55            element.with_element(target_path, with);
56        }
57    }
58}
59
60#[derive(Clone)]
61pub struct ScopeStorage {
62    pub parent_id: Option<ScopeId>,
63    pub current_run: usize,
64    pub current_value: usize,
65    pub values: Vec<Rc<dyn Any>>,
66
67    pub contexts: FxHashMap<TypeId, Rc<dyn Any>>,
68
69    pub reactive_context: ReactiveContext,
70
71    pub owner: Owner,
72}
73
74impl ScopeStorage {
75    pub(crate) fn new<T: 'static>(
76        parent_id: Option<ScopeId>,
77        reactive_context: impl FnOnce(&dyn Fn(T) -> GenerationalBox<T>) -> ReactiveContext,
78    ) -> Self {
79        let owner = UnsyncStorage::owner();
80        let reactive_context = (reactive_context)(&|d: T| owner.insert(d));
81        Self {
82            parent_id,
83            current_run: Default::default(),
84            current_value: Default::default(),
85            values: Default::default(),
86            contexts: Default::default(),
87            reactive_context,
88            owner,
89        }
90    }
91
92    pub(crate) fn reset(&mut self) {
93        self.current_run = 0;
94        self.current_value = 0;
95        self.values.clear();
96        self.contexts.clear();
97    }
98}
99
100#[derive(Clone, Debug, PartialEq)]
101pub struct PathNode {
102    pub node_id: NodeId,
103    pub scope_id: Option<ScopeId>,
104}