Skip to main content

dendryform_core/
container.rs

1//! Container type for nested sub-diagrams.
2
3use std::fmt;
4
5use serde::{Deserialize, Serialize};
6
7use crate::color::Color;
8use crate::layer::Layer;
9
10/// The border style of a container.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13#[non_exhaustive]
14pub enum ContainerBorder {
15    /// Rounded solid border, opaque background.
16    Solid,
17    /// Dashed border, tinted background matching label color.
18    Dashed,
19}
20
21impl fmt::Display for ContainerBorder {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            Self::Solid => f.write_str("solid"),
25            Self::Dashed => f.write_str("dashed"),
26        }
27    }
28}
29
30/// A bordered box with a floating label that contains nested layers.
31///
32/// Used for server boundaries, subsystem groupings, etc. Containers
33/// nest recursively — a tier inside a container can itself have a container.
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub struct Container {
37    label: String,
38    border: ContainerBorder,
39    label_color: Color,
40    layers: Vec<Layer>,
41}
42
43impl Container {
44    /// Creates a new container.
45    pub fn new(
46        label: &str,
47        border: ContainerBorder,
48        label_color: Color,
49        layers: Vec<Layer>,
50    ) -> Self {
51        Self {
52            label: label.to_owned(),
53            border,
54            label_color,
55            layers,
56        }
57    }
58
59    /// Returns the floating label text.
60    pub fn label(&self) -> &str {
61        &self.label
62    }
63
64    /// Returns the border style.
65    pub fn border(&self) -> ContainerBorder {
66        self.border
67    }
68
69    /// Returns the label color.
70    pub fn label_color(&self) -> Color {
71        self.label_color
72    }
73
74    /// Returns the nested layers.
75    pub fn layers(&self) -> &[Layer] {
76        &self.layers
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_border_display() {
86        assert_eq!(format!("{}", ContainerBorder::Solid), "solid");
87        assert_eq!(format!("{}", ContainerBorder::Dashed), "dashed");
88    }
89
90    #[test]
91    fn test_serde_border() {
92        let border = ContainerBorder::Dashed;
93        let json = serde_json::to_string(&border).unwrap();
94        assert_eq!(json, "\"dashed\"");
95    }
96}