pub mod block_source;
pub mod executor;
pub mod refs;
pub use block_source::{ResolvedBlockRefs, resolve_block_refs};
pub use executor::ChartExecutor;
pub use refs::{ChartRange, ChartRefs, ChartSeriesRefs};
use std::sync::Arc;
use imbl::{HashMap, Vector};
use logisheets_base::{BlockId, CellId, SheetId};
use logisheets_workbook::prelude::{ChartData, PassthroughPart};
#[derive(Debug, Clone)]
pub struct ChartMarker {
pub cell: CellId,
pub col_off: i64,
pub row_off: i64,
}
#[derive(Debug, Clone)]
pub enum ChartExtent {
ToCell(ChartMarker),
Size { cx: i64, cy: i64 },
}
#[derive(Debug, Clone, PartialEq)]
pub struct ChartBlockSource {
pub block_id: BlockId,
pub category_field: Option<String>,
pub value_fields: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct Chart {
pub id: String,
pub from: ChartMarker,
pub extent: ChartExtent,
pub part_path: String,
pub data: ChartData,
pub raw: Arc<Vec<PassthroughPart>>,
pub source: Option<ChartBlockSource>,
pub refs: ChartRefs,
}
#[derive(Debug, Clone, Default)]
pub struct ChartManager {
pub charts: HashMap<SheetId, Vector<Chart>>,
}
impl ChartManager {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, sheet_id: SheetId, chart: Chart) {
let mut v = self.charts.get(&sheet_id).cloned().unwrap_or_default();
v.push_back(chart);
self.charts.insert(sheet_id, v);
}
pub fn charts_of_sheet(&self, sheet_id: SheetId) -> impl Iterator<Item = &Chart> {
self.charts
.get(&sheet_id)
.into_iter()
.flat_map(|v| v.iter())
}
pub fn move_chart(
&mut self,
sheet_id: SheetId,
chart_id: &str,
from: ChartMarker,
extent: ChartExtent,
) -> bool {
let mut v = match self.charts.get(&sheet_id) {
Some(v) => v.clone(),
None => return false,
};
let idx = v.iter().position(|c| c.id == chart_id);
let idx = match idx {
Some(i) => i,
None => return false,
};
let mut chart = v[idx].clone();
chart.from = from;
chart.extent = extent;
v.set(idx, chart);
self.charts.insert(sheet_id, v);
true
}
pub fn update_content(
&mut self,
sheet_id: SheetId,
chart_id: &str,
data: ChartData,
raw: Arc<Vec<PassthroughPart>>,
refs: ChartRefs,
) -> bool {
let mut v = match self.charts.get(&sheet_id) {
Some(v) => v.clone(),
None => return false,
};
let idx = match v.iter().position(|c| c.id == chart_id) {
Some(i) => i,
None => return false,
};
let mut chart = v[idx].clone();
chart.data = data;
chart.raw = raw;
chart.refs = refs;
v.set(idx, chart);
self.charts.insert(sheet_id, v);
true
}
pub fn set_refs(&mut self, sheet_id: SheetId, chart_id: &str, refs: ChartRefs) -> bool {
let mut v = match self.charts.get(&sheet_id) {
Some(v) => v.clone(),
None => return false,
};
let idx = match v.iter().position(|c| c.id == chart_id) {
Some(i) => i,
None => return false,
};
let mut chart = v[idx].clone();
chart.refs = refs;
v.set(idx, chart);
self.charts.insert(sheet_id, v);
true
}
pub fn set_source(
&mut self,
sheet_id: SheetId,
chart_id: &str,
source: Option<ChartBlockSource>,
) -> bool {
let mut v = match self.charts.get(&sheet_id) {
Some(v) => v.clone(),
None => return false,
};
let idx = match v.iter().position(|c| c.id == chart_id) {
Some(i) => i,
None => return false,
};
let mut chart = v[idx].clone();
chart.source = source;
v.set(idx, chart);
self.charts.insert(sheet_id, v);
true
}
pub fn remove_chart(&mut self, sheet_id: SheetId, chart_id: &str) -> bool {
let mut v = match self.charts.get(&sheet_id) {
Some(v) => v.clone(),
None => return false,
};
let idx = match v.iter().position(|c| c.id == chart_id) {
Some(i) => i,
None => return false,
};
v.remove(idx);
self.charts.insert(sheet_id, v);
true
}
}