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

View File

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