use std::rc::Rc;
use svg::node::element as svg_element;
use crate::{
draw::{Drawable, LayeredOutput, RenderLayer, StrokeDefinition},
geometry::{Point, Size},
};
#[derive(Debug, Clone)]
pub struct LifelineDefinition {
stroke: Rc<StrokeDefinition>,
}
impl LifelineDefinition {
pub fn new(stroke: Rc<StrokeDefinition>) -> Self {
Self { stroke }
}
pub fn stroke(&self) -> &Rc<StrokeDefinition> {
&self.stroke
}
pub fn set_stroke(&mut self, stroke: Rc<StrokeDefinition>) {
self.stroke = stroke;
}
}
impl Default for LifelineDefinition {
fn default() -> Self {
Self {
stroke: Rc::new(StrokeDefinition::default_dashed()),
}
}
}
#[derive(Debug, Clone)]
pub struct Lifeline {
definition: Rc<LifelineDefinition>,
height: f32,
}
impl Lifeline {
pub fn new(definition: Rc<LifelineDefinition>, height: f32) -> Self {
Self { definition, height }
}
}
impl Drawable for Lifeline {
fn render_to_layers(&self, position: Point) -> LayeredOutput {
let mut output = LayeredOutput::new();
let line = svg_element::Line::new()
.set("x1", position.x())
.set("y1", position.y())
.set("x2", position.x())
.set("y2", position.y() + self.height)
.set("fill-opacity", self.definition.stroke().color().alpha());
let line = crate::apply_stroke!(line, self.definition.stroke());
output.add_to_layer(RenderLayer::Lifeline, Box::new(line));
output
}
fn size(&self) -> Size {
Size::new(self.definition.stroke().width(), self.height)
}
}
#[cfg(test)]
mod tests {
use float_cmp::assert_approx_eq;
use super::*;
use crate::draw::StrokeStyle;
#[test]
fn test_lifeline_definition_new() {
let custom_stroke = Rc::new(StrokeDefinition::default_solid());
let def = LifelineDefinition::new(custom_stroke);
assert_eq!(*def.stroke().style(), StrokeStyle::Solid);
assert_approx_eq!(f32, def.stroke().width(), 2.0);
}
#[test]
fn test_lifeline_definition_set_stroke() {
let mut def = LifelineDefinition::default();
assert_eq!(*def.stroke().style(), StrokeStyle::Dashed);
let new_stroke = Rc::new(StrokeDefinition::default_solid());
def.set_stroke(new_stroke);
assert_eq!(*def.stroke().style(), StrokeStyle::Solid);
assert_approx_eq!(f32, def.stroke().width(), 2.0);
}
#[test]
fn test_lifeline_size() {
let def = Rc::new(LifelineDefinition::default());
let lifeline = Lifeline::new(def, 100.0);
let size = lifeline.size();
assert_approx_eq!(f32, size.width(), 1.0);
assert_approx_eq!(f32, size.height(), 100.0);
}
#[test]
fn test_lifeline_render_to_layers() {
let def = Rc::new(LifelineDefinition::default());
let lifeline = Lifeline::new(def, 200.0);
let output = lifeline.render_to_layers(Point::new(50.0, 10.0));
assert!(!output.is_empty());
}
}