charton 0.5.0

A high-performance, layered charting system for Rust, featuring a flexible data core and multi-backend rendering.
Documentation
use crate::mark::Mark;
use crate::render::line_renderer::PathInterpolation;
use crate::visual::color::SingleColor;

/// Mark type for line/path charts.
///
/// The `MarkLine` struct defines the visual properties of line elements.
/// It supports a fluent interface for configuring stroke appearance,
/// interpolation methods, and statistical smoothing.
#[derive(Clone)]
pub struct MarkLine {
    pub(crate) color: SingleColor,
    pub(crate) stroke_width: f64,
    pub(crate) dash: Vec<f64>,
    pub(crate) opacity: f64,
    pub(crate) interpolation: PathInterpolation,
    pub(crate) loess: bool,
    pub(crate) loess_bandwidth: f64,
}

impl MarkLine {
    pub(crate) fn new() -> Self {
        Self {
            color: SingleColor::new("black"),
            stroke_width: 1.0,
            dash: vec![],
            opacity: 1.0,
            interpolation: PathInterpolation::Linear,
            loess: false,
            loess_bandwidth: 0.75,
        }
    }

    // --- Fluent Configuration Methods (Builder Pattern) ---

    /// Sets the stroke color of the line. Accepts "red", "#hex", etc.
    pub fn with_color(mut self, color: impl Into<SingleColor>) -> Self {
        self.color = color.into();
        self
    }

    /// Sets the thickness of the line.
    pub fn with_stroke_width(mut self, width: f64) -> Self {
        self.stroke_width = width;
        self
    }

    /// Sets the line dash pattern using the standard SVG `stroke-dasharray` rules.
    ///
    /// This property accepts a list of numbers that specify the lengths of
    /// alternating dashes and gaps.
    ///
    /// - `vec![]`: A solid line.
    /// - `vec![step]`: Equivalent to `vec![step, step]`.
    /// - `vec![dash, gap]`: Specifies the length of the dash and the gap.
    ///
    /// For more details, refer to the MDN documentation for `stroke-dasharray`.
    pub fn with_dash(mut self, dash: impl Into<Vec<f64>>) -> Self {
        self.dash = dash.into();
        self
    }

    /// Sets the opacity of the line mark.
    ///
    /// Value should be between 0.0 (transparent) and 1.0 (opaque).
    pub fn with_opacity(mut self, opacity: f64) -> Self {
        self.opacity = opacity.clamp(0.0, 1.0);
        self
    }

    /// Sets the interpolation method for connecting data points.
    ///
    /// Accepts `PathInterpolation` variants or string literals like "linear" or "step".
    pub fn with_interpolation(mut self, interpolation: impl Into<PathInterpolation>) -> Self {
        self.interpolation = interpolation.into();
        self
    }

    /// Enables or disables LOESS (Locally Estimated Scatterplot Smoothing).
    pub fn with_loess(mut self, use_loess: bool) -> Self {
        self.loess = use_loess;
        self
    }

    /// Sets the bandwidth parameter for LOESS smoothing.
    ///
    /// Controls the smoothness; value should be between 0.0 and 1.0.
    pub fn with_loess_bandwidth(mut self, bandwidth: f64) -> Self {
        self.loess_bandwidth = bandwidth.clamp(0.0, 1.0);
        self
    }
}

impl Default for MarkLine {
    fn default() -> Self {
        Self::new()
    }
}

impl Mark for MarkLine {
    fn mark_type(&self) -> &'static str {
        "line"
    }
}