use crate::mark::Mark;
use crate::visual::color::SingleColor;
use crate::visual::shape::PointShape;
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub enum PointLayout {
#[default]
Standard,
Jitter,
Beeswarm,
}
impl From<&str> for PointLayout {
fn from(s: &str) -> Self {
match s.to_lowercase().as_str() {
"jitter" | "random" => PointLayout::Jitter,
"beeswarm" | "swarm" | "force" => PointLayout::Beeswarm,
"standard" | "none" | "center" => PointLayout::Standard,
_ => PointLayout::Standard,
}
}
}
#[derive(Clone)]
pub struct MarkPoint {
pub(crate) color: SingleColor,
pub(crate) shape: PointShape,
pub(crate) size: f64,
pub(crate) opacity: f64,
pub(crate) stroke: SingleColor,
pub(crate) stroke_width: f64,
pub(crate) layout: PointLayout,
pub(crate) width: f64,
pub(crate) spacing: f64,
pub(crate) span: f64,
}
impl MarkPoint {
pub(crate) fn new() -> Self {
Self {
color: SingleColor::new("black"),
shape: PointShape::Circle,
size: 3.0,
opacity: 1.0,
stroke: SingleColor::new("none"),
stroke_width: 0.0,
layout: PointLayout::Standard,
width: 0.5,
spacing: 0.2,
span: 0.7,
}
}
pub fn with_color(mut self, color: impl Into<SingleColor>) -> Self {
self.color = color.into();
self
}
pub fn with_shape(mut self, shape: impl Into<PointShape>) -> Self {
self.shape = shape.into();
self
}
pub fn with_size(mut self, size: f64) -> Self {
self.size = size;
self
}
pub fn with_opacity(mut self, opacity: f64) -> Self {
self.opacity = opacity.clamp(0.0, 1.0);
self
}
pub fn with_stroke(mut self, stroke: impl Into<SingleColor>) -> Self {
self.stroke = stroke.into();
self
}
pub fn with_stroke_width(mut self, width: f64) -> Self {
self.stroke_width = width;
self
}
pub fn with_layout(mut self, layout: impl Into<PointLayout>) -> Self {
self.layout = layout.into();
self
}
pub fn with_width(mut self, width: f64) -> Self {
self.width = width;
self
}
pub fn with_spacing(mut self, spacing: f64) -> Self {
self.spacing = spacing.clamp(0.0, 1.0);
self
}
pub fn with_span(mut self, span: f64) -> Self {
self.span = span.clamp(0.0, 1.0);
self
}
}
impl Default for MarkPoint {
fn default() -> Self {
Self::new()
}
}
impl Mark for MarkPoint {
fn mark_type(&self) -> &'static str {
"point"
}
}