UPDATE: Adds cut/paste
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
dad4755b16
commit
04d8c658ab
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user