utf_railroad/
seq.rs

1use std::fmt;
2use crate::Node;
3
4pub struct Sequence {
5    pub(crate) nodes: Vec<Vec<Box<dyn Node>>>,
6    pub(crate) gap_size: usize,
7}
8
9impl Sequence {
10    pub fn new() -> Self {
11        Self::default()
12    }
13
14    pub fn push(mut self, node: Box<dyn Node>) -> Self {
15        let id = self.nodes.len() - 1;
16        self.nodes[id].push(node);
17        self
18    }
19
20    pub fn gap_size(mut self, size: usize) -> Self {
21        self.gap_size = size;
22        self
23    }
24
25    pub fn next_row(mut self) -> Self {
26        self.nodes.push(Vec::new());
27        self
28    }
29
30    pub fn num_rows(&self) -> usize {
31        self.nodes.len()
32    }
33}
34
35impl Default for Sequence {
36    fn default() -> Self {
37        Self {
38            nodes: vec![Vec::new()],
39            gap_size: 2,
40        }
41    }
42}
43
44impl Node for Sequence {
45    fn get_width(&self) -> usize {
46        let mut width = 0;
47        for row in &self.nodes {
48            let mut row_width = 0;
49            for n in row {
50                row_width += n.get_width();
51            }
52
53            if row.len() > 1 {
54                row_width += self.gap_size * (row.len() - 1);
55            }
56
57            width = row_width.max(width);
58        }
59
60        if self.nodes.len() > 1 { width += 3; }
61
62        width
63    }
64
65    fn get_height(&self) -> usize {
66        let mut height = 0;
67        for row in &self.nodes {
68            let mut row_height = 0;
69            for n in row {
70                row_height = n.get_height().max(row_height);
71            }
72
73            height += row_height;
74        }
75
76        if self.nodes.len() > 1 {
77            height += self.nodes.len() - 1;
78        }
79
80        height
81    }
82
83    fn as_str(&self) -> String {
84        let mut final_s = String::new();
85        let max_width = self.get_width() - if self.nodes.len() > 1 { 3 } else { 0 };
86
87        for row_n in 0..self.nodes.len() {
88            let row = &self.nodes[row_n];
89            let mut row_width = 0;
90            let mut widths = Vec::new();
91            let mut nodes_strs = Vec::new();
92            let mut height = 0;
93
94            for n in row {
95                let w = n.get_width();
96                let s = n.as_str();
97
98                height = n.get_height().max(height);
99                widths.push(w);
100                nodes_strs.push(s);
101                row_width += w;
102            }
103
104            if row.len() > 1 {
105                row_width += self.gap_size * (row.len() - 1);
106            }
107
108            let mut ret = String::new();
109
110            for y in 0..height {
111                if self.nodes.len() > 1 {
112                    ret += if row_n == 0 {
113                        if y == 1 { "─" } else { " " }
114                    } else {
115                        if y == 1 { "└" } else if y == 0 { "│" } else { " " }
116                    };
117                }
118
119                for i in 0..row.len() {
120                    let lines = nodes_strs[i].lines().collect::<Vec<_>>();
121
122                    if y < lines.len() {
123                        ret += lines[y];
124                    } else {
125                        for _ in 0..widths[i] {
126                            ret += " ";
127                        }
128                    }
129
130                    // add the seperation between nodes
131                    if i < row.len() - 1 {
132                        let sep = if y == 1 { "─" } else { " " };
133                        for _ in 0..self.gap_size { ret += sep; }
134                    }
135                }
136
137                for _ in row_width..max_width { ret += if y == 1 { "─" } else { " " }; }
138
139                if self.nodes.len() > 1 { 
140                    if row_n < self.nodes.len() - 1 {
141                        ret += if y == 0 { " " } else if y == 1 { "┐" } else { "│" };
142                    }
143
144                    ret += if row_n == 0 {
145                        if y == 1 { "┌" } else if y == 0 { " " } else { "│" }
146                    } else if row_n < self.nodes.len() - 1 {
147                        "│"
148                    } else {
149                        if y == 0 { " │" } else if y == 1 { "─┘" } else { "  " }
150                    };
151                }
152
153                if y < height - 1 { ret += "\n"; }
154            }
155
156            // migrate to next row
157            final_s += &ret;
158
159            if self.nodes.len() > 1 && row_n < self.nodes.len() - 1 {
160                final_s += "\n┌";
161                for _ in 0..max_width { final_s += "─"; }
162                final_s += "┘│\n";
163            }
164        }
165
166        final_s
167    }
168}
169
170impl fmt::Display for Sequence {
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        write!(f, "{}", self.as_str())
173    }
174}