diff --git a/packages/web/src/datagrid/DataGridCell.svelte b/packages/web/src/datagrid/DataGridCell.svelte index 6779dc6c9..d626d489f 100644 --- a/packages/web/src/datagrid/DataGridCell.svelte +++ b/packages/web/src/datagrid/DataGridCell.svelte @@ -31,6 +31,7 @@ export let isModifiedCell = false; export let isInserted = false; export let isDeleted = false; + export let isAutofillSelected = false; $: value = (rowData || {})[col.uniqueName]; @@ -44,6 +45,7 @@ class:isModifiedCell class:isInserted class:isDeleted + class:isAutofillSelected style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`} > {#if value == null} @@ -101,6 +103,10 @@ outline: 3px solid var(--theme-bg-selected); outline-offset: -3px; } + td.isAutofillSelected { + outline: 3px solid var(--theme-bg-selected); + outline-offset: -3px; + } td.isModifiedRow { background: var(--theme-bg-gold); } diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index 503d5fc67..fb1706e4d 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -3,8 +3,15 @@ import _ from 'lodash'; import ColumnHeaderControl from './ColumnHeaderControl.svelte'; import DataGridRow from './DataGridRow.svelte'; - import { countColumnSizes, countVisibleRealColumns } from './gridutil'; + import { + cellIsSelected, + countColumnSizes, + countVisibleRealColumns, + filterCellForRow, + filterCellsForRow, + } from './gridutil'; import HorizontalScrollBar from './HorizontalScrollBar.svelte'; + import { cellFromEvent, emptyCellArray, getCellRange, isRegularCell, nullCell, topLeftCell } from './selection'; import VerticalScrollBar from './VerticalScrollBar.svelte'; export let loadNextData = undefined; @@ -12,12 +19,32 @@ export let display: GridDisplay = undefined; export let conid = undefined; export let database = undefined; + export let frameSelection = undefined; + + const wheelRowCount = 5; let containerHeight = 0; let containerWidth = 0; let rowHeight = 0; let firstVisibleRowScrollIndex = 0; let firstVisibleColumnScrollIndex = 0; + + let domFocusField; + let domHorizontalScroll; + let domVerticalScroll; + + let currentCell = topLeftCell; + let selectedCells = [topLeftCell]; + let dragStartCell = nullCell; + let shiftDragStartCell = nullCell; + let autofillDragStartCell = nullCell; + let autofillSelectedCells = emptyCellArray; + + $: autofillMarkerCell = + selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1 + ? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))] + : null; + // $: firstVisibleRowScrollIndex = 0; // $: visibleRowCountUpperBound = 25; @@ -57,11 +84,119 @@ loadNextData(); } } + + function handleGridMouseDown(event) { + if (event.target.closest('.buttonLike')) return; + if (event.target.closest('.resizeHandleControl')) return; + if (event.target.closest('input')) return; + + // event.target.closest('table').focus(); + event.preventDefault(); + if (domFocusField) domFocusField.focus(); + const cell = cellFromEvent(event); + + if (event.button == 2 && cell && cellIsSelected(cell[0], cell[1], selectedCells)) return; + + const autofill = event.target.closest('div.autofillHandleMarker'); + if (autofill) { + autofillDragStartCell = cell; + } else { + currentCell = cell; + + if (event.ctrlKey) { + if (isRegularCell(cell)) { + if (selectedCells.find(x => x[0] == cell[0] && x[1] == cell[1])) { + selectedCells = selectedCells.filter(x => x[0] != cell[0] || x[1] != cell[1]); + } else { + selectedCells = [...selectedCells, cell]; + } + } + } else { + selectedCells = getCellRange(cell, cell); + dragStartCell = cell; + + // if (isRegularCell(cell) && !_.isEqual(cell, inplaceEditorState.cell) && _.isEqual(cell, currentCell)) { + // // @ts-ignore + // dispatchInsplaceEditor({ type: 'show', cell, selectAll: true }); + // } else if (!_.isEqual(cell, inplaceEditorState.cell)) { + // // @ts-ignore + // dispatchInsplaceEditor({ type: 'close' }); + // } + } + } + + if (display.focusedColumn) display.focusColumn(null); + } + + function handleGridMouseMove(event) { + if (autofillDragStartCell) { + const cell = cellFromEvent(event); + if (isRegularCell(cell) && (cell[0] == autofillDragStartCell[0] || cell[1] == autofillDragStartCell[1])) { + const autoFillStart = [selectedCells[0][0], _.min(selectedCells.map(x => x[1]))]; + // @ts-ignore + autofillSelectedCells = getCellRange(autoFillStart, cell); + } + } else if (dragStartCell) { + const cell = cellFromEvent(event); + currentCell = cell; + selectedCells = getCellRange(dragStartCell, cell); + } + } + + function handleGridMouseUp(event) { + if (dragStartCell) { + const cell = cellFromEvent(event); + currentCell = cell; + selectedCells = getCellRange(dragStartCell, cell); + dragStartCell = null; + } + if (autofillDragStartCell) { + const currentRowNumber = currentCell[0]; + if (_.isNumber(currentRowNumber)) { + const rowIndexes = _.uniq((autofillSelectedCells || []).map(x => x[0])).filter(x => x != currentRowNumber); + const colNames = selectedCells.map(cell => realColumnUniqueNames[cell[1]]); + const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames); + grider.beginUpdate(); + for (const index of rowIndexes) grider.updateRow(index, changeObject); + grider.endUpdate(); + } + + autofillDragStartCell = null; + autofillSelectedCells = []; + selectedCells = autofillSelectedCells; + } + } + + function handleGridWheel(event) { + let newFirstVisibleRowScrollIndex = firstVisibleRowScrollIndex; + if (event.deltaY > 0) { + newFirstVisibleRowScrollIndex += wheelRowCount; + } + if (event.deltaY < 0) { + newFirstVisibleRowScrollIndex -= wheelRowCount; + } + let rowCount = grider.rowCount; + if (newFirstVisibleRowScrollIndex + visibleRowCountLowerBound > rowCount) { + newFirstVisibleRowScrollIndex = rowCount - visibleRowCountLowerBound + 1; + } + if (newFirstVisibleRowScrollIndex < 0) { + newFirstVisibleRowScrollIndex = 0; + } + firstVisibleRowScrollIndex = newFirstVisibleRowScrollIndex; + + domVerticalScroll.scroll(newFirstVisibleRowScrollIndex); + }
- - + +
{#each _.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) as rowIndex (rowIndex)} - + {/each}
@@ -94,12 +238,14 @@ maximum={maxScrollColumn} viewportRatio={gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()} on:scroll={e => (firstVisibleColumnScrollIndex = e.detail)} + bind:this={domHorizontalScroll} /> (firstVisibleRowScrollIndex = e.detail)} + bind:this={domVerticalScroll} />
diff --git a/packages/web/src/datagrid/DataGridRow.svelte b/packages/web/src/datagrid/DataGridRow.svelte index bf7c5737b..13c9fad72 100644 --- a/packages/web/src/datagrid/DataGridRow.svelte +++ b/packages/web/src/datagrid/DataGridRow.svelte @@ -1,5 +1,6 @@
diff --git a/packages/web/src/datagrid/VerticalScrollBar.svelte b/packages/web/src/datagrid/VerticalScrollBar.svelte index 78bb19bd1..b30f5a6c7 100644 --- a/packages/web/src/datagrid/VerticalScrollBar.svelte +++ b/packages/web/src/datagrid/VerticalScrollBar.svelte @@ -17,6 +17,12 @@ let res = ratio * (maximum - minimum + 1) + minimum; dispatch('scroll', Math.floor(res + 0.3)); } + + export function scroll(value) { + const position01 = (value - minimum) / (maximum - minimum + 1); + const position = position01 * (contentSize - height); + if (node) node.scrollTop = Math.floor(position); + }