/******************************************************************************* * Copyright (c) 2014, 2016 Jonas Hugo, Markus Wahl. * 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: * Jonas Hugo <Jonas.Hugo@jeppesen.com>, * Markus Wahl <Markus.Wahl@jeppesen.com> - initial test ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.selection.preserve; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.util.Arrays; import java.util.HashSet; import org.eclipse.nebula.widgets.nattable.coordinate.Range; import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider; import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor; import org.eclipse.nebula.widgets.nattable.layer.DataLayer; import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; import org.eclipse.nebula.widgets.nattable.selection.preserve.Selections.CellPosition; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.junit.Before; import org.junit.Test; public class PreserveSelectionModelTest { private TestSelectionLayer selectionLayer; private TestRowDataProvider rowDataProvider; private TestRowIdAccessor rowIdAccessor; /** * Each row consist of an array of String, one String for each column, i e * each cell is a String. */ private PreserveSelectionModel<String[]> testee; private static String[] indexRow4 = new String[] { "row 4 hallo0", "hallo2", "hallo3" }; private static String[] indexRow5 = new String[] { "row 5 hallo0", "hallo2", "hallo3" }; private static String[] indexRow6 = new String[] { "row 6 hallo0", "hallo2", "hallo3" }; private int rowCount = 7, columnCount = 3; private TestCell[][] cells = new TestCell[7][3]; @Before public void setUp() throws Exception { this.rowDataProvider = new TestRowDataProvider(); this.rowIdAccessor = new TestRowIdAccessor(); this.selectionLayer = new TestSelectionLayer(new DataLayer(this.rowDataProvider)); /* * row 0 in the immediate table is row 4 in the underlying virtual table * coordinate system: * * row 0: A B C * * row 1: _ D E * * row 2: _ _ F */ mockCells(); this.testee = new PreserveSelectionModel<String[]>(this.selectionLayer, this.rowDataProvider, this.rowIdAccessor); } /** * row 0 in the immediate table is row 4 in the underlying virtual table * coordinate system: * * row 0: A B C * * row 1: _ D E * * row 2: _ _ F */ private void mockCells() { for (int rowIndex = 0; rowIndex < this.cells.length; rowIndex++) { for (int columnIndex = 0; columnIndex < this.cells[rowIndex].length; columnIndex++) { this.cells[rowIndex][columnIndex] = mockCell(columnIndex, rowIndex); } } } private TestCell mockCell(int columnIndex, int rowIndex) { int rowPosition = Math.max(rowIndex - 4, -1); int columnPosition = columnIndex; if (rowPosition != -1) { return new TestCell(columnPosition, rowPosition); } return new TestCell(); } @Test public void Multiple_Selection_Is_Enabled_By_Default() { assertTrue(this.testee.isMultipleSelectionAllowed()); } @Test public void Disabling_Multiple_Selection_Is_Communicated() { this.testee.setMultipleSelectionAllowed(false); assertFalse(this.testee.isMultipleSelectionAllowed()); } @Test public void Disabling_Multiple_Selection_Is_Supported() { this.testee.setMultipleSelectionAllowed(false); this.testee.addSelection(0, 0); this.testee.addSelection(2, 0); assertFalse(isCellSelected(0, 0)); assertTrue(isCellSelected(2, 0)); } @Test public void Multiple_Selection_Is_Supported() { this.testee.addSelection(0, 0); this.testee.addSelection(2, 0); assertTrue(isCellSelected(0, 0)); assertTrue(isCellSelected(2, 0)); } private boolean isCellSelected(int columnPosition, int rowPosition) { boolean singularVersion = this.testee.isCellPositionSelected(columnPosition, rowPosition); boolean rectangleVersion = false; for (Rectangle selection : this.testee.getSelections()) { if (selection.intersects(columnPosition, rowPosition, 1, 1)) { rectangleVersion = true; } } return singularVersion && rectangleVersion; } @Test public void getSelections_Ignores_Invisible_Rows() { // A is on row 0: this.testee.addSelection(0, 0); // D is not on row 0: this.testee.addSelection(1, 1); // Scroll away so that index row 4 is not visible: this.selectionLayer.scrollOffset = 5; assertEquals(1, this.testee.getSelections().size()); assertEquals(new Rectangle(1, 0, 1, 1), this.testee.getSelections() .iterator().next()); } @Test public void Add_Selection_By_Rectangle_Is_Supported() { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); assertTrue(isCellSelected(1, 0)); assertTrue(isCellSelected(1, 1)); assertTrue(isCellSelected(2, 0)); assertTrue(isCellSelected(2, 1)); assertFalse(isCellSelected(0, 0)); assertFalse(isCellSelected(2, 2)); } @Test public void Adding_Infinite_Row_Selection_Is_Truncated_Before_Stored() { this.columnCount = 3; this.testee.addSelection(new Rectangle(0, 0, Integer.MAX_VALUE, 1)); assertTrue(isCellSelected(0, 0)); assertTrue(isCellSelected(1, 0)); assertTrue(isCellSelected(2, 0)); } @Test public void Adding_Infinite_Column_Selection_Is_Truncated_Before_Stored() { this.rowCount = 6; this.testee.addSelection(new Rectangle(2, 0, 1, Integer.MAX_VALUE)); assertTrue(isCellSelected(2, 0)); assertTrue(isCellSelected(2, 1)); assertTrue(isCellSelected(2, 2)); } @Test public void Clear_Selection() { this.testee.addSelection(0, 0); this.testee.addSelection(2, 1); this.testee.clearSelection(); assertFalse(isCellSelected(0, 0)); assertFalse(isCellSelected(2, 1)); } @Test public void Clear_Infinity_Long_Row_Only_Clear_Known_Columns() { long expectedLoops = 3; this.testee.addSelection(0, 0); this.testee.addSelection(1, 0); this.rowIdAccessor.numberOfCalls = 0; this.testee.clearSelection(new Rectangle(0, 0, Integer.MAX_VALUE, 1)); assertEquals(expectedLoops, this.rowIdAccessor.numberOfCalls); assertFalse(isCellSelected(0, 0)); assertFalse(isCellSelected(1, 0)); } @Test public void Clear_Infinity_Long_Column_Only_Clear_Known_Rows() { long expectedLoops = 3; this.testee.addSelection(0, 0); this.testee.addSelection(0, 1); this.rowIdAccessor.numberOfCalls = 0; this.testee.clearSelection(new Rectangle(0, 0, 1, Integer.MAX_VALUE)); assertEquals(expectedLoops, this.rowIdAccessor.numberOfCalls); assertFalse(isCellSelected(0, 0)); assertFalse(isCellSelected(0, 1)); } @Test public void Partial_Clear_Selection() { this.testee.addSelection(0, 0); this.testee.addSelection(2, 1); this.testee.clearSelection(0, 0); assertFalse(isCellSelected(0, 0)); assertTrue(isCellSelected(2, 1)); } @Test public void Clear_Selection_By_Rectangle() { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.clearSelection(new Rectangle(1, 0, 1, 2)); assertFalse(isCellSelected(1, 0)); assertFalse(isCellSelected(1, 1)); assertTrue(isCellSelected(2, 0)); assertTrue(isCellSelected(2, 1)); this.testee.clearSelection(new Rectangle(2, 1, 1, 1)); assertTrue(isCellSelected(2, 0)); assertFalse(isCellSelected(2, 1)); } @Test public void None_Selected_Cells_Is_Empty() { assertTrue(this.testee.isEmpty()); } @Test public void Selected_Cell_Is_Not_Empty() { this.testee.addSelection(0, 0); assertFalse(this.testee.isEmpty()); } @Test public void getSelectedColumnPositions() { this.testee.addSelection(1, 1); this.testee.addSelection(0, 0); this.testee.addSelection(2, 2); int[] selectedColumns = this.testee.getSelectedColumnPositions(); assertEquals(Arrays.toString(new int[] { 0, 1, 2 }), Arrays.toString(selectedColumns)); } @Test public void isColumnPositionSelected() { int column = 0; this.testee.addSelection(column, 0); assertTrue(this.testee.isColumnPositionSelected(column)); assertFalse(this.testee.isColumnPositionSelected(2)); } @Test public void Changed_Sort_Order_Is_Properly_Reflected() { /* * row 0: A _ _ * * row 1: _ D _ * * row 2: _ _ F */ // A this.testee.addSelection(0, 0); // D this.testee.addSelection(1, 1); // F this.testee.addSelection(2, 2); assertTrue(isCellSelected(0, 0)); assertTrue(isCellSelected(1, 1)); assertTrue(isCellSelected(2, 2)); /* * sort * * row 0: _ _ F * * row 1: _ D _ * * row 2: A _ _ */ // let index row 4 and index row 6 change places: TestCell[] oldRow4 = this.cells[4]; TestCell[] oldRow6 = this.cells[6]; this.cells[4] = oldRow6; this.cells[6] = oldRow4; TestCell cellF = this.cells[4][2]; TestCell cellA = this.cells[6][0]; cellF.rowPosition = 0; // Position if index 4 cellA.rowPosition = 2; // Position if index 6 this.rowDataProvider.indexOfRow4 = 6; this.rowDataProvider.indexOfRow6 = 4; assertTrue(isCellSelected(2, 0)); assertTrue(isCellSelected(1, 1)); assertTrue(isCellSelected(0, 2)); } @Test public void isColumnFullySelected() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); assertFalse(this.testee.isColumnPositionFullySelected(1, 3)); assertTrue(this.testee.isColumnPositionFullySelected(1, 2)); } @Test public void isColumnFullySelected_Copes_With_Clear() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.clearSelection(1, 0); assertFalse(this.testee.isColumnPositionFullySelected(1, 2)); assertTrue(this.testee.isColumnPositionFullySelected(1, 1)); } @Test public void isColumnFullySelected_Copes_With_Gap() throws Exception { this.testee.addSelection(2, 0); this.testee.addSelection(2, 2); assertFalse(this.testee.isColumnPositionFullySelected(2, 2)); } @Test public void isColumnFullySelected_Copes_With_Overlapping_Regions() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.addSelection(new Rectangle(2, 1, 1, 2)); assertTrue(this.testee.isColumnPositionFullySelected(2, 3)); } @Test public void isColumnFullySelected_Copes_With_Combining_Adjacent_Individually_Selected_Cells() throws Exception { this.testee.addSelection(1, 0); this.testee.addSelection(1, 1); assertTrue(this.testee.isColumnPositionFullySelected(1, 2)); } @Test public void isColumnPositionFullySelected_For_Unselected_Column() { assertFalse(this.testee.isColumnPositionFullySelected(1, 2)); } @Test public void getFullySelectedColumnPositions() { this.testee.addSelection(0, 0); this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.addSelection(new Rectangle(2, 1, 1, 2)); int[] fullySelectedColumns = this.testee.getFullySelectedColumnPositions(2); assertEquals(Arrays.toString(new int[] { 1, 2 }), Arrays.toString(fullySelectedColumns)); fullySelectedColumns = this.testee.getFullySelectedColumnPositions(1); assertEquals(Arrays.toString(new int[] { 0, 1, 2 }), Arrays.toString(fullySelectedColumns)); fullySelectedColumns = this.testee.getFullySelectedColumnPositions(3); assertEquals(Arrays.toString(new int[] { 2 }), Arrays.toString(fullySelectedColumns)); } @Test public void getSelectedRowCount() { this.testee.addSelection(1, 1); this.testee.addSelection(0, 0); this.testee.addSelection(2, 2); assertEquals(3, this.testee.getSelectedRowCount()); } @Test public void getSelectedRowPositions() { this.testee.addSelection(1, 1); this.testee.addSelection(0, 0); this.testee.addSelection(2, 2); HashSet<Range> actualSelectedRowPositions = new HashSet<Range>( this.testee.getSelectedRowPositions()); HashSet<Range> expectedSelectedRowPositions = new HashSet<Range>(); expectedSelectedRowPositions.add(new Range(0, 1)); expectedSelectedRowPositions.add(new Range(1, 2)); expectedSelectedRowPositions.add(new Range(2, 3)); assertEquals(expectedSelectedRowPositions, actualSelectedRowPositions); } @Test public void isRowPositionSelected() { int row = 0; this.testee.addSelection(0, row); assertTrue(this.testee.isRowPositionSelected(row)); assertFalse(this.testee.isRowPositionSelected(2)); } @Test public void isRowPositionFullySelected() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); assertFalse(this.testee.isRowPositionFullySelected(0, 3)); assertTrue(this.testee.isRowPositionFullySelected(0, 2)); } @Test public void isRowPositionFullySelected_Copes_With_Clear() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.clearSelection(1, 0); assertFalse(this.testee.isRowPositionFullySelected(0, 2)); assertTrue(this.testee.isRowPositionFullySelected(0, 1)); } @Test public void isRowPositionFullySelected_Copes_With_Gap() throws Exception { this.testee.addSelection(2, 0); this.testee.addSelection(0, 0); assertFalse(this.testee.isRowPositionFullySelected(0, 2)); } @Test public void isRowPositionFullySelected_Copes_With_Overlapping_Regions() throws Exception { this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.addSelection(new Rectangle(0, 0, 3, 1)); assertTrue(this.testee.isRowPositionFullySelected(0, 3)); } @Test public void isRowPositionFullySelected_Copes_With_Combining_Adjacent_Individually_Selected_Cells() throws Exception { this.testee.addSelection(1, 0); this.testee.addSelection(2, 0); assertTrue(this.testee.isRowPositionFullySelected(0, 2)); } @Test public void isRowPositionFullySelected_For_Unselected_Row() { assertFalse(this.testee.isRowPositionFullySelected(0, 3)); } @Test public void getFullySelectedRowPositions() { this.testee.addSelection(0, 0); this.testee.addSelection(new Rectangle(1, 0, 2, 2)); this.testee.addSelection(new Rectangle(2, 1, 1, 2)); int[] fullySelectedRows = this.testee.getFullySelectedRowPositions(2); assertEquals(Arrays.toString(new int[] { 0, 1 }), Arrays.toString(fullySelectedRows)); fullySelectedRows = this.testee.getFullySelectedRowPositions(1); assertEquals(Arrays.toString(new int[] { 0, 1, 2 }), Arrays.toString(fullySelectedRows)); fullySelectedRows = this.testee.getFullySelectedRowPositions(3); assertEquals(Arrays.toString(new int[] { 0 }), Arrays.toString(fullySelectedRows)); } // Anchor @Test public void getSelectionAnchor_Copes_With_Missing_Marker() throws Exception { assertEquals(SelectionLayer.NO_SELECTION, this.testee.getSelectionAnchor().x); assertEquals(SelectionLayer.NO_SELECTION, this.testee.getSelectionAnchor().y); } @Test public void getSelectionAnchor() throws Exception { this.testee.selectionAnchor = new CellPosition<String[]>(indexRow4, 0); assertEquals(0, this.testee.getSelectionAnchor().x); assertEquals(0, this.testee.getSelectionAnchor().y); } @Test public void setSelectionAnchor() throws Exception { this.testee.setSelectionAnchor(new Point(0, 0)); assertSame(indexRow4, this.testee.selectionAnchor.getRowObject()); } // Last selected cell @Test public void getLastSelectedCell_Copes_With_Missing_Marker() throws Exception { assertEquals(SelectionLayer.NO_SELECTION, this.testee.getLastSelectedCell().x); assertEquals(SelectionLayer.NO_SELECTION, this.testee.getLastSelectedCell().y); } @Test public void getLastSelectedCell() throws Exception { this.testee.lastSelectedCell = new CellPosition<String[]>(indexRow4, 0); assertEquals(0, this.testee.getLastSelectedCell().x); assertEquals(0, this.testee.getLastSelectedCell().y); } @Test public void setLastSelectedCell() throws Exception { this.testee.setLastSelectedCell(new Point(0, 0)); assertSame(indexRow4, this.testee.lastSelectedCell.getRowObject()); } // Last selected region @Test public void getLastSelectedRegion_Copes_With_Missing_Marker() throws Exception { assertNull(this.testee.getLastSelectedRegion()); } @Test public void getLastSelectedRegion() throws Exception { this.testee.lastSelectedRegion = new Rectangle(0, 0, 1, 1); this.testee.lastSelectedRegionOriginRowObject = indexRow6; assertEquals(2, this.testee.getLastSelectedRegion().y); } @Test public void setLastSelectedRegion_Overrides_Reference() throws Exception { Rectangle oldReference = new Rectangle(0, 0, 1, 1); this.testee.lastSelectedRegion = oldReference; Rectangle newReference = new Rectangle(0, 0, 1, 1); this.testee.setLastSelectedRegion(newReference); assertSame(newReference, this.testee.lastSelectedRegion); assertSame(indexRow4, this.testee.lastSelectedRegionOriginRowObject); } @Test public void setLastSelectedRegion_Clears_Region_On_NULL() throws Exception { this.testee.lastSelectedRegion = new Rectangle(0, 0, 1, 1); this.testee.setLastSelectedRegion(null); assertNull(this.testee.lastSelectedRegion); } @Test public void setLastSelectedRegion_On_Parameters_Copys_Data() throws Exception { Rectangle oldReference = new Rectangle(0, 0, 1, 1); this.testee.lastSelectedRegion = oldReference; this.testee.setLastSelectedRegion(1, 1, 2, 2); assertSame(oldReference, this.testee.lastSelectedRegion); assertEquals(new Rectangle(1, 1, 2, 2), this.testee.lastSelectedRegion); assertSame(indexRow5, this.testee.lastSelectedRegionOriginRowObject); } class TestRowDataProvider implements IRowDataProvider<String[]> { int indexOfRow4 = 4, indexOfRow5 = 5, indexOfRow6 = 6; @Override public Object getDataValue(int columnIndex, int rowIndex) { throw new UnsupportedOperationException(); } @Override public void setDataValue(int columnIndex, int rowIndex, Object newValue) { throw new UnsupportedOperationException(); } @Override public int getColumnCount() { return PreserveSelectionModelTest.this.columnCount; } @Override public int getRowCount() { return PreserveSelectionModelTest.this.rowCount; } @Override public String[] getRowObject(int rowIndex) { if (rowIndex == this.indexOfRow4) { return indexRow4; } else if (rowIndex == this.indexOfRow5) { return indexRow5; } else if (rowIndex == this.indexOfRow6) { return indexRow6; } else { throw new UnsupportedOperationException(); } } @Override public int indexOfRowObject(String[] rowObject) { if (rowObject == indexRow4) { return this.indexOfRow4; } else if (rowObject == indexRow5) { return this.indexOfRow5; } else if (rowObject == indexRow6) { return this.indexOfRow6; } else { throw new UnsupportedOperationException(); } } } class TestRowIdAccessor implements IRowIdAccessor<String[]> { long numberOfCalls = 0; @Override public Serializable getRowId(String[] rowObject) { this.numberOfCalls += 1; if (rowObject == indexRow4) { return "rowA"; } else if (rowObject == indexRow5) { return "rowB"; } else if (rowObject == indexRow6) { return "rowC"; } else { throw new UnsupportedOperationException(); } } } class TestSelectionLayer extends SelectionLayer { int scrollOffset = 4; public TestSelectionLayer(IUniqueIndexLayer underlyingLayer) { super(underlyingLayer); } @Override public int getRowIndexByPosition(int rowPosition) { int rowIndex = rowPosition + this.scrollOffset; return rowIndex < 0 || rowIndex > 6 ? -1 : rowIndex; } @Override public int getRowPositionByIndex(int rowIndex) { int rowPosition = Math.max(rowIndex - this.scrollOffset, -1); return rowPosition > 2 ? -1 : rowPosition; }; @Override public ILayerCell getCellByPosition(int columnPosition, int rowPosition) { return PreserveSelectionModelTest.this.cells[getRowIndexByPosition(rowPosition)][columnPosition]; } } class TestCell extends LayerCell { int columnPosition, rowPosition; public TestCell(int columnPosition, int rowPosition) { super(null, columnPosition, rowPosition); this.columnPosition = columnPosition; this.rowPosition = rowPosition; } public TestCell() { super(null, 0, 0, 0, 0, 0, 0); } @Override public int getOriginRowPosition() { return this.rowPosition; } @Override public int getOriginColumnPosition() { return this.columnPosition; } @Override public int getRowSpan() { return super.getRowSpan(); } @Override public int getColumnSpan() { return super.getColumnSpan(); } } }