use gpui::SharedString;
use crate::data::Data;
#[derive(Clone, Debug)]
pub struct Chart {
pub layers: Vec<Layer>,
pub title: Option<SharedString>,
}
#[derive(Clone, Debug)]
pub struct Layer {
pub data: Data,
pub mark: Mark,
pub encoding: Encoding,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Mark {
Bar,
Line,
Area,
Point,
Arc,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Encoding {
pub x: Option<Channel>,
pub y: Option<Channel>,
pub color: Option<Channel>,
pub theta: Option<Channel>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Channel {
pub field: SharedString,
pub kind: Kind,
pub title: Option<SharedString>,
pub scale: Scale,
pub sort: Sort,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Scale {
pub zero: bool,
pub domain: Option<[f64; 2]>,
pub nice: bool,
}
impl Default for Scale {
fn default() -> Self {
Self {
zero: true,
domain: None,
nice: true,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub enum Sort {
#[default]
Data,
Ascending,
Descending,
Explicit(Vec<SharedString>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Kind {
Quantitative,
Temporal,
Ordinal,
Nominal,
}
impl Chart {
pub fn new(mark: Mark, data: Data) -> Self {
Self {
layers: vec![Layer {
data,
mark,
encoding: Encoding::default(),
}],
title: None,
}
}
pub fn layer(mut self, other: Chart) -> Self {
self.layers.extend(other.layers);
self
}
fn last(&mut self) -> &mut Encoding {
&mut self
.layers
.last_mut()
.expect("a chart has a layer")
.encoding
}
pub fn bar(data: Data) -> Self {
Self::new(Mark::Bar, data)
}
pub fn line(data: Data) -> Self {
Self::new(Mark::Line, data)
}
pub fn area(data: Data) -> Self {
Self::new(Mark::Area, data)
}
pub fn point(data: Data) -> Self {
Self::new(Mark::Point, data)
}
pub fn arc(data: Data) -> Self {
Self::new(Mark::Arc, data)
}
pub fn x(mut self, channel: Channel) -> Self {
self.last().x = Some(channel);
self
}
pub fn y(mut self, channel: Channel) -> Self {
self.last().y = Some(channel);
self
}
pub fn color(mut self, channel: Channel) -> Self {
self.last().color = Some(channel);
self
}
pub fn theta(mut self, channel: Channel) -> Self {
self.last().theta = Some(channel);
self
}
pub fn title(mut self, title: impl Into<SharedString>) -> Self {
self.title = Some(title.into());
self
}
}
impl Channel {
pub fn new(field: impl Into<SharedString>, kind: Kind) -> Self {
Self {
field: field.into(),
kind,
title: None,
scale: Scale::default(),
sort: Sort::default(),
}
}
pub fn quantitative(field: impl Into<SharedString>) -> Self {
Self::new(field, Kind::Quantitative)
}
pub fn temporal(field: impl Into<SharedString>) -> Self {
Self::new(field, Kind::Temporal)
}
pub fn ordinal(field: impl Into<SharedString>) -> Self {
Self::new(field, Kind::Ordinal)
}
pub fn nominal(field: impl Into<SharedString>) -> Self {
Self::new(field, Kind::Nominal)
}
pub fn title(mut self, title: impl Into<SharedString>) -> Self {
self.title = Some(title.into());
self
}
pub fn zero(mut self, zero: bool) -> Self {
self.scale.zero = zero;
self
}
pub fn domain(mut self, low: f64, high: f64) -> Self {
self.scale.domain = Some([low, high]);
self
}
pub fn nice(mut self, nice: bool) -> Self {
self.scale.nice = nice;
self
}
pub fn sort(mut self, sort: Sort) -> Self {
self.sort = sort;
self
}
}