Bug 413224: Reworked selection layer and models to better support large
data sets and to make the models independent of SWT
  - Refactored API, mainly replaced int[], List<Integer> and similar
    position references by RangeList and SWT Rectangle by our version
  - Improved implementation of selection model, especially reduced the
    memory consumption when calculating fully selected columns/rows

Incompatible API changes:
  - Changed method signatures = if methods are used by external code, it
    may be necessary to adapted the code (class RangeList offers different
    constructors to easily create such list, use RangeList#values() to
    get single position values)
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandlerTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandlerTest.java
index 2bf5738..62d129c 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandlerTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandlerTest.java
@@ -18,7 +18,18 @@
 import java.util.Iterator;
 import java.util.Set;
 
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
 import org.eclipse.nebula.widgets.nattable.grid.command.ClientAreaResizeCommand;
 import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
@@ -30,13 +41,7 @@
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand;
 import org.eclipse.nebula.widgets.nattable.test.fixture.data.DataProviderFixture;
 import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
+
 
 public class CopyDataCommandHandlerTest {
 
@@ -112,13 +117,14 @@
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 9, 9, false, true));
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 1, 0, false, true));
 
-		ILayerCell[][] columns = commandHandler.assembleColumnHeaders();
+		RangeList selectedColumns = selectionLayer.getSelectedColumnPositions();
+		ILayerCell[] columns = commandHandler.assembleColumnHeader(selectedColumns, 1, 0);
 
 		assertEquals(5, columns.length);
-		assertEquals("Column 2", columns[0][1].getDataValue());
-		assertEquals("Column 3", columns[0][2].getDataValue());
-		assertEquals("Column 5", columns[0][3].getDataValue());
-		assertEquals("Column 10", columns[0][4].getDataValue());
+		assertEquals("Column 2", columns[1].getDataValue());
+		assertEquals("Column 3", columns[2].getDataValue());
+		assertEquals("Column 5", columns[3].getDataValue());
+		assertEquals("Column 10", columns[4].getDataValue());
 	}
 
 	@Test
@@ -131,12 +137,13 @@
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 9, 9, false, true));
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 5, 0, false, true));
 
-		ILayerCell[] bodyCells = commandHandler.assembleBody(0);
+		RangeList selectedColumns = selectionLayer.getSelectedColumnPositions();
+		ILayerCell[] bodyCells = commandHandler.assembleBody(selectedColumns, 1, 0);
 		assertEquals(8, bodyCells.length);
 		assertEquals("[5,0]", bodyCells[4].getDataValue());
 		assertEquals("[8,0]", bodyCells[6].getDataValue());
 
-		bodyCells = commandHandler.assembleBody(9);
+		bodyCells = commandHandler.assembleBody(selectedColumns, 1, 9);
 		assertEquals("[9,9]", bodyCells[7].getDataValue());
 	}
 
@@ -199,18 +206,20 @@
 		// First cell should be blank, this is the corner
 		assertNull(cells[0]);
 		// Should only have Column headers
-		int[] selectedColumns = gridLayer.getBodyLayer().getSelectionLayer().getSelectedColumnPositions();
+		final RangeList selectedColumns = selectionLayer.getSelectedColumnPositions();
+		
+		IValueIterator columnsIter = selectedColumns.values().iterator();
 		for (int columnPosition = 1; columnPosition < cells.length; columnPosition++) {
 			ILayerCell cell = cells[columnPosition];
 			// Remember to substract offset from columnPosition
-			assertEquals(columnHeaderLayer.getDataValueByPosition(selectedColumns[columnPosition - 1], 0), cell.getDataValue());
+			assertEquals(columnHeaderLayer.getDataValueByPosition(columnsIter.nextValue(), 0), cell.getDataValue());
 		}
 	}
 
 	private void checkBodyCells(ILayerCell[][] copiedGrid) {
 		int cellWithDataCounter = 0;
-		int[] selectedColumns = selectionLayer.getSelectedColumnPositions();
-		Set<Range> selectedRowRanges = selectionLayer.getSelectedRowPositions();
+		RangeList selectedColumns = selectionLayer.getSelectedColumnPositions();
+		RangeList selectedRowRanges = selectionLayer.getSelectedRowPositions();
 
 		Set<Integer> selectedRows = new HashSet<Integer>();
 		for (Range range : selectedRowRanges) {
@@ -219,6 +228,7 @@
 		Iterator<Integer> rowsIterator = selectedRows.iterator();
 
 		// Row zero is for column headers
+		IValueIterator columnsIter = selectedColumns.values().iterator();
 		for (int rowPosition = 1; rowPosition < copiedGrid.length; rowPosition ++) {
 			ILayerCell[] cells = copiedGrid[rowPosition];
 
@@ -231,11 +241,11 @@
 				final ILayerCell cell = cells[columnPosition];
 				if (cell != null) {
 					cellWithDataCounter++;
-					assertEquals(selectionLayer.getDataValueByPosition(selectedColumns[columnPosition - 1], selectedRowPosition), cell
+					assertEquals(selectionLayer.getDataValueByPosition(columnsIter.nextValue(), selectedRowPosition), cell
 							.getDataValue());
 				}
 			}
 		}
-		assertEquals(selectionLayer.getSelectedCellPositions().length, cellWithDataCounter);
+		assertEquals(selectionLayer.getSelectedCellPositions().size(), cellWithDataCounter);
 	}
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/resize/AutoResizeColumnsTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/resize/AutoResizeColumnsTest.java
index e5e8427..98f30e8 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/resize/AutoResizeColumnsTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/resize/AutoResizeColumnsTest.java
@@ -13,6 +13,18 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
 import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
@@ -35,16 +47,7 @@
 import org.eclipse.nebula.widgets.nattable.util.GCFactory;
 import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
 import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+
 
 public class AutoResizeColumnsTest {
 
@@ -135,7 +138,7 @@
 		SelectionLayer selectionLayer = ((DefaultBodyLayerStack) gridLayer.getBodyLayer()).getSelectionLayer();
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 0, 0, false, false));
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 1, 0, true, false));
-		assertEquals(2, selectionLayer.getFullySelectedColumnPositions().length);
+		assertEquals(2, selectionLayer.getFullySelectedColumnPositions().values().size());
 
 		// Resize grid column 5
 		gridLayer.doCommand(new ColumnResizeCommand(gridLayer, 5, 10));
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategyTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategyTest.java
index 571ecfd..dfeef65 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategyTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategyTest.java
@@ -10,6 +10,11 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.search.strategy;
 
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
 
 import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
@@ -18,11 +23,8 @@
 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.search.CellValueAsStringComparator;
-import org.eclipse.nebula.widgets.nattable.search.strategy.ColumnSearchStrategy;
 import org.eclipse.nebula.widgets.nattable.test.fixture.layer.GridLayerFixture;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+
 
 public class ColumnSearchStrategyTest {
 
@@ -42,16 +44,16 @@
 		// Choose three columns for searching
 		ColumnSearchStrategy columnSearchStrategy = new ColumnSearchStrategy(new int[]{2,5,8}, configRegistry);
 		columnSearchStrategy.setComparator(new CellValueAsStringComparator<Comparable<String>>());
-		PositionCoordinate[] cellsToSearch = columnSearchStrategy.getColumnCellsToSearch(layer);
+		List<PositionCoordinate> cellsToSearch = columnSearchStrategy.getColumnCellsToSearch(layer);
 
-		PositionCoordinate cell = cellsToSearch[0];
+		PositionCoordinate cell = cellsToSearch.get(0);
 		Assert.assertEquals(2, cell.columnPosition);
-		cell = cellsToSearch[5];
+		cell = cellsToSearch.get(5);
 		Assert.assertEquals(5, cell.columnPosition);
-		cell = cellsToSearch[10];
+		cell = cellsToSearch.get(10);
 		Assert.assertEquals(8, cell.columnPosition);
 
-		Assert.assertEquals(15, cellsToSearch.length);
+		Assert.assertEquals(15, cellsToSearch.size());
 	}
 
 	@Test
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategyTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategyTest.java
index 88c35b5..1871ec8 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategyTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategyTest.java
@@ -10,6 +10,11 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.search.strategy;
 
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
 
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
@@ -17,11 +22,8 @@
 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.search.CellValueAsStringComparator;
-import org.eclipse.nebula.widgets.nattable.search.strategy.RowSearchStrategy;
 import org.eclipse.nebula.widgets.nattable.test.fixture.layer.GridLayerFixture;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+
 
 public class RowSearchStrategyTest {
 	
@@ -41,14 +43,14 @@
 	public void shouldAccessCellInSelectedRow() {
 		// Select three rows for searching
 		RowSearchStrategy rowStrategy = new RowSearchStrategy(new int[]{0,2,4}, configRegistry);
-		PositionCoordinate[] cellsToSearch = rowStrategy.getRowCellsToSearch(layer);
-		PositionCoordinate cell = cellsToSearch[0];
+		List<PositionCoordinate> cellsToSearch = rowStrategy.getRowCellsToSearch(layer);
+		PositionCoordinate cell = cellsToSearch.get(0);
 		Assert.assertEquals(0, cell.getRowPosition());
-		cell = cellsToSearch[10];
+		cell = cellsToSearch.get(10);
 		Assert.assertEquals(2, cell.getRowPosition());
-		cell = cellsToSearch[20];
+		cell = cellsToSearch.get(20);
 		Assert.assertEquals(4, cell.getRowPosition());
-		Assert.assertEquals(30, cellsToSearch.length);
+		Assert.assertEquals(30, cellsToSearch.size());
 	}
 	@Test
 	public void shouldSearchAllBodyCellsForRowInSelection() {
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategyTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategyTest.java
index 90b1c94..f017dea 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategyTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategyTest.java
@@ -10,6 +10,16 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.search.strategy;
 
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
 
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
@@ -19,19 +29,12 @@
 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer;
 import org.eclipse.nebula.widgets.nattable.search.CellValueAsStringComparator;
 import org.eclipse.nebula.widgets.nattable.search.ISearchDirection;
-import org.eclipse.nebula.widgets.nattable.search.strategy.SelectionSearchStrategy;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectAllCommand;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand;
 import org.eclipse.nebula.widgets.nattable.test.fixture.layer.GridLayerFixture;
 import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+
 
 public class SelectionSearchStrategyTest {
 
@@ -98,8 +101,8 @@
 		
 		// We should get 20 Cells from the body		
 		SelectionSearchStrategy selectionStrategy = new SelectionSearchStrategy(configRegistry);
-		PositionCoordinate[] cellsToSearch = selectionStrategy.getSelectedCells(gridLayer.getBodyLayer().getSelectionLayer());
-		Assert.assertEquals(20, cellsToSearch.length);
+		List<PositionCoordinate> cellsToSearch = selectionStrategy.getSelectedCells(gridLayer.getBodyLayer().getSelectionLayer());
+		Assert.assertEquals(20, cellsToSearch.size());
 	}
 
 	@Test
@@ -110,7 +113,7 @@
 		gridLayer.doCommand(new SelectCellCommand(gridLayer, 5, 4, false, true));
 		gridLayer.doCommand(new SelectCellCommand(gridLayer, 6, 2, false, true));
 		
-		Assert.assertEquals(5, gridLayer.getBodyLayer().getSelectionLayer().getSelectedCellPositions().length);
+		Assert.assertEquals(5, gridLayer.getBodyLayer().getSelectionLayer().getSelectedCellPositions().size());
 		
 		final SelectionLayer selectionLayer = gridLayer.getBodyLayer().getSelectionLayer();
 		SelectionSearchStrategy selectionStrategy = new SelectionSearchStrategy(configRegistry);
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTest.java
index 6c9c781..6f49755 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTest.java
@@ -14,16 +14,18 @@
 import static org.junit.Assert.assertEquals;
 
 import java.util.Collection;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
 
 import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
 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 {
 
@@ -58,12 +60,13 @@
 
 	private boolean wasPreviousSelectionCleared() {
 		// Make sure previous selection was cleared
-		return (selectionLayer.getSelectedColumnPositions().length == 1 && selectionLayer.getSelectedRowCount() == 1);
+		return (selectionLayer.getSelectedColumnPositions().values().size() == 1
+				&& selectionLayer.getSelectedRowCount() == 1);
 	}
 
 	private boolean wasPreviousColumnSelectionAppended() {
 		// Make sure previous column selection was not cleared
-		return selectionLayer.getSelectedColumnPositions().length > 1;
+		return selectionLayer.getSelectedColumnPositions().values().size() > 1;
 	}
 
 	private boolean wasPreviousRowSelectionAppended() {
@@ -377,20 +380,20 @@
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 1, 0, false, true));
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 9, 9, false, true));
 
-		PositionCoordinate[] cells = selectionLayer.getSelectedCellPositions();
-		Assert.assertEquals(4, cells.length);
+		List<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
+		Assert.assertEquals(4, cells.size());
 		// (1, 0)
-		Assert.assertEquals(1, cells[0].columnPosition);
-		Assert.assertEquals(0, cells[0].rowPosition);
+		Assert.assertEquals(1, cells.get(0).columnPosition);
+		Assert.assertEquals(0, cells.get(0).rowPosition);
 		// (2, 3)
-		Assert.assertEquals(2, cells[1].columnPosition);
-		Assert.assertEquals(3, cells[1].rowPosition);
+		Assert.assertEquals(2, cells.get(1).columnPosition);
+		Assert.assertEquals(3, cells.get(1).rowPosition);
 		// (4, 1)
-		Assert.assertEquals(4, cells[2].columnPosition);
-		Assert.assertEquals(1, cells[2].rowPosition);
+		Assert.assertEquals(4, cells.get(2).columnPosition);
+		Assert.assertEquals(1, cells.get(2).rowPosition);
 		// (9, 9)
-		Assert.assertEquals(9, cells[3].columnPosition);
-		Assert.assertEquals(9, cells[3].rowPosition);
+		Assert.assertEquals(9, cells.get(3).columnPosition);
+		Assert.assertEquals(9, cells.get(3).rowPosition);
 	}
 
 	@Test
@@ -403,7 +406,7 @@
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 1, 2, false, true));
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 2, 2, false, true));
 
-		Collection<PositionCoordinate> cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		Collection<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
 
 		Assert.assertEquals(6, cells.size());
 		// (1, 0)
@@ -427,14 +430,14 @@
 		selectionLayer.clear();
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 1, 0, false, true));
 
-		Collection<PositionCoordinate> cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		Collection<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(1, cells.size());
 		Assert.assertTrue(cells.contains(new PositionCoordinate(selectionLayer, 1, 0)));
 
 		//select another cell with control mask
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 2, 0, false, true));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(1, cells.size());
 		Assert.assertTrue(cells.contains(new PositionCoordinate(selectionLayer, 2, 0)));
 
@@ -442,7 +445,7 @@
 		//only the first cell should be selected afterwards
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 2, 10, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(1, cells.size());
 		Assert.assertTrue(cells.contains(new PositionCoordinate(selectionLayer, 2, 0)));
 
@@ -450,7 +453,7 @@
 		//only the first cell should be selected afterwards
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 10, 0, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(1, cells.size());
 		Assert.assertTrue(cells.contains(new PositionCoordinate(selectionLayer, 2, 0)));
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/ColumnSelectionTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/ColumnSelectionTest.java
index 74622cf..35fbcbe 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/ColumnSelectionTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/ColumnSelectionTest.java
@@ -15,14 +15,17 @@
 
 import java.util.Collection;
 
-import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
-import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand;
-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.Before;
 import org.junit.Test;
 
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand;
+import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture;
+
+
 public class ColumnSelectionTest {
 	// Tests for column selection NTBL-225
 
@@ -152,29 +155,32 @@
 		selectionLayer.clear();
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 1, 0, false, true));
 
-		Collection<PositionCoordinate> cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		Collection<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
+		RangeList columns = selectionLayer.getSelectedColumnPositions();
 		assertEquals(1, cells.size());
-		assertEquals(1, selectionLayer.getSelectedColumnPositions().length);
-		assertEquals(1, selectionLayer.getSelectedColumnPositions()[0]);
+		assertEquals(1, columns.size());
+		assertEquals(new Range(1), columns.get(0));
 		assertEquals(1, selectionLayer.getSelectedRowCount());
 
 		//select another column with control mask
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 2, 0, false, true));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
+		columns = selectionLayer.getSelectedColumnPositions();
 		assertEquals(1, cells.size());
-		assertEquals(1, selectionLayer.getSelectedColumnPositions().length);
-		assertEquals(2, selectionLayer.getSelectedColumnPositions()[0]);
+		assertEquals(1, columns.size());
+		assertEquals(new Range(2), columns.get(0));
 		assertEquals(1, selectionLayer.getSelectedRowCount());
 
 		//select additional columns with shift mask
 		//only the last column should be selected afterwards
 		selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, 5, 0, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
+		columns = selectionLayer.getSelectedColumnPositions();
 		assertEquals(1, cells.size());
-		assertEquals(1, selectionLayer.getSelectedColumnPositions().length);
-		assertEquals(5, selectionLayer.getSelectedColumnPositions()[0]);
+		assertEquals(1, columns.size());
+		assertEquals(new Range(5), columns.get(0));
 		assertEquals(1, selectionLayer.getSelectedRowCount());
 	}
 
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionTest.java
index d720568..6a6a265 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionTest.java
@@ -15,15 +15,17 @@
 
 import java.util.Collection;
 
-import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
-import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowsCommand;
-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;
 
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowsCommand;
+import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture;
+
+
 public class RowSelectionTest {
 // Tests for column selection NTBL-225
 
@@ -56,7 +58,7 @@
 		Assert.assertEquals(2, selectionLayer.getLastSelectedCellPosition().getRowPosition());
 
 		// Cells in between should have been selected
-		Assert.assertEquals(columnCount, selectionLayer.getSelectedColumnPositions().length);
+		Assert.assertEquals(columnCount, selectionLayer.getSelectedColumnPositions().values().size());
 	}
 
 	@Test
@@ -151,8 +153,8 @@
 		Assert.assertEquals(1, lastColumnPosition);
 
 		// Cells in row should have been selected
-		final int[] selectedColumns = selectionLayer.getSelectedColumnPositions();
-		Assert.assertEquals(columnCount, selectedColumns.length);
+		final RangeList selectedColumns = selectionLayer.getSelectedColumnPositions();
+		Assert.assertEquals(columnCount, selectedColumns.values().size());
 		Assert.assertTrue(selectionLayer.isCellPositionSelected(4, 1));
 
 		// Test extending column selection to the right of previous column selection
@@ -176,7 +178,7 @@
 		selectionLayer.clear();
 		selectionLayer.doCommand(new SelectRowsCommand(selectionLayer, 1, 0, false, true));
 
-		Collection<PositionCoordinate> cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		Collection<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
 		assertEquals(1, cells.size());
 		assertEquals(1, selectionLayer.getSelectedRowPositions().size());
 		assertEquals(1, selectionLayer.getSelectedRowCount());
@@ -184,7 +186,7 @@
 		//select another row with control mask
 		selectionLayer.doCommand(new SelectRowsCommand(selectionLayer, 1, 2, false, true));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		assertEquals(1, cells.size());
 		assertEquals(1, selectionLayer.getSelectedRowPositions().size());
 		assertEquals(1, selectionLayer.getSelectedRowCount());
@@ -192,7 +194,7 @@
 		//select additional rows with shift mask
 		selectionLayer.doCommand(new SelectRowsCommand(selectionLayer, 1, 5, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		assertEquals(1, cells.size());
 		assertEquals(1, selectionLayer.getSelectedRowPositions().size());
 		assertEquals(1, selectionLayer.getSelectedRowCount());
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModelTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModelTest.java
index 1229bb7..fcffd26 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModelTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModelTest.java
@@ -8,27 +8,26 @@
  * Contributors:
  *     Original authors and others - initial API and implementation
  ******************************************************************************/
+
 package org.eclipse.nebula.widgets.nattable.selection;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-
-import org.eclipse.nebula.widgets.nattable.coordinate.Range;
-import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
-import org.eclipse.nebula.widgets.nattable.selection.SelectionModel;
-import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture;
-import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
-import org.eclipse.swt.graphics.Rectangle;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
+import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture;
+import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
+
 
 public class SelectionModelTest {
 
@@ -54,38 +53,37 @@
 
 	@Test
 	public void isColumnFullySelected() throws Exception {
-		model.addSelection(new Rectangle(3, 0, 10, 10));
+		model.addSelection(new Rectangle(3, 0, 10, 100));
 
-		assertFalse(model.isColumnPositionFullySelected(3, 11));
-		assertTrue(model.isColumnPositionFullySelected(3, 10));
+		assertTrue(model.isColumnPositionFullySelected(3));
 
 		model.clearSelection(3, 1);
-		assertFalse(model.isColumnPositionFullySelected(3, 10));
+		assertFalse(model.isColumnPositionFullySelected(3));
 	}
 
 	@Test
 	public void isColumnFullySelectedForContiguousRectangles() throws Exception {
 		model.addSelection(new Rectangle(0, 0, 10, 10));
-		model.addSelection(new Rectangle(5, 10, 10, 10));
+		model.addSelection(new Rectangle(5, 10, 10, 90));
 
-		assertTrue(model.isColumnPositionFullySelected(5, 20));
+		assertTrue(model.isColumnPositionFullySelected(5));
 	}
 
 	@Test
 	public void isColumnFullySelectedForNonContiguousRectangles() throws Exception {
 		model.addSelection(new Rectangle(0, 0, 10, 10));
 		model.addSelection(new Rectangle(5, 5, 10, 8));
-		model.addSelection(new Rectangle(5, 15, 10, 5));
+		model.addSelection(new Rectangle(5, 15, 10, 90));
 
-		assertFalse(model.isColumnPositionFullySelected(5, 20));
+		assertFalse(model.isColumnPositionFullySelected(5));
 	}
 
 	@Test
 	public void isColumnFullySelectedForOverlapingRectangles() throws Exception {
 		model.addSelection(new Rectangle(0, 0, 10, 10));
-		model.addSelection(new Rectangle(5, 5, 10, 8));
+		model.addSelection(new Rectangle(5, 5, 10, 95));
 
-		assertTrue(model.isColumnPositionFullySelected(5, 13));
+		assertTrue(model.isColumnPositionFullySelected(5));
 	}
 
 	@Test
@@ -93,97 +91,101 @@
 		model.addSelection(new Rectangle(1, 5, 1, 1));
 		model.addSelection(new Rectangle(1, 10, 1, 1));
 
-		assertFalse(model.isColumnPositionFullySelected(1, 10));
+		assertFalse(model.isColumnPositionFullySelected(1));
 	}
 
 	@Test
 	public void isColumnFullySelectedWhenLastCellSelected() throws Exception {
 		model.addSelection(new Rectangle(1, 5, 1, 1));
 
-		assertFalse(model.isColumnPositionFullySelected(1, 6));
-		assertFalse(model.isColumnPositionFullySelected(1, 1000000));
+		assertFalse(model.isColumnPositionFullySelected(1));
 	}
 	
 	@Test
 	public void isRowFullySelected() throws Exception {
-		model.addSelection(new Rectangle(0,3,10,10));
-		assertTrue(model.isRowPositionFullySelected(3, 10));
+		model.addSelection(new Rectangle(0, 3, 100, 10));
+		
+		assertTrue(model.isRowPositionFullySelected(3));
 	}
 
 	@Test
 	public void isRowFullySelectedWhenMultipleRowsAndColumnsAreSelected() throws Exception {
 		//Rows 3, 6 fully selected
-		model.addSelection(new Rectangle(0,3,10,1));
-		model.addSelection(new Rectangle(0,6,10,1));
+		model.addSelection(new Rectangle(0, 3, 100, 1));
+		model.addSelection(new Rectangle(0, 6, 100, 1));
 		
 		//Column 2, 5 fully selected
-		model.addSelection(new Rectangle(2, 0,1,10));
-		model.addSelection(new Rectangle(5, 0,1,10));
+		model.addSelection(new Rectangle(2, 0, 1, 100));
+		model.addSelection(new Rectangle(5, 0, 1, 100));
 		
-		assertTrue(model.isRowPositionFullySelected(6, 10));
-		assertTrue(model.isRowPositionFullySelected(3, 10));
+		assertTrue(model.isRowPositionFullySelected(6));
+		assertTrue(model.isRowPositionFullySelected(3));
 		
 		// Remove Column 2
-		model.clearSelection(new Rectangle(2, 0,1,10));
-		assertFalse(model.isRowPositionFullySelected(6, 10));
-		assertFalse(model.isRowPositionFullySelected(3, 10));
+		model.clearSelection(new Rectangle(2, 0, 1, 100));
+		assertFalse(model.isRowPositionFullySelected(6));
+		assertFalse(model.isRowPositionFullySelected(3));
 		
 		//Add column 2 again
-		model.addSelection(new Rectangle(2, 0,1,10));
-		assertTrue(model.isRowPositionFullySelected(6, 10));
-		assertTrue(model.isRowPositionFullySelected(3, 10));
+		model.addSelection(new Rectangle(2, 0, 1, 100));
+		assertTrue(model.isRowPositionFullySelected(6));
+		assertTrue(model.isRowPositionFullySelected(3));
 	}
 
 	@Test
 	public void isRowNotFullySelected() throws Exception {
-		model.addSelection(new Rectangle(0,3,10,10));
+		model.addSelection(new Rectangle(0, 3, 10, 10));
 		
-		assertFalse(model.isRowPositionFullySelected(3, 11));
+		assertFalse(model.isRowPositionFullySelected(3));
 	}
 	
 	@Test
 	public void contains() throws Exception {
-		assertTrue(model.contains(new Rectangle(0, 0, 10, 10), new Rectangle(1, 1, 5, 5)));
-		assertTrue(model.contains(new Rectangle(0, 0, 10, 1), new Rectangle(5, 0, 1, 1)));
+		assertTrue(new Rectangle(0, 0, 10, 10).contains(new Rectangle(1, 1, 5, 5)));
+		assertTrue(new Rectangle(0, 0, 10, 1).contains(new Rectangle(5, 0, 1, 1)));
 		
-		assertFalse(model.contains(new Rectangle(0, 6, 0, 0), new Rectangle(2, 6, 1, 1)));
+		assertFalse(new Rectangle(0, 6, 0, 0).contains(new Rectangle(2, 6, 1, 1)));
 	}
 	
 	@Test
 	public void isMltipleCol() throws Exception {
-		model.addSelection(new Rectangle(1,0,1,20));
-		model.addSelection(new Rectangle(2,0,1,20));
-		model.addSelection(new Rectangle(3,0,1,20));
+		model.addSelection(new Rectangle(1, 0, 1, 100));
+		model.addSelection(new Rectangle(2, 0, 1, 100));
+		model.addSelection(new Rectangle(3, 0, 1, 100));
 		
-		assertFalse(model.isColumnPositionFullySelected(1, 21));
-		assertTrue(model.isColumnPositionFullySelected(2, 20));
+		assertTrue(model.isColumnPositionFullySelected(1));
+		assertTrue(model.isColumnPositionFullySelected(2));
+		assertFalse(model.isColumnPositionFullySelected(4));
 	}
 	
 	@Test
 	public void shouldReturnListOfFullySelectedColumns() throws Exception {
-		model.addSelection(new Rectangle(1,0,1,20));
-		model.addSelection(new Rectangle(2,10,1,4));
-		model.addSelection(new Rectangle(3,0,1,20));
+		RangeList fullySelectedColumns = model.getFullySelectedColumnPositions();
+		Assert.assertEquals(0, fullySelectedColumns.size());
 		
-		int[] fullySelectedColumns = model.getFullySelectedColumnPositions(20);
-		Assert.assertEquals(2, fullySelectedColumns.length);
-		Assert.assertEquals(1, fullySelectedColumns[0]);
-		Assert.assertEquals(3, fullySelectedColumns[1]);
+		model.addSelection(new Rectangle(1, 0, 1, 100));
+		model.addSelection(new Rectangle(2, 10, 1, 4));
+		model.addSelection(new Rectangle(3, 0, 1, 100));
+		
+		fullySelectedColumns = model.getFullySelectedColumnPositions();
+		Assert.assertEquals(2, fullySelectedColumns.size());
+		Assert.assertEquals(new Range(1), fullySelectedColumns.get(0));
+		Assert.assertEquals(new Range(3), fullySelectedColumns.get(1));
 	}
 	
 	@Test 
 	public void shouldReturnListOfFullySelectedRows() throws Exception {
-		int[] fullySelectedRows = model.getFullySelectedRowPositions(20);
-		Assert.assertEquals(0, fullySelectedRows.length);
+		RangeList fullySelectedRows = model.getFullySelectedRowPositions();
+		Assert.assertEquals(0, fullySelectedRows.size());
 
-		model.addSelection(new Rectangle(0,1,20,1));
-		model.addSelection(new Rectangle(3,2,4,1));
-		model.addSelection(new Rectangle(0,3,20,1));
+		model.addSelection(new Rectangle(0, 1, 100, 1));
+		model.addSelection(new Rectangle(3, 2, 4, 1));
+		model.addSelection(new Rectangle(0, 3, 100, 1));
 		
-		fullySelectedRows = model.getFullySelectedRowPositions(20);
-		Assert.assertEquals(2, fullySelectedRows.length);
-		Assert.assertEquals(1, fullySelectedRows[0]);
-		Assert.assertEquals(3, fullySelectedRows[1]);
+		fullySelectedRows = model.getFullySelectedRowPositions();
+		Assert.assertEquals(2, fullySelectedRows.size());
+		Assert.assertEquals(new Range(1), fullySelectedRows.get(0));
+		Assert.assertEquals(new Range(3), fullySelectedRows.get(1));
 	}
 	
 	@Test
@@ -587,11 +589,11 @@
 			model.addSelection(column, column % 3);
 		}
 		
-		int [] selectedColumns = model.getSelectedColumnPositions();
+		RangeList selectedColumns = model.getSelectedColumnPositions();
 		
 		Arrays.sort(columns);
 		
-		assertEquals(Arrays.toString(columns), Arrays.toString(selectedColumns));
+		assertEquals(Arrays.toString(columns), RangeList.listValues(selectedColumns).toString());
 	}
 	
 	@Test
@@ -715,19 +717,4 @@
 		removeRangeFromRange(col, row, numCols, numRows, removedRow, removedColumn, removedNumCols, removedNumRows);
 	}
 	
-	@Test
-	public void sortByY() throws Exception {
-		List<Rectangle> rectangles = new ArrayList<Rectangle>();
-		rectangles.add(new Rectangle(0, 3, 1, 1));
-		rectangles.add(new Rectangle(0, 5, 1, 1));
-		rectangles.add(new Rectangle(0, 1, 1, 1));
-		rectangles.add(new Rectangle(0, 13, 1, 1));
-
-		model.sortByY(rectangles);
-		
-		Assert.assertEquals(1, rectangles.get(0).y);
-		Assert.assertEquals(3, rectangles.get(1).y);
-		Assert.assertEquals(5, rectangles.get(2).y);
-		Assert.assertEquals(13, rectangles.get(3).y);
-	}
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandlerTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandlerTest.java
index 9a8ea55..2c33cc4 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandlerTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandlerTest.java
@@ -18,10 +18,15 @@
 import java.util.List;
 import java.util.Properties;
 
+import org.junit.Before;
+import org.junit.Test;
+
+import org.eclipse.swt.widgets.Shell;
 
 import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
 import org.eclipse.nebula.widgets.nattable.layer.stack.DummyGridLayerStack;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
@@ -31,15 +36,11 @@
 import org.eclipse.nebula.widgets.nattable.style.Style;
 import org.eclipse.nebula.widgets.nattable.style.VerticalAlignmentEnum;
 import org.eclipse.nebula.widgets.nattable.style.editor.ColumnStyleEditorDialog;
-import org.eclipse.nebula.widgets.nattable.style.editor.command.DisplayColumnStyleEditorCommand;
-import org.eclipse.nebula.widgets.nattable.style.editor.command.DisplayColumnStyleEditorCommandHandler;
 import org.eclipse.nebula.widgets.nattable.test.fixture.CellStyleFixture;
 import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
 import org.eclipse.nebula.widgets.nattable.test.fixture.PropertiesFixture;
 import org.eclipse.nebula.widgets.nattable.test.fixture.layer.DataLayerFixture;
-import org.eclipse.swt.widgets.Shell;
-import org.junit.Before;
-import org.junit.Test;
+
 
 public class DisplayColumnStyleEditorCommandHandlerTest {
 
@@ -63,7 +64,7 @@
 	@Test
 	public void doCommand() throws Exception {
 		handlerUnderTest.dialog = new ColumnStyleEditorDialog(new Shell(), new CellStyleFixture());
-		handlerUnderTest.applySelectedStyleToColumns(commandFixture, new int[]{0});
+		handlerUnderTest.applySelectedStyleToColumns(commandFixture, new RangeList(0));
 
 		Style selectedStyle = (Style) configRegistryFixture.getConfigAttribute(CELL_STYLE, NORMAL, handlerUnderTest.getConfigLabel(0));
 
@@ -102,7 +103,7 @@
 	@Test
 	public void shouldRemoveLabelFromPersistenceIfStyleIsCleared() throws Exception {
 		handlerUnderTest.dialog = new ColumnStyleEditorDialog(new Shell(), null);
-		handlerUnderTest.applySelectedStyleToColumns(commandFixture, new int[]{0});
+		handlerUnderTest.applySelectedStyleToColumns(commandFixture, new RangeList(0));
 
 		Style selectedStyle = (Style) configRegistryFixture.getConfigAttribute(CELL_STYLE, NORMAL, handlerUnderTest.getConfigLabel(0));
 
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/test/integration/SelectionIntegrationTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/test/integration/SelectionIntegrationTest.java
index 7694196..4b01756 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/test/integration/SelectionIntegrationTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/test/integration/SelectionIntegrationTest.java
@@ -12,16 +12,20 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.eclipse.swt.SWT;
+
 import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer;
 import org.eclipse.nebula.widgets.nattable.layer.stack.DummyGridLayerStack;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand;
 import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
-import org.eclipse.swt.SWT;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
 
 /**
  * Integration test for all default selection behavior.
@@ -45,23 +49,28 @@
 
 	@Test
 	public void movingSelectionWithLeftArrow() throws Exception {
+		List<PositionCoordinate> selectedCells;
+		
 		natTable.doCommand(new SelectCellCommand(natTable, 5, 2, NO_SHIFT, NO_CTRL));
 
 		// Note: the co-ordinates from this point on are in selection later co-ordinates
 
 		SWTUtils.pressKey(SWT.ARROW_LEFT, natTable);
-		assertPositionEquals(3, 1, getSelectedCells()[0]);
+		selectedCells = selectionLayer.getSelectedCellPositions();
+		assertPositionEquals(3, 1, selectedCells.get(0));
 		assertSelectionAnchorEquals(3, 1);
 
 		SWTUtils.pressKey(SWT.ARROW_LEFT, SWT.SHIFT, natTable);
+		selectedCells = selectionLayer.getSelectedCellPositions();
 		assertSelectCellsCount(2);
-		assertPositionEquals(2, 1, getSelectedCells()[0]);
-		assertPositionEquals(3, 1, getSelectedCells()[1]);
+		assertPositionEquals(2, 1, selectedCells.get(0));
+		assertPositionEquals(3, 1, selectedCells.get(1));
 		assertSelectionAnchorEquals(3, 1);
 
 		SWTUtils.pressKey(SWT.ARROW_LEFT, SWT.MOD1, natTable);
+		selectedCells = selectionLayer.getSelectedCellPositions();
 		assertSelectCellsCount(1);
-		assertPositionEquals(0, 1, getSelectedCells()[0]);
+		assertPositionEquals(0, 1, selectedCells.get(0));
 		assertSelectionAnchorEquals(0, 1);
 	}
 
@@ -83,7 +92,7 @@
 
 		SWTUtils.pressKey(SWT.ARROW_RIGHT, SWT.MOD1, natTable);
 		assertSelectCellsCount(1);
-		assertPositionEquals(9, 1, selectionLayer.getSelectedCellPositions()[0]);
+		assertPositionEquals(9, 1, selectionLayer.getSelectedCellPositions().get(0));
 		assertPositionEquals(9, 1, selectionLayer.getLastSelectedCellPosition());
 		assertSelectionAnchorEquals(9, 1);
 	}
@@ -109,7 +118,7 @@
 		SWTUtils.pressKey(SWT.ARROW_DOWN, SWT.MOD1, natTable);
 		assertSelectCellsCount(1);
 		int lastRow = selectionLayer.getRowCount() - 1;
-		assertPositionEquals(4, lastRow, selectionLayer.getSelectedCellPositions()[0]);
+		assertPositionEquals(4, lastRow, selectionLayer.getSelectedCellPositions().get(0));
 		assertPositionEquals(4, lastRow, selectionLayer.getLastSelectedCellPosition());
 		assertSelectionAnchorEquals(4, lastRow);
 	}
@@ -121,7 +130,7 @@
 		// Note: the co-ordinates from this point on are in selection later co-ordinates
 
 		SWTUtils.pressKey(SWT.ARROW_UP, natTable);
-		assertPositionEquals(4, 2, selectionLayer.getSelectedCellPositions()[0]);
+		assertPositionEquals(4, 2, selectionLayer.getSelectedCellPositions().get(0));
 		assertSelectionAnchorEquals(4, 2);
 
 		SWTUtils.pressKey(SWT.ARROW_UP, SWT.SHIFT, natTable);
@@ -138,7 +147,7 @@
 		SWTUtils.pressKey(SWT.ARROW_UP, SWT.MOD1, natTable);
 		assertSelectCellsCount(1);
 		int lastRow = 0;
-		assertPositionEquals(4, lastRow, selectionLayer.getSelectedCellPositions()[0]);
+		assertPositionEquals(4, lastRow, selectionLayer.getSelectedCellPositions().get(0));
 		assertPositionEquals(4, lastRow, selectionLayer.getLastSelectedCellPosition());
 		assertSelectionAnchorEquals(4, lastRow);
 	}
@@ -178,7 +187,7 @@
 	// Convenience asserts
 
 	private void assertCellSelected(int column, int row){
-		PositionCoordinate[] selectedCells = selectionLayer.getSelectedCellPositions();
+		List<PositionCoordinate> selectedCells = selectionLayer.getSelectedCellPositions();
 		boolean selected  = false;
 
 		for (PositionCoordinate positionCoordinate : selectedCells) {
@@ -191,12 +200,8 @@
 		Assert.assertTrue(selected);
 	}
 
-	private PositionCoordinate[] getSelectedCells(){
-		return selectionLayer.getSelectedCellPositions();
-	}
-
 	private void assertSelectCellsCount(int count) {
-		assertEquals(count, selectionLayer.getSelectedCellPositions().length);
+		assertEquals(count, selectionLayer.getSelectedCellPositions().size());
 	}
 
 	private void assertSelectionAnchorEquals(int column, int row) {
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandler.java
index 07d4f87..4bd968f 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/CopyDataCommandHandler.java
@@ -10,13 +10,9 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.copy.command;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
-import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.copy.serializing.CopyDataToClipboardSerializer;
 import org.eclipse.nebula.widgets.nattable.copy.serializing.CopyFormattedTextToClipboardSerializer;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
@@ -105,94 +101,87 @@
 
 	/**
 	 * Collects and assembles the selected data that should be copied to the clipboard.
+	 * 
+	 * Creates the two dimensional array whose dimensions are calculated based on the selection
+	 * within the {@link SelectionLayer} and the configured column and row headers.
+	 * 
 	 * @return A two dimensional array containing the selected cells to copy to the clipboard.
 	 * 			The first level of this array represent the row positions of the cells, while the
 	 * 			second level contains the cells itself based on the column position.
 	 */
 	protected ILayerCell[][] assembleCopiedDataStructure() {
-		final Set<Range> selectedRows = selectionLayer.getSelectedRowPositions();
-		final ILayerCell[][] copiedCells = assembleColumnHeaders();
+		final RangeList selectedRowPositions = selectionLayer.getSelectedRowPositions();
+		final RangeList selectedColumnPositions = selectionLayer.getSelectedColumnPositions();
 		
-		//cleanup the row positions to copy
-		//this is needed because taking only the Range.start into account leads to overriding
-		//values in the array instead of adding if there are multiple Ranges returned
-		List<Integer> selectedRowPositions = new ArrayList<Integer>();
-		for (Range range : selectedRows) {
-			for (int rowPosition = range.start; rowPosition < range.end; rowPosition++) {
-				selectedRowPositions.add(rowPosition);
-			}
-		}
-		//ensure the correct order as a Set is not ordered at all and we want to paste the values
-		//in the same order we copied them.
-		Collections.sort(selectedRowPositions);
+		final int rowOffset = (columnHeaderDataLayer != null) ? columnHeaderDataLayer.getRowCount() : 0;
+		final int columnOffset = (rowHeaderDataLayer != null) ? rowHeaderDataLayer.getColumnCount() : 0;
 		
-		final int rowOffset = columnHeaderDataLayer != null ? columnHeaderDataLayer.getRowCount() : 0;
-		for (int i = 0; i < selectedRowPositions.size(); i++) {
-			Integer rowPos = selectedRowPositions.get(i);
-			copiedCells[i+rowOffset] = assembleBody(rowPos);
+		final ILayerCell[][] cells = new ILayerCell[selectedRowPositions.values().size() + rowOffset][];
+		
+		int cellsIdx = 0;
+		while (cellsIdx < rowOffset) {
+			cells[cellsIdx++] = assembleColumnHeader(selectedColumnPositions, columnOffset, cellsIdx);
 		}
-
-		return copiedCells;
+		for (final IValueIterator rowIter = selectedRowPositions.values().iterator(); rowIter.hasNext(); ) {
+			final int rowPosition = rowIter.nextValue();
+			cells[cellsIdx++] = assembleBody(selectedColumnPositions, columnOffset, rowPosition);
+		}
+		
+		return cells;
 	}
-
+	
 	/**
-	 * Creates the two dimensional array whose dimensions are calculated based on the selection
-	 * within the {@link SelectionLayer} and the configured column and row headers.
-	 * If there is a column header configured for this handler, the column header information
-	 * will be added to the resulting array in here. If there is no column header configured
-	 * an empty array with the matching dimensions will be returned.
-	 * @return A two dimensional array with the dimensions to store the selected data to copy
-	 * 			to the clipboard. Will also contain the column header information for the copy
-	 * 			operation if there is one configured.
+	 * Collects and assembles the column header information for the specified column header row.
+	 * 
+	 * If there is no column header configured an empty array with the matching dimensions will be returned.
+	 * 
+	 * @param selectedColumnPositions The column positions of which the information should be collected
+	 * @param columnOffset The column offset of table body
+	 * @param headerRowPosition The row position in the column header of which the information should be collected
+	 * @return An array containing the column header information
 	 */
-	protected ILayerCell[][] assembleColumnHeaders() {
-		// Add offset to rows, remember they need to include the column header rows
-		final int rowOffset = columnHeaderDataLayer != null ? columnHeaderDataLayer.getRowCount() : 0;
-		final int columnOffset = rowHeaderDataLayer != null ? rowHeaderDataLayer.getColumnCount() : 0;
-
-		final ILayerCell[][] copiedCells = new ILayerCell[selectionLayer.getSelectedRowCount() + rowOffset][1];
+	protected ILayerCell[] assembleColumnHeader(final RangeList selectedColumnPositions, final int columnOffset,
+			final int headerRowPosition) {
+		final ILayerCell[] headerCells = new ILayerCell[selectedColumnPositions.values().size() + columnOffset];
 		
+		int headerIdx = columnOffset;
 		if (columnHeaderDataLayer != null) {
-			int[] selectedColumnPositions = selectionLayer.getSelectedColumnPositions();
-			for (int i = 0; i < rowOffset; i++) {
-				final ILayerCell[] cells = new ILayerCell[selectedColumnPositions.length + columnOffset];
-				for (int columnPosition = 0; columnPosition < selectedColumnPositions.length; columnPosition++) {
-					// Pad the width of the vertical layer
-					cells[columnPosition + columnOffset] = 
-							columnHeaderDataLayer.getCellByPosition(selectedColumnPositions[columnPosition], i);
-				}
-				
-				copiedCells[i] = cells;
+			for (final IValueIterator columnIter = selectedColumnPositions.values().iterator(); columnIter.hasNext(); headerIdx++) {
+				final int columnPosition = columnIter.nextValue();
+				headerCells[headerIdx] = columnHeaderDataLayer.getCellByPosition(columnPosition, headerRowPosition);
 			}
 		}
 		
-		return copiedCells;
+		return headerCells;
 	}
 	
 	/**
 	 * Collects and assembles the selected data per row position that should be copied to the clipboard.
 	 * If there is a row header layer configured for this handler, the row header cells of the selected
 	 * row position are also added to the resulting array.
-	 * @param currentRowPosition The row position of which the selected cells should be collected.
-	 * @return An array containing the selected cells that should be copied to the clipboard. 
+	 * 
+	 * @param selectedColumnPositions The column positions of which the information should be collected
+	 * @param columnOffset The column offset of table body
+	 * @param currentRowPosition The row position of which the selected cells should be collected
+	 * @return An array containing the specified cells
 	 */
-	protected ILayerCell[] assembleBody(int currentRowPosition) {		
-		final int[] selectedColumns = selectionLayer.getSelectedColumnPositions();
-		final int columnOffset = rowHeaderDataLayer != null ? rowHeaderDataLayer.getColumnCount() : 0;
-		final ILayerCell[] bodyCells = new ILayerCell[selectedColumns.length + columnOffset];
+	protected ILayerCell[] assembleBody(final RangeList selectedColumnPositions,  final int columnOffset,
+			final int currentRowPosition) {
+		final ILayerCell[] bodyCells = new ILayerCell[selectedColumnPositions.values().size() + columnOffset];
 		
+		int bodyIdx = 0;
 		if (rowHeaderDataLayer != null) {
-			for (int i = 0; i < rowHeaderDataLayer.getColumnCount(); i++) {
-				bodyCells[i] = rowHeaderDataLayer.getCellByPosition(i, currentRowPosition);
+			for (; bodyIdx < columnOffset; bodyIdx++) {
+				bodyCells[bodyIdx] = rowHeaderDataLayer.getCellByPosition(bodyIdx, currentRowPosition);
+			}
+		}
+		for (final IValueIterator columnIter = selectedColumnPositions.values().iterator(); columnIter.hasNext(); bodyIdx++) {
+			final int columnPosition = columnIter.nextValue();
+			if (selectionLayer.isCellPositionSelected(columnPosition, currentRowPosition)) {
+				bodyCells[bodyIdx] = selectionLayer.getCellByPosition(columnPosition, currentRowPosition);
 			}
 		}
 		
-		for (int columnPosition = 0; columnPosition < selectedColumns.length; columnPosition++) {
-			final int selectedColumnPosition = selectedColumns[columnPosition];
-			if (selectionLayer.isCellPositionSelected(selectedColumnPosition, currentRowPosition)) {
-				bodyCells[columnPosition + columnOffset] = selectionLayer.getCellByPosition(selectedColumnPosition, currentRowPosition);
-			}
-		}
 		return bodyCells;
 	}
 	
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/command/EditUtils.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/command/EditUtils.java
index d140eef..7222280 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/command/EditUtils.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/command/EditUtils.java
@@ -124,7 +124,7 @@
 	 * 			configured.
 	 */
 	public static boolean isEditorSame(SelectionLayer selectionLayer, IConfigRegistry configRegistry) {
-		PositionCoordinate[] selectedCells = selectionLayer.getSelectedCellPositions();
+		List<PositionCoordinate> selectedCells = selectionLayer.getSelectedCellPositions();
 		ICellEditor lastSelectedCellEditor = null;
 		for (PositionCoordinate selectedCell : selectedCells) {
 			LabelStack labelStack = selectionLayer.getConfigLabelsByPosition(
@@ -162,7 +162,7 @@
 	 */
 	@SuppressWarnings("rawtypes")
 	public static boolean isConverterSame(SelectionLayer selectionLayer, IConfigRegistry configRegistry){
-		PositionCoordinate[] selectedCells = selectionLayer.getSelectedCellPositions();
+		List<PositionCoordinate> selectedCells = selectionLayer.getSelectedCellPositions();
 		Set<Class> converterSet = new HashSet<Class>();
 		
 		for (PositionCoordinate selectedCell : selectedCells) {
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/layer/event/ColumnHeaderSelectionEvent.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/layer/event/ColumnHeaderSelectionEvent.java
index 5667e6c..9815473 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/layer/event/ColumnHeaderSelectionEvent.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/grid/layer/event/ColumnHeaderSelectionEvent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -10,7 +10,6 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.grid.layer.event;
 
-import java.util.Arrays;
 import java.util.Collection;
 
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
@@ -19,14 +18,7 @@
 
 
 public class ColumnHeaderSelectionEvent extends ColumnVisualChangeEvent {
-
-	public ColumnHeaderSelectionEvent(ILayer layer, int columnPosition) {
-		this(layer, new Range(columnPosition, columnPosition + 1));
-	}
 	
-	public ColumnHeaderSelectionEvent(ILayer layer, Range...columnPositionRanges) {
-		this(layer, Arrays.asList(columnPositionRanges));
-	}
 	
 	public ColumnHeaderSelectionEvent(ILayer layer, Collection<Range> columnPositionRanges) {
 		super(layer, columnPositionRanges);
@@ -36,6 +28,7 @@
 		super(event);
 	}
 	
+	@Override
 	public ColumnHeaderSelectionEvent cloneEvent() {
 		return new ColumnHeaderSelectionEvent(this);
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/RowGroupHeaderLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/RowGroupHeaderLayer.java
index 8f16c19..18c5614 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/RowGroupHeaderLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/RowGroupHeaderLayer.java
@@ -10,11 +10,12 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.group;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
 import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
 import org.eclipse.nebula.widgets.nattable.group.config.DefaultRowGroupHeaderLayerConfiguration;
 import org.eclipse.nebula.widgets.nattable.group.model.IRowGroup;
@@ -269,10 +270,13 @@
 	@Override
 	public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) {
 		int rowIndex = getRowIndexByPosition(rowPosition);
-		if( columnPosition == 0 && RowGroupUtils.isPartOfAGroup(model, rowIndex) ) {
-			List<Integer> selectedRowIndexes = convertToRowIndexes(selectionLayer.getFullySelectedRowPositions());
-			if (selectedRowIndexes.contains(rowIndex)) {
-				return new LabelStack(SelectionStyleLabels.ROW_FULLY_SELECTED_STYLE, GridRegion.ROW_GROUP_HEADER);
+		if (columnPosition == 0 && RowGroupUtils.isPartOfAGroup(model, rowIndex) ) {
+			final RangeList fullySelectedRowPositions = selectionLayer.getFullySelectedRowPositions();
+			for (final IValueIterator rowIter = fullySelectedRowPositions.values().iterator(); rowIter.hasNext(); ) {
+				int index = this.selectionLayer.getRowIndexByPosition(rowIter.nextValue());
+				if (rowIndex == index) {
+					return new LabelStack(SelectionStyleLabels.ROW_FULLY_SELECTED_STYLE, GridRegion.ROW_GROUP_HEADER);
+				}
 			}
 			return new LabelStack(GridRegion.ROW_GROUP_HEADER);
 		} else {
@@ -280,14 +284,6 @@
 		}
 	}
 	
-	private List<Integer> convertToRowIndexes(final int[] rowPositions) {
-		final List <Integer> rowIndexes = new ArrayList<Integer>();
-		for(final Integer rowPosition : rowPositions){
-			rowIndexes.add(this.selectionLayer.getRowIndexByPosition(rowPosition));
-		}
-		return rowIndexes;
-	}
-	
 	@Override
 	public Object getDataValueByPosition(int columnPosition, int rowPosition) {
 		int rowIndex = getRowIndexByPosition(rowPosition);
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/command/ColumnGroupsCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/command/ColumnGroupsCommandHandler.java
index 50c7253..c0aa867 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/command/ColumnGroupsCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/command/ColumnGroupsCommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -11,16 +11,20 @@
 package org.eclipse.nebula.widgets.nattable.group.command;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+
 import org.eclipse.nebula.widgets.nattable.Messages;
 import org.eclipse.nebula.widgets.nattable.columnRename.ColumnRenameDialog;
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel.ColumnGroup;
@@ -29,9 +33,6 @@
 import org.eclipse.nebula.widgets.nattable.group.event.UngroupColumnsEvent;
 import org.eclipse.nebula.widgets.nattable.reorder.command.MultiColumnReorderCommand;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
 
 
 public class ColumnGroupsCommandHandler extends AbstractLayerCommandHandler<IColumnGroupCommand>  {
@@ -57,7 +58,7 @@
 		} else if (command instanceof OpenCreateColumnGroupDialog) {
 			OpenCreateColumnGroupDialog openDialogCommand = (OpenCreateColumnGroupDialog) command;
 			loadSelectedColumnsIndexesWithPositions();
-			if (selectionLayer.getFullySelectedColumnPositions().length > 0 && columnIndexesToPositionsMap.size() > 0) {
+			if (!selectionLayer.getFullySelectedColumnPositions().isEmpty() && columnIndexesToPositionsMap.size() > 0) {
 				openDialogCommand.openDialog(contextLayer);
 			} else {				
 				openDialogCommand.openErrorBox(Messages.getString("ColumnGroups.selectNonGroupedColumns"));				 //$NON-NLS-1$
@@ -101,24 +102,20 @@
 	
 	protected void loadSelectedColumnsIndexesWithPositions() {
 		columnIndexesToPositionsMap = new LinkedHashMap<Integer, Integer>();
-		int[] fullySelectedColumns = selectionLayer.getFullySelectedColumnPositions();
+		final RangeList fullySelectedColumns = selectionLayer.getFullySelectedColumnPositions();
 		
-		if (fullySelectedColumns.length > 0) {
-			for (int index = 0; index < fullySelectedColumns.length; index++) {
-				final int columnPosition = fullySelectedColumns[index];
-				int columnIndex = selectionLayer.getColumnIndexByPosition(columnPosition);
-				if (model.isPartOfAGroup(columnIndex)){
-					columnIndexesToPositionsMap.clear();
-					break;
-				}
-				columnIndexesToPositionsMap.put(Integer.valueOf(columnIndex), Integer.valueOf(columnPosition));
+		for (final IValueIterator columnIter = fullySelectedColumns.values().iterator(); columnIter.hasNext(); ) {
+			final int position = columnIter.nextValue();
+			int index = selectionLayer.getColumnIndexByPosition(position);
+			if (model.isPartOfAGroup(index)) {
+				columnIndexesToPositionsMap.clear();
+				break;
 			}
-			
+			columnIndexesToPositionsMap.put(Integer.valueOf(index), Integer.valueOf(position));
 		}
 	}
 
 	public void handleGroupColumnsCommand(String columnGroupName) {
-			
 		try {
 			List<Integer> selectedPositions = new ArrayList<Integer>();
 			int[] fullySelectedColumns = new int[columnIndexesToPositionsMap.size()];
@@ -137,27 +134,24 @@
 
 	public void handleUngroupCommand() {
 		// Grab fully selected column positions
-		int[] fullySelectedColumns = selectionLayer.getFullySelectedColumnPositions();
+		final RangeList fullySelectedColumns = selectionLayer.getFullySelectedColumnPositions();
 		Map<String, Integer> toColumnPositions = new HashMap<String, Integer>();
-		if (fullySelectedColumns.length > 0) {
 		
-		// Pick the ones which belong to a group and remove them from the group
-			for (int index = 0; index < fullySelectedColumns.length; index++) {
-				final int columnPosition = fullySelectedColumns[index];
-				int columnIndex = selectionLayer.getColumnIndexByPosition(columnPosition);
-				if (model.isPartOfAGroup(columnIndex) && !model.isPartOfAnUnbreakableGroup(columnIndex)){
-					handleRemovalFromGroup(toColumnPositions, columnIndex);
-				}
+		for (final IValueIterator columnIter = fullySelectedColumns.values().iterator(); columnIter.hasNext(); ) {
+			// Pick the ones which belong to a group and remove them from the group
+			final int position = columnIter.nextValue();
+			int index = selectionLayer.getColumnIndexByPosition(position);
+			if (model.isPartOfAGroup(index) && !model.isPartOfAnUnbreakableGroup(index)) {
+				handleRemovalFromGroup(toColumnPositions, index);
 			}
-		// The groups which were affected should be reordered to the start position, this should group all columns together
-			Collection<Integer> values = toColumnPositions.values();
-			final Iterator<Integer> toColumnPositionsIterator = values.iterator();
-			while(toColumnPositionsIterator.hasNext()) {
-				Integer toColumnPosition = toColumnPositionsIterator.next();
-				selectionLayer.doCommand(new ReorderColumnGroupCommand(selectionLayer, toColumnPosition.intValue(), toColumnPosition.intValue()));
+		}
+		if (!toColumnPositions.isEmpty()) {
+			// The groups which were affected should be reordered to the start position, this should group all columns together
+			for (final Integer position : toColumnPositions.values()) {
+				selectionLayer.doCommand(new ReorderColumnGroupCommand(selectionLayer, position, position));
 			}
 			selectionLayer.clear();
-		} 
+		}
 		
 		contextLayer.fireLayerEvent(new UngroupColumnsEvent(contextLayer));
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeColumnsCommand.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeColumnsCommand.java
index d5e1b59..123f4ab 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeColumnsCommand.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeColumnsCommand.java
@@ -71,11 +71,6 @@
 		return sourceLayer;
 	}
 
-	@Deprecated
-	public void setSelectedColumnPositions(final int[] selectedColumnPositions) {
-		setSelectedColumnPositions(new RangeList(selectedColumnPositions));
-	}
-
 	public void setSelectedColumnPositions(final Collection<Range> selectedColumnPositions) {
 		this.selectedColumnPositions = selectedColumnPositions;
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeRowsCommand.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeRowsCommand.java
index 9d7926c..3470735 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeRowsCommand.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/resize/command/InitializeAutoResizeRowsCommand.java
@@ -66,11 +66,6 @@
 		return sourceLayer;
 	}
 
-	@Deprecated
-	public void setSelectedRowPositions(final int[] selectedRowPositions) {
-		setSelectedRowPositions(new RangeList(selectedRowPositions));
-	}
-
 	public void setSelectedRowPositions(final Collection<Range> selectedRowPositions) {
 		this.selectedRowPositions = selectedRowPositions;
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/CellDisplayValueSearchUtil.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/CellDisplayValueSearchUtil.java
index e4c1f98..17d3f74 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/CellDisplayValueSearchUtil.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/CellDisplayValueSearchUtil.java
@@ -11,7 +11,6 @@
 package org.eclipse.nebula.widgets.nattable.search.strategy;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
 
@@ -23,6 +22,7 @@
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
 
+
 public class CellDisplayValueSearchUtil {
 	
 	static List<PositionCoordinate> getCellCoordinates(ILayer contextLayer, int startingColumnPosition, int startingRowPosition, int width, int height) {
@@ -51,14 +51,13 @@
 	
 	
 	@SuppressWarnings("unchecked")
-	static PositionCoordinate findCell(final ILayer layer, final IConfigRegistry configRegistry, final PositionCoordinate[] cellsToSearch, final Object valueToMatch, final Comparator comparator, final boolean caseSensitive) {	
-		final List<PositionCoordinate> cellCoordinates = Arrays.asList(cellsToSearch);		
+	static PositionCoordinate findCell(final ILayer layer, final IConfigRegistry configRegistry, List<PositionCoordinate> cellsToSearch, final Object valueToMatch, final Comparator comparator, final boolean caseSensitive) {	
 		// Find cell
 		PositionCoordinate targetCoordinate = null;
 		
 		String stringValue = caseSensitive ? valueToMatch.toString() : valueToMatch.toString().toLowerCase();
-		for (int cellIndex = 0; cellIndex < cellCoordinates.size(); cellIndex++) {
-			final PositionCoordinate cellCoordinate = cellCoordinates.get(cellIndex);
+		for (int cellIndex = 0; cellIndex < cellsToSearch.size(); cellIndex++) {
+			final PositionCoordinate cellCoordinate = cellsToSearch.get(cellIndex);
 			final int columnPosition = cellCoordinate.columnPosition;
 			final int rowPosition = cellCoordinate.rowPosition;
 			
@@ -84,4 +83,5 @@
 		
 		return targetCoordinate;
 	}
+	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategy.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategy.java
index 22b8d0e..e78c389 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategy.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/ColumnSearchStrategy.java
@@ -49,7 +49,7 @@
 		this.columnPositions = columnPositions;
 	}
 	
-	protected PositionCoordinate[] getColumnCellsToSearch(ILayer contextLayer) {
+	protected List<PositionCoordinate> getColumnCellsToSearch(ILayer contextLayer) {
 		List<PositionCoordinate> cellsToSearch = new ArrayList<PositionCoordinate>();
 		int rowPosition = startingRowPosition;
 		// See how many rows we can add, depends on where the search is starting from
@@ -72,6 +72,7 @@
 			height = rowCount;
 			// After first column is set, start the next column from the top
 		}
-		return cellsToSearch.toArray(new PositionCoordinate[0]);
+		return cellsToSearch;
 	}
+	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategy.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategy.java
index 097988f..f02ee86 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategy.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/RowSearchStrategy.java
@@ -40,7 +40,7 @@
 		return CellDisplayValueSearchUtil.findCell(getContextLayer(), configRegistry, getRowCellsToSearch(getContextLayer()), valueToMatch, getComparator(), isCaseSensitive());
 	}
 
-	protected PositionCoordinate[] getRowCellsToSearch(ILayer contextLayer) {
+	protected List<PositionCoordinate> getRowCellsToSearch(ILayer contextLayer) {
 		List<PositionCoordinate> cellsToSearch = new ArrayList<PositionCoordinate>();
 		for (int rowPosition : rowPositions) {
 			cellsToSearch.addAll(CellDisplayValueSearchUtil.getCellCoordinates(getContextLayer(), 0, rowPosition, contextLayer.getColumnCount(), 1));
@@ -48,6 +48,7 @@
 		if (searchDirection.equals(ISearchDirection.SEARCH_BACKWARDS)) {
 			Collections.reverse(cellsToSearch);
 		}
-		return cellsToSearch.toArray(new PositionCoordinate[0]);
+		return cellsToSearch;
 	}
+	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategy.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategy.java
index 1c13d2f..2b0828f 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategy.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/search/strategy/SelectionSearchStrategy.java
@@ -10,7 +10,6 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.search.strategy;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -45,14 +44,10 @@
 		return coordinate;
 	}
 
-	protected PositionCoordinate[] getSelectedCells(SelectionLayer selectionLayer) {
-		PositionCoordinate[] selectedCells = null;
+	protected List<PositionCoordinate> getSelectedCells(SelectionLayer selectionLayer) {
+		List<PositionCoordinate> selectedCells = selectionLayer.getSelectedCellPositions();
 		if (searchDirection.equals(ISearchDirection.SEARCH_BACKWARDS)) {
-			List<PositionCoordinate> coordinates = Arrays.asList(selectionLayer.getSelectedCellPositions());
-			Collections.reverse(coordinates);
-			selectedCells = coordinates.toArray(new PositionCoordinate[0]);
-		} else {
-			selectedCells = selectionLayer.getSelectedCellPositions();
+			Collections.reverse(selectedCells);
 		}
 		return selectedCells;
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/ISelectionModel.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/ISelectionModel.java
index 090735e..1bcdcd7 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/ISelectionModel.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/ISelectionModel.java
@@ -8,71 +8,157 @@
  * Contributors:
  *     Original authors and others - initial API and implementation
  ******************************************************************************/
+
 package org.eclipse.nebula.widgets.nattable.selection;
 
 import java.util.List;
-import java.util.Set;
 
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 
-import org.eclipse.nebula.widgets.nattable.coordinate.Range;
-import org.eclipse.swt.graphics.Rectangle;
 
 /**
  * Tracks the selections made in the table.
+ * <p>
+ * A column or row is <i>selected</i>, if any cells in that column/row are selected.
+ * A column or row is <i>fully selected</i>, if all cells in that column/row are selected.
+ * A column or row is not selected and not fully selected, if the selection layer is empty
+ * (any dim has size 0).</p>
  */
 public interface ISelectionModel {
 	
-	public boolean isMultipleSelectionAllowed();
 	
-	public void setMultipleSelectionAllowed(boolean multipleSelectionAllowed);
-
-	public void addSelection(int columnPosition, int rowPosition);
-
-	public void addSelection(final Rectangle range);
-
-	public void clearSelection();
-
-	public void clearSelection(int columnPosition, int rowPosition);
-
-	public void clearSelection(Rectangle removedSelection);
-
-	public boolean isEmpty();
-
-	public List<Rectangle> getSelections();
+	boolean isMultipleSelectionAllowed();
 	
-	// Cell features
-
-	public boolean isCellPositionSelected(int columnPosition, int rowPosition);
+	void setMultipleSelectionAllowed(boolean multipleSelectionAllowed);
 	
-	// Column features
-
-	public int[] getSelectedColumnPositions();
-
-	public boolean isColumnPositionSelected(int columnPosition);
-
+	
 	/**
-	 * @param columnHeight the number of rows in a fully selected column
+	 * Adds the specified position to the selection.
+	 * 
+	 * @param columnPosition the column position in the selection layer
+	 * @param rowPosition the row position in the selection layer
 	 */
-	public int[] getFullySelectedColumnPositions(int columnHeight);
-
-	/**
-	 * @param columnHeight the number of rows in a fully selected column
-	 */
-	public boolean isColumnPositionFullySelected(int columnPosition, int columnHeight);
-
-	// Row features
-
-	public int getSelectedRowCount();
+	void addSelection(int columnPosition, int rowPosition);
 	
-	public Set<Range> getSelectedRowPositions();
-	
-	public boolean isRowPositionSelected(int rowPosition);
-
 	/**
-	 * @param rowWidth the number of columns in a fully selected row
+	 * Adds the specified position rectangle to the selection.
+	 * 
+	 * @param rect the position rectangle in the selection layer
 	 */
-	public int[] getFullySelectedRowPositions(int rowWidth);
-
-	public boolean isRowPositionFullySelected(int rowPosition, int rowWidth);
+	void addSelection(Rectangle positions);
+	
+	/**
+	 * Clears the selection completely.
+	 */
+	void clearSelection();
+	
+	/**
+	 * Removes the specified position from the selection.
+	 * 
+	 * @param columnPosition the column position in the selection layer
+	 * @param rowPosition the row position in the selection layer
+	 */
+	void clearSelection(int columnPosition, int rowPosition);
+	
+	/**
+	 * Removes the specified position rectangle from the selection.
+	 * 
+	 * @param rect the position rectangle in the selection layer
+	 */
+	void clearSelection(Rectangle positions);
+	
+	/**
+	 * Returns if the selection is empty.
+	 * 
+	 * @return <code>true</code> if the selection is empty, otherwise <code>false</code>
+	 */
+	boolean isEmpty();
+	
+	/**
+	 * Returns a collection of rectangles of selected positions. If a position is inside a
+	 * rectangle of the list, it is selected, otherwise it is not selected.
+	 * 
+	 * @return a list of position rectangles
+	 */
+	List<Rectangle> getSelections();
+	
+	//-- Cell features --//
+	
+	/**
+	 * Returns if the specified position is selected.
+	 * 
+	 * @param columnPosition the column position in the selection layer
+	 * @param rowPosition the row position in the selection layer
+	 * @return <code>true</code> if the position is selected, otherwise <code>false</code>
+	 */
+	boolean isCellPositionSelected(int columnPosition, int rowPosition);
+	
+	//-- Column features --//
+	
+	/**
+	 * Returns the positions of all selected columns. 
+	 * 
+	 * @return the positions of selected columns as ordered and disjoint list of position ranges
+	 */
+	RangeList getSelectedColumnPositions();
+	
+	/**
+	 * Returns if the specified column position is selected. A column is selected, if any cell in 
+	 * the column is selected.
+	 * 
+	 * @param columnPosition the column position in the selection layer
+	 * @return <code>true</code> if the column is selected, otherwise <code>false</code>
+	 */
+	boolean isColumnPositionSelected(int columnPosition);
+	
+	/**
+	 * Returns the positions of all fully selected columns. 
+	 * 
+	 * @return the positions of fully selected columns as ordered and disjoint list of position ranges
+	 */
+	RangeList getFullySelectedColumnPositions();
+	
+	/**
+	 * Returns if the specified column position is fully selected.
+	 * 
+	 * @param columnPosition the column position in the selection layer
+	 * @return <code>true</code> if the column is fully selected, otherwise <code>false</code>
+	 */
+	boolean isColumnPositionFullySelected(int columnPosition);
+	
+	//-- Row features --//
+	
+	int getSelectedRowCount();
+	
+	/**
+	 * Returns the positions of all selected rows. 
+	 * 
+	 * @return the positions of selected rows as ordered and disjoint list of position ranges
+	 */
+	RangeList getSelectedRowPositions();
+	
+	/**
+	 * Returns if the specified row position is selected.
+	 * 
+	 * @param rowPosition the row position in the selection layer
+	 * @return <code>true</code> if the row is selected, otherwise <code>false</code>
+	 */
+	boolean isRowPositionSelected(int rowPosition);
+	
+	/**
+	 * Returns the positions of all fully selected rows. 
+	 * 
+	 * @return the positions of fully selected rows as ordered and disjoint list of position ranges
+	 */
+	RangeList getFullySelectedRowPositions();
+	
+	/**
+	 * Returns if the specified row position is fully selected.
+	 * 
+	 * @param rowPosition the row position in the selection layer
+	 * @return <code>true</code> if the row is fully selected, otherwise <code>false</code>
+	 */
+	boolean isRowPositionFullySelected(int rowPosition);
 	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionModel.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionModel.java
index b96f848..67b2df5 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionModel.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionModel.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -13,7 +13,6 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -21,14 +20,18 @@
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
 import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
+import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
-import org.eclipse.swt.graphics.Rectangle;
+
 
 public class RowSelectionModel<R> implements IRowSelectionModel<R> {
-
-	protected final SelectionLayer selectionLayer;
+	
+	protected final IUniqueIndexLayer selectionLayer;
+	
 	protected final IRowDataProvider<R> rowDataProvider;
 	protected final IRowIdAccessor<R> rowIdAccessor;
 	private boolean multipleSelectionAllowed;
@@ -37,179 +40,183 @@
 	protected Rectangle lastSelectedRange;  // *live* reference to last range parameter used in addSelection(range)
 	protected Set<Serializable> lastSelectedRowIds;
 	protected final ReadWriteLock selectionsLock;
-
-	public RowSelectionModel(SelectionLayer selectionLayer, IRowDataProvider<R> rowDataProvider, IRowIdAccessor<R> rowIdAccessor) {
+	
+	
+	public RowSelectionModel(/*@NotNull*/ final IUniqueIndexLayer selectionLayer,
+			final IRowDataProvider<R> rowDataProvider, final IRowIdAccessor<R> rowIdAccessor) {
 		this(selectionLayer, rowDataProvider, rowIdAccessor, true);
 	}
 	
-	public RowSelectionModel(SelectionLayer selectionLayer, IRowDataProvider<R> rowDataProvider, IRowIdAccessor<R> rowIdAccessor, boolean multipleSelectionAllowed) {
+	public RowSelectionModel(/*@NotNull*/ final IUniqueIndexLayer selectionLayer,
+			final IRowDataProvider<R> rowDataProvider, final IRowIdAccessor<R> rowIdAccessor,
+			final boolean multipleSelectionAllowed) {
+		if (selectionLayer == null) {
+			throw new NullPointerException("selectionLayer"); //$NON-NLS-1$
+		}
 		this.selectionLayer = selectionLayer;
 		this.rowDataProvider = rowDataProvider;
 		this.rowIdAccessor = rowIdAccessor;
 		this.multipleSelectionAllowed = multipleSelectionAllowed;
 		
-		selectedRows = new HashMap<Serializable, R>();
-		selectionsLock = new ReentrantReadWriteLock();
+		this.selectedRows = new HashMap<Serializable, R>();
+		this.selectionsLock = new ReentrantReadWriteLock();
 	}
 	
+	
 	@Override
 	public boolean isMultipleSelectionAllowed() {
-		return multipleSelectionAllowed;
+		return this.multipleSelectionAllowed;
 	}
 	
 	@Override
-	public void setMultipleSelectionAllowed(boolean multipleSelectionAllowed) {
+	public void setMultipleSelectionAllowed(final boolean multipleSelectionAllowed) {
 		this.multipleSelectionAllowed = multipleSelectionAllowed;
 	}
-
+	
+	
 	@Override
-	public void addSelection(int columnPosition, int rowPosition) {
-		selectionsLock.writeLock().lock();
-		
+	public void addSelection(final int columnPosition, final int rowPosition) {
+		this.selectionsLock.writeLock().lock();
 		try {
-			if (!multipleSelectionAllowed) {
-				selectedRows.clear();
+			if (!this.multipleSelectionAllowed) {
+				this.selectedRows.clear();
 			}
 			
-			R rowObject = getRowObjectByPosition(rowPosition);
+			final R rowObject = getRowObjectByPosition(rowPosition);
 			if (rowObject != null) {
-				Serializable rowId = rowIdAccessor.getRowId(rowObject);
-				selectedRows.put(rowId, rowObject);
+				final Serializable rowId = this.rowIdAccessor.getRowId(rowObject);
+				this.selectedRows.put(rowId, rowObject);
 			}
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public void addSelection(Rectangle range) {
-		selectionsLock.writeLock().lock();
-		
+	public void addSelection(final Rectangle positions) {
+		this.selectionsLock.writeLock().lock();
 		try {
-			if (multipleSelectionAllowed) {
-				if (range.equals(lastSelectedRange)) {
+			if (this.multipleSelectionAllowed) {
+				if (positions.equals(this.lastSelectedRange)) {
 					// Unselect all previously selected rowIds
-					if (lastSelectedRowIds != null) {
-						for (Serializable rowId : lastSelectedRowIds) {
-							selectedRows.remove(rowId);
+					if (this.lastSelectedRowIds != null) {
+						for (final Serializable rowId : this.lastSelectedRowIds) {
+							this.selectedRows.remove(rowId);
 						}
 					}
 				}
 			} else {
-				selectedRows.clear();
+				this.selectedRows.clear();
 				//as no multiple selection is allowed, ensure that only one row 
 				//will be selected
-				range.height = 1;
+				positions.height = 1;
 			}
 			
-			Map<Serializable, R> rowsToSelect = new HashMap<Serializable, R>();
+			final Map<Serializable, R> rowsToSelect = new HashMap<Serializable, R>();
 			
-			int maxY = Math.min(range.y + range.height, selectionLayer.getRowCount());
-			for (int rowPosition = range.y; rowPosition < maxY; rowPosition++) {
-				R rowObject = getRowObjectByPosition(rowPosition);
+			final int maxY = Math.min(positions.y + positions.height, this.selectionLayer.getRowCount());
+			for (int rowPosition = positions.y; rowPosition < maxY; rowPosition++) {
+				final R rowObject = getRowObjectByPosition(rowPosition);
 				if (rowObject != null) {
-					Serializable rowId = rowIdAccessor.getRowId(rowObject);
+					final Serializable rowId = this.rowIdAccessor.getRowId(rowObject);
 					rowsToSelect.put(rowId, rowObject);
 				}
 			}
 			
-			selectedRows.putAll(rowsToSelect);
+			this.selectedRows.putAll(rowsToSelect);
 			
-			if (range.equals(lastSelectedRange)) {
-				lastSelectedRowIds = rowsToSelect.keySet();
+			if (positions.equals(this.lastSelectedRange)) {
+				this.lastSelectedRowIds = rowsToSelect.keySet();
 			} else {
-				lastSelectedRowIds = null;
+				this.lastSelectedRowIds = null;
 			}
 			
-			lastSelectedRange = range;
+			this.lastSelectedRange = positions;
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
 	
 	@Override
 	public void clearSelection() {
-		selectionsLock.writeLock().lock();
+		this.selectionsLock.writeLock().lock();
 		try {
-			selectedRows.clear();
+			this.selectedRows.clear();
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public void clearSelection(int columnPosition, int rowPosition) {
-		selectionsLock.writeLock().lock();
-		
+	public void clearSelection(final int columnPosition, final int rowPosition) {
+		this.selectionsLock.writeLock().lock();
 		try {
-			Serializable rowId = getRowIdByPosition(rowPosition);
-			selectedRows.remove(rowId);
+			final Serializable rowId = getRowIdByPosition(rowPosition);
+			this.selectedRows.remove(rowId);
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public void clearSelection(Rectangle removedSelection) {
-		selectionsLock.writeLock().lock();
-		
+	public void clearSelection(final Rectangle positions) {
+		this.selectionsLock.writeLock().lock();
 		try {
-			int maxY = Math.min(removedSelection.y + removedSelection.height, selectionLayer.getRowCount());
-			for (int rowPosition = removedSelection.y; rowPosition < maxY; rowPosition++) {
+			final int maxY = Math.min(positions.y + positions.height, this.selectionLayer.getRowCount());
+			for (int rowPosition = positions.y; rowPosition < maxY; rowPosition++) {
 				clearSelection(0, rowPosition);
 			}
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public void clearSelection(R rowObject) {
-		selectionsLock.writeLock().lock();
+	public void clearSelection(final R rowObject) {
+		this.selectionsLock.writeLock().lock();
 		
 		try {
-			selectedRows.values().remove(rowObject);
+			this.selectedRows.values().remove(rowObject);
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
-	};
+	}
+	
 	
 	@Override
 	public boolean isEmpty() {
-		selectionsLock.readLock().lock();
-		
+		this.selectionsLock.readLock().lock();
 		try {
-			return selectedRows.isEmpty();
+			return this.selectedRows.isEmpty();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
+	
 	@Override
 	public List<Rectangle> getSelections() {
-		List<Rectangle> selectionRectangles = new ArrayList<Rectangle>();
-		
-		selectionsLock.readLock().lock();
-		
+		this.selectionsLock.readLock().lock();
 		try {
-			int width = selectionLayer.getColumnCount();
-			for (Serializable rowId : selectedRows.keySet()) {
-				int rowPosition = getRowPositionById(rowId);
+			final List<Rectangle> selectionRectangles = new ArrayList<Rectangle>();
+			final int width = this.selectionLayer.getColumnCount();
+			
+			for (final Serializable rowId : this.selectedRows.keySet()) {
+				final int rowPosition = getRowPositionById(rowId);
 				selectionRectangles.add(new Rectangle(0, rowPosition, width, 1));
 			}
+			
+			return selectionRectangles;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-		
-		return selectionRectangles;
 	}
 	
 	// Cell features
-
+	
 	@Override
-	public boolean isCellPositionSelected(int columnPosition, int rowPosition) {
-		ILayerCell cell = selectionLayer.getCellByPosition(columnPosition, rowPosition);
-		int cellOriginRowPosition = cell.getOriginRowPosition();
+	public boolean isCellPositionSelected(final int columnPosition, final int rowPosition) {
+		final ILayerCell cell = this.selectionLayer.getCellByPosition(columnPosition, rowPosition);
+		final int cellOriginRowPosition = cell.getOriginRowPosition();
 		for (int testRowPosition = cellOriginRowPosition; testRowPosition < cellOriginRowPosition + cell.getRowSpan(); testRowPosition++) {
 			if (isRowPositionSelected(testRowPosition)) {
 				return true;
@@ -219,194 +226,178 @@
 	}
 	
 	// Column features
-
+	
 	@Override
-	public int[] getSelectedColumnPositions() {
-		if (!isEmpty()) {
-			selectionsLock.readLock().lock();
+	public RangeList getSelectedColumnPositions() {
+		this.selectionsLock.readLock().lock();
+		try {
+			final RangeList selected = new RangeList();
 			
-			int columnCount;
-			
-			try {
-				columnCount = selectionLayer.getColumnCount();
-			} finally {
-				selectionsLock.readLock().unlock();
+			if (!this.selectedRows.isEmpty()) {
+				selected.add(new Range(0, this.selectionLayer.getColumnCount()));
 			}
 			
-			int[] columns = new int[columnCount];
-			for (int i = 0; i < columnCount; i++) {
-				columns[i] = i;
-			}
-			return columns;
+			return selected;
+		} finally {
+			this.selectionsLock.readLock().unlock();
 		}
-		return new int[] {};
 	}
 	
 	@Override
-	public boolean isColumnPositionSelected(int columnPosition) {
-		selectionsLock.readLock().lock();
-
+	public boolean isColumnPositionSelected(final int columnPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			return !selectedRows.isEmpty();
+			return !this.selectedRows.isEmpty();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public int[] getFullySelectedColumnPositions(int fullySelectedColumnRowCount) {
-		selectionsLock.readLock().lock();
-		
+	public RangeList getFullySelectedColumnPositions() {
+		this.selectionsLock.readLock().lock();
 		try {
-			if (isColumnPositionFullySelected(0, fullySelectedColumnRowCount)) {
-				return getSelectedColumnPositions();
+			final RangeList selected = new RangeList();
+			
+			if (isFullySelected()) {
+				selected.add(new Range(0, this.selectionLayer.getColumnCount()));
 			}
+			
+			return selected;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-		
-		return new int[] {};
 	}
-
+	
 	@Override
-	public boolean isColumnPositionFullySelected(int columnPosition, int fullySelectedColumnRowCount) {
-		selectionsLock.readLock().lock();
-		
+	public boolean isColumnPositionFullySelected(final int columnPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			int selectedRowCount = selectedRows.size();
-			
-			if (selectedRowCount == 0) {
-				return false;
-			}
-			
-			return selectedRowCount == fullySelectedColumnRowCount;
+			return isFullySelected();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
 	
+	private boolean isFullySelected() {
+		final int rowCount = this.selectionLayer.getRowCount();
+		final int selectedRowCount = this.selectedRows.size();
+		
+		return (rowCount > 0 && selectedRowCount == rowCount);
+	}
+	
 	// Row features
 	
 	@Override
 	public List<R> getSelectedRowObjects() {
-		final List<R> rowObjects = new ArrayList<R>();
-
 		this.selectionsLock.readLock().lock();
 		try {
-			rowObjects.addAll(this.selectedRows.values());
+			return new ArrayList<R>(this.selectedRows.values());
 		} finally {
 			this.selectionsLock.readLock().unlock();
 		}
-
-		return rowObjects;
 	}
-
+	
 	@Override
 	public int getSelectedRowCount() {
-		selectionsLock.readLock().lock();
-		
+		this.selectionsLock.readLock().lock();
 		try {
-			return selectedRows.size();
+			return this.selectedRows.size();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public Set<Range> getSelectedRowPositions() {
-		Set<Range> selectedRowRanges = new HashSet<Range>();
-		
-		selectionsLock.readLock().lock();
-		
+	public RangeList getSelectedRowPositions() {
+		this.selectionsLock.readLock().lock();
 		try {
-			for (Serializable rowId : selectedRows.keySet()) {
-				int rowPosition = getRowPositionById(rowId);
-				selectedRowRanges.add(new Range(rowPosition, rowPosition + 1));
+			final RangeList selected = new RangeList();
+			
+			for (final Serializable rowId : this.selectedRows.keySet()) {
+				selected.values().add(getRowPositionById(rowId));
 			}
+			
+			return selected;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-		
-		return selectedRowRanges;
 	}
-
+	
 	@Override
-	public boolean isRowPositionSelected(int rowPosition) {
-		selectionsLock.readLock().lock();
-		
+	public boolean isRowPositionSelected(final int rowPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			Serializable rowId = getRowIdByPosition(rowPosition);
-			return selectedRows.containsKey(rowId);
+			final Serializable rowId = getRowIdByPosition(rowPosition);
+			
+			return this.selectedRows.containsKey(rowId);
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public int[] getFullySelectedRowPositions(int rowWidth) {
-		selectionsLock.readLock().lock();
-		
-		try {
-			int selectedRowCount = selectedRows.size();
-			int[] selectedRowPositions = new int[selectedRowCount];
-			int i = 0;
-			for (Serializable rowId : selectedRows.keySet()) {
-				selectedRowPositions[i] = getRowPositionById(rowId);
-				i++;
-			}
-			return selectedRowPositions;
-		} finally {
-			selectionsLock.readLock().unlock();
-		}
+	public RangeList getFullySelectedRowPositions() {
+		return getSelectedRowPositions();
 	}
-
+	
 	@Override
-	public boolean isRowPositionFullySelected(int rowPosition, int rowWidth) {
+	public boolean isRowPositionFullySelected(final int rowPosition) {
 		return isRowPositionSelected(rowPosition);
 	}
-
-	private Serializable getRowIdByPosition(int rowPosition) {
-		R rowObject = getRowObjectByPosition(rowPosition);
+	
+	private Serializable getRowIdByPosition(final int rowPosition) {
+		final R rowObject = getRowObjectByPosition(rowPosition);
 		if (rowObject != null) {
-			Serializable rowId = rowIdAccessor.getRowId(rowObject);
+			final Serializable rowId = this.rowIdAccessor.getRowId(rowObject);
 			return rowId;
 		}
 		return null;
 	}
-
-	private R getRowObjectByPosition(int rowPosition) {
-		selectionsLock.readLock().lock();
-		
+	
+	private R getRowObjectByPosition(final int rowPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			int rowIndex = selectionLayer.getRowIndexByPosition(rowPosition);
+			final int rowIndex = this.selectionLayer.getRowIndexByPosition(rowPosition);
 			if (rowIndex >= 0) {
 				try {
-					R rowObject = rowDataProvider.getRowObject(rowIndex);
+					final R rowObject = this.rowDataProvider.getRowObject(rowIndex);
 					return rowObject;
-				} catch (Exception e) {
+				} catch (final Exception e) {
 					// row index is invalid for the data provider
 				}
 			}
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 		
 		return null;
 	}
 	
-	private int getRowPositionById(Serializable rowId) {
-		selectionsLock.readLock().lock();
-		
+	private int getRowPositionById(final Serializable rowId) {
+		this.selectionsLock.readLock().lock();
 		try {
-			R rowObject = selectedRows.get(rowId);
-			int rowIndex = rowDataProvider.indexOfRowObject(rowObject);
-			if(rowIndex == -1){
+			final R rowObject = this.selectedRows.get(rowId);
+			final int rowIndex = this.rowDataProvider.indexOfRowObject(rowObject);
+			if (rowIndex < 0) {
 				return -1;
 			}
-			int rowPosition = selectionLayer.getRowPositionByIndex(rowIndex);
-			return rowPosition;
+			
+			return this.selectionLayer.getRowPositionByIndex(rowIndex);
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
+		}
+	}
+	
+	//-- Object methods --//
+	
+	@Override
+	public String toString() {
+		this.selectionsLock.readLock().lock();
+		try {
+			return this.selectedRows.toString();
+		} finally {
+			this.selectionsLock.readLock().unlock();
 		}
 	}
 	
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionProvider.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionProvider.java
index cfacfe9..db91399 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionProvider.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/RowSelectionProvider.java
@@ -23,7 +23,7 @@
 import org.eclipse.jface.viewers.SelectionChangedEvent;
 import org.eclipse.jface.viewers.StructuredSelection;
 
-import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
 import org.eclipse.nebula.widgets.nattable.layer.ILayerListener;
@@ -208,17 +208,10 @@
 		List<RowObjectIndexHolder<Object>> rows = new ArrayList<RowObjectIndexHolder<Object>>();
 
 		if (selectionLayer != null) {
-			if (fullySelectedRowsOnly) {
-				for (int rowPosition : selectionLayer.getFullySelectedRowPositions()) {
-					addToSelection(rows, rowPosition, selectionLayer, rowDataProvider);
-				}
-			} else {
-				Set<Range> rowRanges = selectionLayer.getSelectedRowPositions();
-				for (Range rowRange : rowRanges) {
-					for (int rowPosition = rowRange.start; rowPosition < rowRange.end; rowPosition++) {
-						addToSelection(rows, rowPosition, selectionLayer, rowDataProvider);
-					}
-				}
+			final RangeList selectedRows = (fullySelectedRowsOnly) ?
+					selectionLayer.getFullySelectedRowPositions() : selectionLayer.getSelectedRowPositions();
+			for (final IValueIterator rowIter = selectedRows.values().iterator(); rowIter.hasNext(); ) {
+				addToSelection(rows, rowIter.nextValue(), selectionLayer, rowDataProvider);
 			}
 		}
 		Collections.sort(rows);
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectCellCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectCellCommandHandler.java
index 79da883..56a56cc 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectCellCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectCellCommandHandler.java
@@ -13,10 +13,11 @@
 import static org.eclipse.nebula.widgets.nattable.selection.SelectionUtils.isControlOnly;
 
 import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand;
-import org.eclipse.swt.graphics.Rectangle;
+
 
 public class SelectCellCommandHandler implements ILayerCommandHandler<SelectCellCommand> {
 
@@ -68,7 +69,7 @@
 			selectionLayer.setLastSelectedCell(cell.getOriginColumnPosition(), cell.getOriginRowPosition());
 			
 			// Shift pressed + row selected
-			if (selectionLayer.getSelectionModel().isMultipleSelectionAllowed() 
+			if (selectionLayer.getSelectionModel().isMultipleSelectionAllowed()
 					&& withShiftMask 
 					&& selectionLayer.lastSelectedRegion != null 
 					&& selectionLayer.hasRowSelection()
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectColumnCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectColumnCommandHandler.java
index 7e3897f..63322b0 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectColumnCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectColumnCommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -16,10 +16,11 @@
 import static org.eclipse.nebula.widgets.nattable.selection.SelectionUtils.noShiftOrControl;
 
 import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand;
 import org.eclipse.nebula.widgets.nattable.selection.event.ColumnSelectionEvent;
-import org.eclipse.swt.graphics.Rectangle;
 
 
 public class SelectColumnCommandHandler implements ILayerCommandHandler<SelectColumnCommand> {
@@ -57,7 +58,8 @@
 		selectionLayer.lastSelectedCell.columnPosition = columnPosition;
 		selectionLayer.lastSelectedCell.rowPosition = rowPosition;
 
-		selectionLayer.fireLayerEvent(new ColumnSelectionEvent(selectionLayer, columnPosition));
+		selectionLayer.fireLayerEvent(new ColumnSelectionEvent(selectionLayer,
+				new RangeList(columnPosition) ));
 	}
 
 	private void selectColumnWithCtrlKey(int columnPosition, int rowPosition) {
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowCommandHandler.java
index d458bb1..97d333a 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowCommandHandler.java
@@ -19,13 +19,12 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.eclipse.swt.graphics.Rectangle;
-
 import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
 import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList.ValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowsCommand;
 import org.eclipse.nebula.widgets.nattable.selection.event.RowSelectionEvent;
@@ -49,19 +48,13 @@
 	}
 
 	protected void selectRows(int columnPosition, Collection<Range> rowPositions, boolean withShiftMask, boolean withControlMask, int rowPositionToMoveIntoViewport) {
-		final RangeList changedRowRanges = new RangeList();
+		final RangeList changedRows = new RangeList();
 		
 		for (final IValueIterator rowIter = new ValueIterator(rowPositions); rowIter.hasNext(); ) {
-			changedRowRanges.addAll(internalSelectRow(columnPosition, rowIter.nextValue(),
+			changedRows.addAll(internalSelectRow(columnPosition, rowIter.nextValue(),
 					withShiftMask, withControlMask ));
 		}
-
-		Set<Integer> changedRows = new HashSet<Integer>();
-		for (Range range : changedRowRanges) {
-			for (int i = range.start; i < range.end; i++) {
-				changedRows.add(Integer.valueOf(i));
-			}
-		}
+		
 		selectionLayer.fireLayerEvent(new RowSelectionEvent(selectionLayer, changedRows, rowPositionToMoveIntoViewport));
 	}
 
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowGroupCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowGroupCommandHandler.java
index 9411cb3..96dc1cf 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowGroupCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectRowGroupCommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -22,13 +22,15 @@
 
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.group.RowGroupHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.group.RowGroupUtils;
 import org.eclipse.nebula.widgets.nattable.group.model.IRowGroupModel;
 import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowGroupsCommand;
 import org.eclipse.nebula.widgets.nattable.selection.event.RowSelectionEvent;
 import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
-import org.eclipse.swt.graphics.Rectangle;
+
 
 public class SelectRowGroupCommandHandler<T> extends AbstractLayerCommandHandler<SelectRowGroupsCommand> {
 
@@ -56,18 +58,12 @@
 	}
 	
 	protected void selectRows(int columnPosition, List<Integer> rowPositions, boolean withShiftMask, boolean withControlMask, int rowPositionToMoveIntoViewport, boolean moveAnchorToTopOfGroup) {
-		Set<Range> changedRowRanges = new HashSet<Range>();
+		RangeList changedRows = new RangeList();
 		
-		if( rowPositions.size() > 0 ) {
-			changedRowRanges.addAll(internalSelectRow(columnPosition, rowPositions.get(0), rowPositions.size(), withShiftMask, withControlMask, moveAnchorToTopOfGroup));
+		if (rowPositions.size() > 0) {
+			changedRows.addAll(internalSelectRow(columnPosition, rowPositions.get(0), rowPositions.size(), withShiftMask, withControlMask, moveAnchorToTopOfGroup));
 		}
-
-		Set<Integer> changedRows = new HashSet<Integer>();
-		for (Range range : changedRowRanges) {
-			for (int i = range.start; i < range.end; i++) {
-				changedRows.add(Integer.valueOf(i));
-			}
-		}
+		
 		selectionLayer.fireLayerEvent(new RowSelectionEvent(selectionLayer, changedRows, rowPositionToMoveIntoViewport));
 	}
 	
@@ -114,28 +110,25 @@
 			selectionLayer.selectRegion(0, rowPosition, selectionLayer.getColumnCount(), rowCount);
 		}
 		
-		return new Range(rowPosition, rowPosition + 1);
+		return new Range(rowPosition);
 	}
 
 	private Range selectRowWithShiftKey(int columnPosition, int rowPosition, int rowCount) {
 		if (selectionLayer.lastSelectedRegion != null) {
 			int start = Math.min(selectionLayer.lastSelectedRegion.y, rowPosition);
 			int end = Math.max(selectionLayer.lastSelectedRegion.y, rowPosition);
-		
-		
-		for(int i = start; i <= end; i++){
-			int index = selectionLayer.getRowIndexByPosition(i);
-			if(RowGroupUtils.isPartOfAGroup(model, index) && !selectionLayer.isRowPositionFullySelected(i)){
-				List <Integer> rowPositions = new ArrayList<Integer>(RowGroupUtils.getRowPositionsInGroup(selectionLayer, RowGroupUtils.getRowIndexesInGroup(model, index)));
-				Collections.sort(rowPositions);
-				selectionLayer.selectRegion(0, rowPositions.get(0), selectionLayer.getColumnCount(), rowPositions.size());
-				i=ObjectUtils.getLastElement(rowPositions);
+			
+			for (int i = start; i <= end; i++){
+				int index = selectionLayer.getRowIndexByPosition(i);
+				if (RowGroupUtils.isPartOfAGroup(model, index) && !selectionLayer.isRowPositionFullySelected(i)){
+					List<Integer> rowPositions = new ArrayList<Integer>(RowGroupUtils.getRowPositionsInGroup(selectionLayer, RowGroupUtils.getRowIndexesInGroup(model, index)));
+					Collections.sort(rowPositions);
+					selectionLayer.selectRegion(0, rowPositions.get(0), selectionLayer.getColumnCount(), rowPositions.size());
+					i=ObjectUtils.getLastElement(rowPositions);
+				}
 			}
 		}
-		
-		
-		}
-		return new Range(rowPosition, rowPosition + 1);
+		return new Range(rowPosition);
 	}
-		
+	
 }
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 9d1fa3c..557b009 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
@@ -16,15 +16,12 @@
 import java.util.List;
 import java.util.Set;
 
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-
 import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
 import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
 import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
-import org.eclipse.nebula.widgets.nattable.coordinate.Range;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList.ValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
 import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler;
 import org.eclipse.nebula.widgets.nattable.edit.command.EditSelectionCommandHandler;
 import org.eclipse.nebula.widgets.nattable.grid.command.InitializeAutoResizeColumnsCommandHandler;
@@ -33,9 +30,9 @@
 import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiColumnHideCommand;
 import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiRowHideCommand;
 import org.eclipse.nebula.widgets.nattable.hideshow.command.RowHideCommand;
-import org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform;
 import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
 import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
+import org.eclipse.nebula.widgets.nattable.layer.TransformIndexLayer;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.painter.layer.ILayerPainter;
 import org.eclipse.nebula.widgets.nattable.resize.command.ColumnResizeCommand;
@@ -59,7 +56,7 @@
  * @see DefaultSelectionLayerConfiguration
  * @see MoveDirectionEnum
  */
-public class SelectionLayer extends AbstractIndexLayerTransform {
+public class SelectionLayer extends TransformIndexLayer {
 
 	public static final int MOVE_ALL = -1;
 	public static final int NO_SELECTION = -1;
@@ -168,8 +165,7 @@
 		
 		//if the selection anchor is within the selection that is removed
 		//it needs to be cleared also
-		Point anchorPoint = new Point(selectionAnchor.columnPosition, selectionAnchor.rowPosition);
-		if (selection.contains(anchorPoint)) {
+		if (selection.contains(selectionAnchor.columnPosition, selectionAnchor.rowPosition)) {
 			selectionAnchor.columnPosition = -1;
 			selectionAnchor.rowPosition = -1;
 		}
@@ -202,27 +198,27 @@
 	protected PositionCoordinate getCellPositionToMoveFrom(boolean withShiftMask, boolean withControlMask) {
 		return (!withShiftMask && !withControlMask)	? getSelectionAnchor() : getLastSelectedCellPosition();
 	}
-
-	public PositionCoordinate[] getSelectedCellPositions() {
-		int[] selectedColumnPositions = getSelectedColumnPositions();
-		Set<Range> selectedRowPositions = getSelectedRowPositions();
-
-		List<PositionCoordinate> selectedCells = new LinkedList<PositionCoordinate>();
-
-		for (int columnPositionIndex = 0; columnPositionIndex < selectedColumnPositions.length; columnPositionIndex++) {
-			final int columnPosition = selectedColumnPositions[columnPositionIndex];
-
-			for (Range rowIndexRange : selectedRowPositions) {
-				for (int rowPositionIndex = rowIndexRange.start; rowPositionIndex < rowIndexRange.end; rowPositionIndex++) {
-					if (selectionModel.isCellPositionSelected(columnPosition, rowPositionIndex)) {
-						selectedCells.add(new PositionCoordinate(this, columnPosition, rowPositionIndex));
-					}
+	
+	public List<PositionCoordinate> getSelectedCellPositions() {
+		final RangeList selectedColumnPositions = getSelectedColumnPositions();
+		final RangeList selectedRowPositions = getSelectedRowPositions();
+		
+		final List<PositionCoordinate> selectedCells = new LinkedList<PositionCoordinate>();
+		
+		for (final IValueIterator columnIter = selectedColumnPositions.values().iterator(); columnIter.hasNext(); ) {
+			final int columnPosition = columnIter.nextValue();
+			for (final IValueIterator rowIter = selectedRowPositions.values().iterator(); rowIter.hasNext(); ) {
+				final int rowPosition = rowIter.nextValue();
+				
+				if (selectionModel.isCellPositionSelected(columnPosition, rowPosition)) {
+					selectedCells.add(new PositionCoordinate(this, columnPosition, rowPosition));
 				}
 			}
 		}
-		return selectedCells.toArray(new PositionCoordinate[0]);
+		
+		return selectedCells;
 	}
-
+	
 	/**
 	 * Retrieves the ILayerCells out of the SelectionLayer that are currently marked as selected in
 	 * the SelectionModel. Takes spanning into account.
@@ -231,7 +227,7 @@
 	public Collection<ILayerCell> getSelectedCells() {
 		Set<ILayerCell> selectedCells = new HashSet<ILayerCell>();
 
-		PositionCoordinate[] selectedCoords = getSelectedCellPositions();
+		List<PositionCoordinate> selectedCoords = getSelectedCellPositions();
 		for (PositionCoordinate coord : selectedCoords) {
 			selectedCells.add(getCellByPosition(coord.columnPosition, coord.rowPosition));
 		}
@@ -294,7 +290,7 @@
 		return lastSelectedCell.columnPosition != NO_SELECTION;
 	}
 
-	public int[] getSelectedColumnPositions() {
+	public RangeList getSelectedColumnPositions() {
 		return selectionModel.getSelectedColumnPositions();
 	}
 
@@ -302,12 +298,12 @@
 		return selectionModel.isColumnPositionSelected(columnPosition);
 	}
 
-	public int[] getFullySelectedColumnPositions() {
-		return selectionModel.getFullySelectedColumnPositions(getRowCount());
+	public RangeList getFullySelectedColumnPositions() {
+		return selectionModel.getFullySelectedColumnPositions();
 	}
 
 	public boolean isColumnPositionFullySelected(int columnPosition) {
-		return selectionModel.isColumnPositionFullySelected(columnPosition, getRowCount());
+		return selectionModel.isColumnPositionFullySelected(columnPosition);
 	}
 
 	public void selectColumn(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask) {
@@ -324,7 +320,7 @@
 		return selectionModel.getSelectedRowCount();
 	}
 
-	public Set<Range> getSelectedRowPositions() {
+	public RangeList getSelectedRowPositions() {
 		return selectionModel.getSelectedRowPositions();
 	}
 
@@ -332,12 +328,12 @@
 		return selectionModel.isRowPositionSelected(rowPosition);
 	}
 
-	public int[] getFullySelectedRowPositions() {
-		return selectionModel.getFullySelectedRowPositions(getColumnCount());
+	public RangeList getFullySelectedRowPositions() {
+		return selectionModel.getFullySelectedRowPositions();
 	}
 
 	public boolean isRowPositionFullySelected(int rowPosition) {
-		return selectionModel.isRowPositionFullySelected(rowPosition, getColumnCount());
+		return selectionModel.isRowPositionFullySelected(rowPosition);
 	}
 
 	public void selectRow(int columnPosition, int rowPosition, boolean withShiftMask, boolean withControlMask) {
@@ -361,8 +357,7 @@
 		
 		ILayerCell cell = getCellByPosition(columnPosition, rowPosition);
 		if (cell != null) {
-			Rectangle cellRectangle =
-					new Rectangle(
+			Rectangle cellRectangle = new Rectangle(
 							cell.getOriginColumnPosition(),
 							cell.getOriginRowPosition(),
 							cell.getColumnSpan(),
@@ -418,10 +413,8 @@
 
 	public void fireCellSelectionEvent(int columnPosition, int rowPosition,
 			boolean forcingEntireCellIntoViewport, boolean withShiftMask, boolean withControlMask) {
-
-		final CellSelectionEvent selectionEvent = new CellSelectionEvent(this, columnPosition, rowPosition,
-				withShiftMask, withControlMask);
-		fireLayerEvent(selectionEvent);
+		fireLayerEvent(new CellSelectionEvent(this, columnPosition, rowPosition,
+				withShiftMask, withControlMask ));
 	}
 	
 	// command transformations
@@ -443,8 +436,8 @@
 	 */
 	protected boolean handleColumnHideCommand(ColumnHideCommand command) {
 		if (isColumnPositionFullySelected(command.getColumnPosition())) {
-			return handleMultiColumnHideCommand(
-					new MultiColumnHideCommand(this, new RangeList(getFullySelectedColumnPositions())));
+			return handleMultiColumnHideCommand(new MultiColumnHideCommand(this,
+					getFullySelectedColumnPositions()) );
 		} else {
 			return super.doCommand(command);
 		}
@@ -487,8 +480,8 @@
 	 */
 	protected boolean handleRowHideCommand(RowHideCommand command) {
 		if (isRowPositionFullySelected(command.getRowPosition())) {
-			return handleMultiRowHideCommand(
-					new MultiRowHideCommand(this, new RangeList(getFullySelectedRowPositions())));
+			return handleMultiRowHideCommand(new MultiRowHideCommand(this,
+					getFullySelectedRowPositions()) );
 		} else {
 			return super.doCommand(command);
 		}
@@ -530,8 +523,8 @@
 	 */
 	protected boolean handleColumnResizeCommand(ColumnResizeCommand command) {
 		if (isColumnPositionFullySelected(command.getColumnPosition())) {
-			return super.doCommand(
-					new MultiColumnResizeCommand(this, new RangeList(selectionModel.getFullySelectedColumnPositions(getRowCount())), command.getNewColumnWidth()));
+			return super.doCommand(new MultiColumnResizeCommand(this,
+					selectionModel.getFullySelectedColumnPositions(), command.getNewColumnWidth()));
 		} else {
 			return super.doCommand(command);
 		}
@@ -553,8 +546,8 @@
 	 */
 	protected boolean handleRowResizeCommand(RowResizeCommand command) {
 		if (isRowPositionFullySelected(command.getRowPosition())) {
-			return super.doCommand(
-					new MultiRowResizeCommand(this, new RangeList(selectionModel.getFullySelectedRowPositions(getColumnCount())), command.getNewHeight()));
+			return super.doCommand(new MultiRowResizeCommand(this,
+					selectionModel.getFullySelectedRowPositions(), command.getNewHeight()) );
 		} else {
 			return super.doCommand(command);
 		}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModel.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModel.java
index 1dbb3c2..ddc9ba6 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModel.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionModel.java
@@ -11,21 +11,17 @@
 package org.eclipse.nebula.widgets.nattable.selection;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import org.apache.commons.lang.ArrayUtils;
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
+import org.eclipse.nebula.widgets.nattable.coordinate.Rectangle;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
-import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
-import org.eclipse.swt.graphics.Rectangle;
+
 
 /**
  * Tracks the selections made in the table. All selections are tracked in terms of
@@ -39,65 +35,110 @@
  * @see SelectionLayer
  */
 public class SelectionModel implements ISelectionModel {
-
-	private final SelectionLayer selectionLayer;
+	
+	
+	//-- Utility --//
+	
+	private static final Rectangle getLeftSelection(final Rectangle intersection, final Rectangle selection) {
+		if (intersection.x > selection.x) {
+			return new Rectangle(selection.x, selection.y,
+					intersection.x - selection.x, selection.height);
+		}
+		return null;
+	}
+	
+	private static final Rectangle getRightSelection(final Rectangle intersection, final Rectangle selection) {
+		final int newX = intersection.x + intersection.width;
+		if (newX < selection.x + selection.width) {
+			return new Rectangle(newX, selection.y,
+					selection.x + selection.width - newX, selection.height);
+		}
+		return null;
+	}
+	
+	private static final Rectangle getTopSelection(final Rectangle intersection, final Rectangle selection) {
+		if (intersection.y > selection.y) {
+			return new Rectangle(selection.x, selection.y,
+					selection.width, intersection.y - selection.y);
+		}
+		return null;
+	}
+	
+	private static final Rectangle getBottomSelection(final Rectangle intersection, final Rectangle selection) {
+		final int newY = intersection.y + intersection.height;
+		if (newY < selection.y + selection.height) {
+			return new Rectangle(selection.x, newY,
+					selection.width, selection.y + selection.height - newY);
+		}
+		return null;
+	}
+	
+	
+	private final ILayer selectionLayer;
+	
 	private boolean multipleSelectionAllowed;
 	
 	private final List<Rectangle> selections;
 	private final ReadWriteLock selectionsLock;
-
-	public SelectionModel(SelectionLayer selectionLayer) {
+	
+	
+	public SelectionModel(/*@NotNull*/ final ILayer selectionLayer) {
 		this(selectionLayer, true);
 	}
 	
-	public SelectionModel(SelectionLayer selectionLayer, boolean multipleSelectionAllowed) {
+	public SelectionModel(/*@NotNull*/ final ILayer selectionLayer, final boolean multipleSelectionAllowed) {
+		if (selectionLayer == null) {
+			throw new NullPointerException("selectionLayer"); //$NON-NLS-1$
+		}
 		this.selectionLayer = selectionLayer;
 		this.multipleSelectionAllowed = multipleSelectionAllowed;
 		
-		selections = new LinkedList<Rectangle>();
-		selectionsLock = new ReentrantReadWriteLock();
+		this.selections = new LinkedList<Rectangle>();
+		this.selectionsLock = new ReentrantReadWriteLock();
 	}
-
+	
+	
 	@Override
 	public boolean isMultipleSelectionAllowed() {
-		return multipleSelectionAllowed;
+		return this.multipleSelectionAllowed;
 	}
 	
 	@Override
-	public void setMultipleSelectionAllowed(boolean multipleSelectionAllowed) {
+	public void setMultipleSelectionAllowed(final boolean multipleSelectionAllowed) {
 		this.multipleSelectionAllowed = multipleSelectionAllowed;
 	}
 	
+	
 	@Override
-	public void addSelection(int columnPosition, int rowPosition) {
+	public void addSelection(final int columnPosition, final int rowPosition) {
 		addSelectionIntoList(new Rectangle(columnPosition, rowPosition, 1, 1));
 	}
-
+	
 	@Override
-	public void addSelection(final Rectangle range) {
-		if (range != null) {
-			addSelectionIntoList(range);
+	public void addSelection(final Rectangle positions) {
+		if (positions != null) {
+			addSelectionIntoList(positions);
 		}
-
 	}
-
-	private void addSelectionIntoList(Rectangle selection) {
-		selectionsLock.writeLock().lock();
+	
+	private void addSelectionIntoList(final Rectangle selection) {
+		this.selectionsLock.writeLock().lock();
 		try {
-			if (multipleSelectionAllowed) {
+			if (this.multipleSelectionAllowed) {
 				ArrayList<Rectangle> itemsToRemove = null;
-				for (Rectangle r : selections) {
+				for (final Rectangle r : this.selections) {
 					if (selection.intersects(r)) {
 						if (r.equals(selection)) {
 							break;
 						}
-	
-						Rectangle intersection = selection.intersection(r);
+						
+						final Rectangle intersection = selection.intersection(r);
 						if (intersection.equals(r)) {
 							// r is a subset of intersection
-							if (itemsToRemove == null)
+							if (itemsToRemove == null) {
 								itemsToRemove = new ArrayList<Rectangle>();
-	
+							}
+							
 							itemsToRemove.add(r);
 						} else if (intersection.equals(selection)) {
 							// selection is a subset of r
@@ -105,461 +146,336 @@
 						}
 					}
 				}
-	
+				
 				if (itemsToRemove != null) {
-					selections.removeAll(itemsToRemove);
+					this.selections.removeAll(itemsToRemove);
 				}
 			} else {
-				selections.clear();
+				this.selections.clear();
 				//as no multiple selection is allowed, ensure that only one column 
 				//and one row will be selected
 				selection.height = 1;
 				selection.width = 1;
 			}
-
-			selections.add(selection);
+			
+			this.selections.add(selection);
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
-
 	}
-
+	
 	@Override
 	public void clearSelection() {
-		selectionsLock.writeLock().lock();
+		this.selectionsLock.writeLock().lock();
 		try {
-			selections.clear();
+			this.selections.clear();
 		} finally {
-			selectionsLock.writeLock().unlock();
+			this.selectionsLock.writeLock().unlock();
 		}
 	}
-
+	
 	@Override
-	public void clearSelection(int columnPosition, int rowPosition) {
+	public void clearSelection(final int columnPosition, final int rowPosition) {
 		clearSelection(new Rectangle(columnPosition, rowPosition, 1, 1));
 	}
-
+	
 	@Override
-	public void clearSelection(Rectangle removedSelection) {
-
-		List<Rectangle> removedItems = new LinkedList<Rectangle>();
-		List<Rectangle> addedItems = new LinkedList<Rectangle>();
-
-		selectionsLock.readLock().lock();
-
+	public void clearSelection(final Rectangle positions) {
+		final List<Rectangle> removedItems = new LinkedList<Rectangle>();
+		final List<Rectangle> addedItems = new LinkedList<Rectangle>();
+		
+		this.selectionsLock.readLock().lock();
 		try {
-			for (Rectangle r : selections) {
-				if (r.intersects(removedSelection)) {
-					Rectangle intersection = removedSelection.intersection(r);
+			for (final Rectangle r : this.selections) {
+				if (r.intersects(positions)) {
+					final Rectangle intersection = positions.intersection(r);
 					removedItems.add(r);
-
-					Rectangle topSelection = getTopSelection(intersection, r);
+					
+					final Rectangle topSelection = getTopSelection(intersection, r);
 					if (topSelection != null) {
 						addedItems.add(topSelection);
 					}
-
-					Rectangle rightSelection = getRightSelection(intersection, r);
-					if (rightSelection != null)
+					final Rectangle rightSelection = getRightSelection(intersection, r);
+					if (rightSelection != null) {
 						addedItems.add(rightSelection);
-
-					Rectangle leftSelection = getLeftSelection(intersection, r);
-					if (leftSelection != null)
+					}
+					final Rectangle leftSelection = getLeftSelection(intersection, r);
+					if (leftSelection != null) {
 						addedItems.add(leftSelection);
-
-					Rectangle bottomSelection = getBottomSelection(intersection, r);
-					if (bottomSelection != null)
+					}
+					final Rectangle bottomSelection = getBottomSelection(intersection, r);
+					if (bottomSelection != null) {
 						addedItems.add(bottomSelection);
+					}
 				}
 			}
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-
+		
 		if (removedItems.size() > 0) {
-			selectionsLock.writeLock().lock();
+			this.selectionsLock.writeLock().lock();
 			try {
-				selections.removeAll(removedItems);
+				this.selections.removeAll(removedItems);
 			} finally {
-				selectionsLock.writeLock().unlock();
+				this.selectionsLock.writeLock().unlock();
 			}
-
+			
 			removedItems.clear();
 		}
-
+		
 		if (addedItems.size() > 0) {
-			selectionsLock.writeLock().lock();
+			this.selectionsLock.writeLock().lock();
 			try {
-				selections.addAll(addedItems);
+				this.selections.addAll(addedItems);
 			} finally {
-				selectionsLock.writeLock().unlock();
+				this.selectionsLock.writeLock().unlock();
 			}
-
+			
 			addedItems.clear();
 		}
-
 	}
-
+	
+	
 	@Override
 	public boolean isEmpty() {
-		selectionsLock.readLock().lock();
+		this.selectionsLock.readLock().lock();
 		try {
-			return selections.isEmpty();
+			return this.selections.isEmpty();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
+	
 	@Override
 	public List<Rectangle> getSelections() {
-		return selections;
+		return this.selections;
 	}
 	
 	// Cell features
-
+	
 	@Override
-	public boolean isCellPositionSelected(int columnPosition, int rowPosition) {
-		selectionsLock.readLock().lock();
-
+	public boolean isCellPositionSelected(final int columnPosition, final int rowPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			ILayerCell cell = selectionLayer.getCellByPosition(columnPosition, rowPosition);
-			Rectangle cellRectangle =
-					new Rectangle(
-							cell.getOriginColumnPosition(),
-							cell.getOriginRowPosition(),
-							cell.getColumnSpan(),
-							cell.getRowSpan());
+			final ILayerCell cell = this.selectionLayer.getCellByPosition(columnPosition, rowPosition);
+			final Rectangle cellRectangle = new Rectangle(
+					cell.getOriginColumnPosition(),
+					cell.getOriginRowPosition(),
+					cell.getColumnSpan(),
+					cell.getRowSpan());
 			
-			for (Rectangle selectionRectangle : selections) {
-				if (selectionRectangle.intersects(cellRectangle))
+			for (final Rectangle selectionRectangle : this.selections) {
+				if (selectionRectangle.intersects(cellRectangle)) {
 					return true;
+				}
 			}
+			
+			return false;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-
-		return false;
 	}
 	
 	// Column features
-
-	@Override
-	public int[] getSelectedColumnPositions() {
-		TreeSet<Integer> selectedColumns = new TreeSet<Integer>();
-
-		selectionsLock.readLock().lock();
-
-		int columnCount = selectionLayer.getColumnCount();
-		try {
-			for (Rectangle r : selections) {
-				int startColumn = r.x;
-				if (startColumn < columnCount) {
-					int numColumns = (r.x + r.width <= columnCount) ? r.width : columnCount - r.x;
 	
-					// Change from row < startRow to row < startRow+numRows
-					for (int column = startColumn; column < startColumn + numColumns; column++) {
-						selectedColumns.add(Integer.valueOf(column));
-					}
+	@Override
+	public RangeList getSelectedColumnPositions() {
+		this.selectionsLock.readLock().lock();
+		try {
+			final RangeList selected = new RangeList();
+			final int columnCount = this.selectionLayer.getColumnCount();
+			
+			for (final Rectangle r : this.selections) {
+				if (r.x < columnCount) {
+					selected.add(new Range(r.x, Math.min(r.x + r.width, columnCount)));
 				}
 			}
+			
+			return selected;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-
-		// Convert to array
-		return ObjectUtils.asIntArray(selectedColumns);
 	}
 	
 	@Override
-	public boolean isColumnPositionSelected(int columnPosition) {
-		selectionsLock.readLock().lock();
-
+	public boolean isColumnPositionSelected(final int columnPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			for (int column : getSelectedColumnPositions()) {
-				if (column == columnPosition) {
-					return true;
-				}
-			}
-		} finally {
-			selectionsLock.readLock().unlock();
-		}
-
-		return false;
-	}
-
-	@Override
-	public int[] getFullySelectedColumnPositions(int columnHeight) {
-		final int[] selectedColumns = getSelectedColumnPositions();
-		int[] columnsToHide = new int[selectedColumns.length];
-		int index = 0;
-		for (int columnPosition : selectedColumns) {
-			if (isColumnPositionFullySelected(columnPosition, columnHeight)) {
-				columnsToHide[index++] = columnPosition;
-			}
-		}
-
-		return index > 0  ? ArrayUtils.subarray(columnsToHide, 0, index) : new int[0];
-	}
-
-	/**
-	 * Are all cells in this column selected?
-	 * Different selection rectangles might aggregate to cover the entire column.
-	 * We need to take into account any overlapping selections or any selection rectangles
-	 * contained within each other.
-	 * 
-	 * See the related tests for a better understanding.
-	 */
-	@Override
-	public boolean isColumnPositionFullySelected(int columnPosition, int columnHeight) {
-		selectionsLock.readLock().lock();
-
-		try {
-			// Aggregate all rectangles in the column which are in the selection model
-			List<Rectangle> selectedRectanglesInColumn = new ArrayList<Rectangle>();
-
-			// If X is same add up the height of the selected area
-			for (Rectangle r : selections) {
-				// Column is within the bounds of the selcted rectangle
-				if (columnPosition >= r.x && columnPosition < r.x + r.width) {
-					selectedRectanglesInColumn.add(new Rectangle(columnPosition, r.y, 1, r.height));
-				}
-			}
-			if (selectedRectanglesInColumn.isEmpty()) {
-				return false;
-			}
-			sortByY(selectedRectanglesInColumn);
-			Rectangle finalRectangle = new Rectangle(columnPosition, selectedRectanglesInColumn.get(0).y, 0, 0);
-
-			// Ensure that selections in the column are contiguous and cover the entire column
-			for (int i = 0; i < selectedRectanglesInColumn.size(); i++) {
-				Rectangle rectangle = selectedRectanglesInColumn.get(i);
-				if(contains(finalRectangle, rectangle)){
-					continue;
-				}
-				if (i > 0) {
-					Rectangle previousRect = selectedRectanglesInColumn.get(i - 1);
-					if (rectangle.union(previousRect).height > (rectangle.height + previousRect.height)) {
-						// Rectangles not contiguous
-						return false;
+			final int columnCount = this.selectionLayer.getColumnCount();
+			
+			if (columnPosition >= 0 && columnPosition < columnCount) {
+				for (final Rectangle r : this.selections) {
+					if (columnPosition >= r.x && columnPosition < r.x + r.width) {
+						return true;
 					}
 				}
-				// Union will resolve any overlaping area
-				finalRectangle = finalRectangle.union(rectangle);
 			}
-			return finalRectangle.height >= columnHeight;
+			
+			return false;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
 	
+	@Override
+	public RangeList getFullySelectedColumnPositions() {
+		this.selectionsLock.readLock().lock();
+		try {
+			final RangeList selected = new RangeList();
+			final int rowCount = this.selectionLayer.getRowCount();
+			
+			if (rowCount > 0) {
+				final RangeList selectedColumns = getSelectedColumnPositions();
+				for (final Range range : selectedColumns) {
+					for (int position = range.start; position < range.end; position++) {
+						if (isColumnPositionFullySelected(position, rowCount)) {
+							selected.values().add(position);
+						}
+					}
+				}
+			}
+			
+			return selected;
+		} finally {
+			this.selectionsLock.readLock().unlock();
+		}
+	}
+	
+	@Override
+	public boolean isColumnPositionFullySelected(final int columnPosition) {
+		this.selectionsLock.readLock().lock();
+		try {
+			final int rowCount = this.selectionLayer.getRowCount();
+			
+			return ((rowCount > 0)
+					&& isColumnPositionFullySelected(columnPosition, rowCount) );
+		} finally {
+			this.selectionsLock.readLock().unlock();
+		}
+	}
+	
+	private boolean isColumnPositionFullySelected(final int columnPosition, final int rowCount) {
+		// Aggregate all rows of selection rectangles including the column
+		final RangeList selectedRowsInColumn = new RangeList();
+		
+		for (final Rectangle r : this.selections) {
+			if (columnPosition >= r.x && columnPosition < r.x + r.width) {
+				selectedRowsInColumn.add(new Range(r.y, r.y + r.height));
+			}
+		}
+		
+		final Range range = selectedRowsInColumn.values().getRangeOf(0);
+		return (range != null && range.end >= rowCount);
+	}
+	
 	// Row features
-
+	
 	@Override
 	public int getSelectedRowCount() {
-		Set<Range> selectedRows = getSelectedRowPositions();
-		int count = 0;
-		for (Range range : selectedRows) {
-			count += range.end - range.start;
-		}
-		return count;
+		return getSelectedRowPositions().values().size();
 	}
-
+	
 	@Override
-	public Set<Range> getSelectedRowPositions() {
-		Set<Range> selectedRowsRange = new HashSet<Range>();
-
-		selectionsLock.readLock().lock();
-
-		int rowCount = selectionLayer.getRowCount();
+	public RangeList getSelectedRowPositions() {
+		this.selectionsLock.readLock().lock();
 		try {
-			for (Rectangle r : selections) {
+			final RangeList selected = new RangeList();
+			final int rowCount = this.selectionLayer.getRowCount();
+			
+			for (final Rectangle r : this.selections) {
 				if (r.y < rowCount) {
-					int height = (r.y + r.height <= rowCount) ? r.height : rowCount - r.y;
-					selectedRowsRange.add(new Range(r.y, r.y + height));
+					selected.add(new Range(r.y, Math.min(r.y + r.height, rowCount)));
 				}
 			}
+			
+			return selected;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
-
-		ArrayList<Range> ranges = new ArrayList<Range>(selectedRowsRange);
-		Range.sortByStart(ranges);
-		List<Range> uniqueRanges = new ArrayList<Range>();
-
-		// Adjust for overlaps - between consecutive selections
-		for (int i = 0; i < ranges.size(); i++) {
-			if (i > 0) {
-				Range previousRange = ranges.get(i - 1);
-				Range currentRange = ranges.get(i);
-				if (previousRange.overlap(currentRange) || (previousRange.end == currentRange.start)) {
-					int largerRangeEnd = (previousRange.end > currentRange.end) ? previousRange.end : currentRange.end;
-					uniqueRanges.get(uniqueRanges.size() - 1).end = largerRangeEnd;
-					ranges.get(i).end = largerRangeEnd;
-				} else {
-					uniqueRanges.add(ranges.get(i));
-				}
-			} else {
-				uniqueRanges.add(ranges.get(i));
-			}
-		}
-		return new HashSet<Range>(uniqueRanges);
 	}
-
+	
 	@Override
-	public boolean isRowPositionSelected(int rowPosition) {
-		selectionsLock.readLock().lock();
-
+	public boolean isRowPositionSelected(final int rowPosition) {
+		this.selectionsLock.readLock().lock();
 		try {
-			for (Range rowRange : getSelectedRowPositions()) {
-				if (rowRange.contains(rowPosition)) {
-					return true;
-				}
-			}
-		} finally {
-			selectionsLock.readLock().unlock();
-		}
-
-		return false;
-	}
-
-	@Override
-	public int[] getFullySelectedRowPositions(int rowWidth) {
-		final Set<Range> selectedRows = getSelectedRowPositions();
-		int[] fullySelectedRows = new int[getSelectedRowCount()];
-		int index = 0;
-
-		for (Range rowRange : selectedRows) {
-			for (int i = rowRange.start; i < rowRange.end; i++) {
-				if (isRowPositionFullySelected(i, rowWidth)) {
-					fullySelectedRows[index++] = i;
-				}
-			}
-		}
-
-		return index > 0 ? ArrayUtils.subarray(fullySelectedRows, 0, index) : new int[0];
-	}
-
-	@Override
-	public boolean isRowPositionFullySelected(int rowPosition, int rowWidth) {
-		selectionsLock.readLock().lock();
-
-		try {
-			// Aggregate all rectangles in the row which are in the selection model
-			List<Rectangle> selectedRectanglesInRow = new ArrayList<Rectangle>();
-
-			// If X is same add up the width of the selected area
-			for (Rectangle r : selections) {
-				// Row is within the bounds of the selcted rectangle
-				if (rowPosition >= r.y && rowPosition < r.y + r.height) {
-					selectedRectanglesInRow.add(new Rectangle(r.x, rowPosition, r.width, 1));
-				}
-			}
-			if (selectedRectanglesInRow.isEmpty()) {
-				return false;
-			}
-			sortByX(selectedRectanglesInRow);
-			Rectangle finalRectangle = new Rectangle(selectedRectanglesInRow.get(0).x, rowPosition, 0, 0);
-
-			// Ensure that selections in the row are contiguous and cover the entire row
-			for (int i = 0; i < selectedRectanglesInRow.size(); i++) {
-				Rectangle rectangle = selectedRectanglesInRow.get(i);
-				if(contains(finalRectangle, rectangle)){
-					continue;
-				}
-				if (i > 0) {
-					Rectangle previousRect = selectedRectanglesInRow.get(i - 1);
-					if (rectangle.union(previousRect).width > (rectangle.width + previousRect.width)) {
-						// Rectangles not contiguous
-						return false;
+			final int rowCount = this.selectionLayer.getRowCount();
+			
+			if (rowPosition >= 0 && rowPosition < rowCount) {
+				for (final Rectangle r : this.selections) {
+					if (rowPosition >= r.y && rowPosition < r.y + r.height) {
+						return true;
 					}
 				}
-				// Union will resolve any overlaping area
-				finalRectangle = finalRectangle.union(rectangle);
 			}
-			return finalRectangle.width >= rowWidth;
+			
+			return false;
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
-
-	protected boolean contains(Rectangle containerRectangle, Rectangle rectangle) {
-		Rectangle union = containerRectangle.union(rectangle);
-		return union.equals(containerRectangle); 
-	}
-
-	protected void sortByX(List<Rectangle> selectionRectanglesInRow) {
-		Collections.sort(selectionRectanglesInRow, new Comparator<Rectangle>(){
-			@Override
-			public int compare(Rectangle rectangle1, Rectangle rectangle2) {
-				return new Integer(rectangle1.x).compareTo(new Integer(rectangle2.x)) ;
+	
+	@Override
+	public RangeList getFullySelectedRowPositions() {
+		this.selectionsLock.readLock().lock();
+		try {
+			final RangeList selected = new RangeList();
+			final int columnCount = this.selectionLayer.getColumnCount();
+			
+			if (columnCount > 0) {
+				final RangeList selectedRows = getSelectedRowPositions();
+				for (final Range range : selectedRows) {
+					for (int position = range.start; position < range.end; position++) {
+						if (isRowPositionFullySelected(position, columnCount)) {
+							selected.values().add(position);
+						}
+					}
+				}
 			}
-		});
+			
+			return selected;
+		}
+		finally {
+			this.selectionsLock.readLock().unlock();
+		}
 	}
-
-	protected void sortByY(List<Rectangle> selectionRectanglesInColumn) {
-		Collections.sort(selectionRectanglesInColumn, new Comparator<Rectangle>(){
-			@Override
-			public int compare(Rectangle rectangle1, Rectangle rectangle2) {
-				return new Integer(rectangle1.y).compareTo(new Integer(rectangle2.y)) ;
+	
+	@Override
+	public boolean isRowPositionFullySelected(final int rowPosition) {
+		this.selectionsLock.readLock().lock();
+		try {
+			final int columnCount = this.selectionLayer.getColumnCount();
+			
+			return ((columnCount > 0)
+					&& isRowPositionFullySelected(rowPosition, columnCount) );
+		} finally {
+			this.selectionsLock.readLock().unlock();
+		}
+	}
+	
+	private boolean isRowPositionFullySelected(final int rowPosition, final int columnCount) {
+		// Aggregate all columns of selection rectangles including the row
+		final RangeList selectedColumnsInRow = new RangeList();
+		
+		for (final Rectangle r : this.selections) {
+			if (rowPosition >= r.y && rowPosition < r.y + r.height) {
+				selectedColumnsInRow.add(new Range(r.x, r.x + r.width));
 			}
-		});
-	}
-
-	private Rectangle getLeftSelection(Rectangle intersection, Rectangle selection) {
-		if (intersection.x > selection.x) {
-			Rectangle leftSelection = new Rectangle(selection.x, selection.y,
-					intersection.x - selection.x, selection.height);
-			return leftSelection;
 		}
-
-		return null;
+		
+		final Range range = selectedColumnsInRow.values().getRangeOf(0);
+		return (range != null && range.end >= columnCount);
 	}
-
-	private Rectangle getRightSelection(Rectangle intersection, Rectangle selection) {
-		int newX = intersection.x + intersection.width;
-
-		if (newX < selection.x + selection.width) {
-			Rectangle rightSelection = new Rectangle(newX, selection.y,
-					selection.x + selection.width - newX, selection.height);
-
-			return rightSelection;
-		}
-
-		return null;
-	}
-
-	private Rectangle getTopSelection(Rectangle intersection,
-			Rectangle selectoin) {
-		if (intersection.y > selectoin.y) {
-			Rectangle topSelection = new Rectangle(selectoin.x, selectoin.y,
-					selectoin.width, intersection.y - selectoin.y);
-			return topSelection;
-		}
-		return null;
-	}
-
-	private Rectangle getBottomSelection(Rectangle intersection,
-			Rectangle selection) {
-		int newY = intersection.y + intersection.height;
-
-		if (newY < selection.y + selection.height) {
-			Rectangle bottomSelection = new Rectangle(selection.x, newY,
-					selection.width, selection.y + selection.height - newY);
-			return bottomSelection;
-		}
-
-		return null;
-	}
-
-	// Object methods
-
+	
+	//-- Object methods --//
+	
 	@Override
 	public String toString() {
-		selectionsLock.readLock().lock();
-
+		this.selectionsLock.readLock().lock();
 		try {
-			return selections.toString();
+			return this.selections.toString();
 		} finally {
-			selectionsLock.readLock().unlock();
+			this.selectionsLock.readLock().unlock();
 		}
 	}
 	
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/ColumnSelectionEvent.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/ColumnSelectionEvent.java
index b49db61..5912acf 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/ColumnSelectionEvent.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/ColumnSelectionEvent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -10,16 +10,20 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.selection.event;
 
+import java.util.Collection;
+
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
 import org.eclipse.nebula.widgets.nattable.layer.event.ColumnVisualChangeEvent;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 
+
 public class ColumnSelectionEvent extends ColumnVisualChangeEvent implements ISelectionEvent {
 
 	private final SelectionLayer selectionLayer;
 	
-	public ColumnSelectionEvent(SelectionLayer selectionLayer, int columnPosition) {
-		super(selectionLayer, new Range(columnPosition, columnPosition + 1));
+	
+	public ColumnSelectionEvent(SelectionLayer selectionLayer, Collection<Range> columnPositions) {
+		super(selectionLayer, columnPositions);
 		this.selectionLayer = selectionLayer;
 	}
 	
@@ -28,12 +32,15 @@
 		this.selectionLayer = event.selectionLayer;
 	}
 	
-	public SelectionLayer getSelectionLayer() {
-		return selectionLayer;
-	}
-	
+	@Override
 	public ColumnSelectionEvent cloneEvent() {
 		return new ColumnSelectionEvent(this);
 	}
 	
+	
+	@Override
+	public SelectionLayer getSelectionLayer() {
+		return selectionLayer;
+	}
+	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/RowSelectionEvent.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/RowSelectionEvent.java
index d649f67..ab51770 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/RowSelectionEvent.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/RowSelectionEvent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -12,7 +12,7 @@
 
 import java.util.Collection;
 
-import org.eclipse.nebula.widgets.nattable.coordinate.PositionUtil;
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.layer.event.RowVisualChangeEvent;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
@@ -22,9 +22,10 @@
 
 	private final SelectionLayer selectionLayer;
 	private int rowPositionToMoveIntoViewport;
-
-	public RowSelectionEvent(SelectionLayer selectionLayer, Collection<Integer> rowPositions, int rowPositionToMoveIntoViewport) {
-		super(selectionLayer, PositionUtil.getRanges(rowPositions));
+	
+	
+	public RowSelectionEvent(SelectionLayer selectionLayer, Collection<Range> rowPositions, int rowPositionToMoveIntoViewport) {
+		super(selectionLayer, rowPositions);
 		this.selectionLayer = selectionLayer;
 		this.rowPositionToMoveIntoViewport = rowPositionToMoveIntoViewport;
 	}
@@ -36,6 +37,12 @@
 		this.rowPositionToMoveIntoViewport = event.rowPositionToMoveIntoViewport;
 	}
 	
+	@Override
+	public RowSelectionEvent cloneEvent() {
+		return new RowSelectionEvent(this);
+	}
+	
+	
 	public SelectionLayer getSelectionLayer() {
 		return selectionLayer;
 	}
@@ -51,8 +58,4 @@
 		return super.convertToLocal(localLayer);
 	}
 	
-	public RowSelectionEvent cloneEvent() {
-		return new RowSelectionEvent(this);
-	}
-	
 }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/SelectionLayerStructuralChangeEventHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/SelectionLayerStructuralChangeEventHandler.java
index 9e3b326..25d44a6 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/SelectionLayerStructuralChangeEventHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/event/SelectionLayerStructuralChangeEventHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -11,16 +11,18 @@
 package org.eclipse.nebula.widgets.nattable.selection.event;
 
 import java.util.Collection;
-import java.util.Set;
+
+import org.eclipse.swt.graphics.Rectangle;
 
 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEventHandler;
 import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent;
 import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff;
 import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff.DiffTypeEnum;
 import org.eclipse.nebula.widgets.nattable.selection.ISelectionModel;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
-import org.eclipse.swt.graphics.Rectangle;
+
 
 public class SelectionLayerStructuralChangeEventHandler implements ILayerEventHandler<IStructuralChangeEvent> {
 
@@ -71,8 +73,8 @@
 	}
 	
 	private boolean selectedRowModified(Range changedRange){
-		Set<Range> selectedRows = selectionModel.getSelectedRowPositions();
-		for (Range rowRange : selectedRows) {
+		final RangeList selectedRows = selectionModel.getSelectedRowPositions();
+		for (final Range rowRange : selectedRows) {
 			if (rowRange.overlap(changedRange)){
 				return true;
 			}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/sort/event/SortColumnEvent.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/sort/event/SortColumnEvent.java
index b2ab09b..f5d2507 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/sort/event/SortColumnEvent.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/sort/event/SortColumnEvent.java
@@ -17,13 +17,14 @@
 public class SortColumnEvent extends ColumnVisualChangeEvent {
 
 	public SortColumnEvent(ILayer layer, int columnPosition) {
-		super(layer, new Range(columnPosition, columnPosition + 1));
+		super(layer, new Range(columnPosition));
 	}
 	
 	protected SortColumnEvent(SortColumnEvent event) {
 		super(event);
 	}
 	
+	@Override
 	public SortColumnEvent cloneEvent() {
 		return new SortColumnEvent(this);
 	}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandler.java
index 91169e0..d9e1aee 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/command/DisplayColumnStyleEditorCommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2013 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
@@ -18,9 +18,12 @@
 import java.util.Properties;
 import java.util.Set;
 
+import org.eclipse.swt.widgets.Display;
 
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.coordinate.IValueIterator;
+import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
 import org.eclipse.nebula.widgets.nattable.persistence.IPersistable;
@@ -29,7 +32,6 @@
 import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
 import org.eclipse.nebula.widgets.nattable.style.Style;
 import org.eclipse.nebula.widgets.nattable.style.editor.ColumnStyleEditorDialog;
-import org.eclipse.swt.widgets.Display;
 
 /**
  * 
@@ -73,26 +75,18 @@
 			return true;
 		}
 		
-		applySelectedStyleToColumns(command, getSelectedColumnIndeces());
+		applySelectedStyleToColumns(command, selectionLayer.getSelectedColumnPositions());
 		return true;
 	}
 
-	private int[] getSelectedColumnIndeces() {
-		int[] selectedColumnPositions = selectionLayer.getSelectedColumnPositions();
-		int[] selectedColumnIndeces = new int[selectedColumnPositions.length];
-		for (int i=0; i<selectedColumnPositions.length; i++) {
-			selectedColumnIndeces[i] = selectionLayer.getColumnIndexByPosition(selectedColumnPositions[i]);
-		}
-		return selectedColumnIndeces;
-	}
-
 	public Class<DisplayColumnStyleEditorCommand> getCommandClass() {
 		return DisplayColumnStyleEditorCommand.class;
 	}
 
-	protected void applySelectedStyleToColumns(DisplayColumnStyleEditorCommand command, int[] columnIndeces) {
-		for (int i=0; i<columnIndeces.length; i++) {
-			final int columnIndex = columnIndeces[i];
+	protected void applySelectedStyleToColumns(DisplayColumnStyleEditorCommand command,
+			final RangeList columnPositions) {
+		for (final IValueIterator columnIter = columnPositions.values().iterator(); columnIter.hasNext(); ) {
+			final int columnIndex = selectionLayer.getColumnIndexByPosition(columnIter.nextValue());
 			// Read the edited styles
 			Style newColumnCellStyle = dialog.getNewColumnCellStyle(); 
 			
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tickupdate/command/TickUpdateCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tickupdate/command/TickUpdateCommandHandler.java
index 02fd05f..03838ab 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tickupdate/command/TickUpdateCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tickupdate/command/TickUpdateCommandHandler.java
@@ -10,8 +10,11 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.tickupdate.command;
 
+import java.util.List;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
@@ -49,11 +52,11 @@
 
 	@Override
 	public boolean doCommand(TickUpdateCommand command) {
-		PositionCoordinate[] selectedPositions = selectionLayer.getSelectedCellPositions();
+		List<PositionCoordinate> selectedPositions = selectionLayer.getSelectedCellPositions();
 		IConfigRegistry configRegistry = command.getConfigRegistry();
 		
 		// Tick update for multiple cells in selection 
-		if (selectedPositions.length > 1) {
+		if (selectedPositions.size() > 1) {
 			// Can all cells be updated ?
 			if (EditUtils.allCellsEditable(selectionLayer, configRegistry)
 					&& EditUtils.isEditorSame(selectionLayer, configRegistry) 
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/HideMultipleColumnsIntegrationTest.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/HideMultipleColumnsIntegrationTest.java
index befc6e7..cb96ba9 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/HideMultipleColumnsIntegrationTest.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/HideMultipleColumnsIntegrationTest.java
@@ -15,6 +15,11 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import ca.odell.glazedlists.GlazedLists;
+
+import org.junit.Assert;
+import org.junit.Test;
+
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.coordinate.RangeList;
 import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/RowSelectionIntegrationTest.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/RowSelectionIntegrationTest.java
index e40b797..0d8e293 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/RowSelectionIntegrationTest.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/test/integration/RowSelectionIntegrationTest.java
@@ -12,11 +12,18 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.GlazedLists;
 
 import java.io.Serializable;
 import java.util.Collection;
 
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
 import org.eclipse.jface.viewers.StructuredSelection;
+
 import org.eclipse.nebula.widgets.nattable.NatTable;
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
@@ -36,13 +43,7 @@
 import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
 import org.eclipse.nebula.widgets.nattable.test.fixture.data.RowDataFixture;
 import org.eclipse.nebula.widgets.nattable.test.fixture.data.RowDataListFixture;
-import org.eclipse.nebula.widgets.nattable.util.ArrayUtil;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
 
-import ca.odell.glazedlists.EventList;
-import ca.odell.glazedlists.GlazedLists;
 
 public class RowSelectionIntegrationTest {
 
@@ -91,10 +92,10 @@
 
 	@Test
 	public void shouldPreserveRowSelectionOnDataUpdates() throws Exception {
-		assertEquals(0, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(0, selectionLayer.getFullySelectedRowPositions().values().size());
 
 		nattable.doCommand(new SelectRowsCommand(nattable, 1, 1, false, false));
-		assertEquals(1, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(1, selectionLayer.getFullySelectedRowPositions().values().size());
 
 		// Ford motor at top and selected
 		assertEquals("B Ford Motor", nattable.getDataValueByPosition(2, 1).toString());
@@ -112,7 +113,7 @@
 
 	@Test
 	public void shouldPreserveRowSelectionOnSort() throws Exception {
-		assertEquals(0, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(0, selectionLayer.getFullySelectedRowPositions().values().size());
 
 		// Unsorted order - Ford motor at top
 		assertEquals("B Ford Motor", nattable.getDataValueByPosition(2, 1).toString());
@@ -142,28 +143,28 @@
 		selectionLayer.clear();
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 1, 0, false, true));
 
-		Collection<PositionCoordinate> cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		Collection<PositionCoordinate> cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(selectionLayer.getColumnCount(), cells.size());
 		Assert.assertEquals(1, selectionLayer.getSelectedRowCount());
 
 		//select another cell with control mask
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 2, 1, false, true));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(selectionLayer.getColumnCount(), cells.size());
 		Assert.assertEquals(1, selectionLayer.getSelectedRowCount());
 
 		//select additional cells with shift mask
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 2, 10, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(selectionLayer.getColumnCount(), cells.size());
 		Assert.assertEquals(1, selectionLayer.getSelectedRowCount());
 
 		//select additional cells with shift mask
 		selectionLayer.doCommand(new SelectCellCommand(selectionLayer, 10, 0, true, false));
 
-		cells = ArrayUtil.asCollection(selectionLayer.getSelectedCellPositions());
+		cells = selectionLayer.getSelectedCellPositions();
 		Assert.assertEquals(selectionLayer.getColumnCount(), cells.size());
 		Assert.assertEquals(1, selectionLayer.getSelectedRowCount());
 	}
@@ -190,7 +191,7 @@
 		selectionProvider.setSelection(new StructuredSelection(
 				new RowDataFixture[] { eventListFixture.get(1) }));
 		
-		assertEquals(1, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(1, selectionLayer.getFullySelectedRowPositions().values().size());
 	}
 	
 	@Test
@@ -198,12 +199,12 @@
 		selectionProvider.setSelection(new StructuredSelection(
 				new RowDataFixture[] { eventListFixture.get(1), eventListFixture.get(3) }));
 		
-		assertEquals(2, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(2, selectionLayer.getFullySelectedRowPositions().values().size());
 
 		selectionProvider.setSelection(new StructuredSelection(
 				new RowDataFixture[] { eventListFixture.get(5), eventListFixture.get(7) }));
 		
-		assertEquals(2, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(2, selectionLayer.getFullySelectedRowPositions().values().size());
 	}
 	
 	@Test
@@ -213,12 +214,12 @@
 		selectionProvider.setSelection(new StructuredSelection(
 				new RowDataFixture[] { eventListFixture.get(1), eventListFixture.get(3) }));
 		
-		assertEquals(2, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(2, selectionLayer.getFullySelectedRowPositions().values().size());
 
 		selectionProvider.setSelection(new StructuredSelection(
 				new RowDataFixture[] { eventListFixture.get(5), eventListFixture.get(7) }));
 		
-		assertEquals(4, selectionLayer.getFullySelectedRowPositions().length);
+		assertEquals(4, selectionLayer.getFullySelectedRowPositions().values().size());
 	}
 	
 	private RowDataFixture getSelected() {