1use gpui::SharedString;
5
6use crate::data::Data;
7
8#[derive(Clone, Debug)]
9pub struct Chart {
10 pub layers: Vec<Layer>,
13 pub title: Option<SharedString>,
14}
15
16#[derive(Clone, Debug)]
17pub struct Layer {
18 pub data: Data,
19 pub mark: Mark,
20 pub encoding: Encoding,
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
24pub enum Mark {
25 Bar,
26 Line,
27 Area,
28 Point,
29 Arc,
31}
32
33#[derive(Clone, Debug, Default, PartialEq)]
34pub struct Encoding {
35 pub x: Option<Channel>,
36 pub y: Option<Channel>,
37 pub color: Option<Channel>,
39 pub theta: Option<Channel>,
40}
41
42#[derive(Clone, Debug, PartialEq)]
43pub struct Channel {
44 pub field: SharedString,
45 pub kind: Kind,
46 pub title: Option<SharedString>,
48 pub scale: Scale,
49 pub sort: Sort,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq)]
55pub struct Scale {
56 pub zero: bool,
59 pub domain: Option<[f64; 2]>,
62 pub nice: bool,
64}
65
66impl Default for Scale {
67 fn default() -> Self {
68 Self {
69 zero: true,
70 domain: None,
71 nice: true,
72 }
73 }
74}
75
76#[derive(Clone, Debug, Default, PartialEq)]
77pub enum Sort {
78 #[default]
80 Data,
81 Ascending,
82 Descending,
83 Explicit(Vec<SharedString>),
86}
87
88#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
90pub enum Kind {
91 Quantitative,
92 Temporal,
93 Ordinal,
94 Nominal,
95}
96
97impl Chart {
98 pub fn new(mark: Mark, data: Data) -> Self {
100 Self {
101 layers: vec![Layer {
102 data,
103 mark,
104 encoding: Encoding::default(),
105 }],
106 title: None,
107 }
108 }
109
110 pub fn layer(mut self, other: Chart) -> Self {
112 self.layers.extend(other.layers);
113 self
114 }
115
116 fn last(&mut self) -> &mut Encoding {
117 &mut self
118 .layers
119 .last_mut()
120 .expect("a chart has a layer")
121 .encoding
122 }
123
124 pub fn bar(data: Data) -> Self {
125 Self::new(Mark::Bar, data)
126 }
127
128 pub fn line(data: Data) -> Self {
129 Self::new(Mark::Line, data)
130 }
131
132 pub fn area(data: Data) -> Self {
133 Self::new(Mark::Area, data)
134 }
135
136 pub fn point(data: Data) -> Self {
137 Self::new(Mark::Point, data)
138 }
139
140 pub fn arc(data: Data) -> Self {
141 Self::new(Mark::Arc, data)
142 }
143
144 pub fn x(mut self, channel: Channel) -> Self {
146 self.last().x = Some(channel);
147 self
148 }
149
150 pub fn y(mut self, channel: Channel) -> Self {
151 self.last().y = Some(channel);
152 self
153 }
154
155 pub fn color(mut self, channel: Channel) -> Self {
156 self.last().color = Some(channel);
157 self
158 }
159
160 pub fn theta(mut self, channel: Channel) -> Self {
161 self.last().theta = Some(channel);
162 self
163 }
164
165 pub fn title(mut self, title: impl Into<SharedString>) -> Self {
166 self.title = Some(title.into());
167 self
168 }
169}
170
171impl Channel {
172 pub fn new(field: impl Into<SharedString>, kind: Kind) -> Self {
173 Self {
174 field: field.into(),
175 kind,
176 title: None,
177 scale: Scale::default(),
178 sort: Sort::default(),
179 }
180 }
181
182 pub fn quantitative(field: impl Into<SharedString>) -> Self {
183 Self::new(field, Kind::Quantitative)
184 }
185
186 pub fn temporal(field: impl Into<SharedString>) -> Self {
187 Self::new(field, Kind::Temporal)
188 }
189
190 pub fn ordinal(field: impl Into<SharedString>) -> Self {
191 Self::new(field, Kind::Ordinal)
192 }
193
194 pub fn nominal(field: impl Into<SharedString>) -> Self {
195 Self::new(field, Kind::Nominal)
196 }
197
198 pub fn title(mut self, title: impl Into<SharedString>) -> Self {
199 self.title = Some(title.into());
200 self
201 }
202
203 pub fn zero(mut self, zero: bool) -> Self {
204 self.scale.zero = zero;
205 self
206 }
207
208 pub fn domain(mut self, low: f64, high: f64) -> Self {
209 self.scale.domain = Some([low, high]);
210 self
211 }
212
213 pub fn nice(mut self, nice: bool) -> Self {
214 self.scale.nice = nice;
215 self
216 }
217
218 pub fn sort(mut self, sort: Sort) -> Self {
219 self.sort = sort;
220 self
221 }
222}