1use std::{cell::RefCell, rc::Rc};
2
3use crate::{Context, Diff, Event, IdPath, IdPathBuf, Node, Storage, Update, View};
4
5pub struct Root<T> {
7 view: RefCell<T>,
8 storage: Rc<Storage>,
9 last_render: RefCell<Node>,
10}
11
12impl<T> Root<T> {
13 pub fn new(view: T) -> Self {
14 Self {
15 view: RefCell::new(view),
16 storage: Rc::new(Storage::new()),
17 last_render: RefCell::new(Node::Empty {}),
18 }
19 }
20
21 pub fn storage(&self) -> &Rc<Storage> {
22 &self.storage
23 }
24}
25
26impl<T> Root<T> where T: View {
27 pub fn render(&self) -> Node {
28 let context = Context::new(self.storage.clone());
29 let new_render = self.storage.with_preapplied_changes(|| {
30 self.view.borrow().render(&context)
31 });
32
33 {
34 let last_render = self.last_render.borrow();
35 let diff = new_render.diff(&last_render);
36
37 for (id_path, _) in &diff.removed {
38 self.view.borrow().fire(&Event::Disappear, id_path, &context);
39 }
40
41 self.storage.apply_changes();
42
43 for (id_path, _) in &diff.added {
44 self.view.borrow().fire(&Event::Appear, id_path, &context);
45 }
46 }
47
48 *self.last_render.borrow_mut() = new_render.clone();
49 new_render
50 }
51
52 pub fn render_json(&self) -> String {
53 let node = self.render();
54 serde_json::to_string(&node).expect("Could not serialize view")
55 }
56
57 pub fn fire_event_json(&self, id_path_json: &str, event_json: &str) {
58 let id_path: IdPathBuf = serde_json::from_str(id_path_json).expect("Could not deserialize id path");
59 let event: Event = serde_json::from_str(event_json).expect("Could not deserialize event");
60 self.fire_event(&id_path, &event);
61 }
62
63 pub fn fire_event(&self, id_path: &IdPath, event: &Event) {
64 self.view.borrow().fire(event, id_path, &Context::new(self.storage.clone()));
65 }
66
67 pub fn set_update_callback(&self, update_callback: impl Fn(&Update) + 'static) {
68 self.storage.set_update_callback(update_callback);
69 }
70}