slides/
slides.rs

1use alisa::Children;
2
3
4#[derive(alisa::Serializable)]
5#[project(SlipsProject)]
6pub struct SlipsProject {
7    name: String,
8    slides: alisa::ChildList<Slide>
9}
10
11impl Default for SlipsProject {
12
13    fn default() -> Self {
14        Self {
15            name: "Untitled Slips".to_string(),
16            slides: alisa::ChildList::default()
17        }
18    }
19
20}
21
22impl alisa::Project for SlipsProject {
23
24    type Context = ();
25    type Objects = SlipsObjects;
26
27    fn empty() -> Self {
28        Self::default()
29    }
30
31    fn create_default(&mut self) {
32
33    }
34
35    const OBJECTS: &'static [alisa::ObjectKind<Self>] = &[
36        alisa::ObjectKind::from::<Slide>()
37    ];
38
39    const OPERATIONS: &'static [alisa::OperationKind<Self>] = &[
40        alisa::OperationKind::from::<SetName>(),
41        alisa::OperationKind::from::<CreateSlide>()
42    ];
43
44}
45
46alisa::project_set_property_operation!(SlipsProject, name, String);
47
48#[derive(alisa::Serializable, Clone)]
49#[project(SlipsProject)]
50pub struct Slide {
51    parent: (),
52    title: String,
53    text_boxes: alisa::UnorderedChildList<TextBox>
54}
55
56impl Default for Slide {
57
58    fn default() -> Self {
59        Self {
60            parent: (),
61            title: "Top Text".to_owned(),
62            text_boxes: alisa::UnorderedChildList::new()
63        }
64    }
65
66}
67
68impl alisa::Object for Slide {
69    type Project = SlipsProject;
70
71    const NAME: &'static str = "Slide";
72
73    fn list(objects: &SlipsObjects) -> &alisa::ObjList<Slide> {
74        &objects.slides
75    }
76
77    fn list_mut(objects: &mut SlipsObjects) -> &mut alisa::ObjList<Slide> {
78        &mut objects.slides
79    }
80}
81
82alisa::object_set_property_operation!(Slide, title, String);
83
84#[derive(alisa::Serializable)]
85#[project(SlipsProject)]
86pub struct SlideTreeData {
87    title: String,
88    text_boxes: alisa::UnorderedChildListTreeData<TextBox>
89}
90
91impl Default for SlideTreeData {
92
93    fn default() -> Self {
94        Self {
95            title: "Slide".to_owned(),
96            text_boxes: alisa::UnorderedChildListTreeData::default()
97        }
98    }
99
100}
101
102impl alisa::TreeObj for Slide {
103
104    type ParentPtr = ();
105    type ChildList = alisa::ChildList<Slide>;
106    type TreeData = SlideTreeData;
107
108    fn child_list<'a>(parent: (), project: &'a SlipsProject, objects: &'a SlipsObjects) -> Option<&'a alisa::ChildList<Slide>> {
109        Some(&project.slides)
110    }
111
112    fn child_list_mut<'a>(parent: Self::ParentPtr, context: &'a mut alisa::ProjectContext<Self::Project>) -> Option<&'a mut Self::ChildList> {
113        Some(&mut context.project_mut().slides)
114    }
115
116    fn parent(&self) -> () {
117        self.parent
118    }
119
120    fn parent_mut(&mut self) -> &mut () {
121        &mut self.parent
122    }
123
124    fn instance(data: &SlideTreeData, ptr: alisa::Ptr<Slide>, parent: (), recorder: &mut alisa::Recorder<SlipsProject>) {
125        use alisa::Object;
126        let slide = Slide {
127            parent,
128            title: data.title.clone(),
129            text_boxes: data.text_boxes.instance(ptr, recorder)
130        };
131        Self::add(recorder, ptr, slide);
132    }
133
134    fn destroy(&self, recorder: &mut alisa::Recorder<SlipsProject>) {
135        self.text_boxes.destroy(recorder); 
136    }
137
138    fn collect_data(&self, objects: &<Self::Project as alisa::Project>::Objects) -> Self::TreeData {
139        SlideTreeData {
140            title: self.title.clone(),
141            text_boxes: self.text_boxes.collect_data(objects)
142        }
143    }
144
145}
146
147alisa::tree_object_creation_operations!(Slide);
148
149#[derive(alisa::Serializable, Clone)]
150#[project(SlipsProject)]
151struct TextBox {
152    slide: alisa::Ptr<Slide>,
153    x: f32,
154    y: f32,
155    content: String
156}
157
158impl Default for TextBox {
159
160    fn default() -> Self {
161        Self {
162            slide: alisa::Ptr::null(),
163            x: 0.0,
164            y: 0.0,
165            content: String::new() 
166        }
167    }
168
169}
170
171impl alisa::Object for TextBox {
172
173    type Project = SlipsProject;
174
175    const NAME: &'static str = "TextBox";
176
177    fn list(objects: &SlipsObjects) -> &alisa::ObjList<TextBox> {
178        &objects.text_boxes
179    }
180
181    fn list_mut(objects: &mut SlipsObjects) -> &mut alisa::ObjList<TextBox> {
182        &mut objects.text_boxes
183    }
184
185}
186
187#[derive(alisa::Serializable)]
188#[project(SlipsProject)]
189pub struct TextBoxTreeData {
190    x: f32,
191    y: f32,
192    content: String
193}
194
195impl Default for TextBoxTreeData {
196
197    fn default() -> Self {
198        Self {
199            x: 0.0,
200            y: 0.0,
201            content: String::new() 
202        }
203    }
204
205}
206
207impl alisa::TreeObj for TextBox {
208
209    type ParentPtr = alisa::Ptr<Slide>;
210    type ChildList = alisa::UnorderedChildList<TextBox>;
211    type TreeData = TextBoxTreeData;
212
213    fn child_list<'a>(parent: alisa::Ptr<Slide>, project: &'a SlipsProject, objects: &'a SlipsObjects) -> Option<&'a alisa::UnorderedChildList<TextBox>> {
214        objects.slides.get(parent).map(|slide| &slide.text_boxes)
215    }
216
217    fn child_list_mut<'a>(parent: alisa::Ptr<Slide>, context: &'a mut alisa::ProjectContext<SlipsProject>) -> Option<&'a mut alisa::UnorderedChildList<TextBox>> {
218        context.obj_list_mut().get_mut(parent).map(|slide| &mut slide.text_boxes)
219    }
220
221    fn parent(&self) -> alisa::Ptr<Slide> {
222        self.slide
223    }
224
225    fn parent_mut(&mut self) -> &mut alisa::Ptr<Slide> {
226        &mut self.slide
227    }
228
229    fn instance(data: &TextBoxTreeData, ptr: alisa::Ptr<TextBox>, parent: alisa::Ptr<Slide>, recorder: &mut alisa::Recorder<SlipsProject>) {
230        use alisa::Object;
231        let text_box = TextBox {
232            slide: parent,
233            x: data.x,
234            y: data.y,
235            content: data.content.clone(),
236        };
237        Self::add(recorder, ptr, text_box);
238    }
239
240    fn destroy(&self, recorder: &mut alisa::Recorder<SlipsProject>) {
241
242    }
243
244    fn collect_data(&self, objects: &SlipsObjects) -> TextBoxTreeData {
245        TextBoxTreeData {
246            x: self.x,
247            y: self.y,
248            content: self.content.clone(),
249        }
250    }
251}
252
253pub struct SlipsObjects {
254    slides: alisa::ObjList<Slide>,
255    text_boxes: alisa::ObjList<TextBox>
256}
257
258impl Default for SlipsObjects {
259
260    fn default() -> Self {
261        Self {
262            slides: alisa::ObjList::default(),
263            text_boxes: alisa::ObjList::default()
264        }
265    }
266
267}
268
269fn main() {
270
271    let mut client = alisa::Client::<SlipsProject>::local("my_cool_path.slips").unwrap();
272
273    let mut action = alisa::Action::new();
274    client.perform(&mut action, SetName {
275        name: "My Cool Name".to_string(),
276    });
277
278    if let Some(ptr) = client.next_ptr() {
279        client.perform(&mut action, CreateSlide {
280            ptr,
281            parent: (),
282            idx: client.project().slides.n_children(),
283            data: SlideTreeData {
284                title: "New Slide".to_owned(),
285                text_boxes: alisa::UnorderedChildListTreeData::default()
286            },
287        });
288    }
289
290    client.tick(&mut ());
291
292    for slide_ptr in client.project().slides.iter() {
293        if let Some(slide) = client.get(slide_ptr) {
294            println!("{}", slide.title);
295        }
296    }
297    
298    let mut undo_redo = alisa::UndoRedoManager::new();
299
300    // Add the action to the list of undo's 
301    undo_redo.add(action);
302
303    // If there's an action to undo, undo it
304    undo_redo.undo(&client);
305
306    client.tick(&mut ());
307
308}