This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1use itertools::Itertools; 2 3use crate::{Fill, Filter, Object, ObjectSizes, Point, Region, Toggleable}; 4use std::{collections::HashMap, fmt::Display}; 5 6#[derive(Debug, Clone, Default)] 7// #[wasm_bindgen(getter_with_clone)] 8pub struct Layer { 9 pub object_sizes: ObjectSizes, 10 pub objects: HashMap<String, Object>, 11 pub name: String, 12 pub hidden: bool, 13} 14 15impl Layer { 16 pub fn new(name: impl Display) -> Self { 17 Layer { 18 object_sizes: ObjectSizes::default(), 19 objects: HashMap::new(), 20 name: format!("{}", name), 21 hidden: false, 22 } 23 } 24 25 pub fn hide(&mut self) { 26 self.hidden = true; 27 } 28 29 pub fn show(&mut self) { 30 self.hidden = false; 31 } 32 33 pub fn toggle(&mut self) { 34 self.hidden.toggle(); 35 } 36 37 pub fn object(&mut self, name: &str) -> &mut Object { 38 self.safe_object(name).unwrap() 39 } 40 41 pub fn safe_object(&mut self, name: &str) -> Option<&mut Object> { 42 self.objects.get_mut(name) 43 } 44 45 // Useful to be able to guarantee a stable order when rendering. 46 pub fn objects_sorted(&self) -> impl Iterator<Item = (&String, &Object)> { 47 self.objects 48 .iter() 49 .sorted_by_cached_key(|&(id, _)| id.clone()) 50 } 51 52 // Useful to be able to guarantee a stable order when rendering. 53 pub fn objects_sorted_mut( 54 &mut self, 55 ) -> impl Iterator<Item = (&String, &mut Object)> { 56 self.objects 57 .iter_mut() 58 .sorted_by_cached_key(|&(id, _)| id.clone()) 59 } 60 61 pub fn objects_in( 62 &mut self, 63 region: Region, 64 ) -> impl Iterator<Item = (&String, &mut Object)> { 65 self.objects 66 .iter_mut() 67 .filter(move |(_, obj)| obj.shape.region().within(&region)) 68 } 69 70 pub fn object_at(&mut self, point: Point) -> Option<&mut Object> { 71 self.objects 72 .values_mut() 73 .find(|obj| obj.shape.region().start == point) 74 } 75 76 pub fn has_object_that(&self, pred: impl Fn(&Object) -> bool) -> bool { 77 self.objects.values().any(|obj| pred(obj)) 78 } 79 80 // Remove all objects. 81 pub fn clear(&mut self) { 82 self.objects.clear(); 83 } 84 85 pub fn replace(&mut self, with: Layer) { 86 self.objects.clone_from(&with.objects); 87 } 88 89 pub fn remove_all_objects_in(&mut self, region: &Region) { 90 self.objects.retain(|_, Object { shape: object, .. }| { 91 !object.region().within(region) 92 }) 93 } 94 95 pub fn paint_all_objects(&mut self, fill: Fill) { 96 for obj in self.objects.values_mut() { 97 obj.fill = Some(fill); 98 } 99 } 100 101 pub fn filter_all_objects(&mut self, filter: Filter) { 102 for obj in self.objects.values_mut() { 103 obj.filters.push(filter) 104 } 105 } 106 107 pub fn move_all_objects(&mut self, dx: i32, dy: i32) { 108 self.objects 109 .iter_mut() 110 .for_each(|(_, Object { shape: object, .. })| { 111 object.translate(dx, dy) 112 }); 113 } 114 115 pub fn add(&mut self, name: impl Display, object: impl Into<Object>) { 116 let name_str = format!("{}", name); 117 118 if self.objects.contains_key(&name_str) { 119 panic!("object {} already exists in layer {}", name_str, self.name); 120 } 121 122 self.set(name_str, object); 123 } 124 125 pub fn add_anon(&mut self, object: impl Into<Object>) { 126 self.add(format!("anon-{}", self.objects.len()), object); 127 } 128 129 pub fn add_many( 130 &mut self, 131 objects: impl IntoIterator<Item = (impl Display, Object)>, 132 ) { 133 for (name, obj) in objects { 134 self.add(name, obj); 135 } 136 } 137 138 pub fn add_many_anon(&mut self, objects: impl IntoIterator<Item = Object>) { 139 for obj in objects { 140 self.add_anon(obj); 141 } 142 } 143 144 pub fn set(&mut self, name: impl Display, object: impl Into<Object>) { 145 let name_str = format!("{}", name); 146 147 self.objects.insert(name_str, object.into()); 148 } 149 150 pub fn filter_object( 151 &mut self, 152 name: &str, 153 filter: Filter, 154 ) -> Result<(), String> { 155 self.objects 156 .get_mut(name) 157 .ok_or(format!("Object '{}' not found", name))? 158 .filters 159 .push(filter); 160 161 Ok(()) 162 } 163 164 pub fn remove_object(&mut self, name: &str) { 165 self.objects.remove(name); 166 } 167 168 pub fn replace_object(&mut self, name: &str, object: Object) { 169 self.remove_object(name); 170 self.add(name, object); 171 } 172 173 pub fn add_objects(&mut self, objects: impl IntoIterator<Item = Object>) { 174 for obj in objects { 175 self.add_anon(obj); 176 } 177 } 178 179 pub fn objects_with_tag( 180 &mut self, 181 tag: impl Display, 182 ) -> impl Iterator<Item = (&String, &mut Object)> { 183 let tag_str = format!("{}", tag); 184 self.objects 185 .iter_mut() 186 .filter(move |(_, obj)| obj.has_tag(&tag_str)) 187 } 188 189 pub fn tag_objects( 190 &mut self, 191 tag: impl Display, 192 objects: impl Fn(&String, &Object) -> bool, 193 ) { 194 let tag_str = format!("{}", tag); 195 for (_, obj) in 196 self.objects.iter_mut().filter(|(id, obj)| objects(id, obj)) 197 { 198 obj.tag(&tag_str); 199 } 200 } 201 202 /// Returns the effective region the layer occupies, by merging all its objects' regions. 203 pub fn region(&self) -> Region { 204 self.objects 205 .values() 206 .map(|object| object.region()) 207 .fold(Region::default(), |acc, region| acc.merge(&region)) 208 } 209} 210 211impl Object { 212 pub fn add_to(self, layer: &mut Layer) { 213 layer.add_anon(self); 214 } 215 216 pub fn set_in(self, layer: &mut Layer, name: impl Display) { 217 layer.set(name, self); 218 } 219}