1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
import { produce } from "immer";
import renderGrid, { getRenderedCell } from "./components/grid/renderGrid";
import { getSelectionRange, GridSelection } from "./components/grid/selection";
import Ratio from "./math/Ratio";
import { Cell, Grid, renderedRowIndexToRef } from "./types";
export function getSelectedSubdivisionsCount(
grid: Grid,
selection: GridSelection,
): number | undefined {
const renderedGrid = renderGrid(grid);
const [startCellRef, endCellRef] = getSelectionRange(selection);
const startCell = getRenderedCell(renderedGrid, startCellRef);
const endCell = getRenderedCell(renderedGrid, endCellRef);
if (!startCell || !endCell) throw new Error("Invalid cell refs");
const startRenderedRowIndex = Math.min(
startCell.renderedRowIndex,
endCell.renderedRowIndex,
);
const endRenderedRowIndex = Math.max(
startCell.renderedRowIndex,
endCell.renderedRowIndex,
);
const startRatio = Ratio.min(startCell.startRatio, endCell.startRatio);
const endRatio = Ratio.max(startCell.endRatio, endCell.endRatio);
return Math.min(
...renderedGrid.renderedRows
.slice(startRenderedRowIndex, endRenderedRowIndex + 1)
.map((row) => {
const startCellIndex = row.renderedCells.findIndex((cell) =>
cell.startRatio.equals(startRatio),
);
const endCellIndex = row.renderedCells.findLastIndex((cell) =>
cell.endRatio.equals(endRatio),
);
return endCellIndex - startCellIndex + 1;
}),
);
}
export function changeSelectedSubdivisions(
grid: Grid,
selection: GridSelection,
subdivisions: number,
): Grid {
const renderedGrid = renderGrid(grid);
const [startCellRef, endCellRef] = getSelectionRange(selection);
const startCell = getRenderedCell(renderedGrid, startCellRef);
const endCell = getRenderedCell(renderedGrid, endCellRef);
if (!startCell || !endCell) throw new Error("Invalid cell refs");
const startRenderedRowIndex = Math.min(
startCell.renderedRowIndex,
endCell.renderedRowIndex,
);
const endRenderedRowIndex = Math.max(
startCell.renderedRowIndex,
endCell.renderedRowIndex,
);
const startRatio = Ratio.min(startCell.startRatio, endCell.startRatio);
const endRatio = Ratio.max(startCell.endRatio, endCell.endRatio);
const selectedWidthRatio = endRatio.subtract(startRatio);
const widthRatio = selectedWidthRatio.divideRatio(
Ratio.fromInteger(subdivisions),
);
return produce(grid, (draft) => {
for (
let renderedRowIndex = startRenderedRowIndex;
renderedRowIndex <= endRenderedRowIndex;
renderedRowIndex++
) {
const renderedRow = renderedGrid.renderedRows[renderedRowIndex];
const startCellIndex = renderedRow.renderedCells.findIndex((cell) =>
cell.startRatio.equals(startRatio),
);
const endCellIndex = renderedRow.renderedCells.findLastIndex((cell) =>
cell.endRatio.equals(endRatio),
);
const { partIndex, rowIndex } = renderedRowIndexToRef(
grid,
renderedRowIndex,
);
const row = draft.parts[partIndex].rows[rowIndex];
const previousCells = row.cells.slice(0, startCellIndex);
const nextCells = row.cells.slice(endCellIndex + 1);
const newCells: Cell[] = Array.from({ length: subdivisions }, () => ({
widthRatio,
}));
row.cells = [...previousCells, ...newCells, ...nextCells];
}
});
}
|