mod describe;
mod draw;
mod landscape;
mod model;
mod portrait;
#[cfg(test)]
mod tests;
mod track;
pub(crate) use describe::{data_table, description};
use self::{landscape::Landscape, model::Model, portrait::Portrait};
use crate::{
diagram,
error::ChartWarning,
layout::{push_title, title_extra},
metrics::TextMetrics,
scene::Scene,
spec::{ChartSpec, DiagramOrientation, SequenceSpec},
};
const COMPACT_BELOW: u32 = 600;
const MARGIN: f64 = 24.0;
const COMPACT_MARGIN: f64 = 12.0;
const COMPACT_TEXT: f64 = 64.0;
const BOTTOM: f64 = 16.0;
const LABEL_SIZE: f64 = 13.0;
const SUBLABEL_SIZE: f64 = 11.0;
const MESSAGE_SIZE: f64 = 12.0;
const TAG_SIZE: f64 = 11.0;
const LINE: f64 = 15.0;
const PAD: f64 = 12.0;
const COMPACT_PAD: f64 = 5.0;
const COMPACT_LABEL: f64 = 150.0;
const MIN_BOX: f64 = 72.0;
const COMPACT_BOX: f64 = 56.0;
const BADGE_LIFT: f64 = 7.0;
const MAX_BOX: f64 = 180.0;
const FIGURE: f64 = 26.0;
const BAR: f64 = 5.0;
const NESTED_BAR: f64 = 4.0;
const LOOP_OUT: f64 = 24.0;
const LOOP_ALONG: f64 = 16.0;
const LAST_SELF_LABEL: f64 = 170.0;
const LANDSCAPE_LABEL: f64 = 160.0;
const MAX_STRETCH: f64 = 1.5;
const FRAME_INSET: f64 = 5.0;
const TAG_HEIGHT: f64 = 16.0;
pub(crate) fn layout(
spec: &ChartSpec,
warnings: &mut Vec<ChartWarning>,
metrics: &impl TextMetrics,
) -> Scene {
let sequence = sequence(spec);
let width = f64::from(spec.width);
let compact = spec.width < COMPACT_BELOW;
let margin = if compact { COMPACT_MARGIN } else { MARGIN };
let top = 56.0 + title_extra(spec, width - 2.0 * margin, metrics);
let model = Model::new(sequence, compact, metrics);
let mut ignored = Vec::new();
let landscape = match sequence.orientation {
DiagramOrientation::Portrait => false,
DiagramOrientation::Landscape => true,
DiagramOrientation::Auto => {
let portrait = Portrait::new(spec, &model, top, metrics, &mut ignored);
let landscape = Landscape::new(spec, &model, top, metrics, &mut ignored);
diagram::prefers_landscape(
spec,
(portrait.width, portrait.height),
(landscape.width, landscape.height),
)
}
};
let mut elements = Vec::new();
push_title(
&mut elements,
spec,
margin,
width - 2.0 * margin,
metrics,
warnings,
);
let (scene_width, scene_height) = if landscape {
Landscape::new(spec, &model, top, metrics, warnings).draw(
spec,
&model,
metrics,
warnings,
&mut elements,
)
} else {
Portrait::new(spec, &model, top, metrics, warnings).draw(
spec,
&model,
metrics,
warnings,
&mut elements,
)
};
Scene {
width: scene_width,
height: scene_height,
elements,
}
}
fn pad(compact: bool) -> f64 {
if compact { COMPACT_PAD } else { PAD }
}
fn sequence(spec: &ChartSpec) -> &SequenceSpec {
spec.sequence
.as_ref()
.expect("validated sequence diagrams carry a sequence block")
}
fn label_path(index: usize) -> String {
format!("/sequence/messages/{index}/label")
}