diff options
| author | Dirk Fauth | 2022-07-14 10:58:53 +0000 |
|---|---|---|
| committer | Dirk Fauth | 2022-07-14 10:58:53 +0000 |
| commit | 8d27827b225dade8b3ed7f4edc03509fb9d78eb2 (patch) | |
| tree | 3de2cfebb09e1020f8b9b4a404432e4e7a7e6687 | |
| parent | f975367b8ffcbeb8d73dc5db29f3ab57d7631c17 (diff) | |
| download | org.eclipse.nebula.widgets.nattable-8d27827b225dade8b3ed7f4edc03509fb9d78eb2.tar.gz org.eclipse.nebula.widgets.nattable-8d27827b225dade8b3ed7f4edc03509fb9d78eb2.tar.xz org.eclipse.nebula.widgets.nattable-8d27827b225dade8b3ed7f4edc03509fb9d78eb2.zip | |
Bug 580368 - Avoid horizontal scrolling on row selection using keys
fixed left/right movement in row selection mode and select all behavior
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
Change-Id: I918ea4579ebd9d2f6964202b90b70dcfeee7a0ff
5 files changed, 230 insertions, 52 deletions
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandlerTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandlerTest.java index b871a589..cac387dc 100644 --- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandlerTest.java +++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandlerTest.java @@ -74,7 +74,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveDown() { + public void shouldUpdateSelectionOnMoveDown() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -98,7 +98,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveUp() { + public void shouldUpdateSelectionOnMoveUp() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -122,7 +122,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveDownShift() { + public void shouldExtendSelectionOnMoveDownShift() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -146,7 +146,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveUpShift() { + public void shouldExtendSelectionOnMoveUpShift() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -170,7 +170,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveDownUpShift() { + public void shouldExtendAndUpdateSelectionOnMoveDownUpShift() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -208,7 +208,7 @@ public class MoveRowSelectionCommandHandlerTest { } @Test - public void testMoveUpDownShift() { + public void shouldExtendAndUpdateSelectionOnMoveUpDownShift() { // select a row this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); @@ -244,4 +244,89 @@ public class MoveRowSelectionCommandHandlerTest { // viewport has not scrolled assertEquals(0, this.viewportLayer.getColumnIndexByPosition(0)); } + + @Test + public void shouldUpdateSelectionAnchorOnMoveLeft() { + // select a row + this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); + assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // move left + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.LEFT, false, false)); + + // selection anchor moves + assertEquals(0, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + } + + @Test + public void shouldUpdateSelectionAnchorOnMoveRight() { + // select a row + this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 1, 4, false, false)); + assertEquals(1, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // move right + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.RIGHT, false, false)); + + // selection anchor moves + assertEquals(2, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + } + + @Test + public void shouldUpdateAndScrollSelectionAnchorOnMoveLeft() { + // scroll to last column + this.viewportLayer.moveColumnPositionIntoViewport(9); + + // select a row, use last visible column in viewport + this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 5, 4, false, false)); + assertEquals(9, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // viewport shows last column + assertEquals(4, this.viewportLayer.getColumnIndexByPosition(0)); + assertEquals(9, this.viewportLayer.getColumnIndexByPosition(5)); + + // move left to first column + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.LEFT, 9, false, false)); + + // selection anchor moves + assertEquals(0, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // viewport scrolled to first column + assertEquals(0, this.viewportLayer.getColumnIndexByPosition(0)); + assertEquals(5, this.viewportLayer.getColumnIndexByPosition(5)); + } + + @Test + public void shouldUpdateAndScrollSelectionAnchorOnMoveRight() { + // select a row + this.viewportLayer.doCommand(new SelectRowsCommand(this.viewportLayer, 0, 4, false, false)); + assertEquals(0, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // viewport shows first column + assertEquals(0, this.viewportLayer.getColumnIndexByPosition(0)); + assertEquals(5, this.viewportLayer.getColumnIndexByPosition(5)); + + // move right to last column + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.RIGHT, 9, false, false)); + + // selection anchor moves + assertEquals(9, this.selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(4, this.selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(this.selectionLayer.isRowPositionFullySelected(4)); + + // viewport scrolled to last column + assertEquals(4, this.viewportLayer.getColumnIndexByPosition(0)); + assertEquals(9, this.viewportLayer.getColumnIndexByPosition(5)); + } } diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectAllTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectAllTest.java index 17e6a82d..07204f0e 100644 --- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectAllTest.java +++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectAllTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2022 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,14 +15,20 @@ package org.eclipse.nebula.widgets.nattable.selection; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.Serializable; +import java.util.Arrays; import java.util.List; import org.eclipse.nebula.widgets.nattable.NatTable; import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider; +import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor; import org.eclipse.nebula.widgets.nattable.data.ListDataProvider; import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor; +import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataFixture; +import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataListFixture; import org.eclipse.nebula.widgets.nattable.dataset.person.Person; import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService; +import org.eclipse.nebula.widgets.nattable.layer.DataLayer; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.selection.command.SelectAllCommand; import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand; @@ -32,31 +38,22 @@ import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture; import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture; import org.eclipse.nebula.widgets.nattable.test.fixture.layer.GridLayerFixture; import org.eclipse.nebula.widgets.nattable.test.fixture.layer.LayerListenerFixture; -import org.junit.After; -import org.junit.Before; +import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; +import org.eclipse.swt.graphics.Rectangle; import org.junit.Test; public class SelectAllTest { - private SelectionLayer selectionLayer; + @Test + public void shouldHaveAllCellsSelected() { + SelectionLayer selectionLayer = new SelectionLayer(new DataLayerFixture()); - @Before - public void setUp() { - this.selectionLayer = new SelectionLayer(new DataLayerFixture()); // Selection all cells in grid - this.selectionLayer.selectAll(); - } - - @After - public void cleanUp() { - this.selectionLayer.clear(); - } + selectionLayer.selectAll(); - @Test - public void shouldHaveAllCellsSelected() { - for (int columnPosition = 0; columnPosition < this.selectionLayer.getColumnCount(); columnPosition++) { - for (int rowPosition = 0; rowPosition < this.selectionLayer.getRowCount(); rowPosition++) { - ILayerCell cell = this.selectionLayer.getCellByPosition(columnPosition, rowPosition); + for (int columnPosition = 0; columnPosition < selectionLayer.getColumnCount(); columnPosition++) { + for (int rowPosition = 0; rowPosition < selectionLayer.getRowCount(); rowPosition++) { + ILayerCell cell = selectionLayer.getCellByPosition(columnPosition, rowPosition); assertEquals(DisplayMode.SELECT, cell.getDisplayMode()); } } @@ -88,4 +85,68 @@ public class SelectAllTest { assertTrue(listener.getReceivedEvents().get(0) instanceof CellSelectionEvent); } -} + @Test + public void shouldNotUpdateSelectionAnchorOnSelectAll() { + SelectionLayer selectionLayer = new SelectionLayer(new DataLayerFixture()); + + selectionLayer.selectCell(3, 3, false, false); + + assertEquals(3, selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(3, selectionLayer.getSelectionAnchor().getRowPosition()); + + selectionLayer.selectAll(); + + assertEquals(3, selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(3, selectionLayer.getSelectionAnchor().getRowPosition()); + } + + @Test + public void shouldNotUpdateSelectionAnchorOnSelectAllWithRowSelection() { + String[] propertyNames = Arrays.copyOfRange(RowDataListFixture.getPropertyNames(), 0, 10); + + IRowDataProvider<RowDataFixture> bodyDataProvider = new ListDataProvider<RowDataFixture>( + RowDataListFixture.getList(10), + new ReflectiveColumnPropertyAccessor<RowDataFixture>(propertyNames)); + + SelectionLayer selectionLayer = new SelectionLayer(new DataLayer(bodyDataProvider)); + selectionLayer.registerCommandHandler(new MoveRowSelectionCommandHandler(selectionLayer)); + + selectionLayer.setSelectionModel(new RowSelectionModel<RowDataFixture>( + selectionLayer, bodyDataProvider, + new IRowIdAccessor<RowDataFixture>() { + + @Override + public Serializable getRowId(RowDataFixture rowObject) { + return rowObject.getSecurity_id(); + } + + })); + + ViewportLayer viewportLayer = new ViewportLayer(selectionLayer); + // only show 6 columns + viewportLayer.setClientAreaProvider(() -> new Rectangle(0, 0, 600, 200)); + + selectionLayer.selectCell(3, 3, false, false); + + assertEquals(3, selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(3, selectionLayer.getSelectionAnchor().getRowPosition()); + assertTrue(selectionLayer.isRowPositionFullySelected(3)); + + // viewport shows first column + assertEquals(0, viewportLayer.getColumnIndexByPosition(0)); + + selectionLayer.selectAll(); + + // anchor not moved + assertEquals(3, selectionLayer.getSelectionAnchor().getColumnPosition()); + assertEquals(3, selectionLayer.getSelectionAnchor().getRowPosition()); + + // viewport not scrolled + assertEquals(0, viewportLayer.getColumnIndexByPosition(0)); + + // all rows selected + for (int i = 0; i < selectionLayer.getRowCount(); i++) { + assertTrue(selectionLayer.isRowPositionFullySelected(i)); + } + } +}
\ No newline at end of file diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java index acf07b5f..f881b10f 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java @@ -17,6 +17,7 @@ import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.selection.ITraversalStrategy.TraversalScope; import org.eclipse.nebula.widgets.nattable.selection.command.MoveSelectionCommand; +import org.eclipse.nebula.widgets.nattable.selection.event.CellSelectionEvent; /** * Specifies the semantics of moving the selection in the table, based on @@ -157,7 +158,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); break; } @@ -184,7 +186,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); } } } @@ -277,7 +280,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); break; } @@ -304,7 +308,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); } } } @@ -392,7 +397,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); break; } @@ -419,7 +425,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); } } } @@ -514,7 +521,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); break; } @@ -541,7 +549,8 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedColumnPosition, this.newSelectedRowPosition, withShiftMask, - withControlMask); + withControlMask, + true); } } } @@ -609,20 +618,25 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler * @param withControlMask * boolean flag to indicate whether the control key modifier is * enabled or not + * @param fireEvent + * <code>true</code> if a {@link CellSelectionEvent} should be + * fired, <code>false</code> if not */ - void selectCell(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask) { + void selectCell(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask, boolean fireEvent) { this.selectionLayer.selectCell( columnPosition, rowPosition, withShiftMask, withControlMask); - this.selectionLayer.fireCellSelectionEvent( - columnPosition, - rowPosition, - true, - withShiftMask, - withControlMask); + if (fireEvent) { + this.selectionLayer.fireCellSelectionEvent( + columnPosition, + rowPosition, + true, + withShiftMask, + withControlMask); + } } @Override diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java index 9d9ca24e..429f1b14 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java @@ -146,14 +146,25 @@ public class MoveRowSelectionCommandHandler extends MoveCellSelectionCommandHand } @Override - void selectCell(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask) { - // ignore the given column position and stick with the selection anchor - // and don't fire a CellSelectionEvent to avoid column scrolling - // the required selection event is based on the row selection afterwards - this.selectionLayer.selectCell( - this.selectionLayer.getSelectionAnchor().columnPosition, + void selectCell(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask, boolean fireEvent) { + PositionCoordinate selectionAnchor = this.selectionLayer.getSelectionAnchor(); + int col = columnPosition; + boolean fire = fireEvent; + if (selectionAnchor.columnPosition == columnPosition || withShiftMask) { + // ignore the given column position and stick with the selection + // anchor + // also don't fire a CellSelectionEvent to avoid column scrolling on + // row selection as the required selection event is based on the row + // selection afterwards + col = selectionAnchor.columnPosition; + fire = false; + } + + super.selectCell( + col, rowPosition, withShiftMask, - withControlMask); + withControlMask, + fire); } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java index 6ab1b735..58993cd2 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2022 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -148,7 +148,11 @@ public class SelectionLayer extends AbstractIndexLayerTransform { public void addSelection(Rectangle selection) { if (!selection.equals(getLastSelectedRegion())) { - setSelectionAnchor(getLastSelectedCell().columnPosition, getLastSelectedCell().rowPosition); + // only set the selection anchor if not yet set + PositionCoordinate anchor = getSelectionAnchor(); + if (anchor.columnPosition == NO_SELECTION && anchor.rowPosition == NO_SELECTION) { + setSelectionAnchor(getLastSelectedCell().columnPosition, getLastSelectedCell().rowPosition); + } setLastSelectedRegion(selection); } @@ -225,6 +229,7 @@ public class SelectionLayer extends AbstractIndexLayerTransform { public void selectAll() { Rectangle selection = new Rectangle(0, 0, getColumnCount(), getRowCount()); PositionCoordinate lastSelected = getLastSelectedCell(); + PositionCoordinate updateCoordinate = new PositionCoordinate(getSelectionAnchor()); if (lastSelected.columnPosition == SelectionLayer.NO_SELECTION || lastSelected.columnPosition >= getColumnCount() || lastSelected.rowPosition == SelectionLayer.NO_SELECTION @@ -245,11 +250,13 @@ public class SelectionLayer extends AbstractIndexLayerTransform { } } setLastSelectedCell(column, row); + updateCoordinate.setColumnPosition(column); + updateCoordinate.setRowPosition(row); } addSelection(selection); fireCellSelectionEvent( - getLastSelectedCell().columnPosition, - getLastSelectedCell().rowPosition, + updateCoordinate.columnPosition, + updateCoordinate.rowPosition, false, false, false); |
