• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Coordinate axis
2 
3 use std::borrow::Cow;
4 use std::iter::IntoIterator;
5 
6 use crate::map;
7 use crate::traits::{Configure, Data, Set};
8 use crate::{
9     grid, Axis, Default, Display, Grid, Label, Range, Scale, ScaleFactor, Script, TicLabels,
10 };
11 
12 /// Properties of the coordinate axes
13 #[derive(Clone)]
14 pub struct Properties {
15     grids: map::grid::Map<grid::Properties>,
16     hidden: bool,
17     label: Option<Cow<'static, str>>,
18     logarithmic: bool,
19     range: Option<(f64, f64)>,
20     scale_factor: f64,
21     tics: Option<String>,
22 }
23 
24 impl Default for Properties {
default() -> Properties25     fn default() -> Properties {
26         Properties {
27             grids: map::grid::Map::new(),
28             hidden: false,
29             label: None,
30             logarithmic: false,
31             range: None,
32             scale_factor: 1.,
33             tics: None,
34         }
35     }
36 }
37 
38 impl Properties {
39     /// Hides the axis
40     ///
41     /// **Note** The `TopX` and `RightY` axes are hidden by default
hide(&mut self) -> &mut Properties42     pub fn hide(&mut self) -> &mut Properties {
43         self.hidden = true;
44         self
45     }
46 
47     /// Makes the axis visible
48     ///
49     /// **Note** The `BottomX` and `LeftY` axes are visible by default
show(&mut self) -> &mut Properties50     pub fn show(&mut self) -> &mut Properties {
51         self.hidden = false;
52         self
53     }
54 }
55 
56 impl Configure<Grid> for Properties {
57     type Properties = grid::Properties;
58 
59     /// Configures the gridlines
configure<F>(&mut self, grid: Grid, configure: F) -> &mut Properties where F: FnOnce(&mut grid::Properties) -> &mut grid::Properties,60     fn configure<F>(&mut self, grid: Grid, configure: F) -> &mut Properties
61     where
62         F: FnOnce(&mut grid::Properties) -> &mut grid::Properties,
63     {
64         if self.grids.contains_key(grid) {
65             configure(self.grids.get_mut(grid).unwrap());
66         } else {
67             let mut properties = Default::default();
68             configure(&mut properties);
69             self.grids.insert(grid, properties);
70         }
71 
72         self
73     }
74 }
75 
76 impl Set<Label> for Properties {
77     /// Attaches a label to the axis
set(&mut self, label: Label) -> &mut Properties78     fn set(&mut self, label: Label) -> &mut Properties {
79         self.label = Some(label.0);
80         self
81     }
82 }
83 
84 impl Set<Range> for Properties {
85     /// Changes the range of the axis that will be shown
86     ///
87     /// **Note** All axes are auto-scaled by default
set(&mut self, range: Range) -> &mut Properties88     fn set(&mut self, range: Range) -> &mut Properties {
89         self.hidden = false;
90 
91         match range {
92             Range::Auto => self.range = None,
93             Range::Limits(low, high) => self.range = Some((low, high)),
94         }
95 
96         self
97     }
98 }
99 
100 impl Set<Scale> for Properties {
101     /// Sets the scale of the axis
102     ///
103     /// **Note** All axes use a linear scale by default
set(&mut self, scale: Scale) -> &mut Properties104     fn set(&mut self, scale: Scale) -> &mut Properties {
105         self.hidden = false;
106 
107         match scale {
108             Scale::Linear => self.logarithmic = false,
109             Scale::Logarithmic => self.logarithmic = true,
110         }
111 
112         self
113     }
114 }
115 
116 impl Set<ScaleFactor> for Properties {
117     /// Changes the *scale factor* of the axis.
118     ///
119     /// All the data plotted against this axis will have its corresponding coordinate scaled with
120     /// this factor before being plotted.
121     ///
122     /// **Note** The default scale factor is `1`.
set(&mut self, factor: ScaleFactor) -> &mut Properties123     fn set(&mut self, factor: ScaleFactor) -> &mut Properties {
124         self.scale_factor = factor.0;
125 
126         self
127     }
128 }
129 
130 impl<P, L> Set<TicLabels<P, L>> for Properties
131 where
132     L: IntoIterator,
133     L::Item: AsRef<str>,
134     P: IntoIterator,
135     P::Item: Data,
136 {
137     /// Attaches labels to the tics of an axis
set(&mut self, tics: TicLabels<P, L>) -> &mut Properties138     fn set(&mut self, tics: TicLabels<P, L>) -> &mut Properties {
139         let TicLabels { positions, labels } = tics;
140 
141         let pairs = positions
142             .into_iter()
143             .zip(labels.into_iter())
144             .map(|(pos, label)| format!("'{}' {}", label.as_ref(), pos.f64()))
145             .collect::<Vec<_>>();
146 
147         if pairs.is_empty() {
148             self.tics = None
149         } else {
150             self.tics = Some(pairs.join(", "));
151         }
152 
153         self
154     }
155 }
156 
157 impl<'a> Script for (Axis, &'a Properties) {
script(&self) -> String158     fn script(&self) -> String {
159         let &(axis, properties) = self;
160         let axis_ = axis.display();
161 
162         let mut script = if properties.hidden {
163             return format!("unset {}tics\n", axis_);
164         } else {
165             format!("set {}tics nomirror ", axis_)
166         };
167 
168         if let Some(ref tics) = properties.tics {
169             script.push_str(&format!("({})", tics))
170         }
171 
172         script.push('\n');
173 
174         if let Some(ref label) = properties.label {
175             script.push_str(&format!("set {}label '{}'\n", axis_, label))
176         }
177 
178         if let Some((low, high)) = properties.range {
179             script.push_str(&format!("set {}range [{}:{}]\n", axis_, low, high))
180         }
181 
182         if properties.logarithmic {
183             script.push_str(&format!("set logscale {}\n", axis_));
184         }
185 
186         for (grid, properties) in properties.grids.iter() {
187             script.push_str(&(axis, grid, properties).script());
188         }
189 
190         script
191     }
192 }
193 
194 impl crate::ScaleFactorTrait for Properties {
scale_factor(&self) -> f64195     fn scale_factor(&self) -> f64 {
196         self.scale_factor
197     }
198 }
199