///|
fn paint_flowchart(
view : @flowchart.Flowchart,
theme : @theme.Theme,
mode : Mode,
id_prefix : String?,
limits : @flowchart_layout.Limits,
geometry? : @flowchart_layout.Geometry,
connectors~ : ConnectorOptions = ConnectorOptions::new(),
) -> @render.Rendered {
if !connector_options_valid(connectors) {
return @render.Rendered::failed("image/svg+xml", [
@diagrams.Diagnostic::error(
"connector/invalid-option", "Invalid connector options",
),
])
}
let limits = limits.with_minimum_approach(connectors.minimum_approach)
let geometry = match geometry {
Some(geometry) => geometry
None => {
let result = @flowchart_layout.layout(view, limits~)
guard result.geometry is Some(geometry) else {
return @render.Rendered::failed("image/svg+xml", result.diagnostics[:])
}
geometry
}
}
let drawing = geometry.drawing()
let parents : Array[(String, String?)] = []
for node in view.nodes {
parents.push(
(node.id, node.groups.last().map(id => Some(id)).unwrap_or(node.lane)),
)
}
for note in view.notes {
parents.push(
(note.id, note.groups.last().map(id => Some(id)).unwrap_or(note.lane)),
)
}
for group in view.groups {
parents.push(
(group.id, group.parent.map(id => Some(id)).unwrap_or(group.lane)),
)
}
let rendered = paint_swimlane(
drawing.view,
theme,
mode,
id_prefix,
@swimlane_layout.Limits::new(
nodes=limits.nodes,
edges=limits.edges,
depth=limits.depth,
work=limits.work,
output_units=limits.output_units,
),
connectors~,
precomputed=geometry.drawing_result(),
kind="flowchart",
intentional_containment=geometry.intentional_containment()[:],
hidden_containers=geometry.hidden_containers()[:],
parent_overrides=parents[:],
)
let diagnostics = @flowchart_layout.diagnostics(
geometry
.prior_diagnostics()
.iter()
.concat(rendered.diagnostics.iter())
.to_array()[:],
)
match rendered.output {
Some(output) =>
@render.Rendered::ok(output, "image/svg+xml", diagnostics=diagnostics[:])
None => @render.Rendered::failed("image/svg+xml", diagnostics[:])
}
}
///|
/// Render a standalone flowchart using the shared themes and vector primitives.
pub fn render_flowchart(
view : @flowchart.Flowchart,
theme~ : @theme.Theme = @theme.Theme::classic(),
mode~ : Mode = Adaptive,
id_prefix? : String,
limits~ : @flowchart_layout.Limits = @flowchart_layout.Limits::new(),
connectors~ : ConnectorOptions = ConnectorOptions::new(),
) -> @render.Rendered {
paint_flowchart(view, theme, mode, id_prefix, limits, connectors~)
}
///|
pub fn flowchart_path(edge : @flowchart_layout.Connection) -> String {
let out = StringBuilder()
for i, p in edge.line {
out.write_string(
"\{if i == 0 { "M" } else { " L" }}\{@swimlane_layout.svg_number(p.x)} \{@swimlane_layout.svg_number(p.y)}",
)
}
out.to_string()
}