use std::cmp::Ordering;
use std::fs::OpenOptions;
use std::io;
use std::path::Path;
use std::sync::Arc;
use svg::node::element::SVG as Svg;
use super::record::parse_all_records;
use super::storage::Storage;
use super::{SchDrawCtx, SchRecord};
use crate::draw::{Canvas, Draw, SvgCtx};
use crate::font::FontCollection;
use crate::Error;
#[derive(Clone, Debug)]
pub struct Component {
pub(crate) name: Box<str>,
pub(crate) records: Vec<SchRecord>,
pub(crate) fonts: Arc<FontCollection>,
pub(crate) storage: Arc<Storage>,
}
impl Component {
pub(crate) fn from_buf(
name: &str,
buf: &[u8],
fonts: Arc<FontCollection>,
storage: Arc<Storage>,
) -> Result<Self, Error> {
Ok(Component {
name: name.into(),
records: parse_all_records(buf, name)?,
fonts,
storage,
})
}
pub fn svg(&self) -> Svg {
let mut draw = SvgCtx::new();
let ctx = SchDrawCtx {
fonts: &self.fonts,
storage: &self.storage,
};
for record in &self.records {
record.draw(&mut draw, &ctx);
}
draw.svg()
}
pub fn save_svg<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
let file = OpenOptions::new().write(true).create(true).open(path)?;
svg::write(&file, &self.svg())
}
pub fn draw<C: Canvas>(&self, canvas: &mut C) {
let ctx = SchDrawCtx {
fonts: &self.fonts,
storage: &self.storage,
};
self.records.iter().for_each(|r| r.draw(canvas, &ctx));
}
pub fn name(&self) -> &str {
&self.name
}
pub fn description(&self) -> &str {
let meta = self
.records
.iter()
.find_map(|record| {
if let SchRecord::MetaData(d) = record {
Some(d)
} else {
None
}
})
.expect("no metadata record");
meta.description.as_deref().unwrap_or("")
}
pub fn name_cmp(&self, other: &Self) -> Option<Ordering> {
self.name.partial_cmp(&other.name)
}
pub fn records(&self) -> impl Iterator<Item = &SchRecord> {
self.records.iter()
}
}