Bug 491479 - Add e4 selection listener for NatTable

Change-Id: I023eac58971919e01eae30201e371ec896f2ccb0
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java
index e759d47..ecfd5d2 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (c) 2015 CEA LIST.
+ * Copyright (c) 2015, 2016 CEA LIST, Dirk Fauth.
  *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -14,9 +14,17 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.List;
+
+import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataFixture;
+import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataListFixture;
 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.test.fixture.data.DataProviderFixture;
@@ -177,4 +185,147 @@
         assertNull(bottomRight);
     }
 
+    @Test
+    public void testGetEmptyListOnNoSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                false);
+
+        assertNotNull(selected);
+        assertEquals(0, selected.size());
+    }
+
+    @Test
+    public void testGetSingleItemOnCellSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        selectionLayer.selectCell(1, 3, false, false);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                false);
+
+        assertNotNull(selected);
+        assertEquals(1, selected.size());
+        assertEquals(listFixture.get(3), selected.get(0));
+    }
+
+    @Test
+    public void testGetMultipleItemsOnCellSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        selectionLayer.selectCell(1, 3, false, true);
+        selectionLayer.selectCell(1, 5, false, true);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                false);
+
+        assertNotNull(selected);
+        assertEquals(2, selected.size());
+        assertEquals(listFixture.get(3), selected.get(0));
+        assertEquals(listFixture.get(5), selected.get(1));
+    }
+
+    @Test
+    public void testGetSingleItemsOnFullRowSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        selectionLayer.selectRow(0, 3, false, false);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                true);
+
+        assertNotNull(selected);
+        assertEquals(1, selected.size());
+        assertEquals(listFixture.get(3), selected.get(0));
+    }
+
+    @Test
+    public void testGetMultipleItemsOnFullRowSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        selectionLayer.selectRow(0, 3, false, true);
+        selectionLayer.selectRow(0, 5, false, true);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                true);
+
+        assertNotNull(selected);
+        assertEquals(2, selected.size());
+        assertEquals(listFixture.get(3), selected.get(0));
+        assertEquals(listFixture.get(5), selected.get(1));
+    }
+
+    @Test
+    public void testGetEmptyListOnCellSelectionForFullRowSelection() {
+        List<RowDataFixture> listFixture = RowDataListFixture.getList(10);
+        IRowDataProvider<RowDataFixture> bodyDataProvider =
+                new ListDataProvider<RowDataFixture>(
+                        listFixture,
+                        new ReflectiveColumnPropertyAccessor<RowDataFixture>(
+                                RowDataListFixture.getPropertyNames()));
+
+        DataLayer dataLayer = new DataLayer(bodyDataProvider);
+        SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+        selectionLayer.selectCell(1, 3, false, false);
+
+        List<RowDataFixture> selected = SelectionUtils.getSelectedRowObjects(
+                selectionLayer,
+                bodyDataProvider,
+                true);
+
+        assertNotNull(selected);
+        assertEquals(0, selected.size());
+    }
 }
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 9650533..b124089 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
@@ -10,7 +10,6 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.selection;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -22,7 +21,6 @@
 import org.eclipse.jface.viewers.IStructuredSelection;
 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.data.IRowDataProvider;
 import org.eclipse.nebula.widgets.nattable.layer.ILayerListener;
 import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
@@ -283,47 +281,12 @@
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    static StructuredSelection populateRowSelection(
+    static <T> StructuredSelection populateRowSelection(
             SelectionLayer selectionLayer,
-            IRowDataProvider rowDataProvider,
+            IRowDataProvider<T> rowDataProvider,
             boolean fullySelectedRowsOnly) {
-        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);
-                    }
-                }
-            }
-        }
-        Collections.sort(rows);
-        List<Object> rowObjects = new ArrayList<Object>();
-        for (RowObjectIndexHolder<Object> holder : rows) {
-            rowObjects.add(holder.getRow());
-        }
-        return rows.isEmpty() ? StructuredSelection.EMPTY : new StructuredSelection(rowObjects);
-    }
-
-    @SuppressWarnings("rawtypes")
-    private static void addToSelection(
-            List<RowObjectIndexHolder<Object>> rows,
-            int rowPosition,
-            SelectionLayer selectionLayer,
-            IRowDataProvider rowDataProvider) {
-
-        int rowIndex = selectionLayer.getRowIndexByPosition(rowPosition);
-        if (rowIndex >= 0 && rowIndex < rowDataProvider.getRowCount()) {
-            Object rowObject = rowDataProvider.getRowObject(rowIndex);
-            rows.add(new RowObjectIndexHolder<Object>(rowIndex, rowObject));
-        }
+        List<T> rowObjects = SelectionUtils.getSelectedRowObjects(selectionLayer, rowDataProvider, fullySelectedRowsOnly);
+        return rowObjects.isEmpty() ? StructuredSelection.EMPTY : new StructuredSelection(rowObjects);
     }
 
     /**
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
index f9b0527..9079fa5 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2015 Original authors and others.
+ * Copyright (c) 2012, 2016 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,12 +10,17 @@
  ******************************************************************************/
 package org.eclipse.nebula.widgets.nattable.selection;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 
 /**
@@ -175,4 +180,66 @@
         return null;
     }
 
+    /**
+     * Inspects the current selection on the given {@link SelectionLayer} and
+     * returns a list of the corresponding list item objects. Uses the
+     * {@link IRowDataProvider} to be able to determine the row objects per
+     * selected row position.
+     *
+     * @param selectionLayer
+     *            The {@link SelectionLayer} to retrieve the selected row
+     *            indexes from.
+     * @param rowDataProvider
+     *            The {@link IRowDataProvider} to retrieve the object for the
+     *            row index.
+     * @param fullySelectedRowsOnly
+     *            Flag to determine if only fully selected rows should be taken
+     *            into account.
+     * @return The list of all objects that are currently marked as selected.
+     *         Never <code>null</code>.
+     *
+     * @since 1.4
+     */
+    public static <T> List<T> getSelectedRowObjects(
+            SelectionLayer selectionLayer,
+            IRowDataProvider<T> rowDataProvider,
+            boolean fullySelectedRowsOnly) {
+
+        List<RowObjectIndexHolder<T>> rows = new ArrayList<RowObjectIndexHolder<T>>();
+
+        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);
+                    }
+                }
+            }
+        }
+        Collections.sort(rows);
+        List<T> rowObjects = new ArrayList<T>();
+        for (RowObjectIndexHolder<T> holder : rows) {
+            rowObjects.add(holder.getRow());
+        }
+        return rowObjects;
+    }
+
+    private static <T> void addToSelection(
+            List<RowObjectIndexHolder<T>> rows,
+            int rowPosition,
+            SelectionLayer selectionLayer,
+            IRowDataProvider<T> rowDataProvider) {
+
+        int rowIndex = selectionLayer.getRowIndexByPosition(rowPosition);
+        if (rowIndex >= 0 && rowIndex < rowDataProvider.getRowCount()) {
+            T rowObject = rowDataProvider.getRowObject(rowIndex);
+            rows.add(new RowObjectIndexHolder<T>(rowIndex, rowObject));
+        }
+    }
+
 }
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/Application.e4xmi b/org.eclipse.nebula.widgets.nattable.examples.e4/Application.e4xmi
index 02929e3..ad1124f 100644
--- a/org.eclipse.nebula.widgets.nattable.examples.e4/Application.e4xmi
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/Application.e4xmi
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_c3AF0MjYEeSyMNYR5xypkQ" elementId="org.eclipse.e4.ide.application" bindingContexts="_c3AF2cjYEeSyMNYR5xypkQ">
-  <children xsi:type="basic:TrimmedWindow" xmi:id="_c3AF0cjYEeSyMNYR5xypkQ" label="NatTable Eclipse 4 Examples" iconURI="platform:/plugin/org.eclipse.nebula.widgets.nattable.examples.e4/icons/nebula_logo_16.png" width="800" height="600">
+  <children xsi:type="basic:TrimmedWindow" xmi:id="_c3AF0cjYEeSyMNYR5xypkQ" label="NatTable Eclipse 4 Examples" iconURI="platform:/plugin/org.eclipse.nebula.widgets.nattable.examples.e4/icons/nebula_logo_64.png" width="800" height="600">
     <children xsi:type="basic:PartStack" xmi:id="_K5-ckGU5EeWwHIziFo2EbQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.partstack.0" selectedElement="_Me7oMGU5EeWwHIziFo2EbQ">
       <children xsi:type="basic:Part" xmi:id="_Me7oMGU5EeWwHIziFo2EbQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.nattablecssexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.CSSExample" label="NatTable CSS Example">
         <variables>enabled</variables>
@@ -10,9 +10,10 @@
           <children xsi:type="menu:DirectMenuItem" xmi:id="_a4S1cL1UEeWyieXhE9AcAg" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.directmenuitem.test" label="Test" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.handler.TestHandler"/>
         </menus>
       </children>
-      <children xsi:type="basic:Part" xmi:id="_qELKMLWHEeWcioqLU-ciqQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.percentagestylingexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.PercentagePart" label="Percentage CSS Example"/>
-      <children xsi:type="basic:Part" xmi:id="_r7rusLXlEeWcioqLU-ciqQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.treecssexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.TreePart" label="Tree CSS Example"/>
+      <children xsi:type="basic:Part" xmi:id="_qELKMLWHEeWcioqLU-ciqQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.percentagestylingexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.PercentageExample" label="Percentage CSS Example"/>
+      <children xsi:type="basic:Part" xmi:id="_r7rusLXlEeWcioqLU-ciqQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.treecssexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.TreeExample" label="Tree CSS Example"/>
       <children xsi:type="basic:Part" xmi:id="_CKJZYLexEeWPT6hlm-avUQ" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.darkcssexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.DarkExample" label="Dark CSS Example"/>
+      <children xsi:type="basic:Part" xmi:id="_AQ9SEP6dEeWu6p3ajZ2ebA" elementId="org.eclipse.nebula.widgets.nattable.examples.e4.part.selectionexample" contributionURI="bundleclass://org.eclipse.nebula.widgets.nattable.examples.e4/org.eclipse.nebula.widgets.nattable.examples.e4.SelectionListenerExample" label="SelectionListener Example"/>
     </children>
   </children>
   <rootContext xmi:id="_c3AF2cjYEeSyMNYR5xypkQ" elementId="org.eclipse.ui.contexts.dialogAndWindow" name="In Dialog and Windows">
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/css/default.css b/org.eclipse.nebula.widgets.nattable.examples.e4/css/default.css
index dc03b9a..494c117 100644
--- a/org.eclipse.nebula.widgets.nattable.examples.e4/css/default.css
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/css/default.css
@@ -147,9 +147,9 @@
 	text-align: center;
 }
 
-/* TREE CONFIGURATION */
+/* MODERN CONFIGURATION */
 
-.tree {
+.modern {
 	tree-structure-painter: background padding tree;
 	table-border-color: auto;
 	cell-background-color: white;
@@ -157,7 +157,7 @@
 	padding: 0 5;
 }
 
-.tree:select {
+.modern:select {
 	/* avoid additional registration of a cell painter which would lead to breaking the NatTable inheritance */
 	painter-resolution: false;
 	color: white;
@@ -168,17 +168,17 @@
 	invert-icons: true;
 }
 
-.tree > .selectionAnchor:select {
+.modern > .selectionAnchor:select {
 	color: white;
 	cell-background-color: #87CEFA;
 }
 
-.tree > .CORNER {
+.modern > .CORNER {
 	render-grid-lines: true;
 	cell-background-color: #F5F5F5;
 }
 
-.tree > .COLUMN_HEADER {
+.modern > .COLUMN_HEADER {
 	render-grid-lines: true;
 	cell-background-color: #F5F5F5;
 	color: black;
@@ -187,41 +187,41 @@
 	padding: 0 5;
 }
 
-.tree > .COLUMN_HEADER:select {
+.modern > .COLUMN_HEADER:select {
 	cell-background-color: #c0c0c0;
-	color: white; 
+	color: white;
 }
 
-.tree > .ROW_HEADER {
+.modern > .ROW_HEADER {
 	render-grid-lines: true;
 	cell-background-color: #F5F5F5;
 	color: black;
 	font: "Segoe UI" 9 normal;
 	text-align: center;}
 
-.tree > .ROW_HEADER:select {
+.modern > .ROW_HEADER:select {
 	cell-background-color: #c0c0c0;
-	color: white; 
+	color: white;
 }
 
-.tree > .genderLabel {
+.modern > .genderLabel {
 	painter: background padding combobox;
 }
 
-.tree > .genderLabel:select {
+.modern > .genderLabel:select {
 	invert-icons: true;
 }
 
-.tree > .marriedLabel {
+.modern > .marriedLabel {
 	painter: background padding checkbox;
 	text-align: center;
 }
 
-.tree > .marriedLabel:select {
+.modern > .marriedLabel:select {
 	text-align: center;
 }
 
-.tree > .dateLabel {
+.modern > .dateLabel {
 	converter: date "yyyy-MM-dd";
 }
 
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/CSSExample.java b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/CSSExample.java
index 98d7a87..b923ac9 100644
--- a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/CSSExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/CSSExample.java
@@ -12,8 +12,6 @@
  *****************************************************************************/
 package org.eclipse.nebula.widgets.nattable.examples.e4;
 
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -60,7 +58,6 @@
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Menu;
@@ -74,17 +71,6 @@
 
     @PostConstruct
     public void postConstruct(Composite parent, Shell shell) {
-
-        try {
-            // load the images for the shell
-            Image img16 = GUIHelper.getImageByURL(new URL("platform:/plugin/org.eclipse.nebula.widgets.nattable.examples.e4/icons/nebula_logo_16.png"));
-            Image img32 = GUIHelper.getImageByURL(new URL("platform:/plugin/org.eclipse.nebula.widgets.nattable.examples.e4/icons/nebula_logo_32.png"));
-            Image img64 = GUIHelper.getImageByURL(new URL("platform:/plugin/org.eclipse.nebula.widgets.nattable.examples.e4/icons/nebula_logo_64.png"));
-            shell.setImages(new Image[] { img16, img32, img64 });
-        } catch (MalformedURLException e) {
-            e.printStackTrace();
-        }
-
         parent.setLayout(new GridLayout());
 
         // property names of the Person class
@@ -104,7 +90,7 @@
                 "favouriteDrinks" };
 
         // mapping from property to label, needed for column header labels
-        Map<String, String> propertyToLabelMap = new HashMap<String, String>();
+        Map<String, String> propertyToLabelMap = new HashMap<>();
         propertyToLabelMap.put("firstName", "Firstname");
         propertyToLabelMap.put("lastName", "Lastname");
         propertyToLabelMap.put("password", "Password");
@@ -119,7 +105,7 @@
         propertyToLabelMap.put("favouriteDrinks", "Drinks");
 
         IDataProvider bodyDataProvider =
-                new ListDataProvider<ExtendedPersonWithAddress>(
+                new ListDataProvider<>(
                         PersonService.getExtendedPersonsWithAddress(10),
                         new ExtendedReflectiveColumnPropertyAccessor<ExtendedPersonWithAddress>(propertyNames));
 
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentagePart.java b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentageExample.java
similarity index 98%
rename from org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentagePart.java
rename to org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentageExample.java
index 8118a71..1131429 100644
--- a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentagePart.java
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/PercentageExample.java
@@ -27,7 +27,7 @@
 import org.eclipse.swt.widgets.Composite;
 
 @SuppressWarnings("restriction")
-public class PercentagePart {
+public class PercentageExample {
 
     @PostConstruct
     public void postConstruct(Composite parent) {
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/SelectionListenerExample.java b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/SelectionListenerExample.java
new file mode 100644
index 0000000..d4c6b5d
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/SelectionListenerExample.java
@@ -0,0 +1,152 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Dirk Fauth.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.examples.e4;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.dataset.person.Person;
+import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService;
+import org.eclipse.nebula.widgets.nattable.extension.e4.selection.E4SelectionListener;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+public class SelectionListenerExample {
+
+    @Inject
+    ESelectionService service;
+
+    private Text outputArea;
+
+    @PostConstruct
+    public void postConstruct(Composite parent) {
+        // property names of the Person class
+        String[] propertyNames = {
+                "firstName",
+                "lastName",
+                "gender",
+                "married",
+                "birthday" };
+
+        // mapping from property to label, needed for column header labels
+        Map<String, String> propertyToLabelMap = new HashMap<>();
+        propertyToLabelMap.put("firstName", "Firstname");
+        propertyToLabelMap.put("lastName", "Lastname");
+        propertyToLabelMap.put("gender", "Gender");
+        propertyToLabelMap.put("married", "Married");
+        propertyToLabelMap.put("birthday", "Birthday");
+
+        IColumnPropertyAccessor<Person> columnPropertyAccessor =
+                new ReflectiveColumnPropertyAccessor<>(propertyNames);
+
+        final List<Person> data = PersonService.getPersons(10);
+
+        // create the body layer stack
+        final IRowDataProvider<Person> bodyDataProvider =
+                new ListDataProvider<>(data, columnPropertyAccessor);
+        final DataLayer bodyDataLayer =
+                new DataLayer(bodyDataProvider);
+        final SelectionLayer selectionLayer =
+                new SelectionLayer(bodyDataLayer);
+        ViewportLayer viewportLayer =
+                new ViewportLayer(selectionLayer);
+
+        // create a E4SelectionListener and configure it for providing selection
+        // on cell selection
+        E4SelectionListener<Person> esl = new E4SelectionListener<>(service, selectionLayer, bodyDataProvider);
+        esl.setFullySelectedRowsOnly(false);
+        esl.setHandleSameRowSelection(false);
+
+        selectionLayer.addLayerListener(esl);
+
+        // create the column header layer stack
+        IDataProvider columnHeaderDataProvider =
+                new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
+        ILayer columnHeaderLayer =
+                new ColumnHeaderLayer(
+                        new DataLayer(columnHeaderDataProvider),
+                        viewportLayer,
+                        selectionLayer);
+
+        // create the row header layer stack
+        IDataProvider rowHeaderDataProvider =
+                new DefaultRowHeaderDataProvider(bodyDataProvider);
+        ILayer rowHeaderLayer = new RowHeaderLayer(
+                new DefaultRowHeaderDataLayer(
+                        new DefaultRowHeaderDataProvider(bodyDataProvider)),
+                viewportLayer,
+                selectionLayer);
+
+        // create the corner layer stack
+        ILayer cornerLayer = new CornerLayer(
+                new DataLayer(
+                        new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider)),
+                rowHeaderLayer,
+                columnHeaderLayer);
+
+        // create the grid layer composed with the prior created layer stacks
+        GridLayer gridLayer =
+                new GridLayer(
+                        viewportLayer,
+                        columnHeaderLayer,
+                        rowHeaderLayer,
+                        cornerLayer);
+
+        final NatTable natTable = new NatTable(parent, gridLayer);
+        natTable.setData("org.eclipse.e4.ui.css.CssClassName", "modern");
+
+        outputArea = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
+        outputArea.setEditable(false);
+        GridDataFactory.fillDefaults().grab(true, false).hint(0, 100).align(SWT.FILL, SWT.BEGINNING).applyTo(outputArea);
+    }
+
+    @Inject
+    @Optional
+    void handleSelection(@Named(IServiceConstants.ACTIVE_SELECTION) List<Person> selected) {
+        if (selected != null) {
+            String msg = "";
+            for (Person p : selected) {
+                msg += p.getFirstName() + " " + p.getLastName() + " selected\n";
+            }
+            outputArea.append(msg);
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreePart.java b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreeExample.java
similarity index 96%
rename from org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreePart.java
rename to org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreeExample.java
index f2bebbb..d1c86c9 100644
--- a/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreePart.java
+++ b/org.eclipse.nebula.widgets.nattable.examples.e4/src/org/eclipse/nebula/widgets/nattable/examples/e4/TreeExample.java
@@ -68,7 +68,7 @@
 import ca.odell.glazedlists.TransformedList;
 import ca.odell.glazedlists.TreeList;
 
-public class TreePart {
+public class TreeExample {
 
     public static final String GENDER_LABEL = "genderLabel";
     public static final String MARRIED_LABEL = "marriedLabel";
@@ -83,7 +83,7 @@
         String[] propertyNames = { "lastName", "firstName", "gender", "married", "birthday" };
 
         // mapping from property to label, needed for column header labels
-        Map<String, String> propertyToLabelMap = new HashMap<String, String>();
+        Map<String, String> propertyToLabelMap = new HashMap<>();
         propertyToLabelMap.put("lastName", "Lastname");
         propertyToLabelMap.put("firstName", "Firstname");
         propertyToLabelMap.put("gender", "Gender");
@@ -91,14 +91,14 @@
         propertyToLabelMap.put("birthday", "Birthday");
 
         IColumnPropertyAccessor<PersonWithAddress> columnPropertyAccessor =
-                new ReflectiveColumnPropertyAccessor<PersonWithAddress>(propertyNames);
+                new ReflectiveColumnPropertyAccessor<>(propertyNames);
 
         final BodyLayerStack bodyLayerStack =
                 new BodyLayerStack(
                         PersonService.getPersonsWithAddress(5),
                         columnPropertyAccessor,
                         new PersonWithAddressTwoLevelTreeFormat());
-                        // new PersonWithAddressTreeFormat());
+        // new PersonWithAddressTreeFormat());
 
         // build the column header layer
         IDataProvider columnHeaderDataProvider =
@@ -132,7 +132,7 @@
         // configuration
         final NatTable natTable = new NatTable(container, gridLayer);
 
-        natTable.setData("org.eclipse.e4.ui.css.CssClassName", "tree");
+        natTable.setData("org.eclipse.e4.ui.css.CssClassName", "modern");
 
         GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
 
@@ -197,7 +197,7 @@
             // because the Comparator
             // will be set by configuration
             SortedList<PersonWithAddress> sortedList =
-                    new SortedList<PersonWithAddress>(rowObjectsGlazedList, null);
+                    new SortedList<>(rowObjectsGlazedList, null);
             // wrap the SortedList with the TreeList
             treeList =
                     new TreeList(sortedList, treeFormat, TreeList.nodesStartExpanded());
@@ -241,7 +241,7 @@
                     new GlazedListsEventLayer<PersonWithAddress>(bodyDataLayer, treeList);
 
             GlazedListTreeData<Object> treeData = new GlazedListTreeData<Object>(treeList);
-            ITreeRowModel<Object> treeRowModel = new GlazedListTreeRowModel<Object>(treeData);
+            ITreeRowModel<Object> treeRowModel = new GlazedListTreeRowModel<>(treeData);
 
             // ITreeRowModel<Object> treeRowModel = new
             // TreeRowModel<Object>(treeData);
@@ -345,8 +345,8 @@
     private class PersonWithAddressTwoLevelTreeFormat implements TreeList.Format<Object> {
 
         AtomicInteger counter = new AtomicInteger();
-        Map<String, LastNameGroup> lastNames = new HashMap<String, LastNameGroup>();
-        Map<String, FirstNameGroup> firstNames = new HashMap<String, FirstNameGroup>();
+        Map<String, LastNameGroup> lastNames = new HashMap<>();
+        Map<String, FirstNameGroup> firstNames = new HashMap<>();
 
         @Override
         public void getPath(List<Object> path, Object element) {
diff --git a/org.eclipse.nebula.widgets.nattable.extension.e4/META-INF/MANIFEST.MF b/org.eclipse.nebula.widgets.nattable.extension.e4/META-INF/MANIFEST.MF
index e9c674a..9ba4c00 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.e4/META-INF/MANIFEST.MF
+++ b/org.eclipse.nebula.widgets.nattable.extension.e4/META-INF/MANIFEST.MF
@@ -8,19 +8,29 @@
  org.eclipse.e4.ui.css.core;bundle-version="0.11.0",
  org.eclipse.e4.ui.css.swt;bundle-version="0.12.0",
  org.w3c.css.sac;bundle-version="1.3.1"
-Import-Package: org.apache.commons.logging,
- org.eclipse.nebula.widgets.nattable;version="1.3.0",
+Import-Package: javax.inject;version="1.0.0",
+ org.apache.commons.logging,
+ org.eclipse.e4.core.di.annotations,
+ org.eclipse.e4.ui.workbench.modeling,
+ org.eclipse.nebula.widgets.nattable;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.command;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.config;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.coordinate;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.data;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.data.convert;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.edit;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.fillhandle.config;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.freeze;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.group.painter;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.layer;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.layer.event;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.painter;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.painter.cell;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.painter.cell.decorator;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.resize.command;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.selection;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.selection.command;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.selection.event;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.sort.painter;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.style;version="1.4.0",
  org.eclipse.nebula.widgets.nattable.tree.config;version="1.4.0",
@@ -29,4 +39,5 @@
  org.eclipse.nebula.widgets.nattable.util;version="1.4.0"
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.nebula.widgets.nattable.extension.e4.css;version="1.0.0",
- org.eclipse.nebula.widgets.nattable.extension.e4.painterfactory;version="1.0.0"
+ org.eclipse.nebula.widgets.nattable.extension.e4.painterfactory;version="1.0.0",
+ org.eclipse.nebula.widgets.nattable.extension.e4.selection;version="1.0.0"
diff --git a/org.eclipse.nebula.widgets.nattable.extension.e4/src/org/eclipse/nebula/widgets/nattable/extension/e4/selection/E4SelectionListener.java b/org.eclipse.nebula.widgets.nattable.extension.e4/src/org/eclipse/nebula/widgets/nattable/extension/e4/selection/E4SelectionListener.java
new file mode 100644
index 0000000..74a6f82
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.extension.e4/src/org/eclipse/nebula/widgets/nattable/extension/e4/selection/E4SelectionListener.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Dirk Fauth.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.widgets.nattable.extension.e4.selection;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
+import org.eclipse.nebula.widgets.nattable.layer.ILayerListener;
+import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
+import org.eclipse.nebula.widgets.nattable.selection.RowSelectionModel;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionUtils;
+import org.eclipse.nebula.widgets.nattable.selection.event.ColumnSelectionEvent;
+import org.eclipse.nebula.widgets.nattable.selection.event.ISelectionEvent;
+
+/**
+ * Implementation of {@link ILayerListener} to support E4 selection handling.
+ * Needs to be set to the {@link SelectionLayer}
+ * 
+ * <pre>
+ * E4SelectionListener<Person> esl = new E4SelectionListener<>(service, selectionLayer, bodyDataProvider);
+ * selectionLayer.addLayerListener(esl);
+ * </pre>
+ *
+ * @param <T>
+ *            The type of objects provided by the {@link IRowDataProvider}
+ */
+public class E4SelectionListener<T> implements ILayerListener {
+    /**
+     * The {@link ESelectionService} to set the selection to.
+     */
+    private ESelectionService selectionService;
+    /**
+     * The {@link SelectionLayer} that is used to retrieve the selection.
+     */
+    private SelectionLayer selectionLayer;
+    /**
+     * The {@link IRowDataProvider} to access the selected row data.
+     */
+    private IRowDataProvider<T> rowDataProvider;
+    /**
+     * Flag to determine if only fully selected rows should be used to populate
+     * the selection or if any selection should be populated. Default is to only
+     * populate fully selected rows.
+     */
+    private boolean fullySelectedRowsOnly = true;
+    /**
+     * Flag to configure whether a selection should be set to the
+     * {@link ESelectionService} if the row selection changes or if just another
+     * column is selected.
+     */
+    private boolean handleSameRowSelection = false;
+    /**
+     * Locally stored previous selection which is used to determine if a event
+     * for changed selection should be fired. It is used to avoid firing events
+     * if the same row is selected again (default). If handleSameRowSelection is
+     * set to <code>true</code>, this value is not evaluated at runtime.
+     */
+    private List<T> previousSelection;
+
+    /**
+     * Flag to configure if row selection should be provided in case a column
+     * selection happened.
+     * <p>
+     * To understand this flag consider a {@link SelectionLayer} that is
+     * configured for full row selection by using the {@link RowSelectionModel}.
+     * On performing column selection, all rows would get selected. This matches
+     * the specification because of the {@link RowSelectionModel} and this
+     * listener would process every selected row.
+     * </p>
+     * <p>
+     * As described in Bug 421848 this causes serious issues for huge datasets.
+     * To avoid such issues by still providing the ability to perform and
+     * provide multiple row selections, this flag was introduced. Setting the
+     * value to <code>false</code> will avoid processing in case of column
+     * selections.
+     * </p>
+     *
+     * @see RowSelectionModel
+     */
+    private boolean processColumnSelection = true;
+
+    /**
+     * Flag to configure whether a list of data values should be set as
+     * selection or a single value. Needed for creating typed selection
+     * listeners.
+     */
+    private boolean multiSelection = true;
+
+    /**
+     * Create a {@link E4SelectionListener} and registers it to the given
+     * {@link SelectionLayer}.
+     *
+     * @param service
+     *            The {@link ESelectionService} to which the selection should be
+     *            published to.
+     * @param selectionLayer
+     *            The {@link SelectionLayer} that is used to retrieve the
+     *            selection.
+     * @param rowDataProvider
+     *            The {@link IRowDataProvider} to access the selected row data.
+     */
+    @Inject
+    public E4SelectionListener(
+            ESelectionService service,
+            SelectionLayer selectionLayer,
+            IRowDataProvider<T> rowDataProvider) {
+
+        this.selectionService = service;
+        this.selectionLayer = selectionLayer;
+        this.rowDataProvider = rowDataProvider;
+    }
+
+    @Override
+    public void handleLayerEvent(ILayerEvent event) {
+        if (event instanceof ISelectionEvent) {
+            List<T> selection = SelectionUtils.getSelectedRowObjects(this.selectionLayer, this.rowDataProvider, this.fullySelectedRowsOnly);
+            if ((this.handleSameRowSelection || !selection.equals(this.previousSelection))
+                    && !(!this.processColumnSelection && event instanceof ColumnSelectionEvent)) {
+                try {
+                    if (this.multiSelection) {
+                        this.selectionService.setSelection(selection);
+                    } else {
+                        this.selectionService.setSelection(!selection.isEmpty() ? selection.get(0) : null);
+                    }
+                } finally {
+                    this.previousSelection = selection;
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * @return <code>true</code> if only fully selected rows should be used to
+     *         populate the selection or if any selection should be populated.
+     *         Default is <code>true</code>.
+     */
+    public boolean isFullySelectedRowsOnly() {
+        return this.fullySelectedRowsOnly;
+    }
+
+    /**
+     *
+     * @param fullySelectedRowsOnly
+     *            <code>true</code> if only fully selected rows should be used
+     *            to populate the selection <code>false</code> if any selection
+     *            should be populated.
+     */
+    public void setFullySelectedRowsOnly(boolean fullySelectedRowsOnly) {
+        this.fullySelectedRowsOnly = fullySelectedRowsOnly;
+    }
+
+    /**
+     *
+     * @return <code>true</code> if a selection should only be handled by the
+     *         {@link ESelectionService} if the row selection changes or if just
+     *         another column is selected.
+     */
+    public boolean isHandleSameRowSelection() {
+        return this.handleSameRowSelection;
+    }
+
+    /**
+     *
+     * @param handleSameRowSelection
+     *            <code>true</code> if a selection should only be handled by the
+     *            {@link ESelectionService} if the row selection changes or if
+     *            just another column is selected.
+     */
+    public void setHandleSameRowSelection(boolean handleSameRowSelection) {
+        this.handleSameRowSelection = handleSameRowSelection;
+    }
+
+    /**
+     *
+     * @return <code>true</code> if column selection should trigger setting the
+     *         selection via {@link ESelectionService} (that means basically a
+     *         <i>select all</i>), <code>false</code> if not (needed for huge
+     *         datasets to avoid a <i>select all</i>).
+     */
+    public boolean isProcessColumnSelection() {
+        return this.processColumnSelection;
+    }
+
+    /**
+     * Configure whether column selections should start row selection processing
+     * or not.
+     * <p>
+     * This is necessary to handle issues with huge datasets. Dependent on
+     * different configurations, selecting a column can cause the selection of
+     * all rows in a table, which would then lead to populate the whole dataset
+     * as selection via this provider. Setting the
+     * {@link E4SelectionListener#processColumnSelection} flag to
+     * <code>false</code> will skip processing to avoid such issues.
+     * </p>
+     *
+     * @param processColumnSelection
+     *            <code>true</code> to process row selection in case of column
+     *            selections (default) <code>false</code> to skip processing in
+     *            case of column selections to avoid issues on large datasets.
+     */
+    public void setProcessColumnSelection(boolean processColumnSelection) {
+        this.processColumnSelection = processColumnSelection;
+    }
+
+    /**
+     *
+     * @return <code>true</code> if a list of data values should be set as
+     *         selection or a single value.
+     */
+    public boolean isMultiSelection() {
+        return this.multiSelection;
+    }
+
+    /**
+     * Set this value to <code>true</code> if a list of values should be set as
+     * selection to the {@link ESelectionService} or <code>false</code> if only
+     * a single value object should be set.
+     *
+     * @param multiSelection
+     *            <code>true</code> if a list of data values should be set as
+     *            selection or a single value.
+     */
+    public void setMultiSelection(boolean multiSelection) {
+        this.multiSelection = multiSelection;
+    }
+}
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 5a58947..870f715 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
@@ -312,6 +312,12 @@
         assertEquals(2, listener.getEventsCount());
     }
 
+    @Test
+    public void shouldReturnEmptySelectionOnNoSelection() {
+        this.selectionLayer.clear();
+        assertEquals(StructuredSelection.EMPTY, this.selectionProvider.getSelection());
+    }
+
     private RowDataFixture getSelected() {
         return (RowDataFixture) ((StructuredSelection) this.selectionProvider.getSelection()).iterator().next();
     }