1use crate::{Color, Location, MarkerAppearence, MarkerScale, MarkerStyle};
2use std::fmt;
3
4#[derive(Clone)]
5pub struct Marker<S: AsRef<str> + Clone> {
6 appearence: Option<MarkerAppearence<S>>,
7 scale: Option<MarkerScale>,
8 locations: Vec<Location>,
9}
10
11impl<S: AsRef<str> + Clone> Marker<S> {
12 pub fn new() -> Self {
13 Marker {
14 appearence: None,
15 scale: None,
16 locations: vec![],
17 }
18 }
19
20 pub fn simple(color: &'static Color, label: char, location: Location) -> Self {
21 let marker_style = MarkerStyle::new().color(color).label(label.into());
22 Marker::new()
23 .appearence(marker_style.into())
24 .add_location(location)
25 }
26
27 pub fn add_location(&self, location: Location) -> Marker<S> {
28 let mut new_marker = self.clone();
29 new_marker.locations.push(location);
30 new_marker
31 }
32
33 pub fn appearence(&self, appearence: MarkerAppearence<S>) -> Marker<S> {
34 Marker {
35 appearence: Some(appearence),
36 ..(*self).clone()
37 }
38 }
39
40 pub fn scale(&self, scale: MarkerScale) -> Marker<S> {
41 Marker {
42 scale: Some(scale),
43 ..(*self).clone()
44 }
45 }
46}
47
48impl<S: AsRef<str> + Clone> Default for Marker<S> {
49 fn default() -> Self {
50 Marker::new()
51 }
52}
53
54impl<S: AsRef<str> + Clone> From<Location> for Marker<S> {
55 fn from(location: Location) -> Self {
56 Marker {
57 appearence: None,
58 scale: None,
59 locations: vec![location],
60 }
61 }
62}
63
64impl<S: AsRef<str> + Clone> fmt::Display for Marker<S> {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 let mut parts: Vec<String> = vec![];
67
68 if let Some(scale) = &self.scale {
69 parts.push(scale.to_string());
70 }
71
72 if let Some(appearence) = &self.appearence {
73 parts.push(appearence.to_string());
74 }
75
76 for location in &self.locations {
77 parts.push(location.to_string());
78 }
79
80 write!(f, "{}", parts.join("|"))
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use crate::{MarkerIcon, BLUE};
87
88 use super::*;
89 use crate::MarkerStyle;
90
91 #[test]
92 fn it_builds_a_complete_style() {
93 let marker_appearence: MarkerAppearence<String> =
94 MarkerStyle::new().color(BLUE).label('S'.into()).into();
95 let marker = Marker::new()
96 .appearence(marker_appearence)
97 .add_location("11211".into())
98 .add_location("11206".into())
99 .add_location("11222".into());
100 assert_eq!("color:blue|label:S|11211|11206|11222", marker.to_string());
101 }
102
103 #[test]
104 fn it_builds_a_complete_style_2() {
105 let marker_appearence: MarkerAppearence<&str> = MarkerIcon::new("https://goo.gl/5y3S82")
106 .position((32, 10).into())
107 .into();
108 let marker = Marker::new()
109 .appearence(marker_appearence)
110 .add_location("Canberra ACT".into());
111 assert_eq!(
112 "anchor:32,10|icon:https://goo.gl/5y3S82|Canberra ACT",
113 marker.to_string()
114 );
115 }
116}