use crate::components::{Rgb, TickDirection, ValueExponent};
#[derive(Default, Clone)]
pub struct Axis {
pub show_axis: Option<bool>,
pub axis_side: Option<AxisSide>,
pub axis_position: Option<f64>,
pub axis_type: Option<AxisType>,
pub value_color: Option<Rgb>,
pub value_range: Option<[f64; 2]>,
pub value_thousands: Option<bool>,
pub value_exponent: Option<ValueExponent>,
pub tick_values: Option<Vec<f64>>,
pub tick_labels: Option<Vec<String>>,
pub tick_direction: Option<TickDirection>,
pub tick_length: Option<usize>,
pub tick_width: Option<usize>,
pub tick_color: Option<Rgb>,
pub tick_angle: Option<f64>,
pub tick_font: Option<String>,
pub show_line: Option<bool>,
pub line_color: Option<Rgb>,
pub line_width: Option<usize>,
pub show_grid: Option<bool>,
pub grid_color: Option<Rgb>,
pub grid_width: Option<usize>,
pub show_zero_line: Option<bool>,
pub zero_line_color: Option<Rgb>,
pub zero_line_width: Option<usize>,
}
impl Axis {
pub fn new() -> Self {
Self::default()
}
pub fn show_axis(mut self, bool: bool) -> Self {
self.show_axis = Some(bool);
self
}
pub fn axis_side(mut self, side: AxisSide) -> Self {
self.axis_side = Some(side);
self
}
pub fn axis_position(mut self, position: f64) -> Self {
self.axis_position = Some(position);
self
}
pub fn axis_type(mut self, axis_type: AxisType) -> Self {
self.axis_type = Some(axis_type);
self
}
pub fn value_color(mut self, color: Rgb) -> Self {
self.value_color = Some(color);
self
}
pub fn value_range(mut self, min: f64, max: f64) -> Self {
self.value_range = Some([min, max]);
self
}
pub fn value_thousands(mut self, bool: bool) -> Self {
self.value_thousands = Some(bool);
self
}
pub fn value_exponent(mut self, exponent: ValueExponent) -> Self {
self.value_exponent = Some(exponent);
self
}
pub fn tick_values(mut self, values: Vec<f64>) -> Self {
self.tick_values = Some(values);
self
}
pub fn tick_labels(mut self, labels: Vec<impl Into<String>>) -> Self {
self.tick_labels = Some(labels.into_iter().map(|x| x.into()).collect());
self
}
pub fn tick_direction(mut self, direction: TickDirection) -> Self {
self.tick_direction = Some(direction);
self
}
pub fn tick_length(mut self, length: usize) -> Self {
self.tick_length = Some(length);
self
}
pub fn tick_width(mut self, width: usize) -> Self {
self.tick_width = Some(width);
self
}
pub fn tick_color(mut self, color: Rgb) -> Self {
self.tick_color = Some(color);
self
}
pub fn tick_angle(mut self, angle: f64) -> Self {
self.tick_angle = Some(angle);
self
}
pub fn tick_font(mut self, font: impl Into<String>) -> Self {
self.tick_font = Some(font.into());
self
}
pub fn show_line(mut self, bool: bool) -> Self {
self.show_line = Some(bool);
self
}
pub fn line_color(mut self, color: Rgb) -> Self {
self.line_color = Some(color);
self
}
pub fn line_width(mut self, width: usize) -> Self {
self.line_width = Some(width);
self
}
pub fn show_grid(mut self, bool: bool) -> Self {
self.show_grid = Some(bool);
self
}
pub fn grid_color(mut self, color: Rgb) -> Self {
self.grid_color = Some(color);
self
}
pub fn grid_width(mut self, width: usize) -> Self {
self.grid_width = Some(width);
self
}
pub fn show_zero_line(mut self, bool: bool) -> Self {
self.show_zero_line = Some(bool);
self
}
pub fn zero_line_color(mut self, color: Rgb) -> Self {
self.zero_line_color = Some(color);
self
}
pub fn zero_line_width(mut self, width: usize) -> Self {
self.zero_line_width = Some(width);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_all_none() {
let a = Axis::new();
assert!(a.show_axis.is_none());
assert!(a.show_grid.is_none());
assert!(a.value_range.is_none());
assert!(a.tick_labels.is_none());
assert!(a.show_line.is_none());
}
#[test]
fn test_show_axis() {
let a = Axis::new().show_axis(true);
assert_eq!(a.show_axis, Some(true));
assert!(a.show_grid.is_none());
assert!(a.value_range.is_none());
}
#[test]
fn test_show_grid() {
let a = Axis::new().show_grid(false);
assert_eq!(a.show_grid, Some(false));
assert!(a.show_axis.is_none());
}
#[test]
fn test_value_range() {
let a = Axis::new().value_range(0.0, 100.0);
let range = a.value_range.unwrap();
assert!((range[0] - 0.0).abs() < 1e-6);
assert!((range[1] - 100.0).abs() < 1e-6);
}
#[test]
fn test_tick_labels_converts() {
let a = Axis::new().tick_labels(vec!["a", "b"]);
let labels = a.tick_labels.unwrap();
assert_eq!(labels, vec!["a".to_string(), "b".to_string()]);
}
#[test]
fn test_builder_chaining() {
let a = Axis::new()
.show_axis(true)
.show_grid(false)
.show_line(true)
.value_range(1.0, 50.0)
.tick_labels(vec!["x", "y", "z"]);
assert_eq!(a.show_axis, Some(true));
assert_eq!(a.show_grid, Some(false));
assert_eq!(a.show_line, Some(true));
assert_eq!(a.value_range.unwrap().len(), 2);
assert_eq!(a.tick_labels.unwrap().len(), 3);
}
}
#[derive(Clone)]
pub enum AxisSide {
Top,
Bottom,
Left,
Right,
}
#[derive(Clone)]
pub enum AxisType {
Default,
Linear,
Log,
Date,
Category,
MultiCategory,
}