1use std::borrow::Cow;
4use std::iter::IntoIterator;
5
6use data::Matrix;
7use traits::{self, Data};
8use {Color, Display, ErrorBarDefault, Figure, LineType, Plot, PointType, Script};
9
10pub struct Properties {
12 color: Option<Color>,
13 label: Option<Cow<'static, str>>,
14 line_type: LineType,
15 linewidth: Option<f64>,
16 point_size: Option<f64>,
17 point_type: Option<PointType>,
18 style: Style,
19}
20
21impl Properties {
22 pub fn color(&mut self, color: Color) -> &mut Properties {
24 self.color = Some(color);
25 self
26 }
27
28 pub fn label<S>(&mut self, label: S) -> &mut Properties
30 where
31 S: Into<Cow<'static, str>>,
32 {
33 self.label = Some(label.into());
34 self
35 }
36
37 pub fn line_type(&mut self, lt: LineType) -> &mut Properties {
41 self.line_type = lt;
42 self
43 }
44
45 pub fn line_width(&mut self, lw: f64) -> &mut Properties {
51 assert!(lw > 0.);
52
53 self.linewidth = Some(lw);
54 self
55 }
56
57 pub fn point_size(&mut self, ps: f64) -> &mut Properties {
63 assert!(ps > 0.);
64
65 self.point_size = Some(ps);
66 self
67 }
68
69 pub fn point_type(&mut self, pt: PointType) -> &mut Properties {
71 self.point_type = Some(pt);
72 self
73 }
74}
75
76impl ErrorBarDefault<Style> for Properties {
77 fn default(style: Style) -> Properties {
78 Properties {
79 color: None,
80 label: None,
81 line_type: LineType::Solid,
82 linewidth: None,
83 point_type: None,
84 point_size: None,
85 style,
86 }
87 }
88}
89
90impl Script for Properties {
91 fn script(&self) -> String {
92 let mut script = format!("with {} ", self.style.display());
93
94 script.push_str(&format!("lt {} ", self.line_type.display()));
95
96 if let Some(lw) = self.linewidth {
97 script.push_str(&format!("lw {} ", lw))
98 }
99
100 if let Some(color) = self.color {
101 script.push_str(&format!("lc rgb '{}' ", color.display()))
102 }
103
104 if let Some(pt) = self.point_type {
105 script.push_str(&format!("pt {} ", pt.display()))
106 }
107
108 if let Some(ps) = self.point_size {
109 script.push_str(&format!("ps {} ", ps))
110 }
111
112 if let Some(ref label) = self.label {
113 script.push_str("title '");
114 script.push_str(label);
115 script.push('\'')
116 } else {
117 script.push_str("notitle")
118 }
119
120 script
121 }
122}
123
124#[derive(Clone, Copy)]
125enum Style {
126 XErrorBars,
127 XErrorLines,
128 YErrorBars,
129 YErrorLines,
130}
131
132impl Display<&'static str> for Style {
133 fn display(&self) -> &'static str {
134 match *self {
135 Style::XErrorBars => "xerrorbars",
136 Style::XErrorLines => "xerrorlines",
137 Style::YErrorBars => "yerrorbars",
138 Style::YErrorLines => "yerrorlines",
139 }
140 }
141}
142
143pub enum ErrorBar<X, Y, L, H> {
145 XErrorBars {
147 x: X,
149 y: Y,
151 x_low: L,
153 x_high: H,
155 },
156 XErrorLines {
158 x: X,
160 y: Y,
162 x_low: L,
164 x_high: H,
166 },
167 YErrorBars {
169 x: X,
171 y: Y,
173 y_low: L,
175 y_high: H,
177 },
178 YErrorLines {
180 x: X,
182 y: Y,
184 y_low: L,
186 y_high: H,
188 },
189}
190
191impl<X, Y, L, H> ErrorBar<X, Y, L, H> {
192 fn style(&self) -> Style {
193 match *self {
194 ErrorBar::XErrorBars { .. } => Style::XErrorBars,
195 ErrorBar::XErrorLines { .. } => Style::XErrorLines,
196 ErrorBar::YErrorBars { .. } => Style::YErrorBars,
197 ErrorBar::YErrorLines { .. } => Style::YErrorLines,
198 }
199 }
200}
201
202impl<X, Y, L, H> traits::Plot<ErrorBar<X, Y, L, H>> for Figure
203where
204 H: IntoIterator,
205 H::Item: Data,
206 L: IntoIterator,
207 L::Item: Data,
208 X: IntoIterator,
209 X::Item: Data,
210 Y: IntoIterator,
211 Y::Item: Data,
212{
213 type Properties = Properties;
214
215 fn plot<F>(&mut self, e: ErrorBar<X, Y, L, H>, configure: F) -> &mut Figure
216 where
217 F: FnOnce(&mut Properties) -> &mut Properties,
218 {
219 let (x_factor, y_factor) = ::scale_factor(&self.axes, ::Axes::BottomXLeftY);
220
221 let style = e.style();
222 let (x, y, length, height, e_factor) = match e {
223 ErrorBar::XErrorBars {
224 x,
225 y,
226 x_low,
227 x_high,
228 }
229 | ErrorBar::XErrorLines {
230 x,
231 y,
232 x_low,
233 x_high,
234 } => (x, y, x_low, x_high, x_factor),
235 ErrorBar::YErrorBars {
236 x,
237 y,
238 y_low,
239 y_high,
240 }
241 | ErrorBar::YErrorLines {
242 x,
243 y,
244 y_low,
245 y_high,
246 } => (x, y, y_low, y_high, y_factor),
247 };
248 let data = Matrix::new(
249 izip!(x, y, length, height),
250 (x_factor, y_factor, e_factor, e_factor),
251 );
252 self.plots.push(Plot::new(
253 data,
254 configure(&mut ErrorBarDefault::default(style)),
255 ));
256 self
257 }
258}
259
260