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 undo_redo.add(action);
302
303 undo_redo.undo(&client);
305
306 client.tick(&mut ());
307
308}