1use crate::aes::Aesthetic;
2use crate::data::Value;
3
4use super::Scale;
5
6#[derive(Clone)]
10pub struct ScaleColorGrey {
11 aesthetic: Aesthetic,
12 name: String,
13 start: f64,
14 end: f64,
15 levels: Vec<String>,
16}
17
18impl ScaleColorGrey {
19 pub fn new(aesthetic: Aesthetic) -> Self {
20 ScaleColorGrey {
21 aesthetic,
22 name: String::new(),
23 start: 0.2,
24 end: 0.8,
25 levels: Vec::new(),
26 }
27 }
28
29 pub fn with_range(mut self, start: f64, end: f64) -> Self {
32 self.start = start;
33 self.end = end;
34 self
35 }
36
37 fn grey_for_index(&self, idx: usize) -> u8 {
38 let n = self.levels.len().max(1);
39 let t = if n == 1 {
40 (self.start + self.end) / 2.0
41 } else {
42 self.start + (self.end - self.start) * (idx as f64 / (n - 1) as f64)
43 };
44 (t.clamp(0.0, 1.0) * 255.0) as u8
45 }
46}
47
48impl Scale for ScaleColorGrey {
49 fn aesthetic(&self) -> Aesthetic {
50 self.aesthetic.clone()
51 }
52
53 fn train(&mut self, values: &[Value]) {
54 for v in values {
55 let key = v.to_group_key();
56 if !self.levels.contains(&key) {
57 self.levels.push(key);
58 }
59 }
60 }
61
62 fn map(&self, value: &Value) -> f64 {
63 let key = value.to_group_key();
64 self.levels
65 .iter()
66 .position(|l| l == &key)
67 .map(|i| i as f64)
68 .unwrap_or(0.0)
69 }
70
71 fn breaks(&self) -> Vec<(f64, String)> {
72 self.levels
73 .iter()
74 .enumerate()
75 .map(|(i, label)| (i as f64, label.clone()))
76 .collect()
77 }
78
79 fn name(&self) -> &str {
80 &self.name
81 }
82
83 fn set_name(&mut self, name: &str) {
84 self.name = name.to_string();
85 }
86
87 fn is_discrete(&self) -> bool {
88 true
89 }
90
91 fn map_to_color(&self, value: &Value) -> Option<(u8, u8, u8)> {
92 let key = value.to_group_key();
93 let idx = self.levels.iter().position(|l| l == &key).unwrap_or(0);
94 let g = self.grey_for_index(idx);
95 Some((g, g, g))
96 }
97
98 fn clone_box(&self) -> Box<dyn Scale> {
99 Box::new(self.clone())
100 }
101
102 fn reset_training(&mut self) {
103 self.levels.clear();
104 }
105}