use crate::VectorGrid;
const BOARDER_ROOF: (&str, &str, &str) = (" ", "_", " ");
const BOARDER_WALL: (&str, &str) = ("│", "│");
const BOARDER_FLOOR: (&str, &str, &str) = (" ", "‾", " ");
const BOARDER_CORNER: (&str, &str) = ("│", " ");
pub trait VectorGridItemDisplay {
fn display_str(&self) -> String;
}
#[derive(Default, Clone)]
pub enum UnicodeShadeItemDisplay {
#[default]
Empty,
Light,
Medium,
Dark,
Full,
}
impl VectorGridItemDisplay for UnicodeShadeItemDisplay {
fn display_str(&self) -> String {
match self {
UnicodeShadeItemDisplay::Empty => " ",
UnicodeShadeItemDisplay::Light => "░░",
UnicodeShadeItemDisplay::Medium => "▒▒",
UnicodeShadeItemDisplay::Dark => "▓▓",
UnicodeShadeItemDisplay::Full => "██",
}.to_string()
}
}
impl VectorGridItemDisplay for bool {
fn display_str(&self) -> String {
if *self {
"██".to_string()
} else {
"░░".to_string()
}
}
}
impl VectorGridItemDisplay for u8 {
fn display_str(&self) -> String {
self.to_string()
}
}
impl<T: VectorGridItemDisplay> VectorGridItemDisplay for Option<T> {
fn display_str(&self) -> String {
match self {
Some(some) => {
some.display_str()
}
None => {
String::new()
}
}
}
}
fn display_lines_2d<ItemType: VectorGridItemDisplay>(items: &[ItemType], width: usize, thickness: usize) -> Vec<String> {
let mut item_display_boundries = [0; 2];
let display_items: Vec<String> = items.iter().map(|item| {
let string = item.display_str();
let mut height = 0;
for line in string.lines() {
let length = line.chars().count();
if length > item_display_boundries[0] {
item_display_boundries[0] = length;
}
height += 1
}
if height > item_display_boundries[1] {
item_display_boundries[1] = height;
}
string
}).collect();
let mut output = vec![[" ".repeat(thickness).as_str(), BOARDER_ROOF.0, &BOARDER_ROOF.1.repeat(width * item_display_boundries[0]), BOARDER_ROOF.2].concat()];
for layer in 1..=thickness {
output.push([
" ".repeat(thickness - layer + 1),
["̲╱", &"_".repeat(item_display_boundries[0].max(1) - 1)].concat().repeat(width),
"╱".to_string(),
"│".repeat(layer)
].concat())
}
let mut print_lines = Vec::new();
for (i, item) in display_items.iter().enumerate() {
if i % width == 0 {
print_lines = vec![String::from(BOARDER_WALL.0); item_display_boundries[1]]
}
let item_lines: Vec<&str> = item.lines().collect();
for (i, print_line) in print_lines.iter_mut().enumerate() {
print_line.push_str(&format!("{:width$}", item_lines.get(i).unwrap_or(&""), width = item_display_boundries[0]));
}
if (i + 1) % width == 0 {
let mut perspective = (display_items.len() / width - i / width) * item_display_boundries[1];
for line in print_lines.iter() {
perspective -= 1;
let side = if perspective < thickness {
[BOARDER_WALL.1.repeat(perspective + 1), "╱".to_string()].concat()
} else {
BOARDER_WALL.1.repeat(thickness + 1)
};
output.push([line.as_str(), &side].concat());
}
}
}
let floor_width = (((items.len() - 1) % width) + 1) * item_display_boundries[0];
let floor_gap = width * item_display_boundries[0] - floor_width;
if floor_gap != 0 {
for (i, print_line) in print_lines.iter().enumerate() {
let y = item_display_boundries[1] - i - 1;
let mut side = if y < thickness {
[BOARDER_WALL.1.repeat(y + 1), "╱".to_string()].concat()
} else {
BOARDER_WALL.1.repeat(thickness + 1)
};
if i == 0 {
side.push_str(&[&BOARDER_FLOOR.1.repeat(floor_gap - side.chars().count()), BOARDER_CORNER.1].concat());
}
output.push([print_line.as_str(), &side].concat());
}
}
output.push([BOARDER_FLOOR.0, &BOARDER_FLOOR.1.repeat(floor_width), BOARDER_FLOOR.2].concat());
output
}
impl<ItemType: VectorGridItemDisplay> VectorGrid<ItemType> {
pub fn print(&self) {
println!("VectorGrid: Shape [{}]", self.shape());
if self.defined_shape.len() == 1 {
for line in display_lines_2d(&self.items, self.defined_shape[0].get(), 0) {
println!("{:length$}", line, length = 50)
}
} else if self.defined_shape.len() == 2 {
let step_size = self.defined_shape[0].get() * self.defined_shape[1].get();
let mut i = 0;
while i < self.items.len() {
for line in display_lines_2d(&self.items[i..(i + step_size).min(self.items.len())], self.defined_shape[0].get(), self.items.len() / step_size) {
println!("{:length$}", line, length = 50)
}
i += step_size
}
}
}
}