diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.rs | 2 | ||||
| -rw-r--r-- | src/sheet/cell.rs | 9 | ||||
| -rw-r--r-- | src/sheet/mod.rs | 71 | ||||
| -rw-r--r-- | src/widgets/sheetview.rs | 237 |
4 files changed, 177 insertions, 142 deletions
@@ -16,7 +16,7 @@ pub struct App<'a> { impl App<'_> { pub fn new() -> Self { - let sheet_id = Register::create(200, 1000); + let sheet_id = Register::create(2000, 10000); let sheet = Register::get(sheet_id).unwrap(); { diff --git a/src/sheet/cell.rs b/src/sheet/cell.rs index 413e299..53a4b04 100644 --- a/src/sheet/cell.rs +++ b/src/sheet/cell.rs @@ -110,14 +110,6 @@ impl CellRef { .clone(); } - pub fn set_value(&mut self, value: Cell) { - Register::get(self.sheet_id) - .unwrap() - .write() - .unwrap() - .set_cell(self.row, self.column, value); - } - pub fn left(&self) -> Option<Self> { if self.column > 0 { Self::new(self.sheet_id, self.row, self.column - 1) @@ -185,7 +177,6 @@ where fields.add_field_method_get("row", |_, this| Ok(this.row)); fields.add_field_method_get("column", |_, this| Ok(this.column)); fields.add_field_method_get("value", |_, this| Ok(this.value())); - fields.add_field_method_set("value", |_, this, value| Ok(this.set_value(value))); fields.add_field_method_get("left", |lua, this| this.left().into_lua(lua)); fields.add_field_method_get("right", |lua, this| this.right().into_lua(lua)); fields.add_field_method_get("up", |lua, this| this.up().into_lua(lua)); diff --git a/src/sheet/mod.rs b/src/sheet/mod.rs index 015e3d8..22b73fe 100644 --- a/src/sheet/mod.rs +++ b/src/sheet/mod.rs @@ -1,14 +1,17 @@ +use std::{sync::{Arc, Mutex, RwLock}, thread::JoinHandle}; + use cell::{Cell, CellRef}; -use mlua::{IntoLua, UserData, Value}; +use mlua::{Function, IntoLua, UserData, Value}; use register::{Register, SheetId}; pub mod cell; pub mod register; -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default)] pub struct Sheet { id: register::SheetId, rows: Vec<Vec<Cell>>, + progress: Mutex<u8>, } impl Sheet { @@ -16,6 +19,7 @@ impl Sheet { Self { id, rows: vec![vec![Cell::new_empty(); width]; height], + progress: Mutex::new(0), } } @@ -63,6 +67,24 @@ impl Sheet { pub fn id(&self) -> register::SheetId { self.id } + + pub fn apply(&mut self, other: Sheet) { + self.rows = other.rows; + } + + pub fn progress(&self) -> u8 { + *self.progress.lock().unwrap() + } +} + +impl Clone for Sheet { + fn clone(&self) -> Self { + Sheet { + id: self.id, + rows: self.rows.clone(), + progress: Mutex::new(0), + } + } } struct SheetLuaRef { @@ -96,3 +118,48 @@ impl UserData for SheetLuaRef { }) } } + + +pub trait EvalFunction { + fn eval_function(&self, func: String, range: Vec<(usize, usize)>) -> JoinHandle<Result<Sheet, String>>; +} + +impl EvalFunction for Arc<RwLock<Sheet>> { + fn eval_function( + &self, + func_text: String, + range: Vec<(usize, usize)>, + ) -> JoinHandle<Result<Sheet, String>> { + let this = Arc::clone(self); + std::thread::spawn(move || { + let read_sheet = this.read().unwrap(); + let mut sheet = read_sheet.clone(); + *read_sheet.progress.lock().unwrap() = 0; + let lua = crate::lua::new_instance().unwrap(); + let result = lua + .load(func_text.clone()) + .set_name("Temp Script") + .eval::<Function>(); + + match result { + Ok(func) => { + for (i, (row, column)) in range.iter().enumerate() { + + *read_sheet.progress.lock().unwrap() = (i * 100 / range.len()) as u8; + let cellref = read_sheet.get_ref(*row, *column); + + match func.call::<_, Cell>(cellref) { + Ok(value) => { + sheet.set_cell(*row, *column, value) + }, + Err(error) => return Err(error.to_string()), + } + } + Ok(sheet) + } + Err(error) => Err(error.to_string()), + } + }) + } + +} diff --git a/src/widgets/sheetview.rs b/src/widgets/sheetview.rs index 57894a2..f814cf2 100644 --- a/src/widgets/sheetview.rs +++ b/src/widgets/sheetview.rs @@ -1,10 +1,6 @@ -use std::{ - sync::{Arc, Mutex}, - thread::JoinHandle, -}; +use std::thread::JoinHandle; use layout::Offset; -use mlua::Function; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, prelude::*, @@ -14,8 +10,8 @@ use ratatui::{ }; use crate::sheet::{ - cell::Cell, register::{Register, SheetId}, + EvalFunction, Sheet, }; use super::luaeditor::LuaEditor; @@ -31,8 +27,7 @@ pub struct SheetView<'a> { cursor: (u16, u16), scroll: (u16, u16), error_window: Option<String>, - process_handle: Option<JoinHandle<Option<String>>>, - process_progress: Arc<Mutex<usize>>, + process_handle: Option<JoinHandle<Result<Sheet, String>>>, } impl<'a> SheetView<'a> { @@ -46,7 +41,6 @@ impl<'a> SheetView<'a> { scroll: (0, 0), error_window: None, process_handle: None, - process_progress: Arc::new(Mutex::new(0)), } } @@ -136,7 +130,14 @@ impl<'a> SheetView<'a> { fn join_process_handle_on_finished(&mut self) { if let Some(handle) = self.process_handle.take() { if handle.is_finished() { - self.error_window = handle.join().unwrap(); + 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); @@ -153,63 +154,34 @@ impl<'a> SheetView<'a> { match event.code { KeyCode::Char('r') if event.modifiers == KeyModifiers::CONTROL => { let script = textarea.text(); - *self.process_progress.lock().unwrap() = 0; - - let lua = crate::lua::new_instance().unwrap(); - let result = lua - .load(script.clone()) - .set_name("Temp Script") - .eval::<Function>(); - match result { - Ok(_) => { - let (width, height) = { - let lock = Register::get(self.sheet).unwrap(); - let sheet = lock.write().unwrap(); - (sheet.width(), sheet.height()) - }; - - let mut cells = Vec::new(); - if let Some(_) = self.selection { - cells = self.selection() - } else { - for row in 0..height { - for column in 0..width { - cells.push((row as u16, column as u16)); - } - } - } + let (width, height) = { + let lock = Register::get(self.sheet).unwrap(); + let sheet = lock.read().unwrap(); + (sheet.width(), sheet.height()) + }; - { - let process_progress = Arc::clone(&self.process_progress); - let sheet = self.sheet; - self.process_handle = Some(std::thread::spawn(move || { - let lua = crate::lua::new_instance().unwrap(); - let func = lua - .load(script) - .set_name("Temp Script") - .eval::<Function>() - .unwrap(); - for (i, (row, column)) in cells.iter().enumerate() { - *process_progress.lock().unwrap() = i * 100 / cells.len(); - let cellref = { - let lock = Register::get(sheet).unwrap(); - let sheet = lock.read().unwrap(); - sheet.get_ref(*row as usize, *column as usize) - }; - if let Err(error) = func.call::<_, Cell>(cellref) { - return Some(error.to_string()); - } - } + let mut cells = Vec::new(); - None - })); + 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)); } } - Err(error) => { - self.error_window = Some(error.to_string()); - } } + + self.process_handle = Some( + Register::get(self.sheet) + .unwrap() + .eval_function(script, cells), + ); } KeyCode::Esc => { self.luaeditor = None; @@ -226,7 +198,7 @@ impl<'a> SheetView<'a> { 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\t\nend") + let editor = LuaEditor::new("function(cell)\n\treturn \"\"\nend") .block(Some(Block::bordered().title(" Temp Script "))); self.luaeditor = Some(editor) } @@ -241,92 +213,98 @@ impl Widget for &mut SheetView<'_> { where Self: Sized, { - let lock = Register::get(self.sheet).unwrap(); - let sheet = lock.read().unwrap(); + let progress; - 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 lock = Register::get(self.sheet).unwrap(); + let sheet = lock.read().unwrap(); - let sheet_area = self.block.inner_if_some(block_area); + 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 viewport_rows = sheet.height().min(sheet_area.height as usize); - let viewport_columns = sheet - .width() - .min((sheet_area.width / DEFAULT_COLUMN_WIDTH) as usize); + let sheet_area = self.block.inner_if_some(block_area); - 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; - } + 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.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; - } + 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; + } - 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 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; + } - if let Some(cell) = sheet.get_cell(cell_pos_y as usize, cell_pos_x as usize) { - let cell = cell.to_string() + " "; + 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); - 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() - }; + if let Some(cell) = sheet.get_cell(cell_pos_y as usize, cell_pos_x as usize) { + let cell = cell.to_string() + " "; - 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, - ); + 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() + }; - line.render(rect, buf); + 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); + self.block.render(block_area, buf); - if let Some(textarea) = &mut self.luaeditor { - textarea.render(splits[1], 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; + 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 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); + 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); + 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(); @@ -342,7 +320,6 @@ impl Widget for &mut SheetView<'_> { height, ); - let progress = *self.process_progress.lock().unwrap(); let gauge = Gauge::default() .block(Block::bordered().title("Progress").on_black()) .gauge_style( |