use crate::enums::chart::XlChartType;
use crate::error::PptxResult;
use super::super::super::xmlwriter::ChartXmlWriter;
use super::super::{Categories, Category, CategoryLevel};
#[derive(Debug, Clone)]
pub struct CategoryChartData {
categories: Vec<String>,
series: Vec<CategorySeriesData>,
number_format: String,
hierarchical_categories: Option<Vec<Vec<String>>>,
}
impl CategoryChartData {
#[must_use]
pub fn new() -> Self {
Self {
categories: Vec::new(),
series: Vec::new(),
number_format: "General".to_string(),
hierarchical_categories: None,
}
}
#[must_use]
pub fn with_number_format(number_format: &str) -> Self {
Self {
categories: Vec::new(),
series: Vec::new(),
number_format: number_format.to_string(),
hierarchical_categories: None,
}
}
pub fn add_category(&mut self, label: &str) {
self.categories.push(label.to_string());
}
pub fn add_series(&mut self, name: &str, values: &[f64]) {
let values = values.iter().map(|v| Some(*v)).collect();
let index = self.series.len();
self.series.push(CategorySeriesData {
name: name.to_string(),
values,
number_format: None,
index,
});
}
pub fn add_series_with_options(&mut self, name: &str, values: &[Option<f64>]) {
let index = self.series.len();
self.series.push(CategorySeriesData {
name: name.to_string(),
values: values.to_vec(),
number_format: None,
index,
});
}
#[must_use]
pub fn categories(&self) -> &[String] {
&self.categories
}
#[must_use]
pub fn series(&self) -> &[CategorySeriesData] {
&self.series
}
#[must_use]
pub fn number_format(&self) -> &str {
&self.number_format
}
pub fn set_hierarchical_categories(&mut self, levels: Vec<Vec<String>>) {
if let Some(leaf) = levels.first() {
self.categories.clone_from(leaf);
}
self.hierarchical_categories = Some(levels);
}
#[must_use]
pub const fn hierarchical_categories(&self) -> Option<&Vec<Vec<String>>> {
self.hierarchical_categories.as_ref()
}
#[must_use]
pub fn category_depth(&self) -> usize {
match &self.hierarchical_categories {
Some(levels) if levels.len() > 1 => levels.len(),
_ => 1,
}
}
#[must_use]
pub fn categories_object(&self) -> Categories {
match &self.hierarchical_categories {
Some(levels) if levels.len() > 1 => {
let cat_levels = levels
.iter()
.map(|level_labels| CategoryLevel {
categories: level_labels
.iter()
.enumerate()
.map(|(idx, label)| Category {
idx,
label: label.clone(),
children: Vec::new(),
})
.collect(),
})
.collect();
Categories { levels: cat_levels }
}
_ => {
let level = CategoryLevel {
categories: self
.categories
.iter()
.enumerate()
.map(|(idx, label)| Category {
idx,
label: label.clone(),
children: Vec::new(),
})
.collect(),
};
Categories {
levels: vec![level],
}
}
}
}
pub fn to_xml(&self, chart_type: XlChartType) -> PptxResult<String> {
ChartXmlWriter::write_category(self, chart_type)
}
}
impl Default for CategoryChartData {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct CategorySeriesData {
pub(crate) name: String,
pub(crate) values: Vec<Option<f64>>,
pub(crate) number_format: Option<String>,
pub(crate) index: usize,
}
impl CategorySeriesData {
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn values(&self) -> &[Option<f64>] {
&self.values
}
#[must_use]
pub const fn index(&self) -> usize {
self.index
}
#[must_use]
pub fn number_format(&self) -> Option<&str> {
self.number_format.as_deref()
}
}