Bug 402007 - corrected spanning calculation when static columns are configured
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupGroupHeaderLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupGroupHeaderLayer.java
index a0f776b..8743d6e 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupGroupHeaderLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupGroupHeaderLayer.java
@@ -196,24 +196,30 @@
 	protected int getColumnSpan(int columnPosition) {
 		int columnIndex = getColumnIndexByPosition(columnPosition);
 		ColumnGroup columnGroup = model.getColumnGroupByIndex(columnIndex);
-
+		
+		int sizeOfGroup = columnGroup.getSize();		
+		
 		if (columnGroup.isCollapsed()) {
 			int sizeOfStaticColumns = columnGroup.getStaticColumnIndexes().size();
-			return sizeOfStaticColumns == 0 ? 1 : sizeOfStaticColumns;
-		} else {
-			int startPositionOfGroup = getStartPositionOfGroup(columnPosition);
-			int sizeOfGroup = columnGroup.getSize();
-			int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
-			List<Integer> columnIndexesInGroup = columnGroup.getMembers();
-
-			for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
-				int index = getColumnIndexByPosition(i);
-				if (!columnIndexesInGroup.contains(Integer.valueOf(index))) {
-					sizeOfGroup--;
-				}
+			if (sizeOfStaticColumns == 0) {
+				return 1;
 			}
-			return sizeOfGroup;
+			else {
+				sizeOfGroup = sizeOfStaticColumns;
+			}
 		}
+
+		int startPositionOfGroup = getStartPositionOfGroup(columnPosition);
+		int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
+		List<Integer> columnIndexesInGroup = columnGroup.getMembers();
+
+		for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
+			int index = getColumnIndexByPosition(i);
+			if (!columnIndexesInGroup.contains(Integer.valueOf(index))) {
+				sizeOfGroup--;
+			}
+		}
+		return sizeOfGroup;
 	}
 
 	/**
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupHeaderLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupHeaderLayer.java
index 53a54e7..fb1afdd 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupHeaderLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupHeaderLayer.java
@@ -269,23 +269,29 @@
 		int columnIndex = getColumnIndexByPosition(columnPosition);
 		ColumnGroup columnGroup = model.getColumnGroupByIndex(columnIndex);
 		
+		int sizeOfGroup = columnGroup.getSize();		
+		
 		if (columnGroup.isCollapsed()) {
 			int sizeOfStaticColumns = columnGroup.getStaticColumnIndexes().size();
-			return sizeOfStaticColumns == 0 ? 1 : sizeOfStaticColumns;
-		} else {
-			int startPositionOfGroup = getStartPositionOfGroup(columnPosition);
-			int sizeOfGroup = columnGroup.getSize();
-			int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
-			List<Integer> columnIndexesInGroup = columnGroup.getMembers();
-
-			for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
-				int index = getColumnIndexByPosition(i);
-				if (!columnIndexesInGroup.contains(Integer.valueOf(index))) {
-					sizeOfGroup--;
-				}
+			if (sizeOfStaticColumns == 0) {
+				return 1;
 			}
-			return sizeOfGroup;
+			else {
+				sizeOfGroup = sizeOfStaticColumns;
+			}
 		}
+
+		int startPositionOfGroup = getStartPositionOfGroup(columnPosition);
+		int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
+		List<Integer> columnIndexesInGroup = columnGroup.getMembers();
+
+		for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
+			int index = getColumnIndexByPosition(i);
+			if (!columnIndexesInGroup.contains(Integer.valueOf(index))) {
+				sizeOfGroup--;
+			}
+		}
+		return sizeOfGroup;
 	}
 
 	/**
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupModel.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupModel.java
index b595183..62a5141 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupModel.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/group/ColumnGroupModel.java
@@ -504,8 +504,7 @@
 		
 		public List<Integer> getMembersSorted() {
 			
-			List<Integer> sortedMembers = 
-					Collections.unmodifiableList(members);
+			List<Integer> sortedMembers = new LinkedList<Integer>(members);
 			Collections.sort(sortedMembers);
 			
 			return sortedMembers;
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 a5f71c4..8d7740d 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
@@ -211,23 +211,30 @@
 		// Get the row and the group from our cache and model.
 		final IRowGroup<T> rowGroup = RowGroupUtils.getRowGroupForRowIndex(model, rowIndex);
 		
-		if (RowGroupUtils.isCollapsed(model, rowGroup)) {
-			return rowGroup.getOwnStaticMemberRows().size();			
-		} else {
-			int startPositionOfGroup = getStartPositionOfGroup(rowPosition);
-			int sizeOfGroup = RowGroupUtils.sizeOfGroup(model, rowIndex);
-			int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
-			List<Integer> rowIndexesInGroup = RowGroupUtils.getRowIndexesInGroup(model, rowIndex);
+		int sizeOfGroup = RowGroupUtils.sizeOfGroup(model, rowIndex);
 
-			for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
-				int index = getRowIndexByPosition(i);
-				if (!rowIndexesInGroup.contains(Integer.valueOf(index))) {
-					sizeOfGroup--;
-				}
+		if (RowGroupUtils.isCollapsed(model, rowGroup)) {
+			int sizeOfStaticRows = rowGroup.getOwnStaticMemberRows().size();
+			if (sizeOfStaticRows == 0) {
+				return 1;
 			}
-			
-			return Math.max(1, sizeOfGroup);
+			else {
+				sizeOfGroup = sizeOfStaticRows;
+			}
+		} 
+		
+		int startPositionOfGroup = getStartPositionOfGroup(rowPosition);
+		int endPositionOfGroup = startPositionOfGroup + sizeOfGroup;
+		List<Integer> rowIndexesInGroup = RowGroupUtils.getRowIndexesInGroup(model, rowIndex);
+
+		for (int i = startPositionOfGroup; i < endPositionOfGroup; i++) {
+			int index = getRowIndexByPosition(i);
+			if (!rowIndexesInGroup.contains(Integer.valueOf(index))) {
+				sizeOfGroup--;
+			}
 		}
+		
+		return sizeOfGroup;
 	}
 	
 	/**
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5111_ColumnGroupingExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5111_ColumnGroupingExample.java
index 89b19fb..c09e29c 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5111_ColumnGroupingExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5111_ColumnGroupingExample.java
@@ -14,13 +14,18 @@
 import java.util.Map;
 
 import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.columnChooser.command.DisplayColumnChooserCommandHandler;
+import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
+import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
 import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
-import org.eclipse.nebula.widgets.nattable.examples.data.person.Person;
+import org.eclipse.nebula.widgets.nattable.examples.data.person.ExtendedPersonWithAddress;
 import org.eclipse.nebula.widgets.nattable.examples.data.person.PersonService;
 import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
-import org.eclipse.nebula.widgets.nattable.grid.data.DefaultBodyDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
 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;
@@ -34,14 +39,22 @@
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupReorderLayer;
+import org.eclipse.nebula.widgets.nattable.group.config.ColumnGroupMenuItemProviders;
 import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
+import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
+import org.eclipse.nebula.widgets.nattable.ui.menu.HeaderMenuConfiguration;
+import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
+import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
 import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
 
 /**
  * Simple example showing how to add the {@link ColumnGroupHeaderLayer} to the layer
@@ -68,7 +81,10 @@
 	@Override
 	public Control createExampleControl(Composite parent) {
 		//property names of the Person class
-		String[] propertyNames = {"firstName", "lastName", "gender", "married", "birthday"};
+		String[] propertyNames = {"firstName", "lastName", "gender", "married", 
+				"address.street", "address.housenumber", "address.postalCode", "address.city", 
+				"age", "birthday", "money",
+				"description", "favouriteFood", "favouriteDrinks"};
 
 		//mapping from property to label, needed for column header labels
 		Map<String, String> propertyToLabelMap = new HashMap<String, String>();
@@ -76,7 +92,19 @@
 		propertyToLabelMap.put("lastName", "Lastname");
 		propertyToLabelMap.put("gender", "Gender");
 		propertyToLabelMap.put("married", "Married");
+		propertyToLabelMap.put("address.street", "Street");
+		propertyToLabelMap.put("address.housenumber", "Housenumber");
+		propertyToLabelMap.put("address.postalCode", "Postalcode");
+		propertyToLabelMap.put("address.city", "City");
+		propertyToLabelMap.put("age", "Age");
 		propertyToLabelMap.put("birthday", "Birthday");
+		propertyToLabelMap.put("money", "Money");
+		propertyToLabelMap.put("description", "Description");
+		propertyToLabelMap.put("favouriteFood", "Food");
+		propertyToLabelMap.put("favouriteDrinks", "Drinks");
+
+		IColumnPropertyAccessor<ExtendedPersonWithAddress> columnPropertyAccessor = 
+				new ExtendedReflectiveColumnPropertyAccessor<ExtendedPersonWithAddress>(propertyNames);
 
 		ColumnGroupModel columnGroupModel = new ColumnGroupModel();
 		
@@ -84,7 +112,9 @@
 		//Usually you would create a new layer stack by extending AbstractIndexLayerTransform and
 		//setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer
 		//directly as body layer is also working.
-		IDataProvider bodyDataProvider = new DefaultBodyDataProvider<Person>(PersonService.getPersons(10), propertyNames);
+		IDataProvider bodyDataProvider = 
+				new ListDataProvider<ExtendedPersonWithAddress>(
+						PersonService.getExtendedPersonsWithAddress(10), columnPropertyAccessor);
 		DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
 		ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
 		ColumnGroupReorderLayer columnGroupReorderLayer = new ColumnGroupReorderLayer(columnReorderLayer, columnGroupModel);
@@ -96,12 +126,16 @@
 		//build the column header layer
 		IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
 		DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
-		ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
+		ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
 		ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer, columnGroupModel);
 
 		//configure the column groups
-		columnGroupHeaderLayer.addColumnsIndexesToGroup("Name", 0, 1);
-		columnGroupHeaderLayer.addColumnsIndexesToGroup("Details", 2, 3, 4);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Person", 0, 1, 2, 3);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Address", 4, 5, 6, 7);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Facts", 8, 9, 10);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Personal", 11, 12, 13);
+		columnGroupHeaderLayer.setStaticColumnIndexesByGroup("Person", 0, 1);
+		columnGroupHeaderLayer.setStaticColumnIndexesByGroup("Address", 4, 5, 6);
 		columnGroupHeaderLayer.setGroupUnbreakable(1);
 		
 		//build the row header layer
@@ -124,6 +158,30 @@
 		//DefaultNatTableStyleConfiguration manually	
 		natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
 		
+		natTable.addConfiguration(new HeaderMenuConfiguration(natTable) {
+			@Override
+			protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
+				return super.createColumnHeaderMenu(natTable)
+						.withColumnChooserMenuItem();
+			}
+		});
+		
+		// Column group header menu
+		final Menu columnGroupHeaderMenu =
+				new PopupMenuBuilder(natTable)
+					.withMenuItemProvider(ColumnGroupMenuItemProviders.renameColumnGroupMenuItemProvider())
+					.withMenuItemProvider(ColumnGroupMenuItemProviders.removeColumnGroupMenuItemProvider())
+					.build();
+		
+		natTable.addConfiguration(new AbstractUiBindingConfiguration() {
+			@Override
+			public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
+				uiBindingRegistry.registerFirstMouseDownBinding(
+						new MouseEventMatcher(SWT.NONE, GridRegion.COLUMN_GROUP_HEADER, MouseEventMatcher.RIGHT_BUTTON),
+						new PopupMenuAction(columnGroupHeaderMenu));
+			}
+		});
+		
 		//enable this configuration to verify the automatic height calculation when using vertical text painter
 //		natTable.addConfiguration(new AbstractRegistryConfiguration() {
 //			
@@ -135,6 +193,16 @@
 //			}
 //		});
 		
+		// Register column chooser
+		DisplayColumnChooserCommandHandler columnChooserCommandHandler = new DisplayColumnChooserCommandHandler(
+				selectionLayer,
+				columnHideShowLayer,
+				columnHeaderLayer,
+				columnHeaderDataLayer,
+				columnGroupHeaderLayer,
+				columnGroupModel);
+		viewportLayer.registerCommandHandler(columnChooserCommandHandler);
+
 		natTable.configure();
 		
 		return natTable;
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5112_TwoLevelColumnGroupingExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5112_TwoLevelColumnGroupingExample.java
new file mode 100644
index 0000000..4fc9f00
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_5112_TwoLevelColumnGroupingExample.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Dirk Fauth and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Dirk Fauth <dirk.fauth@gmail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.nebula.widgets.nattable.examples._500_Layers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
+import org.eclipse.nebula.widgets.nattable.examples.data.person.ExtendedPersonWithAddress;
+import org.eclipse.nebula.widgets.nattable.examples.data.person.PersonService;
+import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
+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.DefaultColumnHeaderDataLayer;
+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.group.ColumnGroupExpandCollapseLayer;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupGroupHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
+import org.eclipse.nebula.widgets.nattable.group.ColumnGroupReorderLayer;
+import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Simple example showing how to add the {@link ColumnGroupHeaderLayer} and the
+ * {@link ColumnGroupGroupHeaderLayer} to the layer composition of a grid and 
+ * how to add the corresponding actions to the column header menu.
+ * 
+ * @author Dirk Fauth
+ *
+ */
+public class _5112_TwoLevelColumnGroupingExample extends AbstractNatExample {
+
+	public static void main(String[] args) throws Exception {
+		StandaloneNatExampleRunner.run(new _5112_TwoLevelColumnGroupingExample());
+	}
+
+	@Override
+	public String getDescription() {
+		return "This example shows the usage of the ColumnGroupHeaderLayer and the ColumnGroupHeaderLayer "
+				+ "within a grid and its corresponding actions in the column header menu. If you perform a "
+				+ "right click on the column header, you are able to hide the current selected "
+				+ "column or show all columns again.";
+	}
+	
+	@Override
+	public Control createExampleControl(Composite parent) {
+		//property names of the Person class
+		String[] propertyNames = {"firstName", "lastName", "gender", "married", 
+				"address.street", "address.housenumber", "address.postalCode", "address.city", 
+				"age", "birthday", "money",
+				"description", "favouriteFood", "favouriteDrinks"};
+
+		//mapping from property to label, needed for column header labels
+		Map<String, String> propertyToLabelMap = new HashMap<String, String>();
+		propertyToLabelMap.put("firstName", "Firstname");
+		propertyToLabelMap.put("lastName", "Lastname");
+		propertyToLabelMap.put("gender", "Gender");
+		propertyToLabelMap.put("married", "Married");
+		propertyToLabelMap.put("address.street", "Street");
+		propertyToLabelMap.put("address.housenumber", "Housenumber");
+		propertyToLabelMap.put("address.postalCode", "Postalcode");
+		propertyToLabelMap.put("address.city", "City");
+		propertyToLabelMap.put("age", "Age");
+		propertyToLabelMap.put("birthday", "Birthday");
+		propertyToLabelMap.put("money", "Money");
+		propertyToLabelMap.put("description", "Description");
+		propertyToLabelMap.put("favouriteFood", "Food");
+		propertyToLabelMap.put("favouriteDrinks", "Drinks");
+
+		IColumnPropertyAccessor<ExtendedPersonWithAddress> columnPropertyAccessor = 
+				new ExtendedReflectiveColumnPropertyAccessor<ExtendedPersonWithAddress>(propertyNames);
+
+		ColumnGroupModel columnGroupModel = new ColumnGroupModel();
+		ColumnGroupModel sndColumnGroupModel = new ColumnGroupModel();
+		
+		//build the body layer stack 
+		//Usually you would create a new layer stack by extending AbstractIndexLayerTransform and
+		//setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer
+		//directly as body layer is also working.
+		IDataProvider bodyDataProvider = 
+				new ListDataProvider<ExtendedPersonWithAddress>(
+						PersonService.getExtendedPersonsWithAddress(10), columnPropertyAccessor);
+		DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
+		ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
+		ColumnGroupReorderLayer columnGroupReorderLayer = new ColumnGroupReorderLayer(columnReorderLayer, columnGroupModel);
+		ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnGroupReorderLayer);
+		ColumnGroupExpandCollapseLayer columnGroupExpandCollapseLayer = 
+				new ColumnGroupExpandCollapseLayer(columnHideShowLayer, sndColumnGroupModel, columnGroupModel);
+		SelectionLayer selectionLayer = new SelectionLayer(columnGroupExpandCollapseLayer);
+		ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
+
+		//build the column header layer
+		IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
+		DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
+		ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
+		ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer, columnGroupModel);
+
+		//configure the column groups
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Person", 0, 1, 2, 3);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Address", 4, 5, 6, 7);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Facts", 8, 9, 10);
+		columnGroupHeaderLayer.addColumnsIndexesToGroup("Personal", 11, 12, 13);
+		columnGroupHeaderLayer.setStaticColumnIndexesByGroup("Person", 0, 1);
+		columnGroupHeaderLayer.setStaticColumnIndexesByGroup("Address", 4, 5, 6);
+		columnGroupHeaderLayer.setGroupUnbreakable(1);
+
+		ColumnGroupGroupHeaderLayer sndGroup = 
+				new ColumnGroupGroupHeaderLayer(columnGroupHeaderLayer, selectionLayer, sndColumnGroupModel);
+		
+		sndGroup.addColumnsIndexesToGroup("PersonWithAddress", 0, 1, 2, 3, 4, 5, 6, 7);
+		sndGroup.addColumnsIndexesToGroup("Additional Information", 8, 9, 10, 11, 12, 13);
+
+		sndGroup.setStaticColumnIndexesByGroup("PersonWithAddress", 0, 1);
+		
+		//build the row header layer
+		IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
+		DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
+		ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);
+		
+		//build the corner layer
+		IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
+		DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
+		ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, sndGroup);
+		
+		//build the grid layer
+		GridLayer gridLayer = new GridLayer(viewportLayer, sndGroup, rowHeaderLayer, cornerLayer);
+		
+		//turn the auto configuration off as we want to add our header menu configuration
+		NatTable natTable = new NatTable(parent, gridLayer);
+		
+		return natTable;
+	}
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_807_SortableFilterableColumnGroupExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_807_SortableFilterableColumnGroupExample.java
index 3019891..775dfb9 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_807_SortableFilterableColumnGroupExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_800_Integration/_807_SortableFilterableColumnGroupExample.java
@@ -17,7 +17,9 @@
 import java.util.Map;
 
 import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.columnChooser.command.DisplayColumnChooserCommandHandler;
 import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
@@ -42,6 +44,9 @@
 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowTextCellEditor;
 import org.eclipse.nebula.widgets.nattable.filterrow.TextMatchingMode;
 import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer;
+import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer;
+import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
 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;
@@ -54,6 +59,7 @@
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
 import org.eclipse.nebula.widgets.nattable.group.ColumnGroupReorderLayer;
+import org.eclipse.nebula.widgets.nattable.group.config.ColumnGroupMenuItemProviders;
 import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
 import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
@@ -62,9 +68,16 @@
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
+import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
+import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
+import org.eclipse.nebula.widgets.nattable.ui.menu.HeaderMenuConfiguration;
+import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
+import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
 import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
 
 import ca.odell.glazedlists.EventList;
 import ca.odell.glazedlists.FilterList;
@@ -119,7 +132,7 @@
 
 		IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
 		DataLayer columnHeaderDataLayer = new DataLayer(columnHeaderDataProvider);
-		ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
+		ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
 		
 		SortHeaderLayer<ExtendedPersonWithAddress> sortHeaderLayer = 
 				new SortHeaderLayer<ExtendedPersonWithAddress>(columnHeaderLayer, 
@@ -170,6 +183,40 @@
 		//add filter row configuration
 		natTable.addConfiguration(new FilterRowConfiguration());
 		
+		natTable.addConfiguration(new HeaderMenuConfiguration(natTable) {
+			@Override
+			protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
+				return super.createColumnHeaderMenu(natTable)
+						.withColumnChooserMenuItem();
+			}
+		});
+		
+		// Column group header menu
+		final Menu columnGroupHeaderMenu =
+				new PopupMenuBuilder(natTable)
+					.withMenuItemProvider(ColumnGroupMenuItemProviders.renameColumnGroupMenuItemProvider())
+					.withMenuItemProvider(ColumnGroupMenuItemProviders.removeColumnGroupMenuItemProvider())
+					.build();
+		
+		natTable.addConfiguration(new AbstractUiBindingConfiguration() {
+			@Override
+			public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
+				uiBindingRegistry.registerFirstMouseDownBinding(
+						new MouseEventMatcher(SWT.NONE, GridRegion.COLUMN_GROUP_HEADER, MouseEventMatcher.RIGHT_BUTTON),
+						new PopupMenuAction(columnGroupHeaderMenu));
+			}
+		});
+		
+		// Register column chooser
+		DisplayColumnChooserCommandHandler columnChooserCommandHandler = new DisplayColumnChooserCommandHandler(
+				bodyLayer.getSelectionLayer(),
+				bodyLayer.getColumnHideShowLayer(),
+				columnHeaderLayer,
+				columnHeaderDataLayer,
+				columnGroupHeaderLayer,
+				columnGroupModel);
+		bodyLayer.registerCommandHandler(columnChooserCommandHandler);
+		
 		natTable.configure();
 
 		return natTable;
@@ -217,7 +264,11 @@
 			columnGroupExpandCollapseLayer = new ColumnGroupExpandCollapseLayer(columnHideShowLayer, columnGroupModel);
 			selectionLayer = new SelectionLayer(columnGroupExpandCollapseLayer);
 			viewportLayer = new ViewportLayer(selectionLayer);
-			setUnderlyingLayer(viewportLayer);
+			
+			final FreezeLayer freezeLayer = new FreezeLayer(selectionLayer);
+		    final CompositeFreezeLayer compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer, viewportLayer, selectionLayer);
+
+			setUnderlyingLayer(compositeFreezeLayer);
 		}
 
 		public SortedList<T> getSortedList() {