diff --git a/crates/buildtools/src/generate.rs b/crates/buildtools/src/generate.rs index 85db6ca8..0f75605c 100644 --- a/crates/buildtools/src/generate.rs +++ b/crates/buildtools/src/generate.rs @@ -1,7 +1,5 @@ use gents::FileGroup; -use logisheets_rs::{ - AsyncFuncResult, DisplayWindowRequest, -}; +use logisheets_rs::{AsyncFuncResult, DisplayWindowRequest}; fn main() { let path = "packages/web/src/bindings"; diff --git a/crates/controller/src/api/workbook.rs b/crates/controller/src/api/workbook.rs index 7fc29370..61fea2a2 100644 --- a/crates/controller/src/api/workbook.rs +++ b/crates/controller/src/api/workbook.rs @@ -176,6 +176,7 @@ impl Workbook { value_changed: vec![], cell_removed: vec![], style_changed: vec![], + ..Default::default() }; } self.controller.handle_async_calc_results(tasks, results) diff --git a/crates/controller/src/controller/executor.rs b/crates/controller/src/controller/executor.rs index 6ecce555..9f8d443a 100644 --- a/crates/controller/src/controller/executor.rs +++ b/crates/controller/src/controller/executor.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use logisheets_base::{errors::BasicError, Addr, CellId, CubeId, RangeId, SheetId}; +use logisheets_base::{errors::BasicError, Addr, CellId, ColId, CubeId, RangeId, RowId, SheetId}; use crate::{ async_func_manager::AsyncFuncManager, @@ -42,6 +42,11 @@ pub struct Executor<'a> { pub style_updated: HashSet<(SheetId, CellId)>, pub dirty_vertices: HashSet, + pub row_inserted: Vec<(SheetId, RowId)>, + pub row_removed: Vec<(SheetId, RowId)>, + pub col_inserted: Vec<(SheetId, ColId)>, + pub col_removed: Vec<(SheetId, ColId)>, + pub sheet_updated: bool, pub cell_updated: bool, // todo: updated celll } @@ -142,6 +147,10 @@ impl<'a> Executor<'a> { result.status.field_render_manager = field_render_executor.manager; result.status.navigator = nav_executor.nav; + result.row_inserted.extend(nav_executor.row_inserted); + result.row_removed.extend(nav_executor.row_removed); + result.col_inserted.extend(nav_executor.col_inserted); + result.col_removed.extend(nav_executor.col_removed); result.status.range_manager = range_executor.manager; result.status.cube_manager = cube_executor.manager; @@ -200,6 +209,10 @@ impl<'a> Executor<'a> { cell_updated, sid_assigner: result.sid_assigner, style_updated: result.style_updated, + row_inserted: result.row_inserted, + row_removed: result.row_removed, + col_inserted: result.col_inserted, + col_removed: result.col_removed, }) } @@ -220,6 +233,10 @@ impl<'a> Executor<'a> { dirty_vertices, sheet_updated, cell_updated, + row_inserted, + row_removed, + col_inserted, + col_removed, } = self; let connector = CalcConnector { range_manager: &status.range_manager, @@ -265,6 +282,10 @@ impl<'a> Executor<'a> { dirty_vertices: HashSet::new(), sheet_updated, cell_updated, + row_inserted, + row_removed, + col_inserted, + col_removed, }) } diff --git a/crates/controller/src/controller/mod.rs b/crates/controller/src/controller/mod.rs index 8b6e0dde..49727b9e 100644 --- a/crates/controller/src/controller/mod.rs +++ b/crates/controller/src/controller/mod.rs @@ -10,8 +10,8 @@ mod executor; pub mod status; pub mod style; use crate::edit_action::{ - ActionEffect, CreateSheet, EditAction, PayloadsAction, RecalcCell, SheetCellId, StatusCode, - WorkbookUpdateType, + ActionEffect, CreateSheet, EditAction, PayloadsAction, RecalcCell, SheetCellId, SheetColId, + SheetRowId, StatusCode, WorkbookUpdateType, }; use crate::errors::{Error, Result}; use crate::file_loader::load_file; @@ -194,6 +194,10 @@ impl Controller { cells_removed: HashSet::new(), sid_assigner: &self.sid_assigner, style_updated: HashSet::new(), + row_inserted: vec![], + row_removed: vec![], + col_inserted: vec![], + col_removed: vec![], }; let result = executor.execute_and_calc(action.clone()); match result { @@ -245,6 +249,27 @@ impl Controller { cell_id: c.1, }) .collect(), + row_inserted: result + .row_inserted + .into_iter() + .map(|(sheet_id, row_id)| SheetRowId { sheet_id, row_id }) + .collect(), + row_removed: result + .row_removed + .into_iter() + .map(|(sheet_id, row_id)| SheetRowId { sheet_id, row_id }) + .collect(), + col_inserted: result + .col_inserted + .into_iter() + .map(|(sheet_id, col_id)| SheetColId { sheet_id, col_id }) + .collect(), + col_removed: result + .col_removed + .into_iter() + .map(|(sheet_id, col_id)| SheetColId { sheet_id, col_id }) + .collect(), + ..Default::default() } } Err(e) => { @@ -291,6 +316,10 @@ impl Controller { cells_removed: HashSet::new(), sid_assigner: &self.sid_assigner, style_updated: HashSet::new(), + row_inserted: vec![], + row_removed: vec![], + col_inserted: vec![], + col_removed: vec![], }; let result = executor.execute_and_calc(payloads_action); @@ -335,6 +364,27 @@ impl Controller { cell_id: c.1, }) .collect(), + row_inserted: result + .row_inserted + .into_iter() + .map(|(sheet_id, row_id)| SheetRowId { sheet_id, row_id }) + .collect(), + row_removed: result + .row_removed + .into_iter() + .map(|(sheet_id, row_id)| SheetRowId { sheet_id, row_id }) + .collect(), + col_inserted: result + .col_inserted + .into_iter() + .map(|(sheet_id, col_id)| SheetColId { sheet_id, col_id }) + .collect(), + col_removed: result + .col_removed + .into_iter() + .map(|(sheet_id, col_id)| SheetColId { sheet_id, col_id }) + .collect(), + ..Default::default() } } Err(e) => { @@ -372,6 +422,10 @@ impl Controller { sid_assigner: &self.sid_assigner, cells_removed: HashSet::new(), style_updated: HashSet::new(), + row_inserted: vec![], + row_removed: vec![], + col_inserted: vec![], + col_removed: vec![], }; if let Ok(result) = executor.calc() { ActionEffect { @@ -399,6 +453,7 @@ impl Controller { cell_id: c.1, }) .collect(), + ..Default::default() } } else { ActionEffect::from_err(1) @@ -460,9 +515,9 @@ mod tests { use crate::edit_action::{ Alignment, BlockLineNameFieldUpdate, BlockLineStyleUpdate, CellInput, CellStyleUpdate, - CreateBlock, CreateSheet, DeleteSheet, EditAction, EditPayload, EphemeralCellInput, - HorizontalAlignment, LineStyleUpdate, PayloadsAction, StatusCode, StyleUpdateType, - VerticalAlignment, + CreateBlock, CreateSheet, DeleteCols, DeleteRows, DeleteSheet, EditAction, EditPayload, + EphemeralCellInput, HorizontalAlignment, InsertCols, InsertRows, LineStyleUpdate, + PayloadsAction, StatusCode, StyleUpdateType, VerticalAlignment, }; use super::Controller; @@ -923,4 +978,133 @@ mod tests { .unwrap(); assert!(matches!(cell.value, CellValue::Number(1.0))); } + + #[test] + fn insert_rows_action_effect() { + let mut wb = Controller::default(); + let sheet_idx = 0; + let sheet_id = wb.get_sheet_id_by_idx(sheet_idx).unwrap(); + + let action = PayloadsAction { + payloads: vec![EditPayload::InsertRows(InsertRows { + sheet_idx, + start: 2, + count: 3, + })], + undoable: true, + init: false, + }; + let result = wb.handle_action(EditAction::Payloads(action)); + + assert_eq!(result.row_inserted.len(), 3); + assert!(result.row_inserted.iter().all(|r| r.sheet_id == sheet_id)); + assert!(result.row_removed.is_empty()); + assert!(result.col_inserted.is_empty()); + assert!(result.col_removed.is_empty()); + } + + #[test] + fn delete_rows_action_effect() { + let mut wb = Controller::default(); + let sheet_idx = 0; + let sheet_id = wb.get_sheet_id_by_idx(sheet_idx).unwrap(); + + let action = PayloadsAction { + payloads: vec![EditPayload::DeleteRows(DeleteRows { + sheet_idx, + start: 1, + count: 2, + })], + undoable: true, + init: false, + }; + let result = wb.handle_action(EditAction::Payloads(action)); + + assert_eq!(result.row_removed.len(), 2); + assert!(result.row_removed.iter().all(|r| r.sheet_id == sheet_id)); + assert!(result.row_inserted.is_empty()); + assert!(result.col_inserted.is_empty()); + assert!(result.col_removed.is_empty()); + } + + #[test] + fn insert_cols_action_effect() { + let mut wb = Controller::default(); + let sheet_idx = 0; + let sheet_id = wb.get_sheet_id_by_idx(sheet_idx).unwrap(); + + let action = PayloadsAction { + payloads: vec![EditPayload::InsertCols(InsertCols { + sheet_idx, + start: 0, + count: 2, + })], + undoable: true, + init: false, + }; + let result = wb.handle_action(EditAction::Payloads(action)); + + assert_eq!(result.col_inserted.len(), 2); + assert!(result.col_inserted.iter().all(|c| c.sheet_id == sheet_id)); + assert!(result.col_removed.is_empty()); + assert!(result.row_inserted.is_empty()); + assert!(result.row_removed.is_empty()); + } + + #[test] + fn delete_cols_action_effect() { + let mut wb = Controller::default(); + let sheet_idx = 0; + let sheet_id = wb.get_sheet_id_by_idx(sheet_idx).unwrap(); + + let action = PayloadsAction { + payloads: vec![EditPayload::DeleteCols(DeleteCols { + sheet_idx, + start: 0, + count: 1, + })], + undoable: true, + init: false, + }; + let result = wb.handle_action(EditAction::Payloads(action)); + + assert_eq!(result.col_removed.len(), 1); + assert!(result.col_removed.iter().all(|c| c.sheet_id == sheet_id)); + assert!(result.col_inserted.is_empty()); + assert!(result.row_inserted.is_empty()); + assert!(result.row_removed.is_empty()); + } + + #[test] + fn mixed_insert_delete_action_effect() { + let mut wb = Controller::default(); + let sheet_idx = 0; + let sheet_id = wb.get_sheet_id_by_idx(sheet_idx).unwrap(); + + // Insert 2 rows then delete 1 col in a single action + let action = PayloadsAction { + payloads: vec![ + EditPayload::InsertRows(InsertRows { + sheet_idx, + start: 0, + count: 2, + }), + EditPayload::DeleteCols(DeleteCols { + sheet_idx, + start: 0, + count: 1, + }), + ], + undoable: true, + init: false, + }; + let result = wb.handle_action(EditAction::Payloads(action)); + + assert_eq!(result.row_inserted.len(), 2); + assert_eq!(result.col_removed.len(), 1); + assert!(result.row_inserted.iter().all(|r| r.sheet_id == sheet_id)); + assert!(result.col_removed.iter().all(|c| c.sheet_id == sheet_id)); + assert!(result.row_removed.is_empty()); + assert!(result.col_inserted.is_empty()); + } } diff --git a/crates/controller/src/controller/style.rs b/crates/controller/src/controller/style.rs index ae14c2c7..520d2ff4 100644 --- a/crates/controller/src/controller/style.rs +++ b/crates/controller/src/controller/style.rs @@ -118,35 +118,31 @@ impl<'a> StyleConverter<'a> { pub fn convert_style(&self, raw_style: RawStyle) -> Style { let fill = self.convert_fill(raw_style.fill); let luminance = match &fill { - Fill::PatternFill(pf) => { - if let Some(color) = &pf.fg_color { - if let (Some(r), Some(g), Some(b)) = - (color.red, color.green, color.blue) - { - get_luminance(r, g, b) - } else { - 255. - } + Fill::PatternFill(pf) => { + if let Some(color) = &pf.fg_color { + if let (Some(r), Some(g), Some(b)) = (color.red, color.green, color.blue) { + get_luminance(r, g, b) } else { 255. } + } else { + 255. } - Fill::GradientFill(gf) => { - if !gf.stops.is_empty() { - let stop = &gf.stops[0]; - let color = &stop.color; - if let (Some(r), Some(g), Some(b)) = - (color.red, color.green, color.blue) - { - get_luminance(r, g, b) - } else { - 255. - } + } + Fill::GradientFill(gf) => { + if !gf.stops.is_empty() { + let stop = &gf.stops[0]; + let color = &stop.color; + if let (Some(r), Some(g), Some(b)) = (color.red, color.green, color.blue) { + get_luminance(r, g, b) } else { 255. } + } else { + 255. } - }; + } + }; Style { font: self.convert_font(raw_style.font, luminance), fill, @@ -412,4 +408,3 @@ mod tests { println!("{:?}", result.rgb.unwrap()) } } - diff --git a/crates/controller/src/edit_action/mod.rs b/crates/controller/src/edit_action/mod.rs index 3603e24e..46d5afa7 100644 --- a/crates/controller/src/edit_action/mod.rs +++ b/crates/controller/src/edit_action/mod.rs @@ -1,5 +1,5 @@ use gents_derives::TS; -use logisheets_base::{async_func::Task, BlockId, CellId, EphemeralId, SheetId}; +use logisheets_base::{async_func::Task, BlockId, CellId, ColId, EphemeralId, RowId, SheetId}; pub trait Payload: Into {} @@ -566,6 +566,20 @@ pub struct SheetCellId { pub cell_id: CellId, } +#[derive(Debug, Clone, TS)] +#[ts(file_name = "sheet_row_id.ts", builder, rename_all = "camelCase")] +pub struct SheetRowId { + pub sheet_id: SheetId, + pub row_id: RowId, +} + +#[derive(Debug, Clone, TS)] +#[ts(file_name = "sheet_col_id.ts", builder, rename_all = "camelCase")] +pub struct SheetColId { + pub sheet_id: SheetId, + pub col_id: ColId, +} + /// `ActionEffect` represents the result of handling an `EditAction`. /// The `version` will be incremented if the action is successfully handled. /// @@ -584,6 +598,14 @@ pub struct ActionEffect { pub value_changed: Vec, pub cell_removed: Vec, pub style_changed: Vec, + + pub row_inserted: Vec, + pub row_removed: Vec, + pub row_updated: Vec, + + pub col_inserted: Vec, + pub col_removed: Vec, + pub col_updated: Vec, } impl ActionEffect { diff --git a/crates/controller/src/file_loader/sst.rs b/crates/controller/src/file_loader/sst.rs index e69de29b..8b137891 100644 --- a/crates/controller/src/file_loader/sst.rs +++ b/crates/controller/src/file_loader/sst.rs @@ -0,0 +1 @@ + diff --git a/crates/controller/src/navigator/executor.rs b/crates/controller/src/navigator/executor.rs index 7f028398..e5fdcf14 100644 --- a/crates/controller/src/navigator/executor.rs +++ b/crates/controller/src/navigator/executor.rs @@ -1,15 +1,25 @@ -use logisheets_base::{errors::BasicError, CellId}; +use logisheets_base::{errors::BasicError, CellId, ColId, RowId, SheetId}; use super::{ctx::NavExecCtx, BlockPlace, Navigator, SheetNav}; use crate::{edit_action::EditPayload, Error}; pub struct NavExecutor { pub nav: Navigator, + pub row_inserted: Vec<(SheetId, RowId)>, + pub row_removed: Vec<(SheetId, RowId)>, + pub col_inserted: Vec<(SheetId, ColId)>, + pub col_removed: Vec<(SheetId, ColId)>, } impl NavExecutor { pub fn new(nav: Navigator) -> Self { - NavExecutor { nav } + NavExecutor { + nav, + row_inserted: vec![], + row_removed: vec![], + col_inserted: vec![], + col_removed: vec![], + } } pub fn execute( @@ -132,11 +142,17 @@ impl NavExecutor { .fetch_sheet_id_by_index(insert_cols.sheet_idx) .map_err(|l| BasicError::SheetIdxExceed(l))?; let sheet_nav = self.nav.get_sheet_nav_mut(&sheet_id).clone(); - let new_sheet_nav = + let (new_sheet_nav, inserted) = insert_new_cols(sheet_nav, insert_cols.start, insert_cols.count as u32); let sheet_navs = self.nav.sheet_navs.update(sheet_id, new_sheet_nav); + let mut col_inserted = self.col_inserted; + col_inserted.extend(inserted.into_iter().map(|id| (sheet_id, id))); let res = NavExecutor { nav: Navigator { sheet_navs }, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted, + col_removed: self.col_removed, }; Ok((res, true)) } @@ -145,10 +161,16 @@ impl NavExecutor { .fetch_sheet_id_by_index(p.sheet_idx) .map_err(|l| BasicError::SheetIdxExceed(l))?; let sheet_nav = self.nav.get_sheet_nav_mut(&sheet_id).clone(); - let new_sheet_nav = delete_cols(sheet_nav, p.start, p.count as u32); + let (new_sheet_nav, removed) = delete_cols(sheet_nav, p.start, p.count as u32); let sheet_navs = self.nav.sheet_navs.update(sheet_id, new_sheet_nav); + let mut col_removed = self.col_removed; + col_removed.extend(removed.into_iter().map(|id| (sheet_id, id))); let res = NavExecutor { nav: Navigator { sheet_navs }, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed, }; Ok((res, true)) } @@ -157,11 +179,17 @@ impl NavExecutor { .fetch_sheet_id_by_index(insert_rows.sheet_idx) .map_err(|l| BasicError::SheetIdxExceed(l))?; let sheet_nav = self.nav.get_sheet_nav_mut(&sheet_id).clone(); - let new_sheet_nav = + let (new_sheet_nav, inserted) = insert_new_rows(sheet_nav, insert_rows.start, insert_rows.count as u32); let sheet_navs = self.nav.sheet_navs.update(sheet_id, new_sheet_nav); + let mut row_inserted = self.row_inserted; + row_inserted.extend(inserted.into_iter().map(|id| (sheet_id, id))); let res = NavExecutor { nav: Navigator { sheet_navs }, + row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, }; Ok((res, true)) } @@ -170,10 +198,16 @@ impl NavExecutor { .fetch_sheet_id_by_index(p.sheet_idx) .map_err(|l| BasicError::SheetIdxExceed(l))?; let sheet_nav = self.nav.get_sheet_nav_mut(&sheet_id).clone(); - let new_sheet_nav = delete_rows(sheet_nav, p.start, p.count as u32); + let (new_sheet_nav, removed) = delete_rows(sheet_nav, p.start, p.count as u32); let sheet_navs = self.nav.sheet_navs.update(sheet_id, new_sheet_nav); + let mut row_removed = self.row_removed; + row_removed.extend(removed.into_iter().map(|id| (sheet_id, id))); let res = NavExecutor { nav: Navigator { sheet_navs }, + row_inserted: self.row_inserted, + row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, }; Ok((res, true)) } @@ -184,7 +218,13 @@ impl NavExecutor { let bp = self.nav.get_block_place(&sheet_id, &p.block_id)?.clone(); let new_bp = bp.add_new_cols(p.start, p.cnt as u32); let nav = self.nav.add_block_place(sheet_id, p.block_id, new_bp); - let result = NavExecutor { nav }; + let result = NavExecutor { + nav, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, + }; Ok((result, true)) } EditPayload::DeleteColsInBlock(p) => { @@ -194,7 +234,13 @@ impl NavExecutor { let bp = self.nav.get_block_place(&sheet_id, &p.block_id)?.clone(); let new_bp = bp.delete_cols(p.start, p.cnt as u32); let nav = self.nav.add_block_place(sheet_id, p.block_id, new_bp); - let result = NavExecutor { nav }; + let result = NavExecutor { + nav, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, + }; Ok((result, true)) } EditPayload::InsertRowsInBlock(p) => { @@ -204,7 +250,13 @@ impl NavExecutor { let bp = self.nav.get_block_place(&sheet_id, &p.block_id)?.clone(); let new_bp = bp.add_new_rows(p.start, p.cnt as u32); let nav = self.nav.add_block_place(sheet_id, p.block_id, new_bp); - let result = NavExecutor { nav }; + let result = NavExecutor { + nav, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, + }; Ok((result, true)) } EditPayload::DeleteRowsInBlock(p) => { @@ -214,7 +266,13 @@ impl NavExecutor { let bp = self.nav.get_block_place(&sheet_id, &p.block_id)?.clone(); let new_bp = bp.delete_rows(p.start, p.cnt as u32); let nav = self.nav.add_block_place(sheet_id, p.block_id, new_bp); - let result = NavExecutor { nav }; + let result = NavExecutor { + nav, + row_inserted: self.row_inserted, + row_removed: self.row_removed, + col_inserted: self.col_inserted, + col_removed: self.col_removed, + }; Ok((result, true)) } _ => Ok((self, false)), @@ -222,9 +280,10 @@ impl NavExecutor { } } -fn insert_new_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { +fn insert_new_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> (SheetNav, Vec) { let mut new_id_manager = sheet_nav.id_manager.clone(); let new_ids = new_id_manager.get_row_ids(cnt); + let inserted: Vec = new_ids.iter().cloned().collect(); let new_rows = { let rows = sheet_nav.data.rows.clone(); let row_max = rows.len(); @@ -234,17 +293,19 @@ fn insert_new_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { left.truncate(row_max); left }; - SheetNav { + let sheet_nav = SheetNav { sheet_id: sheet_nav.sheet_id, data: sheet_nav.data.update_rows(new_rows), cache: Default::default(), id_manager: new_id_manager, - } + }; + (sheet_nav, inserted) } -fn insert_new_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { +fn insert_new_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> (SheetNav, Vec) { let mut new_id_manager = sheet_nav.id_manager.clone(); let new_ids = new_id_manager.get_col_ids(cnt); + let inserted: Vec = new_ids.iter().cloned().collect(); let new_cols = { let cols = sheet_nav.data.cols.clone(); let col_max = cols.len(); @@ -254,23 +315,26 @@ fn insert_new_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { left.truncate(col_max); left }; - SheetNav { + let sheet_nav = SheetNav { sheet_id: sheet_nav.sheet_id, data: sheet_nav.data.update_cols(new_cols), cache: Default::default(), id_manager: new_id_manager, - } + }; + (sheet_nav, inserted) } -fn delete_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { +fn delete_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> (SheetNav, Vec) { let sheet_id = sheet_nav.sheet_id; let result = sheet_nav; let mut new_id_manager = result.id_manager.clone(); let new_ids = new_id_manager.get_row_ids(cnt); + let removed: Vec; let new_rows = { let rows = result.data.rows.clone(); let removed_cnt = std::cmp::min(rows.len() - idx, cnt as usize); let (mut left, right) = rows.split_at(idx); + removed = right.iter().take(removed_cnt).cloned().collect(); left.append(right.skip(removed_cnt)); left.append(new_ids.clone()); left @@ -288,23 +352,26 @@ fn delete_rows(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { }); old_blocks }; - SheetNav { + let sheet_nav = SheetNav { sheet_id, data: result.data.update_rows(new_rows).update_blocks(new_blocks), cache: Default::default(), id_manager: new_id_manager, - } + }; + (sheet_nav, removed) } -fn delete_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { +fn delete_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> (SheetNav, Vec) { let sheet_id = sheet_nav.sheet_id; let result = sheet_nav; let mut new_id_manager = result.id_manager.clone(); let new_ids = new_id_manager.get_col_ids(cnt); + let removed: Vec; let new_cols = { let cols = result.data.cols.clone(); let removed_cnt = std::cmp::min(cols.len() - idx, cnt as usize); let (mut left, right) = cols.split_at(idx); + removed = right.iter().take(removed_cnt).cloned().collect(); left.append(right.skip(removed_cnt)); left.append(new_ids.clone()); left @@ -322,12 +389,13 @@ fn delete_cols(sheet_nav: SheetNav, idx: usize, cnt: u32) -> SheetNav { }); old_blocks }; - SheetNav { + let sheet_nav = SheetNav { sheet_id, data: result.data.update_cols(new_cols).update_blocks(new_blocks), cache: Default::default(), id_manager: new_id_manager, - } + }; + (sheet_nav, removed) } #[cfg(test)] @@ -341,7 +409,7 @@ mod tests { fn delete_row_test() { let sheet_nav = SheetNav::init(5, 5, 0); assert_eq!(&sheet_nav.data.rows, &Vector::from(vec![0, 1, 2, 3, 4])); - let new_sheet_nav = delete_rows(sheet_nav, 1, 1); + let (new_sheet_nav, _) = delete_rows(sheet_nav, 1, 1); assert_eq!(&new_sheet_nav.data.rows, &Vector::from(vec![0, 2, 3, 4, 5])); } @@ -349,7 +417,7 @@ mod tests { fn delete_col_test() { let sheet_nav = SheetNav::init(5, 5, 0); assert_eq!(&sheet_nav.data.cols, &Vector::from(vec![0, 1, 2, 3, 4])); - let new_sheet_nav = delete_cols(sheet_nav, 1, 1); + let (new_sheet_nav, _) = delete_cols(sheet_nav, 1, 1); assert_eq!(&new_sheet_nav.data.cols, &Vector::from(vec![0, 2, 3, 4, 5])); } } diff --git a/crates/wasms/server/src/rpc.rs b/crates/wasms/server/src/rpc.rs index 4bb08f37..2b76fcb2 100644 --- a/crates/wasms/server/src/rpc.rs +++ b/crates/wasms/server/src/rpc.rs @@ -2,10 +2,9 @@ use gents_derives::{Interface, TS}; use logisheets_rs::BlockId; use logisheets_rs::{ ActionEffect, AppData, AppendixWithCell, BlockField, BlockInfo, CellCoordinateWithSheet, - CellInfo, CellPosition, ColId, DisplayWindow, DisplayWindowWithStartPoint, - EditPayload, ErrorMessage, FormulaDisplayInfo, MergeCell, ReproducibleCell, RowId, RowInfo, - SaveFileResult, ShadowCellInfo, SheetCellId, SheetCoordinate, SheetDimension, SheetId, - SheetInfo, Style, Value, + CellInfo, CellPosition, ColId, DisplayWindow, DisplayWindowWithStartPoint, EditPayload, + ErrorMessage, FormulaDisplayInfo, MergeCell, ReproducibleCell, RowId, RowInfo, SaveFileResult, + ShadowCellInfo, SheetCellId, SheetCoordinate, SheetDimension, SheetId, SheetInfo, Style, Value, }; use wasm_bindgen::prelude::*; @@ -556,8 +555,7 @@ pub struct WorkbookMethods { pub get_value: fn(params: GetCellParams, book_id: Option) -> Result, pub get_formula: fn(params: GetCellParams, book_id: Option) -> Result, - pub get_style: - fn(params: GetCellParams, book_id: Option) -> Result, + pub get_style: fn(params: GetCellParams, book_id: Option) -> Result, pub get_cells_except_window: fn( params: GetCellsExceptWindowParams, book_id: Option, @@ -816,9 +814,13 @@ pub fn handle(msg: JsValue, book_id: Option) -> JsValue { params.craft_id, params.tag, ), - Message::GetNextVisibleCell(params) => { - ws::get_next_visible_cell(id, params.sheet_idx, params.row_idx, params.col_idx, params.direction) - } + Message::GetNextVisibleCell(params) => ws::get_next_visible_cell( + id, + params.sheet_idx, + params.row_idx, + params.col_idx, + params.direction, + ), Message::GetDisplayUnitsOfFormula(params) => { controller::get_display_units_of_formula(¶ms.formula) } @@ -877,16 +879,14 @@ pub fn handle(msg: JsValue, book_id: Option) -> JsValue { ); serde_wasm_bindgen::to_value(&result).unwrap() } - Message::GetDisplayWindowWithStartPoint(params) => { - ws::get_display_window_with_start_point( - id, - params.sheet_idx, - params.start_x, - params.start_y, - params.height, - params.width, - ) - } + Message::GetDisplayWindowWithStartPoint(params) => ws::get_display_window_with_start_point( + id, + params.sheet_idx, + params.start_x, + params.start_y, + params.height, + params.width, + ), Message::GetDisplayWindowWithinCell(params) => ws::get_display_window_within_cell( id, params.sheet_idx, diff --git a/crates/wasms/server/src/ws.rs b/crates/wasms/server/src/ws.rs index f2c001b0..78a17ee4 100644 --- a/crates/wasms/server/src/ws.rs +++ b/crates/wasms/server/src/ws.rs @@ -169,7 +169,8 @@ pub fn get_display_window_within_cell( let CellPosition { x, y } = cell_position; let start_x = x - width / 2.5; let start_y = y - height / 2.5; - let result = get_display_window_with_start_point(id, sheet_idx, start_x, start_y, height, width); + let result = + get_display_window_with_start_point(id, sheet_idx, start_x, start_y, height, width); result } @@ -303,7 +304,11 @@ pub fn get_reproducible_cell(id: usize, sheet_idx: usize, row: usize, col: usize serde_wasm_bindgen::to_value(&result).unwrap() } -pub fn get_reproducible_cells(id: usize, sheet_idx: usize, coordinates: Vec) -> JsValue { +pub fn get_reproducible_cells( + id: usize, + sheet_idx: usize, + coordinates: Vec, +) -> JsValue { init(); let manager = MANAGER.get(); let wb = manager.get_workbook(&id).unwrap();