aboutsummaryrefslogtreecommitdiff
path: root/libpsi-visualizer/src/cli/renderer.rs
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2024-09-29 18:45:29 +0200
committerhachem <im@hachem.wtf>2024-09-29 18:45:29 +0200
commit53314e6154760c20b0d17ea206bfa084ed911e81 (patch)
tree7fad21982e4326941f065165dc4f684239407f1e /libpsi-visualizer/src/cli/renderer.rs
parent88ae20ff8254dd60c3de252e49369d4125f9e1a2 (diff)
Line connections and nodes
Diffstat (limited to 'libpsi-visualizer/src/cli/renderer.rs')
-rw-r--r--libpsi-visualizer/src/cli/renderer.rs236
1 files changed, 216 insertions, 20 deletions
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, '■');
+ }
}