diff options
| author | hachem <im@hachem.wtf> | 2024-09-29 18:45:29 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2024-09-29 18:45:29 +0200 |
| commit | 53314e6154760c20b0d17ea206bfa084ed911e81 (patch) | |
| tree | 7fad21982e4326941f065165dc4f684239407f1e | |
| parent | 88ae20ff8254dd60c3de252e49369d4125f9e1a2 (diff) | |
Line connections and nodes
| -rw-r--r-- | libpsi-visualizer/src/cli/horizontal_cli.rs | 12 | ||||
| -rw-r--r-- | libpsi-visualizer/src/cli/renderer.rs | 236 |
2 files changed, 220 insertions, 28 deletions
diff --git a/libpsi-visualizer/src/cli/horizontal_cli.rs b/libpsi-visualizer/src/cli/horizontal_cli.rs index 151dae1..7c9a242 100644 --- a/libpsi-visualizer/src/cli/horizontal_cli.rs +++ b/libpsi-visualizer/src/cli/horizontal_cli.rs @@ -31,15 +31,11 @@ impl<'a> Visualizer<'a> for HorizontalCLIVisualizer<'a> { } fn render(&mut self) { - self.renderer.draw_quad(Quad::new(2, 2, 2, 2), false); - self.renderer.draw_quad(Quad::new(5, 10, 6, 3), true); - self.renderer.draw_quad(Quad::new(17, 4, 17, 10), true); - self.renderer.draw_quad(Quad::new(15, 7, 7, 4), false); + let quad = Quad::new(2, 2, 5, 5); + let point = (10usize, 0usize); - self.renderer.draw_vline(4, 4, 5, true); - self.renderer.draw_hline(3, 6, 5, false); - - self.renderer.draw_text(4, 15, "This is some text."); + self.renderer.draw_quad(quad, false); + self.renderer.connect(quad, point); println!("{}", self.renderer.to_string()); } } diff --git a/libpsi-visualizer/src/cli/renderer.rs b/libpsi-visualizer/src/cli/renderer.rs index d95d609..ba5a28b 100644 --- a/libpsi-visualizer/src/cli/renderer.rs +++ b/libpsi-visualizer/src/cli/renderer.rs @@ -1,3 +1,4 @@ +#[derive(Clone, Copy)] pub struct Quad { pub x: usize, pub y: usize, @@ -27,16 +28,7 @@ impl CLIRenderer { } } - pub fn to_string(&self) -> String { - self.buffer - .clone() - .into_iter() - .map(|inner| inner.into_iter().collect::<String>()) - .collect::<Vec<String>>() - .join("\n") - } - - pub fn place(&mut self, x: usize, y: usize, character: char) { + fn expand(&mut self, x: usize, y: usize) { if y >= self.buffer.len() { self.buffer.resize( y + 1, @@ -47,30 +39,37 @@ impl CLIRenderer { if x >= self.buffer[y].len() { self.buffer[y].resize(x + 1, ' '); } + } + + pub fn to_string(&self) -> String { + self.buffer + .clone() + .into_iter() + .map(|inner| inner.into_iter().collect::<String>()) + .collect::<Vec<String>>() + .join("\n") + } + + pub fn place(&mut self, x: usize, y: usize, character: char) { + self.expand(x, y); self.buffer[y][x] = character; } pub fn get(&mut self, x: usize, y: usize) -> char { - if y >= self.buffer.len() { - self.buffer.resize( - y + 1, - vec![' '; self.buffer.get(0).map_or(0, |row| row.len())], - ); - } - - if x >= self.buffer[y].len() { - self.buffer[y].resize(x + 1, ' '); - } + self.expand(x, y); self.buffer[y][x] } pub fn draw_text(&mut self, x: usize, y: usize, text: &'static str) { + self.expand(x + text.len(), y); for i in 0..text.len() { self.place(x + i, y, text.as_bytes()[i].into()); } } pub fn draw_vline(&mut self, x: usize, y: usize, height: usize, thick: bool) { + self.expand(x, y + height); + for i in y..y + height { if self.get(x, i) == '─' { self.place(x, i, if thick { '╫' } else { '┼' }); @@ -83,6 +82,8 @@ impl CLIRenderer { } pub fn draw_hline(&mut self, x: usize, y: usize, width: usize, thick: bool) { + self.expand(x + width, y); + for i in x..x + width { if self.get(i, y) == '│' { self.place(i, y, if thick { '╪' } else { '┼' }); @@ -95,6 +96,8 @@ impl CLIRenderer { } pub fn draw_quad(&mut self, quad: Quad, thick: bool) { + self.expand(quad.x + quad.width, quad.y + quad.height); + for x in quad.x..quad.x + quad.width { for y in quad.y..quad.y + quad.height { if x == quad.x && y == quad.y { @@ -113,4 +116,197 @@ impl CLIRenderer { } } } + + pub fn connect(&mut self, quad: Quad, point: (usize, usize)) { + enum Directions { + Bottom, + BottomLeft, + BottomRight, + + Top, + TopLeft, + TopRight, + + Right, + Left, + None, + } + + let center_x = (((quad.x + quad.width) as f32 / 2.0).ceil()) as usize; + let center_y = (((quad.y + quad.height) as f32 / 2.0).ceil()) as usize; + + let point_x = point.0; + let point_y = point.1; + + let mut edge_midpoint_x = 0usize; + let mut edge_midpoint_y = 0usize; + + let line_midpoint_x = center_x; + let line_midpoint_y = point_y; + + let mut direction = Directions::None; + + if point_y > center_y && point_x == center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y + quad.height - 1; + direction = Directions::Bottom; + } else if point_y > center_y && point_x < center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y + quad.height - 1; + direction = Directions::BottomLeft; + } else if point_y > center_y && point_x > center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y + quad.height - 1; + direction = Directions::BottomRight; + } else if point_y < center_y && point_x == center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y; + direction = Directions::Top; + } else if point_y < center_y && point_x < center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y; + direction = Directions::TopLeft; + } else if point_y < center_y && point_x > center_x { + edge_midpoint_x = center_x; + edge_midpoint_y = quad.y; + direction = Directions::TopRight; + } else if point_x > center_x && point_y == center_y { + edge_midpoint_x = quad.x + quad.width - 1; + edge_midpoint_y = center_y; + direction = Directions::Right; + } else if point_x < center_x && point_y == center_y { + edge_midpoint_x = quad.x; + edge_midpoint_y = center_y; + + direction = Directions::Left; + } + + match direction { + Directions::Bottom | Directions::BottomRight | Directions::BottomLeft => { + let character = self.get(edge_midpoint_x, edge_midpoint_y); + self.place( + edge_midpoint_x, + edge_midpoint_y, + if character == '─' { '┬' } else { '╤' }, + ); + } + + Directions::Top | Directions::TopRight | Directions::TopLeft => { + let character = self.get(edge_midpoint_x, edge_midpoint_y); + self.place( + edge_midpoint_x, + edge_midpoint_y, + if character == '─' { '┴' } else { '╧' }, + ); + } + + Directions::Right => { + let character = self.get(edge_midpoint_x, edge_midpoint_y); + self.place( + edge_midpoint_x, + edge_midpoint_y, + if character == '│' { '├' } else { '╟' }, + ); + } + + Directions::Left => { + let character = self.get(edge_midpoint_x, edge_midpoint_y); + self.place( + edge_midpoint_x, + edge_midpoint_y, + if character == '│' { '┤' } else { '╢' }, + ); + } + + Directions::None => {} + } + + match direction { + Directions::Top => { + self.draw_vline(edge_midpoint_x, point_y, edge_midpoint_y - point_y, false); + } + + Directions::Bottom => { + self.draw_vline( + edge_midpoint_x, + edge_midpoint_y + 1, + point_y - edge_midpoint_y - 1, + false, + ); + } + + Directions::Right => { + self.draw_hline( + edge_midpoint_x + 1, + edge_midpoint_y, + point_x - edge_midpoint_x - 1, + false, + ); + } + + Directions::Left => { + self.draw_hline( + point_x + 1, + edge_midpoint_y, + edge_midpoint_x - point_x - 1, + false, + ); + } + + Directions::BottomRight => { + self.place(line_midpoint_x, line_midpoint_y, '└'); + self.draw_hline( + line_midpoint_x + 1, + line_midpoint_y, + point_x - line_midpoint_x - 1, + false, + ); + self.draw_vline( + edge_midpoint_x, + edge_midpoint_y + 1, + point_y - edge_midpoint_y - 1, + false, + ); + } + Directions::BottomLeft => { + self.place(line_midpoint_x, line_midpoint_y, '┘'); + self.draw_hline(point_x, point_y, line_midpoint_x - point_x, false); + self.draw_vline( + edge_midpoint_x, + edge_midpoint_y + 1, + point_y - edge_midpoint_y - 1, + false, + ); + } + Directions::TopRight => { + self.place(line_midpoint_x, line_midpoint_y, '┌'); + self.draw_hline( + line_midpoint_x + 1, + line_midpoint_y, + point_x - line_midpoint_x - 1, + false, + ); + + self.draw_vline( + edge_midpoint_x, + point_y + 1, + edge_midpoint_y - point_y - 1, + false, + ); + } + Directions::TopLeft => { + self.place(line_midpoint_x, line_midpoint_y, '┐'); + self.draw_hline(point_x, point_y, line_midpoint_x - point_x, false); + self.draw_vline( + edge_midpoint_x, + point_y + 1, + edge_midpoint_y - point_y - 1, + false, + ); + } + _ => {} + } + + self.place(point_x, point_y, '■'); + } } |
