1use std::collections::BTreeMap;
4
5use dotloom_document::{
6 Constraint, ConstraintId, Document, Entity, EntityId, Group, GroupId, Layer, LayerId, Settings,
7};
8
9pub trait DocView {
11 fn entity(&self, id: EntityId) -> Option<&Entity>;
13 fn constraint(&self, id: ConstraintId) -> Option<&Constraint>;
15 fn layer(&self, id: LayerId) -> Option<&Layer>;
17 fn group(&self, id: GroupId) -> Option<&Group>;
19 fn settings(&self) -> &Settings;
21}
22
23impl DocView for Document {
24 fn entity(&self, id: EntityId) -> Option<&Entity> {
25 Document::entity(self, id)
26 }
27 fn constraint(&self, id: ConstraintId) -> Option<&Constraint> {
28 Document::constraint(self, id)
29 }
30 fn layer(&self, id: LayerId) -> Option<&Layer> {
31 Document::layer(self, id)
32 }
33 fn group(&self, id: GroupId) -> Option<&Group> {
34 Document::group(self, id)
35 }
36 fn settings(&self) -> &Settings {
37 &self.settings
38 }
39}
40
41#[derive(Debug, Clone)]
43pub struct Overlay<'a> {
44 pub base: &'a Document,
46 pub entities: BTreeMap<EntityId, Option<Entity>>,
48 pub constraints: BTreeMap<ConstraintId, Option<Constraint>>,
50 pub groups: BTreeMap<GroupId, Option<Group>>,
52 pub layers: Option<Vec<Layer>>,
54 pub settings: Option<Settings>,
56 pub order_ops: Vec<OrderOp>,
58 pub next_id: u64,
60}
61
62#[derive(Debug, Clone, Default)]
64pub struct OverlayData {
65 entities: BTreeMap<EntityId, Option<Entity>>,
66 constraints: BTreeMap<ConstraintId, Option<Constraint>>,
67 groups: BTreeMap<GroupId, Option<Group>>,
68 layers: Option<Vec<Layer>>,
69 settings: Option<Settings>,
70 order_ops: Vec<OrderOp>,
71 next_id: u64,
72}
73
74impl<'a> Overlay<'a> {
75 #[must_use]
77 pub fn into_data(self) -> OverlayData {
78 OverlayData {
79 entities: self.entities,
80 constraints: self.constraints,
81 groups: self.groups,
82 layers: self.layers,
83 settings: self.settings,
84 order_ops: self.order_ops,
85 next_id: self.next_id,
86 }
87 }
88
89 #[must_use]
91 pub fn from_data(base: &'a Document, d: OverlayData) -> Self {
92 Self {
93 base,
94 entities: d.entities,
95 constraints: d.constraints,
96 groups: d.groups,
97 layers: d.layers,
98 settings: d.settings,
99 order_ops: d.order_ops,
100 next_id: d.next_id,
101 }
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum OrderOp {
108 Move(EntityId, usize),
110}
111
112impl<'a> Overlay<'a> {
113 #[must_use]
115 pub fn new(base: &'a Document) -> Self {
116 Self {
117 base,
118 entities: BTreeMap::new(),
119 constraints: BTreeMap::new(),
120 groups: BTreeMap::new(),
121 layers: None,
122 settings: None,
123 order_ops: Vec::new(),
124 next_id: base.next_id(),
125 }
126 }
127
128 pub fn alloc_id(&mut self) -> u64 {
130 let id = self.next_id;
131 self.next_id = self.next_id.saturating_add(1);
132 id
133 }
134
135 pub fn entity_mut(&mut self, id: EntityId) -> Option<&mut Entity> {
137 if !self.entities.contains_key(&id) {
138 let e = self.base.entity(id)?.clone();
139 self.entities.insert(id, Some(e));
140 }
141 self.entities.get_mut(&id).and_then(Option::as_mut)
142 }
143
144 pub fn put_entity(&mut self, e: Entity) {
146 self.entities.insert(e.id, Some(e));
147 }
148
149 pub fn delete_entity(&mut self, id: EntityId) {
151 self.entities.insert(id, None);
152 }
153
154 pub fn put_constraint(&mut self, c: Constraint) {
156 self.constraints.insert(c.id, Some(c));
157 }
158
159 pub fn delete_constraint(&mut self, id: ConstraintId) {
161 self.constraints.insert(id, None);
162 }
163
164 pub fn layers_mut(&mut self) -> &mut Vec<Layer> {
166 self.layers.get_or_insert_with(|| self.base.layers().to_vec())
167 }
168
169 #[must_use]
171 pub fn layers(&self) -> &[Layer] {
172 self.layers.as_deref().unwrap_or(self.base.layers())
173 }
174
175 pub fn settings_mut(&mut self) -> &mut Settings {
177 self.settings.get_or_insert_with(|| self.base.settings.clone())
178 }
179
180 #[must_use]
182 pub fn constraint_ids(&self) -> Vec<ConstraintId> {
183 let mut ids: Vec<ConstraintId> = self
184 .base
185 .constraints()
186 .map(|c| c.id)
187 .filter(|id| !matches!(self.constraints.get(id), Some(None)))
188 .collect();
189 ids.extend(
190 self.constraints
191 .iter()
192 .filter(|(id, c)| c.is_some() && self.base.constraint(**id).is_none())
193 .map(|(id, _)| *id),
194 );
195 ids.sort_unstable();
196 ids
197 }
198
199 #[must_use]
201 pub fn entity_ids(&self) -> Vec<EntityId> {
202 let mut ids: Vec<EntityId> =
203 self.base.order().iter().copied().filter(|id| !matches!(self.entities.get(id), Some(None))).collect();
204 ids.extend(
205 self.entities.iter().filter(|(id, e)| e.is_some() && self.base.entity(**id).is_none()).map(|(id, _)| *id),
206 );
207 ids
208 }
209
210 #[must_use]
212 pub fn group_ids(&self) -> Vec<GroupId> {
213 let mut ids: Vec<GroupId> =
214 self.base.groups().map(|g| g.id).filter(|id| !matches!(self.groups.get(id), Some(None))).collect();
215 ids.extend(
216 self.groups.iter().filter(|(id, g)| g.is_some() && self.base.group(**id).is_none()).map(|(id, _)| *id),
217 );
218 ids.sort_unstable();
219 ids
220 }
221}
222
223impl DocView for Overlay<'_> {
224 fn entity(&self, id: EntityId) -> Option<&Entity> {
225 match self.entities.get(&id) {
226 Some(e) => e.as_ref(),
227 None => self.base.entity(id),
228 }
229 }
230 fn constraint(&self, id: ConstraintId) -> Option<&Constraint> {
231 match self.constraints.get(&id) {
232 Some(c) => c.as_ref(),
233 None => self.base.constraint(id),
234 }
235 }
236 fn layer(&self, id: LayerId) -> Option<&Layer> {
237 self.layers().iter().find(|l| l.id == id)
238 }
239 fn group(&self, id: GroupId) -> Option<&Group> {
240 match self.groups.get(&id) {
241 Some(g) => g.as_ref(),
242 None => self.base.group(id),
243 }
244 }
245 fn settings(&self) -> &Settings {
246 self.settings.as_ref().unwrap_or(&self.base.settings)
247 }
248}