summaryrefslogtreecommitdiff
path: root/src/widgets/sheetview.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/sheetview.rs')
-rw-r--r--src/widgets/sheetview.rs336
1 files changed, 0 insertions, 336 deletions
diff --git a/src/widgets/sheetview.rs b/src/widgets/sheetview.rs
deleted file mode 100644
index c4f7a73..0000000
--- a/src/widgets/sheetview.rs
+++ /dev/null
@@ -1,336 +0,0 @@
-use std::thread::JoinHandle;
-
-use layout::Offset;
-use ratatui::{
- crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
- prelude::*,
- style::Stylize,
- text::ToLine,
- widgets::{block::BlockExt, Block, Clear, Gauge, Widget},
-};
-
-use crate::sheet::{
- register::{Register, SheetId},
- eval::EvalFunction, Sheet,
-};
-
-use super::luaeditor::LuaEditor;
-
-const DEFAULT_COLUMN_WIDTH: u16 = 10;
-
-pub struct SheetView<'a> {
- block: Option<Block<'a>>,
- luaeditor: Option<LuaEditor<'a>>,
- sheet: SheetId,
- selection: Option<(u16, u16)>,
- cursor: (u16, u16),
- scroll: (u16, u16),
- error_window: Option<String>,
- process_handle: Option<JoinHandle<Result<Sheet, String>>>,
-}
-
-impl<'a> SheetView<'a> {
- pub fn new(sheet: SheetId) -> Self {
- Self {
- block: None,
- luaeditor: None,
- sheet,
- selection: None,
- cursor: (0, 0),
- scroll: (0, 0),
- error_window: None,
- process_handle: None,
- }
- }
-
- pub fn block(mut self, block: Block<'a>) -> Self {
- self.block = Some(block);
- self
- }
-
- pub fn sheet(mut self, sheet: SheetId) -> Self {
- self.sheet = sheet;
- self
- }
-
- pub fn move_cursor_by(&mut self, delta: (i32, i32)) {
- let lock = Register::get(self.sheet).unwrap();
- let sheet = lock.read().unwrap();
-
- self.cursor.0 = ((self.cursor.0 as i32) + delta.0)
- .max(0)
- .min(sheet.height() as i32 - 1) as u16;
- self.cursor.1 = ((self.cursor.1 as i32) + delta.1)
- .max(0)
- .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();
-
- if let Some((row, column)) = self.selection_range() {
- for i in row.0..=row.1 {
- for j in column.0..=column.1 {
- selection.push((i, j))
- }
- }
- }
-
- selection
- }
-
- fn is_in_selection(&mut self, row: u16, column: u16) -> bool {
- if let Some((row_range, column_range)) = self.selection_range() {
- row >= row_range.0
- && row <= row_range.1
- && column >= column_range.0
- && column <= column_range.1
- } else {
- false
- }
- }
-
- fn selection_range(&self) -> Option<((u16, u16), (u16, u16))> {
- if let Some(selection) = self.selection {
- let row = if selection.0 > self.cursor.0 {
- (self.cursor.0, selection.0)
- } else {
- (selection.0, self.cursor.0)
- };
-
- let column = if selection.1 > self.cursor.1 {
- (self.cursor.1, selection.1)
- } else {
- (selection.1, self.cursor.1)
- };
-
- Some((row, column))
- } else {
- None
- }
- }
-
- fn join_process_handle_on_finished(&mut self) {
- if let Some(handle) = self.process_handle.take() {
- 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),
- };
- self.process_handle = None;
- } else {
- self.process_handle = 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 {
- KeyCode::Char('r') if event.modifiers == KeyModifiers::CONTROL => {
- let script = textarea.text();
-
- let (width, height) = {
- let lock = Register::get(self.sheet).unwrap();
- let sheet = lock.read().unwrap();
- (sheet.width(), sheet.height())
- };
-
- let mut cells = Vec::new();
-
- if let Some(_) = self.selection {
- cells = self
- .selection()
- .iter()
- .map(|(r, c)| (*r as usize, *c as usize))
- .collect()
- } else {
- for row in 0..height {
- for column in 0..width {
- cells.push((row, column));
- }
- }
- }
-
- self.process_handle = Some(
- Register::get(self.sheet)
- .unwrap()
- .eval_function(script, cells),
- );
- }
- KeyCode::Esc => {
- self.luaeditor = None;
- }
- _ => {
- textarea.handle_key_event(event);
- }
- }
- } 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")
- .block(Some(Block::bordered().title(" Temp Script ")));
- self.luaeditor = Some(editor)
- }
- _ => {}
- }
- }
- }
-}
-
-impl Widget for &mut SheetView<'_> {
- fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer)
- where
- Self: Sized,
- {
- let progress;
-
- {
- let lock = Register::get(self.sheet).unwrap();
- let sheet = lock.read().unwrap();
-
- let splits = Layout::horizontal([Constraint::Min(1), Constraint::Length(50)]).split(area);
- let block_area = if self.luaeditor.is_some() {
- splits[0]
- } else {
- area
- };
-
- let sheet_area = self.block.inner_if_some(block_area);
-
- let viewport_rows = sheet.height().min(sheet_area.height as usize);
- let viewport_columns = sheet
- .width()
- .min((sheet_area.width / DEFAULT_COLUMN_WIDTH) as usize);
-
- if self.cursor.0 >= viewport_rows as u16 + self.scroll.0 {
- self.scroll.0 = self.cursor.0 - viewport_rows as u16 + 1;
- } else if self.cursor.0 < self.scroll.0 {
- self.scroll.0 = self.cursor.0;
- }
-
- if self.cursor.1 >= viewport_columns as u16 + self.scroll.1 {
- self.scroll.1 = self.cursor.1 - viewport_columns as u16 + 1;
- } else if self.cursor.1 < self.scroll.1 {
- self.scroll.1 = self.cursor.1;
- }
-
- for row in 0..viewport_rows as u16 {
- for column in 0..(viewport_columns + 1) as u16 {
- let (cell_pos_y, cell_pos_x) = (row + self.scroll.0, column + self.scroll.1);
-
- if let Some(cell) = sheet.get_cell(cell_pos_y as usize, cell_pos_x as usize) {
- let cell = cell.to_string() + " ";
-
- let line = if (cell_pos_y, cell_pos_x) == self.cursor {
- cell.to_line().bg(Color::Rgb(120, 90, 90)).white()
- } else if self.is_in_selection(cell_pos_y, cell_pos_x) {
- cell.to_line().bg(Color::Rgb(120, 120, 90)).white()
- } else if (row + column) % 2 == 0 {
- cell.to_line().bg(Color::Rgb(30, 30, 30)).white()
- } else {
- cell.to_line().bg(Color::Rgb(50, 50, 50)).white()
- };
-
- let rect = Rect::new(
- sheet_area.x + column * DEFAULT_COLUMN_WIDTH,
- sheet_area.y + row,
- (sheet_area.width - column * DEFAULT_COLUMN_WIDTH)
- .min(DEFAULT_COLUMN_WIDTH),
- 1,
- );
-
- line.render(rect, buf);
- }
- }
- }
-
- self.block.render(block_area, buf);
-
- if let Some(textarea) = &mut self.luaeditor {
- textarea.render(splits[1], buf)
- }
-
- if let Some(error_msg) = &self.error_window {
- let lines = error_msg.lines().collect::<Vec<_>>();
- let height = lines.len() as u16 + 2;
- let width = lines.iter().map(|s| s.len()).max().unwrap_or(0) as u16 + 2;
-
- let centered = Rect::new(
- (area.width - width) / 2,
- (area.height - height) / 2,
- width,
- height,
- );
-
- let block = Block::bordered().red().on_black().bold().title(" Error ");
- let inner_centered = block.inner(centered);
- Clear::default().render(centered, buf);
- block.render(centered, buf);
-
- for (i, line) in lines.iter().enumerate() {
- let line = line.replace('\t', " ").red().on_black().bold();
- line.render(inner_centered.offset(Offset { x: 0, y: i as i32 }), buf);
- }
- }
-
- progress = sheet.progress();
- }
-
- self.join_process_handle_on_finished();
-
- if self.process_handle.is_some() {
- let height = 3;
- let width = area.width / 2;
-
- let centered = Rect::new(
- (area.width - width) / 2,
- (area.height - height) / 2,
- width,
- height,
- );
-
- let gauge = Gauge::default()
- .block(Block::bordered().title("Progress").on_black())
- .gauge_style(
- Style::default()
- .fg(Color::White)
- .bg(Color::Black)
- .add_modifier(Modifier::ITALIC),
- )
- .percent(progress as u16);
-
- Clear::default().render(centered, buf);
- gauge.render(centered, buf);
- }
- }
-}