use crate::color::Rgba;
#[derive(Debug, Clone, Default)]
pub struct Aes {
pub x: Option<String>,
pub y: Option<String>,
pub color: Option<String>,
pub size: Option<String>,
pub shape: Option<String>,
pub alpha: Option<String>,
pub fill: Option<String>,
pub group: Option<String>,
pub label: Option<String>,
pub color_value: Option<Rgba>,
pub size_value: Option<f32>,
pub alpha_value: Option<f32>,
}
impl Aes {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn x(mut self, column: &str) -> Self {
self.x = Some(column.to_string());
self
}
#[must_use]
pub fn y(mut self, column: &str) -> Self {
self.y = Some(column.to_string());
self
}
#[must_use]
pub fn color(mut self, column: &str) -> Self {
self.color = Some(column.to_string());
self
}
#[must_use]
pub fn size(mut self, column: &str) -> Self {
self.size = Some(column.to_string());
self
}
#[must_use]
pub fn shape(mut self, column: &str) -> Self {
self.shape = Some(column.to_string());
self
}
#[must_use]
pub fn alpha(mut self, column: &str) -> Self {
self.alpha = Some(column.to_string());
self
}
#[must_use]
pub fn fill(mut self, column: &str) -> Self {
self.fill = Some(column.to_string());
self
}
#[must_use]
pub fn group(mut self, column: &str) -> Self {
self.group = Some(column.to_string());
self
}
#[must_use]
pub fn label(mut self, column: &str) -> Self {
self.label = Some(column.to_string());
self
}
#[must_use]
pub fn color_value(mut self, color: Rgba) -> Self {
self.color_value = Some(color);
self
}
#[must_use]
pub fn size_value(mut self, size: f32) -> Self {
self.size_value = Some(size);
self
}
#[must_use]
pub fn alpha_value(mut self, alpha: f32) -> Self {
self.alpha_value = Some(alpha.clamp(0.0, 1.0));
self
}
#[must_use]
pub fn merge(&self, other: &Aes) -> Aes {
Aes {
x: other.x.clone().or_else(|| self.x.clone()),
y: other.y.clone().or_else(|| self.y.clone()),
color: other.color.clone().or_else(|| self.color.clone()),
size: other.size.clone().or_else(|| self.size.clone()),
shape: other.shape.clone().or_else(|| self.shape.clone()),
alpha: other.alpha.clone().or_else(|| self.alpha.clone()),
fill: other.fill.clone().or_else(|| self.fill.clone()),
group: other.group.clone().or_else(|| self.group.clone()),
label: other.label.clone().or_else(|| self.label.clone()),
color_value: other.color_value.or(self.color_value),
size_value: other.size_value.or(self.size_value),
alpha_value: other.alpha_value.or(self.alpha_value),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aes_builder() {
let aes = Aes::new().x("xvar").y("yvar").color("category").size_value(5.0);
assert_eq!(aes.x, Some("xvar".to_string()));
assert_eq!(aes.y, Some("yvar".to_string()));
assert_eq!(aes.color, Some("category".to_string()));
assert_eq!(aes.size_value, Some(5.0));
}
#[test]
fn test_aes_merge() {
let base = Aes::new().x("x").y("y").color_value(Rgba::RED);
let override_aes = Aes::new().y("y2").size_value(3.0);
let merged = base.merge(&override_aes);
assert_eq!(merged.x, Some("x".to_string())); assert_eq!(merged.y, Some("y2".to_string())); assert_eq!(merged.color_value, Some(Rgba::RED)); assert_eq!(merged.size_value, Some(3.0)); }
#[test]
fn test_aes_size() {
let aes = Aes::new().size("size_col");
assert_eq!(aes.size, Some("size_col".to_string()));
}
#[test]
fn test_aes_shape() {
let aes = Aes::new().shape("shape_col");
assert_eq!(aes.shape, Some("shape_col".to_string()));
}
#[test]
fn test_aes_alpha() {
let aes = Aes::new().alpha("alpha_col");
assert_eq!(aes.alpha, Some("alpha_col".to_string()));
}
#[test]
fn test_aes_fill() {
let aes = Aes::new().fill("fill_col");
assert_eq!(aes.fill, Some("fill_col".to_string()));
}
#[test]
fn test_aes_group() {
let aes = Aes::new().group("group_col");
assert_eq!(aes.group, Some("group_col".to_string()));
}
#[test]
fn test_aes_label() {
let aes = Aes::new().label("label_col");
assert_eq!(aes.label, Some("label_col".to_string()));
}
#[test]
fn test_aes_alpha_value() {
let aes = Aes::new().alpha_value(0.5);
assert_eq!(aes.alpha_value, Some(0.5));
}
#[test]
fn test_aes_alpha_value_clamp() {
let aes1 = Aes::new().alpha_value(1.5);
assert_eq!(aes1.alpha_value, Some(1.0));
let aes2 = Aes::new().alpha_value(-0.5);
assert_eq!(aes2.alpha_value, Some(0.0));
}
#[test]
fn test_aes_default() {
let aes = Aes::default();
assert!(aes.x.is_none());
assert!(aes.y.is_none());
}
#[test]
fn test_aes_merge_all_fields() {
let base = Aes::new()
.x("x")
.color("c")
.shape("s")
.alpha("a")
.fill("f")
.group("g")
.label("l")
.alpha_value(0.5);
let other = Aes::new().y("y").size("sz");
let merged = base.merge(&other);
assert_eq!(merged.x, Some("x".to_string()));
assert_eq!(merged.y, Some("y".to_string()));
assert_eq!(merged.color, Some("c".to_string()));
assert_eq!(merged.size, Some("sz".to_string()));
assert_eq!(merged.shape, Some("s".to_string()));
assert_eq!(merged.alpha, Some("a".to_string()));
assert_eq!(merged.fill, Some("f".to_string()));
assert_eq!(merged.group, Some("g".to_string()));
assert_eq!(merged.label, Some("l".to_string()));
assert_eq!(merged.alpha_value, Some(0.5));
}
#[test]
fn test_aes_debug_clone() {
let aes = Aes::new().x("x").y("y");
let aes2 = aes.clone();
let _ = format!("{aes2:?}");
}
}