polyhorn_core/
manager.rs

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}