FIX: When cut and paste to a different sheet origin is removed

Fixes #193
This commit is contained in:
Nicolás Hatcher
2024-12-16 01:02:12 +01:00
committed by Nicolás Hatcher Andrés
parent a5919d837f
commit e098105531
5 changed files with 44 additions and 9 deletions

View File

@@ -99,7 +99,7 @@ fn cut_paste() {
// paste in cell D4 (4, 4) // paste in cell D4 (4, 4)
model model
.paste_from_clipboard((1, 1, 2, 2), &copy.data, true) .paste_from_clipboard(0, (1, 1, 2, 2), &copy.data, true)
.unwrap(); .unwrap();
assert_eq!(model.get_cell_content(0, 4, 4), Ok("42".to_string())); assert_eq!(model.get_cell_content(0, 4, 4), Ok("42".to_string()));
@@ -119,6 +119,26 @@ fn cut_paste() {
assert_eq!(model.get_cell_content(0, 2, 2), Ok("".to_string())); assert_eq!(model.get_cell_content(0, 2, 2), Ok("".to_string()));
} }
#[test]
fn cut_paste_different_sheet() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
model.set_user_input(0, 1, 1, "42").unwrap();
model.set_selected_range(1, 1, 1, 1).unwrap();
let copy = model.copy_to_clipboard().unwrap();
model.new_sheet().unwrap();
model.set_selected_sheet(1).unwrap();
model.set_selected_cell(4, 4).unwrap();
// paste in cell D4 (4, 4) of Sheet2
model
.paste_from_clipboard(0, (1, 1, 1, 1), &copy.data, true)
.unwrap();
assert_eq!(model.get_cell_content(1, 4, 4), Ok("42".to_string()));
assert_eq!(model.get_cell_content(0, 1, 1), Ok("".to_string()));
}
#[test] #[test]
fn copy_paste_internal() { fn copy_paste_internal() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap(); let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
@@ -152,7 +172,7 @@ fn copy_paste_internal() {
// paste in cell D4 (4, 4) // paste in cell D4 (4, 4)
model model
.paste_from_clipboard((1, 1, 2, 2), &copy.data, false) .paste_from_clipboard(0, (1, 1, 2, 2), &copy.data, false)
.unwrap(); .unwrap();
assert_eq!(model.get_cell_content(0, 4, 4), Ok("42".to_string())); assert_eq!(model.get_cell_content(0, 4, 4), Ok("42".to_string()));

View File

@@ -39,6 +39,7 @@ pub struct ClipboardCell {
pub struct Clipboard { pub struct Clipboard {
pub(crate) csv: String, pub(crate) csv: String,
pub(crate) data: ClipboardData, pub(crate) data: ClipboardData,
pub(crate) sheet: u32,
pub(crate) range: (i32, i32, i32, i32), pub(crate) range: (i32, i32, i32, i32),
} }
@@ -1520,6 +1521,7 @@ impl UserModel {
Ok(Clipboard { Ok(Clipboard {
csv, csv,
data, data,
sheet,
range: (row_start, column_start, row_end, column_end), range: (row_start, column_start, row_end, column_end),
}) })
} }
@@ -1527,6 +1529,7 @@ impl UserModel {
/// Paste text that we copied /// Paste text that we copied
pub fn paste_from_clipboard( pub fn paste_from_clipboard(
&mut self, &mut self,
source_sheet: u32,
source_range: ClipboardTuple, source_range: ClipboardTuple,
clipboard: &ClipboardData, clipboard: &ClipboardData,
is_cut: bool, is_cut: bool,
@@ -1617,17 +1620,17 @@ impl UserModel {
let old_value = self let old_value = self
.model .model
.workbook .workbook
.worksheet(sheet)? .worksheet(source_sheet)?
.cell(row, column) .cell(row, column)
.cloned(); .cloned();
diff_list.push(Diff::CellClearContents { diff_list.push(Diff::CellClearContents {
sheet, sheet: source_sheet,
row, row,
column, column,
old_value: Box::new(old_value), old_value: Box::new(old_value),
}); });
self.model.cell_clear_contents(sheet, row, column)?; self.model.cell_clear_contents(source_sheet, row, column)?;
} }
} }
} }

View File

@@ -169,20 +169,22 @@ clipboard_types = r"""
paste_from_clipboard = r""" paste_from_clipboard = r"""
/** /**
* @param {number} source_sheet
* @param {any} source_range * @param {any} source_range
* @param {any} clipboard * @param {any} clipboard
* @param {boolean} is_cut * @param {boolean} is_cut
*/ */
pasteFromClipboard(source_range: any, clipboard: any, is_cut: boolean): void; pasteFromClipboard(source_sheet: number, source_range: any, clipboard: any, is_cut: boolean): void;
""" """
paste_from_clipboard_types = r""" paste_from_clipboard_types = r"""
/** /**
* @param {number} source_sheet
* @param {[number, number, number, number]} source_range * @param {[number, number, number, number]} source_range
* @param {ClipboardData} clipboard * @param {ClipboardData} clipboard
* @param {boolean} is_cut * @param {boolean} is_cut
*/ */
pasteFromClipboard(source_range: [number, number, number, number], clipboard: ClipboardData, is_cut: boolean): void; pasteFromClipboard(source_sheet: number, source_range: [number, number, number, number], clipboard: ClipboardData, is_cut: boolean): void;
""" """
def fix_types(text): def fix_types(text):

View File

@@ -520,6 +520,7 @@ impl Model {
#[wasm_bindgen(js_name = "pasteFromClipboard")] #[wasm_bindgen(js_name = "pasteFromClipboard")]
pub fn paste_from_clipboard( pub fn paste_from_clipboard(
&mut self, &mut self,
source_sheet: u32,
source_range: JsValue, source_range: JsValue,
clipboard: JsValue, clipboard: JsValue,
is_cut: bool, is_cut: bool,
@@ -529,7 +530,7 @@ impl Model {
let clipboard: ClipboardData = let clipboard: ClipboardData =
serde_wasm_bindgen::from_value(clipboard).map_err(|e| to_js_error(e.to_string()))?; serde_wasm_bindgen::from_value(clipboard).map_err(|e| to_js_error(e.to_string()))?;
self.model self.model
.paste_from_clipboard(source_range, &clipboard, is_cut) .paste_from_clipboard(source_sheet, source_range, &clipboard, is_cut)
.map_err(|e| to_js_error(e.to_string())) .map_err(|e| to_js_error(e.to_string()))
} }

View File

@@ -390,7 +390,12 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
} }
data.set(Number.parseInt(row, 10), rowMap); data.set(Number.parseInt(row, 10), rowMap);
} }
model.pasteFromClipboard(source.area, data, source.type === "cut"); model.pasteFromClipboard(
source.sheet,
source.area,
data,
source.type === "cut",
);
setRedrawId((id) => id + 1); setRedrawId((id) => id + 1);
} else if (mimeType === "text/plain") { } else if (mimeType === "text/plain") {
const { const {
@@ -416,6 +421,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
}} }}
onCopy={(event: React.ClipboardEvent) => { onCopy={(event: React.ClipboardEvent) => {
const data = model.copyToClipboard(); const data = model.copyToClipboard();
const sheet = model.getSelectedSheet();
// '2024-10-18T14:07:37.599Z' // '2024-10-18T14:07:37.599Z'
let clipboardId = sessionStorage.getItem( let clipboardId = sessionStorage.getItem(
@@ -443,6 +449,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
type: "copy", type: "copy",
area: data.range, area: data.range,
sheetData, sheetData,
sheet,
clipboardId, clipboardId,
}); });
event.clipboardData.setData("text/plain", data.csv); event.clipboardData.setData("text/plain", data.csv);
@@ -452,6 +459,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
}} }}
onCut={(event: React.ClipboardEvent) => { onCut={(event: React.ClipboardEvent) => {
const data = model.copyToClipboard(); const data = model.copyToClipboard();
const sheet = model.getSelectedSheet();
// '2024-10-18T14:07:37.599Z' // '2024-10-18T14:07:37.599Z'
let clipboardId = sessionStorage.getItem( let clipboardId = sessionStorage.getItem(
@@ -479,6 +487,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
type: "cut", type: "cut",
area: data.range, area: data.range,
sheetData, sheetData,
sheet,
clipboardId, clipboardId,
}); });
event.clipboardData.setData("text/plain", data.csv); event.clipboardData.setData("text/plain", data.csv);