UPDATE: Adds cut/paste

This commit is contained in:
Nicolás Hatcher
2024-10-26 22:39:10 +02:00
committed by Nicolás Hatcher Andrés
parent dad4755b16
commit 04d8c658ab
8 changed files with 162 additions and 12 deletions

View File

@@ -1239,6 +1239,35 @@ export default class WorksheetCanvas {
cellOutlineHandle.style.top = `${handleY - handleHeight / 2 - 1}px`;
}
private drawCutRange(): void {
const range = this.workbookState.getCutRange() || null;
if (!range) {
return;
}
const selectedSheet = this.model.getSelectedSheet();
if (range.sheet !== selectedSheet) {
return;
}
const ctx = this.ctx;
ctx.setLineDash([2, 2]);
const [xStart, yStart] = this.getCoordinatesByCell(
range.rowStart,
range.columnStart,
);
const [xEnd, yEnd] = this.getCoordinatesByCell(
range.rowEnd + 1,
range.columnEnd + 1,
);
ctx.strokeStyle = "red";
ctx.lineWidth = 1;
ctx.strokeRect(xStart, yStart, xEnd - xStart, yEnd - yStart);
// ctx.fillStyle = hexToRGBA10Percent(range.color);
// ctx.fillRect(xStart, yStart, xEnd - xStart, yEnd - yStart);
ctx.setLineDash([]);
}
private drawActiveRanges(topLeftCell: Cell, bottomRightCell: Cell): void {
let activeRanges = this.workbookState.getActiveRanges();
const ctx = this.ctx;
@@ -1437,5 +1466,6 @@ export default class WorksheetCanvas {
this.drawCellEditor();
this.drawExtendToArea();
this.drawActiveRanges(topLeftCell, bottomRightCell);
this.drawCutRange();
}
}

View File

@@ -31,6 +31,7 @@ interface Options {
onRedo: () => void;
onNextSheet: () => void;
onPreviousSheet: () => void;
onEscape: () => void;
root: RefObject<HTMLDivElement>;
}
@@ -212,6 +213,9 @@ const useKeyboardNavigation = (
break;
}
case "Escape": {
options.onEscape();
}
// No default
}
event.stopPropagation();

View File

@@ -28,7 +28,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
const rootRef = useRef<HTMLDivElement>(null);
// Calling `setRedrawId((id) => id + 1);` forces a redraw
// This is needed because `model` can change without React being aware of it
// This is needed because `model` or `workbookState` can change without React being aware of it
const setRedrawId = useState(0)[1];
const info = model
.getWorksheetsProperties()
@@ -293,6 +293,10 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
model.setSelectedSheet(nextSheet);
}
},
onEscape: (): void => {
workbookState.clearCutRange();
setRedrawId((id) => id + 1);
},
root: rootRef,
});
@@ -346,6 +350,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
}
}}
onPaste={(event: React.ClipboardEvent) => {
workbookState.clearCutRange();
const { items } = event.clipboardData;
if (!items) {
return;
@@ -385,7 +390,7 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
}
data.set(Number.parseInt(row, 10), rowMap);
}
model.pasteFromClipboard(source.area, data);
model.pasteFromClipboard(source.area, data, source.type === "cut");
setRedrawId((id) => id + 1);
} else if (mimeType === "text/plain") {
const {
@@ -445,7 +450,50 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
event.preventDefault();
event.stopPropagation();
}}
onCut={() => {}}
onCut={(event: React.ClipboardEvent) => {
const data = model.copyToClipboard();
// '2024-10-18T14:07:37.599Z'
let clipboardId = sessionStorage.getItem(
CLIPBOARD_ID_SESSION_STORAGE_KEY,
);
if (!clipboardId) {
clipboardId = getNewClipboardId();
sessionStorage.setItem(CLIPBOARD_ID_SESSION_STORAGE_KEY, clipboardId);
}
const sheetData: {
[row: number]: {
[column: number]: ClipboardCell;
};
} = {};
data.data.forEach((value, row) => {
const rowData: {
[column: number]: ClipboardCell;
} = {};
value.forEach((val, column) => {
rowData[column] = val;
});
sheetData[row] = rowData;
});
const clipboardJsonStr = JSON.stringify({
type: "cut",
area: data.range,
sheetData,
clipboardId,
});
event.clipboardData.setData("text/plain", data.csv);
event.clipboardData.setData("application/json", clipboardJsonStr);
workbookState.setCutRange({
sheet: model.getSelectedSheet(),
rowStart: data.range[0],
rowEnd: data.range[2],
columnStart: data.range[1],
columnEnd: data.range[3],
});
event.preventDefault();
event.stopPropagation();
setRedrawId((id) => id + 1);
}}
>
<Toolbar
canUndo={model.canUndo()}

View File

@@ -15,6 +15,14 @@
import type { CellStyle } from "@ironcalc/wasm";
export interface CutRange {
sheet: number;
rowStart: number;
rowEnd: number;
columnStart: number;
columnEnd: number;
}
export enum AreaType {
rowsDown = 0,
columnsRight = 1,
@@ -83,12 +91,14 @@ export class WorkbookState {
private extendToArea: Area | null;
private copyStyles: AreaStyles | null;
private cell: EditingCell | null;
private cutRange: CutRange | null;
constructor() {
// the extendTo area is the area we are covering
this.extendToArea = null;
this.copyStyles = null;
this.cell = null;
this.cutRange = null;
}
getExtendToArea(): Area | null {
@@ -155,4 +165,16 @@ export class WorkbookState {
}
return "";
}
setCutRange(range: CutRange): void {
this.cutRange = range;
}
clearCutRange(): void {
this.cutRange = null;
}
getCutRange(): CutRange | null {
return this.cutRange;
}
}