use svg::node::element as svg_element;
pub type SvgNode = Box<dyn svg::Node>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RenderLayer {
Background,
Lifeline,
Content,
Activation,
Fragment,
Note,
Arrow,
Text,
}
impl RenderLayer {
pub fn name(&self) -> &'static str {
match self {
Self::Background => "background",
Self::Lifeline => "lifeline",
Self::Content => "content",
Self::Activation => "activation",
Self::Fragment => "fragment",
Self::Note => "note",
Self::Arrow => "arrow",
Self::Text => "text",
}
}
}
#[derive(Debug, Default)]
pub struct LayeredOutput {
items: Vec<(RenderLayer, SvgNode)>,
}
impl LayeredOutput {
pub fn new() -> Self {
Self::default()
}
pub fn add_to_layer(&mut self, layer: RenderLayer, node: SvgNode) {
self.items.push((layer, node));
}
pub fn merge(&mut self, other: LayeredOutput) {
self.items.extend(other.items);
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn render(mut self) -> Vec<SvgNode> {
if self.is_empty() {
return Vec::new();
}
self.items.sort_by_key(|(layer, _)| *layer);
let mut result = Vec::new();
let mut current_layer = self.items[0].0;
let mut current_group = svg_element::Group::new().set("data-layer", current_layer.name());
for (layer, node) in self.items {
if layer != current_layer {
result.push(Box::new(current_group) as SvgNode);
current_layer = layer;
current_group = svg_element::Group::new().set("data-layer", layer.name());
}
current_group = current_group.add(node);
}
result.push(Box::new(current_group) as SvgNode);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use svg::node::element::Rectangle;
#[test]
fn test_layered_output_new() {
let output = LayeredOutput::new();
assert!(output.is_empty());
}
#[test]
fn test_layered_output_add_to_layer() {
let mut output = LayeredOutput::new();
assert!(output.is_empty());
let rect = Rectangle::new();
output.add_to_layer(RenderLayer::Content, Box::new(rect));
assert!(!output.is_empty());
}
#[test]
fn test_layered_output_merge() {
let mut output1 = LayeredOutput::new();
output1.add_to_layer(RenderLayer::Content, Box::new(Rectangle::new()));
let mut output2 = LayeredOutput::new();
output2.add_to_layer(RenderLayer::Note, Box::new(Rectangle::new()));
output1.merge(output2);
assert!(!output1.is_empty());
let nodes = output1.render();
assert_eq!(nodes.len(), 2);
}
#[test]
fn test_layered_output_is_empty() {
let mut output = LayeredOutput::new();
assert!(output.is_empty());
output.add_to_layer(RenderLayer::Content, Box::new(Rectangle::new()));
assert!(!output.is_empty());
}
#[test]
fn test_layered_output_render() {
let mut output = LayeredOutput::new();
output.add_to_layer(RenderLayer::Content, Box::new(Rectangle::new()));
output.add_to_layer(RenderLayer::Note, Box::new(Rectangle::new()));
output.add_to_layer(RenderLayer::Text, Box::new(Rectangle::new()));
let svg_nodes = output.render();
assert_eq!(svg_nodes.len(), 3);
}
#[test]
fn test_layered_output_merge_same_layer() {
let mut output1 = LayeredOutput::new();
output1.add_to_layer(RenderLayer::Content, Box::new(Rectangle::new()));
let mut output2 = LayeredOutput::new();
output2.add_to_layer(RenderLayer::Content, Box::new(Rectangle::new()));
output1.merge(output2);
let nodes = output1.render();
assert_eq!(nodes.len(), 1);
}
}