diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-07-28 12:50:02 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2024-07-28 12:50:02 +0200 |
| commit | 417cee4eeeaf7516dfeb59cdbe34fed18f30e0f7 (patch) | |
| tree | 74354a7b14a65f4dc514b6ed0367945f69349bc4 /src/widgets/sheetview | |
| parent | 6ca07d6af8a338e76817d06c6c6c6f13e64fba9c (diff) | |
add statusbar widget
Diffstat (limited to 'src/widgets/sheetview')
| -rw-r--r-- | src/widgets/sheetview/mod.rs | 229 |
1 files changed, 138 insertions, 91 deletions
diff --git a/src/widgets/sheetview/mod.rs b/src/widgets/sheetview/mod.rs index 37e3d16..40adfc7 100644 --- a/src/widgets/sheetview/mod.rs +++ b/src/widgets/sheetview/mod.rs @@ -8,46 +8,55 @@ use ratatui::{ widgets::{Block, Borders, Clear, Gauge, Paragraph, Widget, Wrap}, }; -use crate::{config::GlobalConfig, sheet::{ - eval::EvalFunction, - register::{Register, SheetId}, - Sheet, -}}; +use crate::{ + config::GlobalConfig, + sheet::{ + eval::EvalFunction, + register::{Register, SheetId}, + Sheet, + }, +}; -use super::luaeditor::LuaEditor; +use super::{luaeditor::LuaEditor, statusbar::StatusBar}; const DEFAULT_COLUMN_WIDTH: u16 = 10; -pub struct SheetView<'a> { - block: Block<'a>, - luaeditor: Option<LuaEditor<'a>>, +enum SheetViewMode { + Normal, + Insert, + Visual, + Command, + CommandError(String), + Script, + Processing(Option<JoinHandle<Result<Sheet, String>>>), + EditorError(String), +} + +pub struct SheetView { + bar: StatusBar, sheet: SheetId, - selection: Option<(u16, u16)>, cursor: (u16, u16), scroll: (u16, u16), - error_window: Option<String>, - process_handle: Option<JoinHandle<Result<Sheet, String>>>, + selection_anchor: Option<(u16, u16)>, + mode: SheetViewMode, + editor: LuaEditor, } -impl<'a> SheetView<'a> { +impl SheetView { pub fn new(sheet: SheetId) -> Self { Self { - block: Block::default() - .title_bottom(" Sheet ") - .title_style(Style::default().on_magenta().black()) - .borders(Borders::BOTTOM) - .border_style( - Style::default() - .bg(Color::Rgb(29, 32, 33)) - .fg(Color::Rgb(29, 32, 33)), - ), - luaeditor: None, + bar: StatusBar::new() + .left(" NORMAL ") + .left_style(Style::default().on_magenta()) + .middle("Sheet") + .right("") + .right_style(Style::default().on_red()), sheet, - selection: None, cursor: (0, 0), scroll: (0, 0), - error_window: None, - process_handle: None, + mode: SheetViewMode::Normal, + selection_anchor: None, + editor: LuaEditor::new(), } } @@ -68,22 +77,6 @@ impl<'a> SheetView<'a> { .min(sheet.width() as i32 - 1) as u16; } - pub fn select_mode(&mut self, flag: bool) { - if flag { - self.selection = Some(self.cursor); - } else { - self.selection = None; - } - } - - pub fn is_select_mode(&self) -> bool { - self.selection.is_some() - } - - pub fn toggle_select_mode(&mut self) { - self.select_mode(!self.is_select_mode()); - } - pub fn selection(&self) -> Vec<(u16, u16)> { let mut selection = Vec::new(); @@ -110,7 +103,7 @@ impl<'a> SheetView<'a> { } fn selection_range(&self) -> Option<((u16, u16), (u16, u16))> { - if let Some(selection) = self.selection { + if let Some(selection) = self.selection_anchor { let row = if selection.0 > self.cursor.0 { (self.cursor.0, selection.0) } else { @@ -130,32 +123,67 @@ impl<'a> SheetView<'a> { } fn join_process_handle_on_finished(&mut self) { - if let Some(handle) = self.process_handle.take() { + if let SheetViewMode::Processing(opt) = &mut self.mode { + let handle = opt.take().unwrap(); if handle.is_finished() { match handle.join().unwrap() { - Ok(sheet) => Register::get(self.sheet) - .unwrap() - .write() - .unwrap() - .apply(sheet), - Err(message) => self.error_window = Some(message), + Ok(sheet) => { + Register::get(self.sheet) + .unwrap() + .write() + .unwrap() + .apply(sheet); + self.mode = SheetViewMode::Script; + } + Err(message) => self.mode = SheetViewMode::EditorError(message), }; - self.process_handle = None; } else { - self.process_handle = Some(handle); + self.mode = SheetViewMode::Processing(Some(handle)); } } } pub fn handle_key_event(&mut self, event: KeyEvent) { - if self.process_handle.is_some() { - self.join_process_handle_on_finished() - } else if let Some(_) = &self.error_window { - self.error_window = None; - } else if let Some(textarea) = &mut self.luaeditor { - match event.code { + match self.mode { + SheetViewMode::Normal => match event.code { + KeyCode::Char('j') => self.move_cursor_by((1, 0)), + KeyCode::Char('k') => self.move_cursor_by((-1, 0)), + KeyCode::Char('h') => self.move_cursor_by((0, -1)), + KeyCode::Char('l') => self.move_cursor_by((0, 1)), + KeyCode::Char('v') => { + self.selection_anchor = Some(self.cursor.clone()); + self.mode = SheetViewMode::Visual + }, + KeyCode::Char('s') => { + self.editor.set_text("function(cell)\n\treturn \"\"\nend"); + self.mode = SheetViewMode::Script; + } + _ => {} + }, + SheetViewMode::Insert => {} + SheetViewMode::Visual => match event.code { + KeyCode::Char('j') => self.move_cursor_by((1, 0)), + KeyCode::Char('k') => self.move_cursor_by((-1, 0)), + KeyCode::Char('h') => self.move_cursor_by((0, -1)), + KeyCode::Char('l') => self.move_cursor_by((0, 1)), + KeyCode::Esc | KeyCode::Char('v') => { + self.selection_anchor = None; + self.mode = SheetViewMode::Normal; + }, + KeyCode::Char('s') => { + self.editor.set_text("function(cell)\n\treturn \"\"\nend"); + self.mode = SheetViewMode::Script; + } + _ => {} + }, + SheetViewMode::Command => {} + SheetViewMode::CommandError(_) => match event.code { + KeyCode::Esc => self.mode = SheetViewMode::Normal, + _ => {} + }, + SheetViewMode::Script => match event.code { KeyCode::Char('r') if event.modifiers == KeyModifiers::CONTROL => { - let script = textarea.text(); + let script = self.editor.text(); let (width, height) = { let lock = Register::get(self.sheet).unwrap(); @@ -165,7 +193,7 @@ impl<'a> SheetView<'a> { let mut cells = Vec::new(); - if let Some(_) = self.selection { + if let Some(_) = self.selection_anchor { cells = self .selection() .iter() @@ -179,32 +207,51 @@ impl<'a> SheetView<'a> { } } - self.process_handle = Some( + self.mode = SheetViewMode::Processing(Some( Register::get(self.sheet) .unwrap() .eval_function(script, cells), - ); + )); } KeyCode::Esc => { - self.luaeditor = None; - } - _ => { - textarea.handle_key_event(event); + if self.selection_anchor.is_some() { + self.mode = SheetViewMode::Visual; + } else { + self.mode = SheetViewMode::Normal; + } } + _ => self.editor.handle_key_event(event), + }, + SheetViewMode::Processing(_) => { + self.join_process_handle_on_finished(); } - } else { - match event.code { - KeyCode::Char('j') => self.move_cursor_by((1, 0)), - KeyCode::Char('k') => self.move_cursor_by((-1, 0)), - KeyCode::Char('h') => self.move_cursor_by((0, -1)), - KeyCode::Char('l') => self.move_cursor_by((0, 1)), - KeyCode::Char('v') => self.toggle_select_mode(), - KeyCode::Char('s') => { - let editor = LuaEditor::new("function(cell)\n\treturn \"\"\nend"); - self.luaeditor = Some(editor) - } + SheetViewMode::EditorError(_) => match event.code { + KeyCode::Esc => self.mode = SheetViewMode::Script, _ => {} - } + }, + } + } + + fn is_editor_visible(&self) -> bool { + match self.mode { + SheetViewMode::Script + | SheetViewMode::Processing(_) + | SheetViewMode::EditorError(_) => true, + _ => false, + } + } + + fn is_error_window_visible(&self) -> bool { + match self.mode { + SheetViewMode::EditorError(_) => true, + _ => false, + } + } + + fn is_progress_visible(&self) -> bool { + match self.mode { + SheetViewMode::Processing(_) => true, + _ => false, } } @@ -214,20 +261,20 @@ impl<'a> SheetView<'a> { let mut error = Rect::default(); let mut progress = Rect::default(); - if self.luaeditor.is_some() { + if self.is_editor_visible() { let layout = Layout::horizontal([Constraint::Min(1), Constraint::Length(50)]).split(sheet); sheet = layout[0]; editor = layout[1]; - if self.error_window.is_some() { + if self.is_error_window_visible() { let layout = Layout::vertical([Constraint::Min(1), Constraint::Length(10)]).split(editor); editor = layout[0]; error = layout[1]; } - if self.process_handle.is_some() { + if self.is_progress_visible() { let layout = Layout::vertical([Constraint::Min(1), Constraint::Length(1)]).split(editor); editor = layout[0]; @@ -239,7 +286,7 @@ impl<'a> SheetView<'a> { } } -impl Widget for &mut SheetView<'_> { +impl Widget for &mut SheetView { fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) where Self: Sized, @@ -257,13 +304,13 @@ impl Widget for &mut SheetView<'_> { let lock = Register::get(self.sheet).unwrap(); let sheet = lock.read().unwrap(); - let mut sheet_area_inner = self.block.inner(sheet_area); + let mut sheet_area_inner = self.bar.area(sheet_area); - if self.luaeditor.is_some() { + if self.is_editor_visible() { sheet_area_inner = separator.inner(sheet_area_inner); } - let viewport_rows = sheet.height().min(sheet_area.height as usize); + let viewport_rows = sheet.height().min(sheet_area_inner.height as usize); let viewport_columns = sheet .width() .min((sheet_area_inner.width / DEFAULT_COLUMN_WIDTH) as usize); @@ -310,14 +357,14 @@ impl Widget for &mut SheetView<'_> { } } - self.block.clone().render(sheet_area, buf); + self.bar.render(sheet_area, buf); - if let Some(textarea) = &mut self.luaeditor { - separator.render(self.block.inner(sheet_area), buf); - textarea.render(editor_area, buf) + if self.is_editor_visible() { + separator.render(sheet_area, buf); + self.editor.render(editor_area, buf) } - if let Some(error_msg) = &self.error_window { + if let SheetViewMode::EditorError(error_msg) = &self.mode { let lines = error_msg.lines().collect::<Vec<_>>(); let block = Block::default() @@ -341,7 +388,7 @@ impl Widget for &mut SheetView<'_> { self.join_process_handle_on_finished(); - if self.process_handle.is_some() { + if self.is_progress_visible() { let gauge = Gauge::default() .gauge_style( Style::default() |