Skip to content

Commit 5644dad

Browse files
authored
fix: Context menu using stale selection (#2414)
Cherry-pick #2407 and #2412 to `v0.85`
1 parent 632f2f2 commit 5644dad

3 files changed

Lines changed: 92 additions & 7 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { GridRange } from '../GridRange';
2+
import GridSelectionMouseHandler from './GridSelectionMouseHandler';
3+
4+
describe('getLatestSelection', () => {
5+
it('should return the original selection if the clicked cell is within the original selection', () => {
6+
const originalSelection = [new GridRange(1, 1, 2, 2)];
7+
const result = GridSelectionMouseHandler.getLatestSelection(
8+
originalSelection,
9+
1,
10+
1
11+
);
12+
13+
expect(result).toBe(originalSelection);
14+
});
15+
16+
it('should return a new selection with the clicked cell if it is outside the original selection', () => {
17+
const originalSelection = [new GridRange(1, 1, 2, 2)];
18+
const columnIndex = 3;
19+
const rowIndex = 3;
20+
21+
const result = GridSelectionMouseHandler.getLatestSelection(
22+
originalSelection,
23+
columnIndex,
24+
rowIndex
25+
);
26+
27+
expect(result).toEqual([GridRange.makeCell(columnIndex, rowIndex)]);
28+
});
29+
30+
it('should return the original selection if columnIndex is null', () => {
31+
const originalSelection = [new GridRange(1, 1, 2, 2)];
32+
33+
const result = GridSelectionMouseHandler.getLatestSelection(
34+
originalSelection,
35+
null,
36+
1
37+
);
38+
39+
expect(result).toBe(originalSelection);
40+
});
41+
42+
it('should return the original selection if rowIndex is null', () => {
43+
const originalSelection = [new GridRange(1, 1, 2, 2)];
44+
45+
const result = GridSelectionMouseHandler.getLatestSelection(
46+
originalSelection,
47+
null,
48+
1
49+
);
50+
51+
expect(result).toBe(originalSelection);
52+
});
53+
});

packages/grid/src/mouse-handlers/GridSelectionMouseHandler.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
1-
import { EventHandlerResult } from '../EventHandlerResult';
2-
import Grid from '../Grid';
3-
import GridMouseHandler, { GridMouseEvent } from '../GridMouseHandler';
4-
import GridRange from '../GridRange';
5-
import GridUtils, { GridPoint } from '../GridUtils';
1+
import { type EventHandlerResult } from '../EventHandlerResult';
2+
import type Grid from '../Grid';
3+
import GridMouseHandler, { type GridMouseEvent } from '../GridMouseHandler';
4+
import GridRange, { type GridRangeIndex } from '../GridRange';
5+
import GridUtils, { type GridPoint } from '../GridUtils';
66

77
const DEFAULT_INTERVAL_MS = 100;
88

99
class GridSelectionMouseHandler extends GridMouseHandler {
10+
/**
11+
* Returns the latest grid selection based on the current grid selection and where the user clicked
12+
* This code is dependent on the behavior of onContextMenu
13+
* @param originalSelection The selection from the current grid state which may be stale
14+
* @param columnIndex The column index where the user clicked
15+
* @param rowIndex The row index where the user clicked
16+
*/
17+
static getLatestSelection(
18+
originalSelection: readonly GridRange[],
19+
columnIndex: GridRangeIndex,
20+
rowIndex: GridRangeIndex
21+
): readonly GridRange[] {
22+
const clickedInOriginalSelection = GridRange.containsCell(
23+
originalSelection,
24+
columnIndex,
25+
rowIndex
26+
);
27+
28+
// If the user clicked in a valid cell outside of the original selection,
29+
// the selection will be changed to just that cell.
30+
return clickedInOriginalSelection || columnIndex == null || rowIndex == null
31+
? originalSelection
32+
: [GridRange.makeCell(columnIndex, rowIndex)];
33+
}
34+
1035
private startPoint?: GridPoint;
1136

1237
private hasExtendedFloating = false;
@@ -246,7 +271,7 @@ class GridSelectionMouseHandler extends GridMouseHandler {
246271
);
247272

248273
// only change the selected range if the selected cell is not in the selected range
249-
if (!isInRange && gridPoint.row !== null) {
274+
if (!isInRange && gridPoint.row !== null && gridPoint.column !== null) {
250275
this.startPoint = undefined;
251276
this.stopTimer();
252277
grid.clearSelectedRanges();

packages/iris-grid/src/mousehandlers/IrisGridContextMenuHandler.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
GridPoint,
2424
GridRange,
2525
GridRenderer,
26+
GridSelectionMouseHandler,
2627
isDeletableGridModel,
2728
isEditableGridModel,
2829
isExpandableGridModel,
@@ -818,9 +819,15 @@ class IrisGridContextMenuHandler extends GridMouseHandler {
818819
isFilterBarShown,
819820
quickFilters,
820821
advancedFilters,
821-
selectedRanges,
822+
selectedRanges: stateSelectedRanges,
822823
} = irisGrid.state;
823824

825+
const selectedRanges = GridSelectionMouseHandler.getLatestSelection(
826+
stateSelectedRanges,
827+
columnIndex,
828+
rowIndex
829+
);
830+
824831
assertNotNull(metrics);
825832

826833
const { columnHeaderHeight, gridY, columnHeaderMaxDepth } = metrics;

0 commit comments

Comments
 (0)