use crate::visualization::{ColorScheme, Graph, GraphConfig, GraphData, LineStyle};
#[cfg(feature = "static_export")]
use {crate::error::GraphError, std::path::Path};
pub trait Plottable {
type Error;
fn plot(&self) -> PlotBuilder<Self>
where
Self: Sized + Graph;
}
pub struct PlotBuilder<T: Plottable + Graph> {
pub(crate) data: T,
pub(crate) options: GraphConfig,
}
impl<T: Plottable + Graph> PlotBuilder<T> {
pub fn title(mut self, title: impl Into<String>) -> Self {
self.options.title = title.into();
if self.options.legend.is_none() {
self.options.legend = Some(vec![self.options.title.clone()]);
}
self
}
pub fn x_label(mut self, label: impl Into<String>) -> Self {
self.options.x_label = Some(label.into());
self
}
pub fn y_label(mut self, label: impl Into<String>) -> Self {
self.options.y_label = Some(label.into());
self
}
pub fn z_label(mut self, label: impl Into<String>) -> Self {
self.options.z_label = Some(label.into());
self
}
pub fn line_style(mut self, line_style: LineStyle) -> Self {
self.options.line_style = line_style;
self
}
pub fn legend(mut self, legend: Vec<impl Into<String>>) -> Self {
let legend: Vec<String> = legend.into_iter().map(|l| l.into()).collect();
self.options.legend = Some(legend);
self
}
pub fn add_legend(mut self, legend: impl Into<String>) -> Self {
if let Some(ref mut legends) = self.options.legend {
legends.push(legend.into());
} else {
self.options.legend = Some(vec![legend.into()]);
}
self
}
pub fn dimensions(mut self, width: u32, height: u32) -> Self {
self.options.width = width;
self.options.height = height;
self
}
pub fn color_scheme(mut self, color_scheme: ColorScheme) -> Self {
self.options.color_scheme = color_scheme;
self
}
pub fn show_legend(mut self, show_legend: bool) -> Self {
self.options.show_legend = show_legend;
self
}
#[cfg(feature = "static_export")]
pub fn save(self, path: impl AsRef<Path>) -> Result<(), GraphError> {
let path = path.as_ref();
self.write_png(path).map_err(|e| {
GraphError::Render(format!("Failed to save plot to {} {}", path.display(), e))
})
}
}
impl<T: Plottable + Graph> Graph for PlotBuilder<T> {
fn graph_data(&self) -> GraphData {
self.data.graph_data()
}
fn graph_config(&self) -> GraphConfig {
GraphConfig {
title: self.options.title.clone(),
width: 1600,
height: 900,
x_label: self.options.x_label.clone(),
y_label: self.options.y_label.clone(),
z_label: self.options.z_label.clone(),
line_style: self.options.line_style,
color_scheme: self.options.color_scheme.clone(),
legend: self.options.legend.clone(),
show_legend: self.options.show_legend,
}
}
}