ggplot_rs/scale/
manual.rs1use crate::aes::Aesthetic;
2use crate::data::Value;
3
4use super::color::RGBAColor;
5use super::Scale;
6
7#[derive(Clone, Debug)]
9pub struct ScaleManual {
10 aesthetic: Aesthetic,
11 name: String,
12 levels: Vec<String>,
13 colors: Vec<RGBAColor>,
14}
15
16impl ScaleManual {
17 pub fn new(aesthetic: Aesthetic, values: Vec<(&str, RGBAColor)>) -> Self {
18 let levels: Vec<String> = values.iter().map(|(k, _)| k.to_string()).collect();
19 let colors: Vec<RGBAColor> = values.iter().map(|(_, c)| *c).collect();
20 ScaleManual {
21 aesthetic,
22 name: String::new(),
23 levels,
24 colors,
25 }
26 }
27}
28
29impl Scale for ScaleManual {
30 fn aesthetic(&self) -> Aesthetic {
31 self.aesthetic.clone()
32 }
33
34 fn train(&mut self, values: &[Value]) {
35 for v in values {
36 let key = v.to_group_key();
37 if !self.levels.contains(&key) {
38 self.levels.push(key);
39 }
40 }
41 }
42
43 fn map(&self, value: &Value) -> f64 {
44 let key = value.to_group_key();
45 self.levels
46 .iter()
47 .position(|l| l == &key)
48 .map(|i| i as f64)
49 .unwrap_or(0.0)
50 }
51
52 fn breaks(&self) -> Vec<(f64, String)> {
53 self.levels
54 .iter()
55 .enumerate()
56 .map(|(i, label)| (i as f64, label.clone()))
57 .collect()
58 }
59
60 fn name(&self) -> &str {
61 &self.name
62 }
63
64 fn set_name(&mut self, name: &str) {
65 self.name = name.to_string();
66 }
67
68 fn is_discrete(&self) -> bool {
69 true
70 }
71
72 fn map_to_color(&self, value: &Value) -> Option<(u8, u8, u8)> {
73 let key = value.to_group_key();
74 let idx = self.levels.iter().position(|l| l == &key).unwrap_or(0);
75 if idx < self.colors.len() {
76 let c = self.colors[idx];
77 Some((c.r, c.g, c.b))
78 } else {
79 let c = self.colors[idx % self.colors.len()];
81 Some((c.r, c.g, c.b))
82 }
83 }
84
85 fn clone_box(&self) -> Box<dyn Scale> {
86 Box::new(self.clone())
87 }
88
89 fn reset_training(&mut self) {
90 self.levels.clear();
91 }
92}