This repository has no description
1use crate::{ColoredObject, Fill, Filter, ObjectSizes, Region, Toggleable};
2use std::{collections::HashMap, fmt::Display};
3
4#[derive(Debug, Clone, Default)]
5// #[wasm_bindgen(getter_with_clone)]
6pub struct Layer {
7 pub object_sizes: ObjectSizes,
8 pub objects: HashMap<String, ColoredObject>,
9 pub name: String,
10 pub hidden: bool,
11}
12
13impl Layer {
14 pub fn new(name: impl Display) -> Self {
15 Layer {
16 object_sizes: ObjectSizes::default(),
17 objects: HashMap::new(),
18 name: format!("{}", name),
19 hidden: false,
20 }
21 }
22
23 pub fn hide(&mut self) {
24 self.hidden = true;
25 }
26
27 pub fn show(&mut self) {
28 self.hidden = false;
29 }
30
31 pub fn toggle(&mut self) {
32 self.hidden.toggle();
33 }
34
35 pub fn object(&mut self, name: &str) -> &mut ColoredObject {
36 self.safe_object(name).unwrap()
37 }
38
39 pub fn safe_object(&mut self, name: &str) -> Option<&mut ColoredObject> {
40 self.objects.get_mut(name)
41 }
42
43 // Flush the render cache.
44 pub fn flush(&mut self) {
45 // nothing
46 }
47
48 // Remove all objects.
49 pub fn clear(&mut self) {
50 self.objects.clear();
51 self.flush();
52 }
53
54 pub fn replace(&mut self, with: Layer) {
55 self.objects.clone_from(&with.objects);
56 self.flush();
57 }
58
59 pub fn remove_all_objects_in(&mut self, region: &Region) {
60 self.objects.retain(|_, ColoredObject { object, .. }| {
61 !object.region().within(region)
62 })
63 }
64
65 pub fn paint_all_objects(&mut self, fill: Fill) {
66 for obj in self.objects.values_mut() {
67 obj.fill = Some(fill);
68 }
69 self.flush();
70 }
71
72 pub fn filter_all_objects(&mut self, filter: Filter) {
73 for obj in self.objects.values_mut() {
74 obj.filters.push(filter)
75 }
76 self.flush();
77 }
78
79 pub fn move_all_objects(&mut self, dx: i32, dy: i32) {
80 self.objects
81 .iter_mut()
82 .for_each(|(_, ColoredObject { object, .. })| {
83 object.translate(dx, dy)
84 });
85 self.flush();
86 }
87
88 pub fn add(&mut self, name: impl Display, object: impl Into<ColoredObject>) {
89 let name_str = format!("{}", name);
90
91 if self.objects.contains_key(&name_str) {
92 panic!("object {} already exists in layer {}", name_str, self.name);
93 }
94
95 self.set(name_str, object);
96 }
97
98 pub fn add_anon(&mut self, object: impl Into<ColoredObject>) {
99 self.add(format!("anon-{}", self.objects.len()), object);
100 }
101
102 pub fn set(&mut self, name: impl Display, object: impl Into<ColoredObject>) {
103 let name_str = format!("{}", name);
104
105 self.objects.insert(name_str, object.into());
106 self.flush();
107 }
108
109 pub fn filter_object(
110 &mut self,
111 name: &str,
112 filter: Filter,
113 ) -> Result<(), String> {
114 self.objects
115 .get_mut(name)
116 .ok_or(format!("Object '{}' not found", name))?
117 .filters
118 .push(filter);
119
120 self.flush();
121 Ok(())
122 }
123
124 pub fn remove_object(&mut self, name: &str) {
125 self.objects.remove(name);
126 self.flush();
127 }
128
129 pub fn replace_object(&mut self, name: &str, object: ColoredObject) {
130 self.remove_object(name);
131 self.add(name, object);
132 }
133
134 pub fn add_objects(
135 &mut self,
136 objects: impl IntoIterator<Item = ColoredObject>,
137 ) {
138 for obj in objects {
139 self.add_anon(obj);
140 }
141 }
142
143 /// Returns the effective region the layer occupies, by merging all its objects' regions.
144 pub fn region(&self) -> Region {
145 self.objects
146 .values()
147 .map(|object| object.region())
148 .fold(Region::default(), |acc, region| acc.merge(®ion))
149 }
150}
151
152impl ColoredObject {
153 pub fn add_to(self, layer: &mut Layer) {
154 layer.add_anon(self);
155 }
156
157 pub fn set_in(self, layer: &mut Layer, name: impl Display) {
158 layer.set(name, self);
159 }
160}