gmaps_static/
marker.rs

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}