diff --git a/packages/web/src/datagrid/DataFilterControl.svelte b/packages/web/src/datagrid/DataFilterControl.svelte index 7f2a5025a..b9ac95731 100644 --- a/packages/web/src/datagrid/DataFilterControl.svelte +++ b/packages/web/src/datagrid/DataFilterControl.svelte @@ -25,6 +25,7 @@ export let setFilter; export let showResizeSplitter = false; export let onFocusGrid = null; + export let onFocusGridHeader = null; export let onGetReference = null; export let foreignKey = null; export let conid = null; @@ -204,6 +205,11 @@ // ev.stopPropagation(); ev.preventDefault(); } + if (ev.keyCode == keycodes.upArrow) { + if (onFocusGridHeader) onFocusGridHeader(); + // ev.stopPropagation(); + ev.preventDefault(); + } // if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) { // if (this.props.onControlKey) this.props.onControlKey(ev.keyCode); // } diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index ed58051df..87960d799 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -380,7 +380,17 @@ filterCellsForRow, } from './gridutil'; import HorizontalScrollBar from './HorizontalScrollBar.svelte'; - import { cellFromEvent, emptyCellArray, getCellRange, isRegularCell, nullCell, topLeftCell } from './selection'; + import { + cellFromEvent, + emptyCellArray, + getCellRange, + isColumnHeaderCell, + isRegularCell, + isRowHeaderCell, + isTableHeaderCell, + nullCell, + topLeftCell, + } from './selection'; import VerticalScrollBar from './VerticalScrollBar.svelte'; import LoadingInfo from '../elements/LoadingInfo.svelte'; import InlineButton from '../buttons/InlineButton.svelte'; @@ -1305,7 +1315,7 @@ function scrollIntoView(cell) { const [row, col] = cell; - if (row != null) { + if (_.isNumber(row)) { let newRow = null; const rowCount = grider.rowCount; if (rowCount == 0) return; @@ -1323,7 +1333,7 @@ } } - if (col != null) { + if (_.isNumber(col)) { if (col >= columnSizes.frozenCount) { let newColumn = columnSizes.scrollInView( firstVisibleColumnScrollIndex, @@ -1553,7 +1563,11 @@ } if (event.shiftKey) { - if (!isRegularCell(shiftDragStartCell)) { + if ( + !isRegularCell(shiftDragStartCell) && + !isColumnHeaderCell(shiftDragStartCell) && + !isRowHeaderCell(shiftDragStartCell) + ) { shiftDragStartCell = currentCell; } } else { @@ -1581,7 +1595,13 @@ } function handleCursorMove(event) { - if (!isRegularCell(currentCell)) return null; + if ( + !isRegularCell(currentCell) && + !isColumnHeaderCell(currentCell) && + !isRowHeaderCell(currentCell) && + !isTableHeaderCell(currentCell) + ) + return null; let rowCount = grider.rowCount; if (isCtrlOrCommandKey(event)) { switch (event.keyCode) { @@ -1608,24 +1628,36 @@ switch (event.keyCode) { case keycodes.upArrow: if (currentCell[0] == 0) return focusFilterEditor(currentCell[1]); - return moveCurrentCell(currentCell[0] - 1, currentCell[1], event); + return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] - 1, currentCell[1], event) : null; case keycodes.downArrow: - return moveCurrentCell(currentCell[0] + 1, currentCell[1], event); + if (currentCell[0] == 'header') return focusFilterEditor(currentCell[1]); + return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null; case keycodes.enter: - if (!grider.editable) return moveCurrentCell(currentCell[0] + 1, currentCell[1], event); + if (!grider.editable) + return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null; break; case keycodes.leftArrow: - return moveCurrentCell(currentCell[0], currentCell[1] - 1, event); + return _.isNumber(currentCell[1]) + ? moveCurrentCell(currentCell[0], currentCell[1] == 0 ? 'header' : currentCell[1] - 1, event) + : null; case keycodes.rightArrow: - return moveCurrentCell(currentCell[0], currentCell[1] + 1, event); + return currentCell[1] == 'header' + ? moveCurrentCell(currentCell[0], 0, event) + : _.isNumber(currentCell[1]) + ? moveCurrentCell(currentCell[0], currentCell[1] + 1, event) + : null; case keycodes.home: return moveCurrentCell(currentCell[0], 0, event); case keycodes.end: return moveCurrentCell(currentCell[0], columnSizes.realCount - 1, event); case keycodes.pageUp: - return moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event); + return _.isNumber(currentCell[0]) + ? moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event) + : null; case keycodes.pageDown: - return moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event); + return _.isNumber(currentCell[0]) + ? moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event) + : null; case keycodes.tab: { return moveCurrentCellWithTabKey(event.shiftKey); } @@ -1659,10 +1691,14 @@ function moveCurrentCell(row, col, event = null) { const rowCount = grider.rowCount; - if (row < 0) row = 0; - if (row >= rowCount) row = rowCount - 1; - if (col < 0) col = 0; - if (col >= columnSizes.realCount) col = columnSizes.realCount - 1; + if (_.isNumber(row)) { + if (row < 0) row = 0; + if (row >= rowCount) row = rowCount - 1; + } + if (_.isNumber(col)) { + if (col < 0) col = 0; + if (col >= columnSizes.realCount) col = columnSizes.realCount - 1; + } currentCell = [row, col]; // setSelectedCells([...(event.ctrlKey ? selectedCells : []), [row, col]]); selectedCells = [[row, col]]; @@ -1782,6 +1818,17 @@ if (domFocusField) domFocusField.focus(); }; + const selectColumnHeaderCell = uniquePath => { + const modelIndex = columns.findIndex(x => x.uniquePath == uniquePath); + const realIndex = columnSizes.modelToReal(modelIndex); + let cell = ['header', realIndex]; + // @ts-ignore + currentCell = cell; + // @ts-ignore + selectedCells = [cell]; + if (domFocusField) domFocusField.focus(); + }; + const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => { switch (action.type) { case 'show': @@ -2031,6 +2078,7 @@ data-row="header" data-col={col.colIndex} style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`} + class:active-header-cell={currentCell && currentCell[0] == 'header' && currentCell[1] == col.colIndex} > { selectTopmostCell(col.uniqueName); }} + onFocusGridHeader={() => { + selectColumnHeaderCell(col.uniqueName); + }} dataType={col.dataType} filterDisabled={display.isFilterDisabled(col.uniqueName)} /> @@ -2231,6 +2282,9 @@ background-color: var(--theme-bg-1); overflow: hidden; } + :global(.data-grid-focused) .active-header-cell { + background-color: var(--theme-bg-selected); + } .filter-cell { text-align: left; overflow: hidden; diff --git a/packages/web/src/datagrid/DataGridRow.svelte b/packages/web/src/datagrid/DataGridRow.svelte index 6110a754f..bed6f07e2 100644 --- a/packages/web/src/datagrid/DataGridRow.svelte +++ b/packages/web/src/datagrid/DataGridRow.svelte @@ -76,6 +76,7 @@ onShowForm={onSetFormView && !overlayDefinition ? () => onSetFormView(rowData, null) : null} extraIcon={overlayDefinition ? OVERLAY_STATUS_ICONS[rowStatus.status] : null} extraIconTooltip={overlayDefinition ? OVERLAY_STATUS_TOOLTIPS[rowStatus.status] : null} + isSelected={frameSelection ? false : !!selectedCells?.find(cell => cell[0] == rowIndex && cell[1] == 'header')} /> {#each visibleRealColumns as col (col.uniqueName)} {#if inplaceEditorState.cell && rowIndex == inplaceEditorState.cell[0] && col.colIndex == inplaceEditorState.cell[1]} diff --git a/packages/web/src/datagrid/RowHeaderCell.svelte b/packages/web/src/datagrid/RowHeaderCell.svelte index c4a3612bb..85586b0a2 100644 --- a/packages/web/src/datagrid/RowHeaderCell.svelte +++ b/packages/web/src/datagrid/RowHeaderCell.svelte @@ -7,6 +7,7 @@ export let extraIcon = null; export let extraIconTooltip = null; + export let isSelected = false; let mouseIn = false; @@ -14,6 +15,7 @@ (mouseIn = true)} on:mouseleave={() => (mouseIn = false)} > @@ -43,4 +45,7 @@ right: 0px; top: 1px; } + :global(.data-grid-focused) td.selected { + background-color: var(--theme-bg-selected); + } diff --git a/packages/web/src/datagrid/selection.ts b/packages/web/src/datagrid/selection.ts index 18b8c2aa5..f0a85a682 100644 --- a/packages/web/src/datagrid/selection.ts +++ b/packages/web/src/datagrid/selection.ts @@ -13,6 +13,24 @@ export function isRegularCell(cell: CellAddress): cell is RegularCellAddress { return _.isNumber(row) && _.isNumber(col); } +export function isRowHeaderCell(cell: CellAddress): boolean { + if (!cell) return false; + const [row, col] = cell; + return col === 'header' && _.isNumber(row); +} + +export function isColumnHeaderCell(cell: CellAddress): boolean { + if (!cell) return false; + const [row, col] = cell; + return row === 'header' && _.isNumber(col); +} + +export function isTableHeaderCell(cell: CellAddress): boolean { + if (!cell) return false; + const [row, col] = cell; + return row === 'header' && col === 'header'; +} + function normalizeHeaderForSelection(addr: CellAddress): CellAddress { if (addr[0] == 'filter') return ['header', addr[1]]; return addr;