1use super::hooks::{UseAsync, UseContext, UseEffect, UseLayoutEffect, UseReference, UseState};
2use super::{
3 Context, ContextTree, Effect, EffectLink, Element, EventLoop, Instance, Key, LayoutEffect,
4 Link, Memory, Platform, Reference, State, Weak, WeakLink,
5};
6use serde::{Deserialize, Serialize};
7use std::future::Future;
8use std::rc::Rc;
9
10pub struct Manager<'a, P>
11where
12 P: Platform + ?Sized,
13{
14 compositor: &'a P::Compositor,
15 bus: &'a EventLoop,
16 memory: &'a mut Memory,
17 context: &'a ContextTree,
18 children: Element<P>,
19 effects: Vec<Effect<P>>,
20 layout_effects: Vec<LayoutEffect<P>>,
21 instance: &'a Rc<Instance<P>>,
22}
23
24impl<'a, P> Manager<'a, P>
25where
26 P: Platform + ?Sized,
27{
28 pub fn new(
29 compositor: &'a P::Compositor,
30 bus: &'a EventLoop,
31 memory: &'a mut Memory,
32 context: &'a ContextTree,
33 children: Element<P>,
34 instance: &'a Rc<Instance<P>>,
35 ) -> Manager<'a, P> {
36 Manager {
37 compositor,
38 bus,
39 memory,
40 context,
41 children,
42 effects: vec![],
43 layout_effects: vec![],
44 instance,
45 }
46 }
47
48 pub fn compositor(&self) -> &P::Compositor {
49 self.compositor
50 }
51
52 pub fn children(&mut self) -> Element<P> {
53 self.children.clone()
54 }
55
56 pub fn bind<F, I>(&self, closure: F) -> impl Fn(I)
57 where
58 F: Fn(&WeakLink<P>, I),
59 {
60 let weak = Weak::new(self.instance);
61
62 move |input: I| {
63 weak.with_link(|link| closure(link, input));
64 }
65 }
66
67 pub(crate) fn into_effects(self) -> (Vec<Effect<P>>, Vec<LayoutEffect<P>>) {
68 (self.effects, self.layout_effects)
69 }
70}
71
72impl<'a, P> UseAsync for Manager<'a, P>
73where
74 P: Platform + ?Sized,
75{
76 fn use_async<F>(&mut self, key: Key, task: F)
77 where
78 F: Future<Output = ()> + 'static,
79 {
80 let bus = &mut self.bus;
81 self.memory.future(key, || bus.queue(task))
82 }
83}
84
85impl<'a, P> UseContext for Manager<'a, P>
86where
87 P: Platform + ?Sized,
88{
89 fn use_context<T>(&mut self) -> Option<Context<T>>
90 where
91 T: 'static,
92 {
93 self.context.get::<T>().map(|value| Context::new(&value))
94 }
95}
96
97impl<'a, P> UseEffect<P> for Manager<'a, P>
98where
99 P: Platform + ?Sized,
100{
101 fn use_effect<F>(&mut self, key: Key, conditions: Option<Key>, effect: F)
102 where
103 F: FnOnce(&EffectLink<P>) + 'static,
104 {
105 if let Some(conditions) = conditions {
106 if !self.memory.effect(key, conditions) {
107 return;
108 }
109 }
110
111 self.effects.push(Effect::new(self.instance, effect))
112 }
113}
114
115impl<'a, P> UseLayoutEffect<P> for Manager<'a, P>
116where
117 P: Platform + ?Sized,
118{
119 fn use_layout_effect<F>(&mut self, key: Key, conditions: Option<Key>, effect: F)
120 where
121 F: FnOnce(&EffectLink<P>, &mut P::CommandBuffer) + 'static,
122 {
123 if let Some(conditions) = conditions {
124 if !self.memory.effect(key, conditions) {
125 return;
126 }
127 }
128
129 let effect = LayoutEffect::new(self.instance, effect);
130 self.layout_effects.push(effect)
131 }
132}
133
134impl<'a, P> UseState for Manager<'a, P>
135where
136 P: Platform + ?Sized,
137{
138 fn use_state<S>(&mut self, key: Key, initial_value: S) -> State<S>
139 where
140 S: Serialize + for<'b> Deserialize<'b> + 'static,
141 {
142 let state_id = self.memory.state_id(key, move || initial_value);
143
144 State::new(self.instance.id, state_id)
145 }
146}
147
148impl<'a, P> UseReference for Manager<'a, P>
149where
150 P: Platform + ?Sized,
151{
152 fn use_reference<R, I>(&mut self, key: Key, initializer: I) -> Reference<R>
153 where
154 R: 'static,
155 I: FnOnce() -> R,
156 {
157 let reference_id = self.memory.reference_id(key, initializer);
158
159 Reference::new(self.instance.id, reference_id)
160 }
161}
162
163impl<'a, P> Link for Manager<'a, P>
164where
165 P: Platform + ?Sized,
166{
167 type Platform = P;
168
169 fn instance(&self) -> &Rc<Instance<Self::Platform>> {
170 self.instance
171 }
172
173 fn memory(&self) -> &Memory {
174 self.memory
175 }
176}