fix row remove

This commit is contained in:
samunohito 2024-02-03 12:19:37 +09:00
parent 295440a347
commit a06ce1137a
2 changed files with 87 additions and 47 deletions

View File

@ -24,7 +24,7 @@
v-for="row in rows" v-for="row in rows"
:key="row.index" :key="row.index"
:row="row" :row="row"
:cells="cells[row.index]" :cells="cells[row.index].cells"
:gridSetting="gridSetting" :gridSetting="gridSetting"
:bus="bus" :bus="bus"
@operation:beginEdit="onCellEditBegin" @operation:beginEdit="onCellEditBegin"
@ -37,7 +37,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, getCurrentInstance, onMounted, reactive, ref, toRefs, watch } from 'vue'; import { computed, onMounted, ref, toRefs, watch } from 'vue';
import { DataSource, GridEventEmitter, GridSetting, GridState, Size } from '@/components/grid/grid.js'; import { DataSource, GridEventEmitter, GridSetting, GridState, Size } from '@/components/grid/grid.js';
import MkDataRow from '@/components/grid/MkDataRow.vue'; import MkDataRow from '@/components/grid/MkDataRow.vue';
import MkHeaderRow from '@/components/grid/MkHeaderRow.vue'; import MkHeaderRow from '@/components/grid/MkHeaderRow.vue';
@ -50,6 +50,11 @@ import { GridCurrentState, GridEvent } from '@/components/grid/grid-event.js';
import { ColumnSetting, createColumn, GridColumn } from '@/components/grid/column.js'; import { ColumnSetting, createColumn, GridColumn } from '@/components/grid/column.js';
import { createRow, GridRow } from '@/components/grid/row.js'; import { createRow, GridRow } from '@/components/grid/row.js';
type RowHolder = {
cells: GridCell[],
origin: DataSource,
}
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
gridSetting?: GridSetting, gridSetting?: GridSetting,
columnSettings: ColumnSetting[], columnSettings: ColumnSetting[],
@ -100,7 +105,7 @@ const rows = ref<GridRow[]>([]);
/** /**
* グリッドのセル定義propsで受け取った{@link data}をもとに{@link refreshData}で再計算される * グリッドのセル定義propsで受け取った{@link data}をもとに{@link refreshData}で再計算される
*/ */
const cells = ref<GridCell[][]>([]); const cells = ref<RowHolder[]>([]);
/** /**
* mousemoveイベントが発生した際にイベントから取得したセルアドレスを保持するための変数 * mousemoveイベントが発生した際にイベントから取得したセルアドレスを保持するための変数
@ -126,13 +131,13 @@ const firstSelectionRowIdx = ref<number>(CELL_ADDRESS_NONE.row);
* 選択状態のセルを取得するための計算プロパティ選択状態とは{@link GridCell.selected}がtrueのセルのこと * 選択状態のセルを取得するための計算プロパティ選択状態とは{@link GridCell.selected}がtrueのセルのこと
*/ */
const selectedCell = computed(() => { const selectedCell = computed(() => {
const selected = cells.value.flat().filter(it => it.selected); const selected = cells.value.flatMap(it => it.cells).filter(it => it.selected);
return selected.length > 0 ? selected[0] : undefined; return selected.length > 0 ? selected[0] : undefined;
}); });
/** /**
* 範囲選択状態のセルを取得するための計算プロパティ範囲選択状態とは{@link GridCell.ranged}がtrueのセルのこと * 範囲選択状態のセルを取得するための計算プロパティ範囲選択状態とは{@link GridCell.ranged}がtrueのセルのこと
*/ */
const rangedCells = computed(() => cells.value.flat().filter(it => it.ranged)); const rangedCells = computed(() => cells.value.flatMap(it => it.cells).filter(it => it.ranged));
/** /**
* 範囲選択状態のセルの範囲を取得するための計算プロパティ左上のセル番地と右下のセル番地を計算する * 範囲選択状態のセルの範囲を取得するための計算プロパティ左上のセル番地と右下のセル番地を計算する
*/ */
@ -441,7 +446,7 @@ function onLeftMouseDown(ev: MouseEvent) {
} else if (isColumnHeaderCellAddress(cellAddress)) { } else if (isColumnHeaderCellAddress(cellAddress)) {
unSelectionRangeAll(); unSelectionRangeAll();
const colCells = cells.value.map(row => row[cellAddress.col]); const colCells = cells.value.map(row => row.cells[cellAddress.col]);
selectionRange(...colCells.map(cell => cell.address)); selectionRange(...colCells.map(cell => cell.address));
registerMouseUp(); registerMouseUp();
@ -453,7 +458,7 @@ function onLeftMouseDown(ev: MouseEvent) {
} else if (isRowNumberCellAddress(cellAddress)) { } else if (isRowNumberCellAddress(cellAddress)) {
unSelectionRangeAll(); unSelectionRangeAll();
const rowCells = cells.value[cellAddress.row]; const rowCells = cells.value[cellAddress.row].cells;
selectionRange(...rowCells.map(cell => cell.address)); selectionRange(...rowCells.map(cell => cell.address));
expandRowRange(cellAddress.row, cellAddress.row); expandRowRange(cellAddress.row, cellAddress.row);
@ -560,7 +565,7 @@ function onMouseMove(ev: MouseEvent) {
}; };
const rightBottom = { const rightBottom = {
col: Math.min(...cells.value.map(it => it.length - 1)), col: Math.min(...cells.value.map(it => it.cells.length - 1)),
row: Math.max(targetCellAddress.row, firstSelectionRowIdx.value), row: Math.max(targetCellAddress.row, firstSelectionRowIdx.value),
}; };
@ -619,7 +624,7 @@ function onContextMenu(ev: MouseEvent) {
function onCellEditBegin(sender: GridCell) { function onCellEditBegin(sender: GridCell) {
state.value = 'cellEditing'; state.value = 'cellEditing';
editingCellAddress.value = sender.address; editingCellAddress.value = sender.address;
for (const cell of cells.value.flat()) { for (const cell of cells.value.flatMap(it => it.cells)) {
if (cell.address.col !== sender.address.col || cell.address.row !== sender.address.row) { if (cell.address.col !== sender.address.col || cell.address.row !== sender.address.row) {
// //
cell.selected = false; cell.selected = false;
@ -637,7 +642,7 @@ function onChangeCellValue(sender: GridCell, newValue: CellValue) {
} }
function onChangeCellContentSize(sender: GridCell, contentSize: Size) { function onChangeCellContentSize(sender: GridCell, contentSize: Size) {
cells.value[sender.address.row][sender.address.col].contentSize = contentSize; cells.value[sender.address.row].cells[sender.address.col].contentSize = contentSize;
if (sender.column.setting.width === 'auto') { if (sender.column.setting.width === 'auto') {
calcLargestCellWidth(sender.column); calcLargestCellWidth(sender.column);
} }
@ -707,7 +712,7 @@ function calcLargestCellWidth(column: GridColumn) {
const largestCellWidth = (_cells.length > 0) const largestCellWidth = (_cells.length > 0)
? _cells ? _cells
.map(row => row[column.index]) .map(row => row.cells[column.index])
.reduce( .reduce(
(acc, value) => Math.max(acc, value.contentSize.width), (acc, value) => Math.max(acc, value.contentSize.width),
0, 0,
@ -749,7 +754,7 @@ function emitGridEvent(ev: GridEvent) {
*/ */
function emitCellValue(sender: GridCell | CellAddress, newValue: CellValue) { function emitCellValue(sender: GridCell | CellAddress, newValue: CellValue) {
const cellAddress = 'address' in sender ? sender.address : sender; const cellAddress = 'address' in sender ? sender.address : sender;
const cell = cells.value[cellAddress.row][cellAddress.col]; const cell = cells.value[cellAddress.row].cells[cellAddress.col];
const violation = cellValidation(cell, newValue); const violation = cellValidation(cell, newValue);
cell.violation = violation; cell.violation = violation;
@ -794,8 +799,8 @@ function selectionCell(target: CellAddress) {
unSelectionRangeAll(); unSelectionRangeAll();
const _cells = cells.value; const _cells = cells.value;
_cells[target.row][target.col].selected = true; _cells[target.row].cells[target.col].selected = true;
_cells[target.row][target.col].ranged = true; _cells[target.row].cells[target.col].ranged = true;
} }
/** /**
@ -804,7 +809,7 @@ function selectionCell(target: CellAddress) {
function selectionRange(...targets: CellAddress[]) { function selectionRange(...targets: CellAddress[]) {
const _cells = cells.value; const _cells = cells.value;
for (const target of targets) { for (const target of targets) {
_cells[target.row][target.col].ranged = true; _cells[target.row].cells[target.col].ranged = true;
} }
} }
@ -849,7 +854,7 @@ function unSelectionOutOfRange(leftTop: CellAddress, rightBottom: CellAddress) {
function expandCellRange(leftTop: CellAddress, rightBottom: CellAddress) { function expandCellRange(leftTop: CellAddress, rightBottom: CellAddress) {
const targetRows = cells.value.slice(leftTop.row, rightBottom.row + 1); const targetRows = cells.value.slice(leftTop.row, rightBottom.row + 1);
for (const row of targetRows) { for (const row of targetRows) {
for (const cell of row.slice(leftTop.col, rightBottom.col + 1)) { for (const cell of row.cells.slice(leftTop.col, rightBottom.col + 1)) {
cell.ranged = true; cell.ranged = true;
} }
} }
@ -911,20 +916,23 @@ function refreshData() {
} }
const _data: DataSource[] = data.value; const _data: DataSource[] = data.value;
const _rows: GridRow[] = _data.map((it, index) => createRow(index, it)); const _rows: GridRow[] = _data.map((it, index) => createRow(index));
const _cols: GridColumn[] = columnSettings.value.map(createColumn); const _cols: GridColumn[] = columnSettings.value.map(createColumn);
// //
// //
const _cells = _rows.map((row, rowIndex) => const _cells: RowHolder[] = _rows.map((row, rowIndex) => (
_cols.map(col => {
cells: _cols.map(col =>
createCell( createCell(
col, col,
row, row,
(col.setting.bindTo in _data[rowIndex]) ? _data[rowIndex][col.setting.bindTo] : undefined, (col.setting.bindTo in _data[rowIndex]) ? _data[rowIndex][col.setting.bindTo] : undefined,
), ),
), ),
); origin: _data[rowIndex],
}
));
rows.value = _rows; rows.value = _rows;
columns.value = _cols; columns.value = _cols;
@ -942,17 +950,52 @@ function refreshData() {
* そこで新しい値とセルが持つ値を突き合わせ変更があった場合のみセルの値を更新することでセルを使いまわしつつ値を最新化する * そこで新しい値とセルが持つ値を突き合わせ変更があった場合のみセルの値を更新することでセルを使いまわしつつ値を最新化する
*/ */
function patchData(newItems: DataSource[]) { function patchData(newItems: DataSource[]) {
const oldRows = cells.value; const gridRows = cells.value;
if (oldRows.length !== newItems.length) { if (gridRows.length > newItems.length) {
// //
// const diff = gridRows
refreshData(); .map((it, idx) => ({ origin: it.origin, idx }))
return; .filter(it => !newItems.includes(it.origin));
for (const { idx } of diff) {
rows.value.splice(idx, 1);
gridRows.splice(idx, 1);
} }
//
for (let rowIdx = 0; rowIdx < rows.value.length; rowIdx++) {
rows.value[rowIdx].index = rowIdx;
for (const cell of gridRows[rowIdx].cells) {
cell.address.row = rowIdx;
}
}
} else if (gridRows.length < newItems.length) {
//
const oldOrigins = gridRows.map(it => it.origin);
const diff = newItems
.map((it, idx) => ({ origin: it, idx }))
.filter(it => oldOrigins.indexOf(it.origin) === -1);
const _cols = columns.value; const _cols = columns.value;
for (let rowIdx = 0; rowIdx < oldRows.length; rowIdx++) { for (const { origin, idx } of diff) {
const oldCells = oldRows[rowIdx]; const newRow = createRow(idx);
const newCells = _cols.map(col => createCell(col, newRow, origin[col.setting.bindTo]));
rows.value.splice(idx, 0, newRow);
gridRows.splice(idx, 0, { cells: newCells, origin });
}
//
for (let rowIdx = 0; rowIdx < rows.value.length; rowIdx++) {
rows.value[rowIdx].index = rowIdx;
for (const cell of gridRows[rowIdx].cells) {
cell.address.row = rowIdx;
}
}
} else {
//
const _cols = columns.value;
for (let rowIdx = 0; rowIdx < gridRows.length; rowIdx++) {
const oldCells = gridRows[rowIdx].cells;
const newItem = newItems[rowIdx]; const newItem = newItems[rowIdx];
for (let colIdx = 0; colIdx < oldCells.length; colIdx++) { for (let colIdx = 0; colIdx < oldCells.length; colIdx++) {
const _col = _cols[colIdx]; const _col = _cols[colIdx];
@ -965,6 +1008,7 @@ function patchData(newItems: DataSource[]) {
} }
} }
} }
}
// endregion // endregion
// #endregion // #endregion

View File

@ -1,15 +1,11 @@
import { DataSource } from '@/components/grid/grid.js';
export type GridRow = { export type GridRow = {
index: number; index: number;
ranged: boolean; ranged: boolean;
origin: DataSource;
} }
export function createRow(index: number, origin: DataSource): GridRow { export function createRow(index: number): GridRow {
return { return {
index, index,
ranged: false, ranged: false,
origin: origin,
}; };
} }