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
9pub 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}