1
//! Manage how elements should be drawn
2

3
//! All style structs follows the 'optional builder' pattern:
4
//! Each field is a `Option` which start as `None`.
5
//! They can all be set with setter methods, and instances
6
//! can be overlaid with another one to set many at once.
7
//! Settings will be cloned in and out of it.
8

9
/// The style that line corners should use
10
#[derive(Debug, Clone, Copy)]
11
pub enum LineJoin {
12
    Miter,
13
    Round,
14
}
15

16
#[derive(Debug, Default, Clone)]
17
pub struct LineStyle {
18
    pub colour: Option<String>,
19
    pub width: Option<f32>,
20
    pub linejoin: Option<LineJoin>,
21
}
22
impl LineStyle {
23 2
    pub fn new() -> Self {
24
        LineStyle {
25
            colour: None,
26
            width: None,
27
            linejoin: None,
28
        }
29
    }
30

31 2
    pub fn overlay(&mut self, other: &Self) {
32 2
        if let Some(ref v) = other.colour {
33 2
            self.colour = Some(v.clone())
34
        }
35

36 2
        if let Some(ref v) = other.width {
37 2
            self.width = Some(*v)
38
        }
39

40 2
        if let Some(ref v) = other.linejoin {
41 2
            self.linejoin = Some(*v)
42
        }
43
    }
44 2
    pub fn colour<T>(mut self, value: T) -> Self
45
    where
46
        T: Into<String>,
47
    {
48 2
        self.colour = Some(value.into());
49 2
        self
50
    }
51 2
    pub fn get_colour(&self) -> String {
52 2
        self.colour.clone().unwrap_or_else(|| "black".into())
53
    }
54

55 2
    pub fn width<T>(mut self, value: T) -> Self
56
    where
57
        T: Into<f32>,
58
    {
59 2
        self.width = Some(value.into());
60 2
        self
61
    }
62 2
    pub fn get_width(&self) -> f32 {
63 2
        self.width.unwrap_or_else(|| 2.0)
64
    }
65

66 2
    pub fn linejoin<T>(mut self, value: T) -> Self
67
    where
68
        T: Into<LineJoin>,
69
    {
70 2
        self.linejoin = Some(value.into());
71 2
        self
72
    }
73 2
    pub fn get_linejoin(&self) -> LineJoin {
74 2
        self.linejoin.unwrap_or_else(|| LineJoin::Round)
75
    }
76
}
77

78
/// The marker that should be used for the points of the scatter plot
79
#[derive(Debug, Clone, Copy)]
80
pub enum PointMarker {
81
    Circle,
82
    Square,
83
    Cross,
84
}
85

86
#[derive(Debug, Default, Clone)]
87
pub struct PointStyle {
88
    marker: Option<PointMarker>,
89
    colour: Option<String>,
90
    size: Option<f32>,
91
}
92
impl PointStyle {
93 2
    pub fn new() -> Self {
94
        PointStyle {
95
            marker: None,
96
            colour: None,
97
            size: None,
98
        }
99
    }
100

101 0
    pub fn overlay(&mut self, other: &Self) {
102 0
        if let Some(ref v) = other.marker {
103 0
            self.marker = Some(*v)
104
        }
105

106 0
        if let Some(ref v) = other.colour {
107 0
            self.colour = Some(v.clone())
108
        }
109

110 0
        if let Some(v) = other.size {
111 0
            self.size = Some(v)
112
        }
113
    }
114 2
    pub fn marker<T>(mut self, value: T) -> Self
115
    where
116
        T: Into<PointMarker>,
117
    {
118 2
        self.marker = Some(value.into());
119 2
        self
120
    }
121 2
    pub fn get_marker(&self) -> PointMarker {
122 2
        self.marker.unwrap_or(PointMarker::Circle)
123
    }
124

125 2
    pub fn colour<T>(mut self, value: T) -> Self
126
    where
127
        T: Into<String>,
128
    {
129 2
        self.colour = Some(value.into());
130 2
        self
131
    }
132 2
    pub fn get_colour(&self) -> String {
133 2
        self.colour.clone().unwrap_or_else(|| "".into())
134
    }
135

136
    pub fn size<T>(mut self, value: T) -> Self
137
    where
138
        T: Into<f32>,
139
    {
140 0
        self.size = Some(value.into());
141 0
        self
142
    }
143 2
    pub fn get_size(&self) -> f32 {
144 2
        self.size.unwrap_or(5.0)
145
    }
146
}
147

148
#[derive(Debug, Default)]
149
pub struct BoxStyle {
150
    fill: Option<String>,
151
}
152
impl BoxStyle {
153 2
    pub fn new() -> Self {
154
        BoxStyle { fill: None }
155
    }
156

157 0
    pub fn overlay(&mut self, other: &Self) {
158 0
        if let Some(ref v) = other.fill {
159 0
            self.fill = Some(v.clone())
160
        }
161
    }
162

163
    pub fn fill<T>(mut self, value: T) -> Self
164
    where
165
        T: Into<String>,
166
    {
167 0
        self.fill = Some(value.into());
168 0
        self
169
    }
170 0
    pub fn get_fill(&self) -> String {
171 0
        self.fill.clone().unwrap_or_else(|| "".into())
172
    }
173
}
174

175
#[cfg(test)]
176
mod tests {
177
    use super::*;
178

179
    #[test]
180 2
    fn test_linestyle_plain_overlay() {
181 2
        let mut p = LineStyle::new();
182 2
        p.overlay(
183 2
            &LineStyle::new()
184
                .colour("red")
185 2
                .linejoin(LineJoin::Miter)
186
                .width(1.),
187
        );
188 2
        assert_eq!(p.get_colour(), "red".to_string());
189 2
        assert_eq!(p.get_width(), 1.);
190 2
        if let LineJoin::Miter = p.get_linejoin() {
191
        } else {
192 0
            panic!()
193
        }
194
    }
195
}

Read our documentation on viewing source code .

Loading