workflow_egui/module/
manager.rs

1use crate::imports::*;
2
3struct Inner<T> {
4    deactivation: Option<Module<T>>,
5    module: Module<T>,
6    modules: AHashMap<TypeId, Module<T>>,
7    stack: VecDeque<Module<T>>,
8}
9
10impl<T> Inner<T>
11where
12    T: App,
13{
14    pub fn new(module: Module<T>, modules: AHashMap<TypeId, Module<T>>) -> Self {
15        Self {
16            deactivation: None,
17            module,
18            modules,
19            stack: VecDeque::new(),
20        }
21    }
22}
23
24pub struct ModuleManager<T> {
25    inner: Rc<RefCell<Inner<T>>>,
26}
27
28impl<T> Clone for ModuleManager<T> {
29    fn clone(&self) -> Self {
30        Self {
31            inner: Rc::clone(&self.inner),
32        }
33    }
34}
35
36impl<T> ModuleManager<T>
37where
38    T: App,
39{
40    pub fn new(default_module: TypeId, modules: AHashMap<TypeId, Module<T>>) -> Self {
41        let default_module = modules
42            .get(&default_module)
43            .expect("Unknown module")
44            .clone();
45        Self {
46            inner: Rc::new(RefCell::new(Inner::new(default_module, modules))),
47        }
48    }
49
50    fn inner(&self) -> Ref<Inner<T>> {
51        self.inner.borrow()
52    }
53
54    fn inner_mut(&self) -> RefMut<Inner<T>> {
55        self.inner.borrow_mut()
56    }
57
58    pub fn module(&self) -> Module<T> {
59        self.inner().module.clone()
60    }
61
62    pub fn select<M>(&mut self, core: &mut T)
63    where
64        M: 'static,
65    {
66        self.select_with_type_id(TypeId::of::<M>(), core);
67    }
68
69    pub fn select_with_type_id(&self, type_id: TypeId, core: &mut T) {
70        let (current, next) = {
71            let inner = self.inner();
72            (
73                inner.module.clone(),
74                inner.modules.get(&type_id).expect("Unknown module").clone(),
75            )
76        };
77
78        if let Some(next) = (current.type_id() != next.type_id()).then(|| {
79            let mut inner = self.inner_mut();
80            inner.stack.push_back(current.clone());
81            inner.deactivation = Some(current);
82            inner.module = next.clone();
83            next
84        }) {
85            next.activate(core);
86        }
87    }
88
89    pub fn has_stack(&self) -> bool {
90        !self.inner().stack.is_empty()
91    }
92
93    pub fn render(
94        &self,
95        app: &mut T,
96        ctx: &egui::Context,
97        frame: &mut eframe::Frame,
98        ui: &mut egui::Ui,
99    ) {
100        self.module().render(app, ctx, frame, ui);
101        if let Some(previous) = self.inner_mut().deactivation.take() {
102            previous.deactivate(app);
103        }
104    }
105
106    pub fn back(&mut self) {
107        let mut inner = self.inner_mut();
108        while let Some(module) = inner.stack.pop_back() {
109            if !module.secure() {
110                inner.module = module;
111                return;
112            }
113        }
114    }
115
116    pub fn purge_secure_stack(&mut self) {
117        self.inner_mut().stack.retain(|module| !module.secure());
118    }
119
120    pub fn get<M>(&self) -> ModuleReference<T, M>
121    where
122        M: ModuleT<Context = T> + 'static,
123    {
124        let inner = self.inner();
125        let cell = inner.modules.get(&TypeId::of::<M>()).unwrap();
126        ModuleReference::new(&cell.inner.module)
127    }
128}
129
130pub struct ModuleReference<T, M>
131where
132    T: App,
133{
134    module: Rc<RefCell<dyn ModuleT<Context = T>>>,
135    _phantom: PhantomData<M>,
136}
137
138impl<T, M> ModuleReference<T, M>
139where
140    T: App,
141{
142    fn new(module: &Rc<RefCell<dyn ModuleT<Context = T>>>) -> Self {
143        Self {
144            module: module.clone(),
145            _phantom: PhantomData,
146        }
147    }
148
149    pub fn as_ref(&self) -> Ref<'_, M>
150    where
151        M: ModuleT<Context = T> + 'static,
152    {
153        Ref::map(self.module.borrow(), |r| {
154            (r).as_any()
155                .downcast_ref::<M>()
156                .expect("unable to downcast section")
157        })
158    }
159
160    pub fn as_mut(&self) -> RefMut<'_, M>
161    where
162        M: ModuleT<Context = T> + 'static,
163    {
164        RefMut::map(self.module.borrow_mut(), |r| {
165            (r).as_any_mut()
166                .downcast_mut::<M>()
167                .expect("unable to downcast section")
168        })
169    }
170}