pub mod color;
pub mod shape;
pub mod size;
pub mod text;
pub mod x;
pub mod y;
pub mod y2;
use self::{color::Color, shape::Shape, size::Size, text::Text, x::X, y::Y, y2::Y2};
use crate::scale::{Expansion, Scale, ScaleDomain};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Channel {
X,
Y,
Color,
Shape,
Size,
}
pub trait IntoEncoding {
fn apply(self, enc: &mut Encoding);
}
#[derive(Default, Clone)]
pub struct Encoding {
pub(crate) x: Option<X>,
pub(crate) y: Option<Y>,
pub(crate) y2: Option<Y2>,
pub(crate) color: Option<Color>,
pub(crate) shape: Option<Shape>,
pub(crate) size: Option<Size>,
pub(crate) text: Option<Text>,
}
impl Encoding {
pub(crate) fn new() -> Self {
Default::default()
}
pub fn is_empty(&self) -> bool {
self.x.is_none()
&& self.y.is_none()
&& self.y2.is_none()
&& self.color.is_none()
&& self.shape.is_none()
&& self.size.is_none()
&& self.text.is_none()
}
pub fn get_field_by_channel(&self, channel: Channel) -> Option<&str> {
match channel {
Channel::X => self.x.as_ref().map(|v| v.field.as_str()),
Channel::Y => self.y.as_ref().map(|v| v.field.as_str()),
Channel::Color => self.color.as_ref().map(|v| v.field.as_str()),
Channel::Shape => self.shape.as_ref().map(|v| v.field.as_str()),
Channel::Size => self.size.as_ref().map(|v| v.field.as_str()),
}
}
pub fn get_scale_by_channel(&self, channel: Channel) -> Option<Scale> {
match channel {
Channel::X => self.x.as_ref().and_then(|v| v.scale_type),
Channel::Y => self.y.as_ref().and_then(|v| v.scale_type),
Channel::Color => self.color.as_ref().and_then(|v| v.scale_type),
Channel::Shape => self.shape.as_ref().and_then(|v| v.scale_type),
Channel::Size => self.size.as_ref().and_then(|v| v.scale_type),
}
}
pub fn get_domain_by_channel(&self, channel: Channel) -> Option<ScaleDomain> {
match channel {
Channel::X => self.x.as_ref().and_then(|v| v.domain.clone()),
Channel::Y => self.y.as_ref().and_then(|v| v.domain.clone()),
Channel::Color => self.color.as_ref().and_then(|v| v.domain.clone()),
Channel::Shape => self.shape.as_ref().and_then(|v| v.domain.clone()),
Channel::Size => self.size.as_ref().and_then(|v| v.domain.clone()),
}
}
pub fn get_expand_by_channel(&self, channel: Channel) -> Option<Expansion> {
match channel {
Channel::X => self.x.as_ref().and_then(|v| v.expansion),
Channel::Y => self.y.as_ref().and_then(|v| v.expansion),
Channel::Color => self.color.as_ref().and_then(|v| v.expansion),
Channel::Shape => self.shape.as_ref().and_then(|v| v.expansion),
Channel::Size => self.size.as_ref().and_then(|v| v.expansion),
}
}
pub fn get_zero_by_channel(&self, channel: Channel) -> bool {
match channel {
Channel::X => self.x.as_ref().and_then(|v| v.zero),
Channel::Y => self.y.as_ref().and_then(|v| v.zero),
_ => None,
}
.unwrap_or(false)
}
pub(crate) fn active_fields(&self) -> Vec<&str> {
let mut fields = Vec::new();
let core_channels = [
Channel::X,
Channel::Y,
Channel::Color,
Channel::Shape,
Channel::Size,
];
for ch in core_channels {
if let Some(field) = self.get_field_by_channel(ch) {
fields.push(field);
}
}
if let Some(ref y2) = self.y2 {
fields.push(y2.field.as_str());
}
if let Some(ref txt) = self.text {
fields.push(txt.field.as_str());
}
fields
}
}
impl IntoEncoding for X {
fn apply(self, enc: &mut Encoding) {
enc.x = Some(self);
}
}
impl IntoEncoding for Y {
fn apply(self, enc: &mut Encoding) {
enc.y = Some(self);
}
}
impl IntoEncoding for Y2 {
fn apply(self, enc: &mut Encoding) {
enc.y2 = Some(self);
}
}
impl IntoEncoding for Color {
fn apply(self, enc: &mut Encoding) {
enc.color = Some(self);
}
}
impl IntoEncoding for Shape {
fn apply(self, enc: &mut Encoding) {
enc.shape = Some(self);
}
}
impl IntoEncoding for Size {
fn apply(self, enc: &mut Encoding) {
enc.size = Some(self);
}
}
impl IntoEncoding for Text {
fn apply(self, enc: &mut Encoding) {
enc.text = Some(self);
}
}
macro_rules! impl_tuple_encoding {
($($idx:tt $T:ident),+) => {
impl<$($T: IntoEncoding),+> IntoEncoding for ($($T,)+) {
#[inline]
fn apply(self, enc: &mut Encoding) {
$( self.$idx.apply(enc); )+
}
}
};
}
impl_tuple_encoding!(0 T0);
impl_tuple_encoding!(0 T0, 1 T1);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7);
impl_tuple_encoding!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8);