This repository has no description
0

Configure Feed

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

1use super::shapes::Shape; 2use crate::{Angle, Fill, Filter, Region, Transformation}; 3use itertools::Itertools; 4use std::fmt::Display; 5#[cfg(feature = "web")] 6use wasm_bindgen::prelude::*; 7 8use super::{Color, fill::FillOperations}; 9 10impl Shape { 11 pub fn filled(self, fill: Fill) -> Object { 12 Object::from((self, Some(fill))) 13 } 14 15 pub fn colored(self, color: Color) -> Object { 16 Object::from((self, None)).colored(color) 17 } 18 19 pub fn filtered(self, filter: Filter) -> Object { 20 Object::from((self, None)).filtered(filter) 21 } 22 23 pub fn transform(self, transformation: Transformation) -> Object { 24 Object::from((self, None)).transformed(transformation) 25 } 26} 27 28#[derive(Debug, Clone)] 29pub struct Object { 30 pub shape: Shape, 31 pub fill: Option<Fill>, 32 pub filters: Vec<Filter>, 33 pub transformations: Vec<Transformation>, 34 pub tags: Vec<String>, 35 pub clip_to: Option<Region>, 36} 37 38impl Object { 39 pub fn filtered(mut self, filter: Filter) -> Self { 40 self.filters.push(filter); 41 self 42 } 43 44 pub fn transformed(mut self, transformation: Transformation) -> Self { 45 self.transformations.push(transformation); 46 self 47 } 48 49 pub fn filled(mut self, fill: Fill) -> Self { 50 self.fill = Some(fill); 51 self 52 } 53 54 pub fn colored(mut self, color: Color) -> Self { 55 self.fill = Some(Fill::Solid(color)); 56 self 57 } 58 59 pub fn opacified(mut self, opacity: f32) -> Self { 60 if let Some(fill) = &mut self.fill { 61 *fill = fill.opacify(opacity); 62 } 63 self 64 } 65 66 pub fn clipped_to(mut self, region: impl Into<Region>) -> Self { 67 self.clip_to = Some(region.into()); 68 self 69 } 70 71 pub fn clear_filters(&mut self) { 72 self.filters.clear(); 73 } 74 75 pub fn refill(&mut self, fill: Fill) { 76 self.fill = Some(fill); 77 } 78 79 pub fn recolor(&mut self, color: Color) { 80 self.fill = Some(Fill::Solid(color)) 81 } 82 83 pub fn filter(&mut self, filter: Filter) { 84 self.filters.push(filter) 85 } 86 87 pub fn rotate(&mut self, angle: Angle) { 88 self.transformations 89 .push(Transformation::Rotate(angle.degrees())) 90 } 91 92 pub fn set_rotation(&mut self, angle: Angle) { 93 self.transformations 94 .retain(|t| !matches!(t, Transformation::Rotate(_))); 95 self.transformations 96 .push(Transformation::Rotate(angle.degrees())) 97 } 98 99 pub fn region(&self) -> Region { 100 self.shape.region() 101 } 102 103 pub fn tag(&mut self, tag: impl Display) { 104 self.tags.push(format!("{tag}")); 105 } 106 107 pub fn remove_tag(&mut self, tag: impl Display) { 108 let tag_str = format!("{tag}"); 109 self.tags.retain(|t| t != &tag_str); 110 } 111 112 pub fn tagged(mut self, tag: impl Display) -> Self { 113 self.tags.push(format!("{tag}")); 114 self 115 } 116 117 pub fn has_tag(&self, tag: impl Display) -> bool { 118 let tag_str = format!("{tag}"); 119 self.tags.iter().any(|t| t == &tag_str) 120 } 121} 122 123impl std::fmt::Display for Object { 124 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 125 let Object { 126 shape: object, 127 fill, 128 filters, 129 transformations, 130 tags, 131 clip_to, 132 } = self; 133 134 if fill.is_some() { 135 write!(f, "{:?} {:?}", fill.unwrap(), object)?; 136 } else { 137 write!(f, "transparent {:?}", object)?; 138 } 139 140 if !filters.is_empty() { 141 write!(f, " with filters {:?}", filters)?; 142 } 143 144 if !transformations.is_empty() { 145 write!(f, " with transformations {:?}", transformations)?; 146 } 147 148 if !tags.is_empty() { 149 write!(f, "{}", tags.iter().map(|t| format!("#{t}")).join(" "))?; 150 } 151 152 if let Some(clip_to) = clip_to { 153 write!(f, " (clipped to {:?})", clip_to)?; 154 } 155 156 Ok(()) 157 } 158} 159 160impl From<Shape> for Object { 161 fn from(value: Shape) -> Self { 162 Object { 163 shape: value, 164 fill: None, 165 filters: vec![], 166 transformations: vec![], 167 tags: vec![], 168 clip_to: None, 169 } 170 } 171} 172 173impl From<(Shape, Option<Fill>)> for Object { 174 fn from((object, fill): (Shape, Option<Fill>)) -> Self { 175 Object { 176 shape: object, 177 fill, 178 filters: vec![], 179 transformations: vec![], 180 tags: vec![], 181 clip_to: None, 182 } 183 } 184} 185 186#[cfg_attr(feature = "web", wasm_bindgen)] 187#[derive(Debug, Clone, Copy)] 188pub struct ObjectSizes { 189 pub empty_shape_stroke_width: f32, 190 pub small_circle_radius: f32, 191 pub dot_radius: f32, 192 pub default_line_width: f32, 193} 194 195impl Default for ObjectSizes { 196 fn default() -> Self { 197 Self { 198 empty_shape_stroke_width: 0.5, 199 small_circle_radius: 5.0, 200 dot_radius: 2.0, 201 default_line_width: 2.0, 202 } 203 } 204}