pub mod config;
mod error;
mod export;
mod layout;
mod structure;
pub use orrery_core::{color, draw, identifier, semantic};
pub use orrery_parser::error::ParseError;
pub use error::RenderError;
use std::{fs, path::Path};
pub use orrery_parser::{InMemorySourceProvider, SourceProvider};
use bumpalo::Bump;
use log::{debug, info, trace};
use orrery_core::geometry::Insets;
use orrery_parser::ElaborateConfig;
use config::AppConfig;
use export::Exporter;
pub struct DiagramBuilder<'a, P: SourceProvider> {
config: AppConfig,
provider: &'a P,
}
impl<'a, P: SourceProvider> DiagramBuilder<'a, P> {
pub fn new(config: AppConfig, provider: &'a P) -> Self {
Self { config, provider }
}
pub fn parse<'b>(
&self,
arena: &'b Bump,
root_path: &Path,
) -> Result<semantic::Diagram, ParseError<'b>> {
info!("Parsing diagram");
let elaborate_config = ElaborateConfig::new(
self.config.layout().component(),
self.config.layout().sequence(),
);
let diagram = orrery_parser::parse(arena, root_path, self.provider, elaborate_config)?;
debug!("Diagram parsed successfully");
trace!(diagram:?; "Parsed diagram");
Ok(diagram)
}
pub fn render_svg(&self, diagram: &semantic::Diagram) -> Result<String, RenderError> {
info!(diagram_kind:? = diagram.kind(); "Building diagram structure");
let diagram_hierarchy = structure::DiagramHierarchy::from_diagram(diagram)?;
debug!("Structure built successfully");
let engine_builder = layout::EngineBuilder::new()
.with_padding(Insets::uniform(35.0))
.with_min_spacing(50.0)
.with_horizontal_spacing(50.0)
.with_vertical_spacing(50.0)
.with_event_padding(15.0);
info!("Processing diagrams in hierarchy");
let layered_layout = engine_builder.build(&diagram_hierarchy)?;
info!(layers_count = layered_layout.len(); "Layout calculated");
let temp_file =
tempfile::NamedTempFile::new().map_err(|err| RenderError::Export(Box::new(err)))?;
let temp_path = temp_file.path().to_string_lossy().to_string();
let mut svg_exporter = export::svg::SvgBuilder::new(&temp_path)
.with_style(self.config.style())
.with_diagram(diagram)
.build()?;
svg_exporter.export_layered_layout(&layered_layout)?;
let svg_string = fs::read_to_string(&temp_path).map_err(RenderError::Io)?;
info!("SVG rendered successfully");
Ok(svg_string)
}
}