use crate::text_buffer::{Color, TextBuffer, TextStyle};
pub struct BorderChars {
pub top_left: char,
pub bottom_left: char,
pub top_right: char,
pub bottom_right: char,
pub vertical_line: char,
pub horizontal_line: char,
pub top_split: char,
pub bottom_split: char,
pub left_split: char,
pub right_split: char,
pub middle_split: char,
}
impl BorderChars {
pub fn empty() -> BorderChars {
BorderChars {
top_left: ' ',
bottom_left: ' ',
top_right: ' ',
bottom_right: ' ',
vertical_line: ' ',
horizontal_line: ' ',
top_split: ' ',
bottom_split: ' ',
left_split: ' ',
right_split: ' ',
middle_split: ' ',
}
}
}
impl Default for BorderChars {
fn default() -> BorderChars {
BorderChars {
top_left: '╔',
bottom_left: '╚',
top_right: '╗',
bottom_right: '╝',
vertical_line: '║',
horizontal_line: '═',
top_split: '╦',
bottom_split: '╩',
left_split: '╠',
right_split: '╣',
middle_split: '╬',
}
}
}
pub struct Window {
x: u32,
y: u32,
vertical_splits: Vec<u32>,
horizontal_splits: Vec<u32>,
pub width: u32,
pub height: u32,
pub title: String,
pub border_style: TextStyle,
pub border_chars: BorderChars,
pub background_color: Color,
}
impl Window {
pub fn new(width: u32, height: u32) -> Window {
Window {
x: 0,
y: 0,
vertical_splits: Vec::new(),
horizontal_splits: Vec::new(),
width: width.max(1),
height: height.max(1),
title: String::new(),
border_style: Default::default(),
border_chars: Default::default(),
background_color: [0.0; 4],
}
}
pub fn with_pos(mut self, position: (u32, u32)) -> Window {
let (x, y) = position;
self.x = x;
self.y = y;
self
}
pub fn with_width(mut self, width: u32) -> Window {
self.width = width;
self
}
pub fn with_height(mut self, height: u32) -> Window {
self.height = height;
self
}
pub fn with_title<T: Into<String>>(mut self, title: T) -> Window {
self.title = title.into();
self
}
pub fn with_border_color(mut self, style: TextStyle) -> Window {
self.border_style = style;
self
}
pub fn with_background_color(mut self, color: Color) -> Window {
self.background_color = color;
self
}
pub fn with_vertical_split(mut self, split_index: u32) -> Window {
self.add_vertical_split(split_index);
self
}
pub fn with_horizontal_split(mut self, split_index: u32) -> Window {
self.add_horizontal_split(split_index);
self
}
pub fn set_pos(&mut self, position: (u32, u32)) {
let (x, y) = position;
self.x = x;
self.y = y;
}
pub fn add_vertical_split(&mut self, split_index: u32) {
let split_index = split_index.max(0).min(self.width);
if !self.vertical_splits.contains(&split_index) {
self.vertical_splits.push(split_index);
}
}
pub fn add_horizontal_split(&mut self, split_index: u32) {
let split_index = split_index.max(0).min(self.height);
if !self.horizontal_splits.contains(&split_index) {
self.horizontal_splits.push(split_index);
}
}
pub fn draw(&self, text_buffer: &mut TextBuffer) {
let empty_style = TextStyle {
bg_color: self.background_color,
..Default::default()
};
for y in 0..(self.height + 2) {
text_buffer.cursor.move_to(self.x, self.y + y);
for x in 0..(self.width + 2) {
text_buffer.cursor.style = self.border_style;
if x == 0 {
if y == 0 {
text_buffer.put_char(self.border_chars.top_left);
} else if self.h_split(y) {
text_buffer.put_char(self.border_chars.left_split);
} else if y == self.height + 1 {
text_buffer.put_char(self.border_chars.bottom_left);
} else {
text_buffer.put_char(self.border_chars.vertical_line);
}
} else if y == 0 {
if self.v_split(x) {
text_buffer.put_char(self.border_chars.top_split);
} else if x == self.width + 1 {
text_buffer.put_char(self.border_chars.top_right);
} else {
text_buffer.put_char(self.border_chars.horizontal_line);
}
} else if x == self.width + 1 && y == self.height + 1 {
text_buffer.put_char(self.border_chars.bottom_right);
} else if x == self.width + 1 {
if self.h_split(y) {
text_buffer.put_char(self.border_chars.right_split);
} else {
text_buffer.put_char(self.border_chars.vertical_line);
}
} else if y == self.height + 1 {
if self.v_split(x) {
text_buffer.put_char(self.border_chars.bottom_split);
} else {
text_buffer.put_char(self.border_chars.horizontal_line);
}
} else if self.h_split(y) {
if self.v_split(x) {
text_buffer.put_char(self.border_chars.middle_split);
} else {
text_buffer.put_char(self.border_chars.horizontal_line);
}
} else if self.v_split(x) {
text_buffer.put_char(self.border_chars.vertical_line);
} else {
text_buffer.cursor.style = empty_style;
text_buffer.put_char(' ');
}
}
}
text_buffer.cursor.move_to(self.x + 1, self.y);
text_buffer.cursor.style = self.border_style;
text_buffer.write(
self.title
.chars()
.take(self.width as usize)
.collect::<String>(),
);
}
pub fn set_limits(&self, text_buffer: &mut TextBuffer) {
text_buffer.cursor.set_limits(
Some(self.x),
Some(self.x + self.width + 1),
Some(self.y),
Some(self.y + self.height + 1),
);
}
fn v_split(&self, idx: u32) -> bool {
self.vertical_splits.contains(&idx)
}
fn h_split(&self, idx: u32) -> bool {
self.horizontal_splits.contains(&idx)
}
}