1use super::element::{ElementBuiltin, ElementComponent, ElementContext, ElementFragment};
2use super::{
3 CommandBuffer, Component, Compositor, Disposable, Effect, EffectLink, Element, EventLoop,
4 Instance, LayoutEffect, Manager, Platform,
5};
6use std::cell::RefCell;
7use std::ops::DerefMut;
8use std::rc::Rc;
9
10pub struct Render<P>
11where
12 P: Platform + ?Sized,
13{
14 renderer: Rc<Renderer<P>>,
15 buffer: P::CommandBuffer,
16 layout_effects: Vec<LayoutEffect<P>>,
17 effects: Vec<Effect<P>>,
18}
19
20impl<P> Render<P>
21where
22 P: Platform + ?Sized,
23{
24 fn new(renderer: Rc<Renderer<P>>) -> Render<P> {
25 let buffer = renderer
26 .compositor
27 .try_borrow_mut()
28 .expect("Couldn't acquire new command buffer from busy compositor.")
29 .buffer();
30
31 Render {
32 renderer,
33 buffer,
34 layout_effects: vec![],
35 effects: vec![],
36 }
37 }
38
39 fn rerender_builtin(&mut self, instance: &Rc<Instance<P>>, element: ElementBuiltin<P>) {
40 let container = instance.container();
41 let builtin = element.builtin;
42
43 self.buffer
44 .mutate(&[container], move |containers, environment| {
45 builtin.update(containers[0], environment);
46 });
47
48 self.rerender_edges(instance, vec![*element.children]);
49 }
50
51 fn rerender_component(&mut self, instance: &Rc<Instance<P>>, element: ElementComponent<P>) {
52 let (edges, (effects, layout_effects)) = {
53 let mut memory = instance.memory_mut();
54 let compositor = self
55 .renderer
56 .compositor
57 .try_borrow()
58 .expect("Couldn't borrow compositor.");
59 let bus = self
60 .renderer
61 .bus
62 .try_borrow()
63 .expect("Couldn't borrow bus.");
64 let mut manager = Manager::new(
65 &*compositor,
66 &*bus,
67 &mut memory,
68 instance.context(),
69 *element.children,
70 &instance,
71 );
72 (
73 vec![element.component.render(&mut manager)],
74 manager.into_effects(),
75 )
76 };
77
78 self.rerender_edges(instance, edges);
79
80 self.effects.extend(effects);
81 self.layout_effects.extend(layout_effects);
82 }
83
84 fn rerender_context(&mut self, instance: &Rc<Instance<P>>, element: ElementContext<P>) {
85 instance.context().insert_raw(element.value);
86
87 self.rerender_edges(instance, vec![*element.children])
88 }
89
90 fn rerender_fragment(&mut self, instance: &Rc<Instance<P>>, element: ElementFragment<P>) {
91 self.rerender_edges(instance, element.elements)
92 }
93
94 fn rerender_edges(&mut self, instance: &Rc<Instance<P>>, edges: Vec<Element<P>>) {
95 let mut topology = instance.topology_mut();
96 let topology = topology.deref_mut();
97
98 let mut keys = topology.keys();
101
102 for element in edges {
103 let key = element.key();
104
105 keys.remove(key);
106
107 if let Some(existing) = topology.edge(key) {
108 existing.topology_mut().deref_mut().update(element);
111 self.rerender(existing)
112 } else {
113 let key = key.clone();
116 let instance = self.render(
117 Some(instance.clone()),
118 element,
119 instance.container().clone(),
120 );
121 topology.add_edge(key, instance);
122 }
123 }
124
125 for key in keys {
128 if let Some(instance) = topology.remove_edge(&key) {
129 self.unmount(&instance);
130 }
131 }
132 }
133
134 fn unmount(&mut self, instance: &Rc<Instance<P>>) {
135 for edge in instance.topology_mut().edges() {
136 self.unmount(&edge);
137 }
138
139 match instance.topology_mut().deref_mut().element() {
140 Element::Builtin(_) => {
141 self.buffer.unmount(instance.container());
142 }
143 _ => {}
144 }
145 }
146
147 pub fn rerender(&mut self, instance: &Rc<Instance<P>>) {
149 let element = instance.topology_mut().element().clone();
150
151 match element {
152 Element::Builtin(element) => self.rerender_builtin(instance, element),
153 Element::Component(element) => self.rerender_component(instance, element),
154 Element::Context(element) => self.rerender_context(instance, element),
155 Element::Fragment(element) => self.rerender_fragment(instance, element),
156 Element::String(_text) => unimplemented!("Can't render string element directly."),
157 }
158 }
159
160 pub fn render(
163 &mut self,
164 parent: Option<Rc<Instance<P>>>,
165 element: Element<P>,
166 in_container: P::ContainerID,
167 ) -> Rc<Instance<P>> {
168 let container = match &element {
171 Element::Builtin(element) => {
172 let builtin = element.builtin.clone();
173 let container = self.buffer.mount(in_container, move |parent, environment| {
174 builtin.instantiate(parent, environment)
175 });
176
177 if let Some(reference) = &element.reference {
178 reference.replace(Some(container));
179 }
180
181 container
182 }
183 _ => in_container,
184 };
185
186 let renderer = self.renderer.clone();
187
188 let instance = Rc::new(Instance::new(renderer, parent, element, container));
190
191 self.rerender(&instance);
193
194 instance
195 }
196
197 pub fn finish(mut self) {
198 self.buffer.layout();
199
200 for effect in self.layout_effects.into_iter() {
202 let instance = effect.instance().clone();
203 let memory = instance.memory();
204 let link = EffectLink::new(&instance, &memory);
205
206 effect.invoke(&link, &mut self.buffer);
207 }
208
209 self.buffer.commit();
210
211 let effects = self.effects;
212
213 self.renderer.bus.borrow().queue_retain(async move {
214 for effect in effects.into_iter() {
215 let instance = effect.instance().clone();
216 let memory = instance.memory();
217 let link = EffectLink::new(&instance, &memory);
218
219 effect.invoke(&link);
220 }
221 });
222 }
223}
224
225pub struct Renderer<P>
226where
227 P: Platform + ?Sized,
228{
229 compositor: RefCell<P::Compositor>,
230 bus: RefCell<EventLoop>,
231}
232
233impl<P> Renderer<P>
234where
235 P: Platform + ?Sized,
236{
237 pub fn new(compositor: P::Compositor, bus: EventLoop) -> Rc<Renderer<P>> {
240 Rc::new(Renderer {
241 compositor: RefCell::new(compositor),
242 bus: RefCell::new(bus),
243 })
244 }
245
246 pub fn queue_rerender(self: &Rc<Self>, instance: &Rc<Instance<P>>) {
247 let renderer = self.clone();
248 let instance = instance.clone();
249
250 self.bus.borrow().queue_retain(async move {
251 let mut render = Render::new(renderer);
252 render.rerender(&instance);
253 render.finish();
254 });
255 }
256
257 pub fn render(
258 self: &Rc<Self>,
259 element: Element<P>,
260 container: P::ContainerID,
261 ) -> Rc<Instance<P>> {
262 let mut render = Render::new(self.clone());
263 let instance = render.render(None, element, container);
264 render.finish();
265
266 instance
267 }
268}
269
270pub fn render<F, P>(element: F, container: P::Container) -> Disposable
274where
275 F: FnOnce() -> Element<P> + Send + 'static,
276 P: Platform + ?Sized,
277{
278 P::with_compositor(container, move |container_id, compositor, bus| {
279 let renderer = Renderer::new(compositor, bus);
281 Disposable::new(renderer.render(element(), container_id))
282 })
283}