From 1d18cd17158ca18e92f65630bdf32a67985bc0ba Mon Sep 17 00:00:00 2001 From: Maddie <32415621+SpyHoodle@users.noreply.github.com> Date: Fri, 11 Nov 2022 11:15:33 +0000 Subject: [PATCH] reverted oop changes --- src/main.rs | 3 +- src/terminal/mod.rs | 1 + src/terminal/screen.rs | 4 +- src/terminal/tui.rs | 131 ++++++++++++++++++++++++++++++++ src/tui/components/mod.rs | 2 - src/tui/components/statusbar.rs | 74 ------------------ src/tui/components/welcome.rs | 62 --------------- src/tui/mod.rs | 3 - src/tui/ui.rs | 79 ------------------- src/tui/utils.rs | 14 ---- 10 files changed, 135 insertions(+), 238 deletions(-) create mode 100644 src/terminal/tui.rs delete mode 100644 src/tui/components/mod.rs delete mode 100644 src/tui/components/statusbar.rs delete mode 100644 src/tui/components/welcome.rs delete mode 100644 src/tui/mod.rs delete mode 100644 src/tui/ui.rs delete mode 100644 src/tui/utils.rs diff --git a/src/main.rs b/src/main.rs index c3e961d..108ccaa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,8 @@ mod core; mod terminal; -mod tui; fn main() { let lambda = core::editor::Editor::new(); let mut screen = terminal::screen::Screen::new().unwrap(); - tui::ui::Ui::run(&mut screen, lambda); + terminal::tui::start(&mut screen, lambda); } diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs index 63ac656..a865f33 100644 --- a/src/terminal/mod.rs +++ b/src/terminal/mod.rs @@ -1 +1,2 @@ pub mod screen; +pub mod tui; diff --git a/src/terminal/screen.rs b/src/terminal/screen.rs index c880a83..2d32374 100644 --- a/src/terminal/screen.rs +++ b/src/terminal/screen.rs @@ -11,7 +11,7 @@ pub struct Coords { pub y: usize, } -// Creating a set of coordinates from two values +// Creating a coordinates from two values impl Coords { pub fn from(x: usize, y: usize) -> Self { Self { x, y } @@ -146,7 +146,7 @@ impl Screen { execute!(stdout(), Print(text)).unwrap(); } - pub fn write_at(&mut self, text: &String, position: Coords) { + pub fn write_at(&mut self, text: String, position: Coords) { // Writes a line at a set of coordinates self.cursor.move_to(position); Screen::write(&text); diff --git a/src/terminal/tui.rs b/src/terminal/tui.rs new file mode 100644 index 0000000..a939730 --- /dev/null +++ b/src/terminal/tui.rs @@ -0,0 +1,131 @@ +use crate::core::editor::Editor; +use crate::terminal::screen::{Coords, Screen}; +use crossterm::style::Stylize; +use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; + +// Utils +fn with_spaces(text: &str) -> String { + format!(" {} ", text) +} +fn calc_x(screen_width: usize, item_length: usize) -> usize { + (screen_width / 2) - (item_length / 2) +} +fn longest_element_in_array(elements: Vec<&str>) -> usize { + elements.iter().max_by_key(|x: &&&str| x.len()).unwrap().len() +} + +pub fn draw_status(screen: &mut Screen, editor: &Editor) -> Result<(), ()> { + // Calculate where to draw the status bar + let status_height = screen.size.height - 2; + + // Get the editor logo from the config + let editor_logo = &with_spaces(editor.config.logo) as &str; + // Get the current mode into a string + let mode_string = &with_spaces(editor.mode.as_str()) as &str; + // Get the current open file name + let file_name = &with_spaces(editor.buffer.name) as &str; + + // Calculate the total length of all the status bar components + let total_length = editor_logo.len() + mode_string.len() + file_name.len() + 1; + + // If the screen isn't wide enough, panic as we can't draw the status bar + if screen.size.width < total_length { + Err(()) + + } else { + // Write the editor logo + screen.write_at( + editor_logo.yellow().bold().reverse().to_string(), + Coords::from(0, status_height), + ); + + // Calculate where to write the current mode + let x = editor_logo.len() - 1; + // Write the current mode + screen.write_at( + mode_string.green().bold().reverse().to_string(), + Coords::from(x, status_height), + ); + // Calculate where to write the file name + let x = x + mode_string.len(); + // Write the current file name + screen.write_at( + file_name.magenta().bold().reverse().to_string(), + Coords::from(x, status_height), + ); + + // Draw the rest of the status bar + let x = x + file_name.len(); + screen.write_at( + " ".repeat(screen.size.width - x).reverse().to_string(), + Coords::from(x, status_height), + ); + + Ok(()) + } +} + +pub fn draw_welcome(screen: &mut Screen, editor: &Editor) { + // The welcome message + let title = format!("{} {}", editor.config.logo, editor.config.friendly_name); + let message: [&str; 5] = [ + "Hackable text editor for nerds", + "", + "Type :help to open the README.md document", + "Type :o to open a file and edit", + "Type :q! or to quit lambda", + ]; + + // If the screen is big enough, we can draw + if screen.size.width > longest_element_in_array(message.to_vec()) && screen.size.height > message.len() + 4 { + // The starting y position in the centre of the screen + let mut y = (screen.size.height / 2) - (message.len() / 2) - 2; + + // Calculate where to place the title + let x = calc_x(screen.size.width, title.len()); + + // Write the title to the screen + screen.write_at(title.yellow().to_string(), Coords::from(x, y)); + + for line in message { + // Each line has different width so requires a different x position to center it + let x = calc_x(screen.size.width, line.len()) ; + + // For each line we move downwards so increment y + y += 1; + + // Write the line to the screen at position (x, y) + screen.write_at(line.to_string(), Coords::from(x, y)); + } + } +} + +pub fn start(screen: &mut Screen, editor: Editor) { + loop { + // Refresh the screen + screen.refresh().unwrap(); + + // Draw the welcome message + draw_welcome(screen, &editor); + + // Draw the status bar + draw_status(screen, &editor).unwrap(); + + // Check for any key presses + match read().unwrap() { + Event::Key(KeyEvent { + code: KeyCode::Char('q'), + modifiers: KeyModifiers::CONTROL, + .. + }) => break, + Event::Key(KeyEvent { + code: KeyCode::Char('c'), + modifiers: KeyModifiers::CONTROL, + .. + }) => break, + _ => (), + } + } + + screen.exit(); +} diff --git a/src/tui/components/mod.rs b/src/tui/components/mod.rs deleted file mode 100644 index 6fb9fd5..0000000 --- a/src/tui/components/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod statusbar; -pub mod welcome; diff --git a/src/tui/components/statusbar.rs b/src/tui/components/statusbar.rs deleted file mode 100644 index 8c74359..0000000 --- a/src/tui/components/statusbar.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::tui::utils::with_spaces; -use crate::tui::ui::Component; -use crate::core::editor::Editor; -use crate::terminal::screen::{Coords, Screen}; -use crossterm::style::Stylize; - -pub struct StatusBar<'a> { - logo: &'a str, - mode: &'a str, - file_name: &'a str, -} - -impl<'a> StatusBar<'a> { - pub fn new(editor: &'a Editor<'a>) -> Self { - Self { - logo: editor.config.logo, - mode: editor.mode.as_str(), - file_name: editor.buffer.name, - } - } -} - -impl<'a> Component for StatusBar<'a> { - fn draw(&self, screen: &mut Screen, editor: &Editor) -> Result<(), ()> { - // Calculate where to draw the status bar - let status_height = screen.size.height - 2; - - // Get the editor logo from the config - let editor_logo = &with_spaces(editor.config.logo) as &str; - // Get the current mode into a string - let mode_string = &with_spaces(editor.mode.as_str()) as &str; - // Get the current open file name - let file_name = &with_spaces(editor.buffer.name) as &str; - - // Calculate the total length of all the status bar components - let total_length = editor_logo.len() + mode_string.len() + file_name.len() + 1; - - // If the screen isn't wide enough, panic as we can't draw the status bar - if screen.size.width < total_length { - Err(()) - - } else { - // Write the editor logo - screen.write_at( - &editor_logo.yellow().bold().reverse().to_string(), - Coords::from(0, status_height), - ); - - // Calculate where to write the current mode - let x = editor_logo.len() - 1; - // Write the current mode - screen.write_at( - &mode_string.green().bold().reverse().to_string(), - Coords::from(x, status_height), - ); - // Calculate where to write the file name - let x = x + mode_string.len(); - // Write the current file name - screen.write_at( - &file_name.magenta().bold().reverse().to_string(), - Coords::from(x, status_height), - ); - - // Draw the rest of the status bar - let x = x + file_name.len(); - screen.write_at( - &" ".repeat(screen.size.width - x).reverse().to_string(), - Coords::from(x, status_height), - ); - - Ok(()) - } - } -} diff --git a/src/tui/components/welcome.rs b/src/tui/components/welcome.rs deleted file mode 100644 index dc093b8..0000000 --- a/src/tui/components/welcome.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::tui::utils; -use crate::tui::ui::Component; -use crate::core::editor::Editor; -use crate::terminal::screen::{Coords, Screen}; -use crossterm::style::Stylize; - -pub struct WelcomeMessage<'a> { - title: String, - message: [&'a str; 5], -} - -impl<'a> WelcomeMessage<'a> { - pub fn new(editor: &'a Editor<'a>) -> Self { - // The title message - let title = format!("{} {}", editor.config.logo, editor.config.friendly_name); - - // The welcome message - let message: [&str; 5] = [ - "Hackable text editor for nerds", - "", - "Type :help to open the README.md document", - "Type :o to open a file and edit", - "Type :q! or to quit lambda", - ]; - Self { - title, - message, - } - } -} - -impl<'a> Component for WelcomeMessage<'a> { - fn draw(&self, screen: &mut Screen, _editor: &Editor) -> Result<(), ()> { - // If the screen is big enough, we can draw - if screen.size.width > utils::longest_element_in_vec(self.message.to_vec()) && screen.size.height > self.message.len() + 4 { - // The starting y position in the centre of the screen - let mut y = (screen.size.height / 2) - (self.message.len() / 2) - 2; - - // Calculate where to place the title - let x = utils::calc_centered_x(screen.size.width, self.title.len()); - - // Write the title to the screen - screen.write_at(&self.title.clone().yellow().to_string(), Coords::from(x, y)); - - for line in &self.message { - // Each line has different width so requires a different x position to center it - let x = utils::calc_centered_x(screen.size.width, line.len()) ; - - // For each line we move downwards so increment y - y += 1; - - // Write the line to the screen at position (x, y) - screen.write_at(&line.to_string(), Coords::from(x, y)); - }; - - Ok(()) - - } else { - Err(()) - } - } -} diff --git a/src/tui/mod.rs b/src/tui/mod.rs deleted file mode 100644 index 3f5a315..0000000 --- a/src/tui/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod ui; -pub mod components; -mod utils; diff --git a/src/tui/ui.rs b/src/tui/ui.rs deleted file mode 100644 index 15ad0ef..0000000 --- a/src/tui/ui.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; -use crate::core::editor::Editor; -use crate::terminal::screen::Screen; -use crate::tui::components; - -pub trait Component { - fn draw(&self, screen: &mut Screen, editor: &Editor) -> Result<(), ()>; -} - -struct Components<'a> { - bottom: Vec>, - centre: Vec>, -} - -pub struct Ui<'a> { - components: Components<'a>, -} - -impl<'a> Ui<'a> { - pub fn new(editor: &'a Editor<'a>) -> Self { - let status_bar = components::statusbar::StatusBar::new(editor); - let welcome_msg = components::welcome::WelcomeMessage::new(editor); - - Self { - components: Components { - bottom: vec![Box::new(status_bar)], - centre: vec![Box::new(welcome_msg)], - }, - } - } - - pub fn draw(&self, screen: &mut Screen, editor: &Editor) { - // Dereference the box - let _ = &*self.components.bottom; - - // Draw all components on the bottom - for component in &self.components.bottom { - component.draw(screen, &editor).unwrap(); - }; - - // Dereference the box - let _ = &*self.components.centre; - - // Draw all components in the center - for component in &self.components.centre { - component.draw(screen, &editor).unwrap(); - } - } - - pub fn run(screen: &mut Screen, editor: Editor) { - loop { - // Refresh the screen - screen.refresh().unwrap(); - - // Generate all the UI elements - let components = Ui::new(&editor); - - // Draw all UI elements - components.draw(screen, &editor); - - // Check for any key presses - match read().unwrap() { - Event::Key(KeyEvent { - code: KeyCode::Char('q'), - modifiers: KeyModifiers::CONTROL, - .. - }) => break, - Event::Key(KeyEvent { - code: KeyCode::Char('c'), - modifiers: KeyModifiers::CONTROL, - .. - }) => break, - _ => (), - } - } - - screen.exit(); - } -} diff --git a/src/tui/utils.rs b/src/tui/utils.rs deleted file mode 100644 index ba1b23c..0000000 --- a/src/tui/utils.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Surrounds a &str with spaces -pub fn with_spaces(text: &str) -> String { - format!(" {} ", text) -} - -// Calculates the x coordinate for centered text -pub fn calc_centered_x(screen_width: usize, item_length: usize) -> usize { - (screen_width / 2) - (item_length / 2) -} - -// Finds and returns the longest element in a vector -pub fn longest_element_in_vec(elements: Vec<&str>) -> usize { - elements.iter().max_by_key(|x: &&&str| x.len()).unwrap().len() -}