use crate::dml::fill::FillFormat;
use crate::dml::line::LineFormat;
use crate::enums::chart::XlChartType;
use super::datalabel::DataLabels;
use super::marker::Marker;
#[derive(Debug, Clone, Default)]
pub struct SeriesCollection {
series: Vec<Series>,
}
impl SeriesCollection {
#[must_use]
pub const fn new() -> Self {
Self { series: Vec::new() }
}
pub fn add(&mut self, series: Series) {
self.series.push(series);
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&Series> {
self.series.get(index)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut Series> {
self.series.get_mut(index)
}
#[must_use]
pub fn len(&self) -> usize {
self.series.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.series.is_empty()
}
pub fn iter(&self) -> std::slice::Iter<'_, Series> {
self.series.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Series> {
self.series.iter_mut()
}
}
impl<'a> IntoIterator for &'a SeriesCollection {
type Item = &'a Series;
type IntoIter = std::slice::Iter<'a, Series>;
fn into_iter(self) -> Self::IntoIter {
self.series.iter()
}
}
impl<'a> IntoIterator for &'a mut SeriesCollection {
type Item = &'a mut Series;
type IntoIter = std::slice::IterMut<'a, Series>;
fn into_iter(self) -> Self::IntoIter {
self.series.iter_mut()
}
}
#[derive(Debug, Clone)]
pub struct SeriesFormat {
pub fill: Option<FillFormat>,
pub line: Option<LineFormat>,
}
impl SeriesFormat {
#[must_use]
pub const fn new() -> Self {
Self {
fill: None,
line: None,
}
}
}
impl Default for SeriesFormat {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Point {
index: usize,
format: Option<SeriesFormat>,
}
impl Point {
#[must_use]
pub const fn new(index: usize) -> Self {
Self {
index,
format: None,
}
}
#[must_use]
pub const fn index(&self) -> usize {
self.index
}
#[must_use]
pub const fn format(&self) -> Option<&SeriesFormat> {
self.format.as_ref()
}
pub fn set_format(&mut self, format: SeriesFormat) {
self.format = Some(format);
}
}
#[derive(Debug, Clone)]
pub struct Series {
name: String,
index: usize,
chart_type: XlChartType,
marker: Option<Marker>,
data_labels: Option<DataLabels>,
smooth: bool,
invert_if_negative: bool,
format: Option<SeriesFormat>,
values: Vec<Option<f64>>,
points: Vec<Point>,
}
impl Series {
#[must_use]
pub fn new(name: &str, index: usize, chart_type: XlChartType) -> Self {
Self {
name: name.to_string(),
index,
chart_type,
marker: None,
data_labels: None,
smooth: false,
invert_if_negative: false,
format: None,
values: Vec::new(),
points: Vec::new(),
}
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub const fn index(&self) -> usize {
self.index
}
#[must_use]
pub const fn chart_type(&self) -> XlChartType {
self.chart_type
}
#[must_use]
pub const fn marker(&self) -> Option<&Marker> {
self.marker.as_ref()
}
pub fn set_marker(&mut self, marker: Marker) {
self.marker = Some(marker);
}
#[must_use]
pub const fn data_labels(&self) -> Option<&DataLabels> {
self.data_labels.as_ref()
}
pub fn set_data_labels(&mut self, data_labels: DataLabels) {
self.data_labels = Some(data_labels);
}
#[must_use]
pub const fn smooth(&self) -> bool {
self.smooth
}
pub fn set_smooth(&mut self, value: bool) {
self.smooth = value;
}
#[must_use]
pub const fn invert_if_negative(&self) -> bool {
self.invert_if_negative
}
pub fn set_invert_if_negative(&mut self, value: bool) {
self.invert_if_negative = value;
}
#[must_use]
pub const fn format(&self) -> Option<&SeriesFormat> {
self.format.as_ref()
}
pub fn format_mut(&mut self) -> &mut SeriesFormat {
self.format.get_or_insert_with(SeriesFormat::new)
}
pub fn set_format(&mut self, format: SeriesFormat) {
self.format = Some(format);
}
#[must_use]
pub fn values(&self) -> &[Option<f64>] {
&self.values
}
pub fn set_values(&mut self, values: Vec<Option<f64>>) {
self.values = values;
}
#[must_use]
pub fn points(&self) -> &[Point] {
&self.points
}
pub fn points_mut(&mut self) -> &mut Vec<Point> {
&mut self.points
}
pub fn add_point(&mut self, point: Point) {
self.points.push(point);
}
}
#[cfg(test)]
#[path = "series_tests.rs"]
mod tests;