/******************************************************************************* * Copyright (c) 2012, 2013, 2014 Original authors and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Original authors and others - initial API and implementation ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.selection; import static org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum.RIGHT; import static org.junit.Assert.assertEquals; import java.util.Collection; import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand; import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture; import org.eclipse.nebula.widgets.nattable.util.ArrayUtil; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class CellSelectionTest { private SelectionLayer selectionLayer; private MoveCellSelectionCommandHandler moveCommandHandler; private ITraversalStrategy AXIS_TRAVERSAL_ALL = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return SelectionLayer.MOVE_ALL; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; @Before public void setUp() { this.selectionLayer = new SelectionLayer(new DataLayerFixture(10, 10, 100, 40)); // Selection grid origin as starting point this.selectionLayer.setSelectedCell(0, 0); this.moveCommandHandler = new MoveCellSelectionCommandHandler(this.selectionLayer); } @After public void cleanUp() { this.selectionLayer.clear(); } @Test public void shouldHaveOriginSelected() { Assert.assertTrue(isLastCellInOrigin()); } private boolean isLastCellInOrigin() { return (0 == this.selectionLayer.getLastSelectedCellPosition().columnPosition && 0 == this.selectionLayer .getLastSelectedCellPosition().rowPosition); } private boolean isSelectonAnchorInOrigin() { return (0 == this.selectionLayer.getSelectionAnchor().columnPosition && 0 == this.selectionLayer .getSelectionAnchor().rowPosition); } private boolean wasPreviousSelectionCleared() { // Make sure previous selection was cleared return (this.selectionLayer.getSelectedColumnPositions().length == 1 && this.selectionLayer .getSelectedRowCount() == 1); } private boolean wasPreviousColumnSelectionAppended() { // Make sure previous column selection was not cleared return this.selectionLayer.getSelectedColumnPositions().length > 1; } private boolean wasPreviousRowSelectionAppended() { // Make sure previous column selection was not cleared return this.selectionLayer.getSelectedRowCount() > 1; } // Tests for cell selection NTBL-224 @Test public void shouldMoveTheSelectionAnchorLeftUsingLeftArrowKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); this.selectionLayer.setSelectedCell(1, 0); // Should move back to origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); Assert.assertTrue(isLastCellInOrigin()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionToTheLeftUsingLeftArrowAndShiftKeys() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); this.selectionLayer.setSelectedCell(2, 0); // Should move back to origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); // Last selected cell should now be the origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); Assert.assertTrue(isLastCellInOrigin()); // Selection anchor should not have changed Assert.assertEquals(2, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getRowPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousColumnSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorRightUsingRightArrowKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.RIGHT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); // Previous selection was cleared and origin should no longer be // selected Assert.assertFalse(isLastCellInOrigin()); // The selection anchor moved right Assert.assertEquals(1, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getRowPosition()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionRightUsingRightArrowAndShiftKeys() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.RIGHT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); this.moveCommandHandler.moveSelection( MoveDirectionEnum.RIGHT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); // Since selection started at origin, then origin should be part of the // selected range Assert.assertTrue(isSelectonAnchorInOrigin()); // Selection should now end on the cell to the right of the selection // anchor Assert.assertEquals(2, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousColumnSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorUpUsingUpArrowKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); this.selectionLayer.setSelectedCell(0, 2); // Should move back to origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); Assert.assertTrue(isLastCellInOrigin()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionUpUsingUpArrowAndShiftKeys() { this.selectionLayer.setSelectedCell(0, 1); this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); // Anchor should not have changed Assert.assertEquals(1, this.selectionLayer.getSelectionAnchor() .getRowPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); // Last selected cell should be the origin Assert.assertTrue(isLastCellInOrigin()); // Cells in between should have been appended Assert.assertTrue(wasPreviousRowSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorDownUsingDownArrowKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.DOWN, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); // Previous selection was cleared and origin should no longer be // selected Assert.assertFalse(isLastCellInOrigin()); // Las selected cell is one step below origin Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(1, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionDownUsingDownArrowAndShiftKeys() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.DOWN, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, true, false); // Selection anchor remains at origing Assert.assertTrue(isSelectonAnchorInOrigin()); // Las selected cell is one step below origin Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(1, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousRowSelectionAppended()); } @Test public void shouldMoveTheSelecitonAnchorToStartOfRowUsingHomeKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, this.AXIS_TRAVERSAL_ALL, false, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); // Move to middle of grid this.selectionLayer.setSelectedCell(2, 0); // Should move back to origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, this.AXIS_TRAVERSAL_ALL, false, false); Assert.assertTrue(isLastCellInOrigin()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionToStartOfRowUsingHomeAndShiftKeys() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, this.AXIS_TRAVERSAL_ALL, true, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); // Move to middle of grid this.selectionLayer.setSelectedCell(2, 0); // Should move back to origin this.moveCommandHandler.moveSelection( MoveDirectionEnum.LEFT, this.AXIS_TRAVERSAL_ALL, true, false); Assert.assertTrue(isLastCellInOrigin()); // Selection anchor should not have changed Assert.assertEquals(2, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getRowPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousColumnSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorToEndOfRowUsingEndKey() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.RIGHT, this.AXIS_TRAVERSAL_ALL, false, false); // Selection anchor moved to end of grid Assert.assertEquals(9, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getSelectionAnchor() .getRowPosition()); // Previous selection was cleared and origin should no longer be // selected Assert.assertFalse(isLastCellInOrigin()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendTheSelectionToEndOfRowUsingEndAndShiftKeys() { this.moveCommandHandler.moveSelection( MoveDirectionEnum.RIGHT, this.AXIS_TRAVERSAL_ALL, true, false); // Selection anchor should stay at the origin Assert.assertTrue(isSelectonAnchorInOrigin()); // Last selected cell is at end of grid Assert.assertEquals(9, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousColumnSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorOnePageUpUsingPageUpKey() { ITraversalStrategy customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 6; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, customTraversal, false, false); // Should not have moved Assert.assertTrue(isLastCellInOrigin()); // Move to middle of grid final int columnPosition = 2; final int rowPosition = 4; this.selectionLayer.setSelectedCell(columnPosition, rowPosition); customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 10; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; // Should not have moved this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, customTraversal, false, false); // Previous selection was cleared and origin should no longer be // selected Assert.assertFalse(isLastCellInOrigin()); customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 60; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; // Should move back to first row event if step size is greater than // available number of rows this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, customTraversal, false, false); Assert.assertEquals(2, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendSelectionOnePageUpUsingThePageUpAndShiftKeys() { ITraversalStrategy customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 10; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; // Move to middle of grid final int columnPosition = 2; final int rowPosition = 4; this.selectionLayer.setSelectedCell(columnPosition, rowPosition); // Should move back to first row event if step size is greater than // available number of rows this.moveCommandHandler.moveSelection( MoveDirectionEnum.UP, customTraversal, true, false); Assert.assertEquals(2, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Selection anchor should not have changed Assert.assertEquals(2, this.selectionLayer.getSelectionAnchor() .getColumnPosition()); Assert.assertEquals(4, this.selectionLayer.getSelectionAnchor() .getRowPosition()); // Cells in between should have been appended Assert.assertTrue(wasPreviousRowSelectionAppended()); } @Test public void shouldMoveTheSelectionAnchorOnePageDownUsingPageDownKey() { ITraversalStrategy customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 6; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; this.moveCommandHandler.moveSelection( MoveDirectionEnum.DOWN, customTraversal, false, false); customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 60; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; // Should move to last row even if step size is greater than available // number of rows this.moveCommandHandler.moveSelection( MoveDirectionEnum.DOWN, customTraversal, false, false); Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(9, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Previous selection was cleared Assert.assertTrue(wasPreviousSelectionCleared()); } @Test public void shouldExtendSelectionOnePageDownUsingPageDownAndShiftKeys() { ITraversalStrategy customTraversal = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { return TraversalScope.AXIS; } @Override public boolean isCycle() { return false; } @Override public int getStepCount() { return 6; } @Override public boolean isValidTarget(ILayerCell from, ILayerCell to) { return true; } }; this.moveCommandHandler.moveSelection( MoveDirectionEnum.DOWN, customTraversal, true, false); // Selection anchor should not have changed Assert.assertTrue(isSelectonAnchorInOrigin()); // Last selected cell should be in the last row Assert.assertEquals(0, this.selectionLayer.getLastSelectedCellPosition() .getColumnPosition()); Assert.assertEquals(6, this.selectionLayer.getLastSelectedCellPosition() .getRowPosition()); // Previous selection was cleared Assert.assertTrue(wasPreviousRowSelectionAppended()); } /** * If a range of cells is selected - clear selection and move anchor to the * next cell in the direction moved */ @Test public void moveCellWhenARangeOfCellsIsSelected() throws Exception { new SelectColumnCommandHandler(this.selectionLayer).selectColumn(2, 0, false, false); this.moveCommandHandler.moveSelection( RIGHT, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY, false, false); assertEquals(3, this.selectionLayer.getSelectionAnchor().columnPosition); assertEquals(0, this.selectionLayer.getSelectionAnchor().rowPosition); } /** * Selected cells are (col,row): (2,3),(4,1),(1,0),(9,9) */ @Test public void shouldReturnTheCorrectCountOfSelectedCells() { this.selectionLayer.clear(); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 3, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 4, 1, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 1, 0, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 9, 9, false, true)); PositionCoordinate[] cells = this.selectionLayer.getSelectedCellPositions(); Assert.assertEquals(4, cells.length); // (1, 0) Assert.assertEquals(1, cells[0].columnPosition); Assert.assertEquals(0, cells[0].rowPosition); // (2, 3) Assert.assertEquals(2, cells[1].columnPosition); Assert.assertEquals(3, cells[1].rowPosition); // (4, 1) Assert.assertEquals(4, cells[2].columnPosition); Assert.assertEquals(1, cells[2].rowPosition); // (9, 9) Assert.assertEquals(9, cells[3].columnPosition); Assert.assertEquals(9, cells[3].rowPosition); } @Test public void shouldReturnSixCells() { this.selectionLayer.clear(); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 1, 0, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 0, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 1, 1, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 1, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 1, 2, false, true)); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 2, false, true)); Collection<PositionCoordinate> cells = ArrayUtil .asCollection(this.selectionLayer.getSelectedCellPositions()); Assert.assertEquals(6, cells.size()); // (1, 0) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 1, 0))); // (1, 1) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 1, 1))); // (1, 2) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 1, 2))); // (2, 0) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 0))); // (2, 1) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 1))); // (2, 2) Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 2))); } @Test public void onlyOneCellSelectedAtAnyTime() { this.selectionLayer.getSelectionModel().setMultipleSelectionAllowed(false); this.selectionLayer.clear(); this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 1, 0, false, true)); Collection<PositionCoordinate> cells = ArrayUtil .asCollection(this.selectionLayer.getSelectedCellPositions()); Assert.assertEquals(1, cells.size()); Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 1, 0))); // select another cell with control mask this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 0, false, true)); cells = ArrayUtil.asCollection(this.selectionLayer .getSelectedCellPositions()); Assert.assertEquals(1, cells.size()); Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 0))); // select additional cells with shift mask // only the first cell should be selected afterwards this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 2, 10, true, false)); cells = ArrayUtil.asCollection(this.selectionLayer .getSelectedCellPositions()); Assert.assertEquals(1, cells.size()); Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 0))); // select additional cells with shift mask // only the first cell should be selected afterwards this.selectionLayer.doCommand(new SelectCellCommand(this.selectionLayer, 10, 0, true, false)); cells = ArrayUtil.asCollection(this.selectionLayer .getSelectedCellPositions()); Assert.assertEquals(1, cells.size()); Assert.assertTrue(cells.contains(new PositionCoordinate(this.selectionLayer, 2, 0))); } }