fkl_dot/
graph.rs

1use std::fmt;
2use std::fmt::{Display, Formatter};
3
4use crate::edge::Edge;
5use crate::helper::config::indent;
6use crate::node::Node;
7use crate::subgraph::Subgraph;
8
9// use domain_derive::Entity;
10
11// #[derive(Entity)]
12pub struct Graph {
13  name: String,
14  nodes: Vec<Node>,
15  edges: Vec<Edge>,
16  node_styles: Vec<String>,
17  graph_style: Vec<String>,
18  subgraph: Vec<Subgraph>,
19}
20
21impl Graph {
22  pub fn new(name: &str) -> Self {
23    Graph {
24      name: name.to_string(),
25      nodes: Vec::new(),
26      edges: Vec::new(),
27      node_styles: vec![],
28      graph_style: vec![],
29      subgraph: Vec::new(),
30    }
31  }
32
33  pub fn add_node(&mut self, node: Node) {
34    self.nodes.push(node);
35  }
36
37  pub fn add_edge(&mut self, source: &str, target: &str) {
38    self.edges.push(Edge::new(source.to_string(), target.to_string()));
39  }
40
41  pub fn add_subgraph(&mut self, subgraph: Subgraph) {
42    self.subgraph.push(subgraph);
43  }
44
45  pub fn set_name(&mut self, name: &str) {
46    self.name = name.to_string();
47  }
48
49  pub fn add_node_style(&mut self, style: &str) {
50    self.node_styles.push(style.to_string());
51  }
52
53  pub(crate) fn set_shape(&mut self, shape: &str) {
54    self.add_node_style(&format!("shape={}", shape));
55  }
56
57  pub fn add_edge_with_style(&mut self, source: &str, target: &str, style: Vec<String>) {
58    self.edges.push(Edge::styled(source.to_string(), target.to_string(), style));
59  }
60
61  pub(crate) fn set_style(&mut self, style: &str) {
62    self.add_node_style(&format!("style={}", style));
63  }
64
65  pub fn use_default_style(&mut self) {
66    self.set_shape("box");
67    self.set_style("filled");
68
69    self.graph_style.push("component=true".to_string());
70    self.graph_style.push("layout=fdp".to_string());
71  }
72}
73
74impl Display for Graph {
75  fn fmt(&self, out: &mut Formatter<'_>) -> fmt::Result {
76    let space = indent(1);
77    out.write_str(&format!("digraph {} {{\n", self.name))?;
78
79    if !self.graph_style.is_empty() {
80      out.write_str(&format!("{}{};\n", space, self.graph_style.join(";")))?;
81    }
82
83    if !self.node_styles.is_empty() {
84      out.write_str(&format!("{}node [{}];\n", space, self.node_styles.join(" ")))?;
85    }
86
87    for node in &self.nodes {
88      out.write_str(&format!("{}{}\n", space, node))?
89    }
90
91    for edge in &self.edges {
92      out.write_str(&format!("{}{}\n", space, edge))?
93    }
94
95    for subgraph in &self.subgraph {
96      out.write_str(&format!("\n{}\n", subgraph))?
97    }
98
99    out.write_str("}")
100  }
101}