summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.rs2
-rw-r--r--src/sheet/cell.rs9
-rw-r--r--src/sheet/mod.rs71
-rw-r--r--src/widgets/sheetview.rs237
4 files changed, 177 insertions, 142 deletions
diff --git a/src/app.rs b/src/app.rs
index 3544fdf..d74a06f 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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(