You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/01/25 16:08:00 UTC

[39/50] [abbrv] isis git commit: ISIS-993: factored out ListOfTabGroupsPanel.

ISIS-993: factored out ListOfTabGroupsPanel.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/55c4ac75
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/55c4ac75
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/55c4ac75

Branch: refs/heads/ISIS-993
Commit: 55c4ac753fe9985db6b0419469001e65710eda2d
Parents: 24046fc
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jan 14 16:03:54 2016 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Jan 25 15:06:07 2016 +0000

----------------------------------------------------------------------
 .../viewer/wicket/model/models/EntityModel.java |  20 +-
 .../entity/properties/EntityColumn.html         |  46 +++++
 .../entity/properties/EntityColumn.java         | 191 +++++++++++++++++++
 .../entity/properties/EntityColumnMembers.html  |  46 -----
 .../entity/properties/EntityColumnMembers.java  | 191 -------------------
 .../entity/properties/EntityPropertiesForm.java |   4 +-
 .../entity/tabgroups/EntityTabGroupsPanel.html  |   6 +-
 .../entity/tabgroups/EntityTabGroupsPanel.java  | 128 ++-----------
 .../entity/tabgroups/ListOfTabGroupsPanel.html  |  28 +++
 .../entity/tabgroups/ListOfTabGroupsPanel.java  | 144 ++++++++++++++
 10 files changed, 450 insertions(+), 354 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
index 559e110..0fb28ac 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
@@ -20,6 +20,7 @@
 package org.apache.isis.viewer.wicket.model.models;
 
 import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -30,7 +31,9 @@ import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.isis.applib.annotation.BookmarkPolicy;
 import org.apache.isis.applib.layout.v1_0.Column;
+import org.apache.isis.applib.layout.v1_0.Column.Hint;
 import org.apache.isis.applib.layout.v1_0.Tab;
+import org.apache.isis.applib.layout.v1_0.TabGroup;
 import org.apache.isis.applib.services.memento.MementoService.Memento;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
@@ -44,7 +47,6 @@ import org.apache.isis.core.metamodel.facets.object.bookmarkpolicy.BookmarkPolic
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.applib.layout.v1_0.Column.Hint;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
@@ -642,6 +644,22 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
     // tab and column metadata (if any)
     // //////////////////////////////////////////////////////////
 
+    private List<TabGroup> tabGroupListMetadata;
+
+    public List<TabGroup> getTabGroupListMetadata() {
+        return tabGroupListMetadata;
+    }
+
+    /**
+     * Returns a new copy that SHARES the property scalar models (for edit form).
+     */
+    public EntityModel cloneWithTabGroupListMetadata(final List<TabGroup> tabGroupListMetadata) {
+        final EntityModel entityModel = new EntityModel(this.adapterMemento, this.propertyScalarModels);
+        entityModel.tabGroupListMetadata = tabGroupListMetadata;
+        return entityModel;
+    }
+
+
     private Tab tabMetadata;
 
     public Tab getTabMetadata() {

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html
new file mode 100644
index 0000000..43c76da
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns:wicket="http://wicket.apache.org">
+    <body>
+        <wicket:panel>
+            <div class="columnMembers">
+                <div class="inputFormTable properties">
+                    <fieldset wicket:id="memberGroup" class="memberGroup myBlockContainer">
+                        <div class="panel panel-default">
+                            <div class="panel-heading">
+                                <span wicket:id="memberGroupName" class="panel-title">[group name]</span>
+                                <div class="pull-right additionalLinks">
+                                    <div wicket:id="associatedActionLinksPanel"></div>
+                                    <div wicket:id="associatedActionLinksPanelDropDown"></div>
+                                </div>
+                            </div>
+                            <div class="properties panel-body">
+                                <div wicket:id="properties">
+                                    <div wicket:id="property" class="property">[property]</div>
+                                </div>
+                            </div>
+                        </div>
+                    </fieldset>
+                </div>
+                <div wicket:id="collections"></div>
+            </div>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java
new file mode 100644
index 0000000..a0b7b2b
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java
@@ -0,0 +1,191 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.entity.properties;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.RepeatingView;
+
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.layout.v1_0.Column;
+import org.apache.isis.applib.layout.v1_0.PropertyGroup;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.ObjectSpecifications;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.runtime.system.DeploymentType;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPathSignificantWebMarkupContainer;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+
+public class EntityColumn extends PanelAbstract<EntityModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_MEMBER_GROUP = "memberGroup";
+    private static final String ID_MEMBER_GROUP_NAME = "memberGroupName";
+
+    private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL = "associatedActionLinksPanel";
+    private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN = "associatedActionLinksPanelDropDown";
+
+    private static final String ID_PROPERTIES = "properties";
+    private static final String ID_PROPERTY = "property";
+
+    private final Component owningPanel;
+
+    public EntityColumn(
+            final String id,
+            final EntityModel entityModel,
+            final Component owningPanel) {
+
+        super(id, entityModel);
+        this.owningPanel = owningPanel; // for repainting, perhaps
+
+        buildGui();
+    }
+
+    private void buildGui() {
+        addPropertiesAndCollections(this, getModel());
+    }
+
+    private void addPropertiesAndCollections(
+            final MarkupContainer col,
+            final EntityModel entityModel) {
+        addPropertiesInColumn(col, entityModel);
+        addCollectionsIfRequired(col, entityModel);
+    }
+
+    private void addPropertiesInColumn(
+            final MarkupContainer markupContainer,
+            final EntityModel entityModel) {
+
+        final Column columnMetaDataIfAny = entityModel.getColumnMetadata();
+        final Column.Hint hint = entityModel.getColumnHint();
+        final ObjectAdapter adapter = entityModel.getObject();
+        final ObjectSpecification objSpec = adapter.getSpecification();
+
+        final Map<String, List<ObjectAssociation>> associationsByGroup = PropUtil
+                .propertiesByMemberOrder(adapter);
+        final List<String> groupNames = columnMetaDataIfAny != null
+                ? FluentIterable
+                .from(columnMetaDataIfAny.getPropertyGroups())
+                .transform(PropertyGroup.Util.nameOf())
+                .toList()
+                : ObjectSpecifications.orderByMemberGroups(objSpec, associationsByGroup.keySet(), hint);
+
+        final RepeatingView memberGroupRv = new RepeatingView(ID_MEMBER_GROUP);
+        markupContainer.add(memberGroupRv);
+
+        for(final String groupName: groupNames) {
+            final List<ObjectAssociation> associationsInGroup = associationsByGroup.get(groupName);
+            if(associationsInGroup==null) {
+                continue;
+            }
+
+            final WebMarkupContainer memberGroupRvContainer = new WebMarkupContainer(memberGroupRv.newChildId());
+            memberGroupRv.add(memberGroupRvContainer);
+            memberGroupRvContainer.add(new Label(ID_MEMBER_GROUP_NAME, groupName));
+
+            final List<LinkAndLabel> memberGroupActions = Lists.newArrayList();
+
+            final RepeatingView propertyRv = new RepeatingView(ID_PROPERTIES);
+            memberGroupRvContainer.add(propertyRv);
+
+            @SuppressWarnings("unused")
+            Component component;
+            for (final ObjectAssociation association : associationsInGroup) {
+                final WebMarkupContainer propertyRvContainer = new UiHintPathSignificantWebMarkupContainer(propertyRv.newChildId());
+                propertyRv.add(propertyRvContainer);
+
+                addPropertyToForm(entityModel, (OneToOneAssociation) association, propertyRvContainer, memberGroupActions);
+            }
+
+            final List<LinkAndLabel> actionsPanel = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL);
+            final List<LinkAndLabel> actionsPanelDropDown = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL_DROPDOWN);
+
+            AdditionalLinksPanel.addAdditionalLinks(
+                    memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL,
+                    actionsPanel,
+                    AdditionalLinksPanel.Style.INLINE_LIST);
+            AdditionalLinksPanel.addAdditionalLinks(
+                    memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN,
+                    actionsPanelDropDown,
+                    AdditionalLinksPanel.Style.DROPDOWN);
+        }
+    }
+
+    private void addCollectionsIfRequired(
+            final MarkupContainer column,
+            final EntityModel entityModel) {
+
+        final Column columnMetaDataIfAny = entityModel.getColumnMetadata();
+
+        if(columnMetaDataIfAny != null) {
+            getComponentFactoryRegistry()
+                    .addOrReplaceComponent(column, "collections", ComponentType.ENTITY_COLLECTIONS, entityModel);
+        } else {
+            Components.permanentlyHide(column, "collections");
+        }
+    }
+
+    private void addPropertyToForm(
+            final EntityModel entityModel,
+            final OneToOneAssociation otoa,
+            final WebMarkupContainer container,
+            final List<LinkAndLabel> entityActions) {
+        final PropertyMemento pm = new PropertyMemento(otoa);
+
+        final ScalarModel scalarModel = entityModel.getPropertyModel(pm);
+        final Component component = getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
+
+        final List<ObjectAction> associatedActions = EntityActionUtil.getObjectActionsForAssociation(entityModel,
+                otoa, getDeploymentType());
+
+        entityActions.addAll(EntityActionUtil.asLinkAndLabelsForAdditionalLinksPanel(entityModel, associatedActions));
+    }
+
+
+
+    ///////////////////////////////////////////////////////
+    // Dependencies (from context)
+    ///////////////////////////////////////////////////////
+
+    protected DeploymentType getDeploymentType() {
+        return IsisContext.getDeploymentType();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.html
deleted file mode 100644
index 43c76da..0000000
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-  
-         http://www.apache.org/licenses/LICENSE-2.0
-         
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-<html xmlns:wicket="http://wicket.apache.org">
-    <body>
-        <wicket:panel>
-            <div class="columnMembers">
-                <div class="inputFormTable properties">
-                    <fieldset wicket:id="memberGroup" class="memberGroup myBlockContainer">
-                        <div class="panel panel-default">
-                            <div class="panel-heading">
-                                <span wicket:id="memberGroupName" class="panel-title">[group name]</span>
-                                <div class="pull-right additionalLinks">
-                                    <div wicket:id="associatedActionLinksPanel"></div>
-                                    <div wicket:id="associatedActionLinksPanelDropDown"></div>
-                                </div>
-                            </div>
-                            <div class="properties panel-body">
-                                <div wicket:id="properties">
-                                    <div wicket:id="property" class="property">[property]</div>
-                                </div>
-                            </div>
-                        </div>
-                    </fieldset>
-                </div>
-                <div wicket:id="collections"></div>
-            </div>
-        </wicket:panel>
-    </body>
-</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.java
deleted file mode 100644
index a294969..0000000
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumnMembers.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.viewer.wicket.ui.components.entity.properties;
-
-import java.util.List;
-import java.util.Map;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.repeater.RepeatingView;
-
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.layout.v1_0.Column;
-import org.apache.isis.applib.layout.v1_0.PropertyGroup;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.ObjectSpecifications;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.runtime.system.DeploymentType;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
-import org.apache.isis.viewer.wicket.model.models.EntityModel;
-import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
-import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
-import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPathSignificantWebMarkupContainer;
-import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
-import org.apache.isis.viewer.wicket.ui.util.Components;
-
-public class EntityColumnMembers extends PanelAbstract<EntityModel> {
-
-    private static final long serialVersionUID = 1L;
-
-    private static final String ID_MEMBER_GROUP = "memberGroup";
-    private static final String ID_MEMBER_GROUP_NAME = "memberGroupName";
-
-    private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL = "associatedActionLinksPanel";
-    private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN = "associatedActionLinksPanelDropDown";
-
-    private static final String ID_PROPERTIES = "properties";
-    private static final String ID_PROPERTY = "property";
-
-    private final Component owningPanel;
-
-    public EntityColumnMembers(
-            final String id,
-            final EntityModel entityModel,
-            final Component owningPanel) {
-
-        super(id, entityModel);
-        this.owningPanel = owningPanel; // for repainting, perhaps
-
-        buildGui();
-    }
-
-    private void buildGui() {
-        addPropertiesAndCollections(this, getModel());
-    }
-
-    private void addPropertiesAndCollections(
-            final MarkupContainer col,
-            final EntityModel entityModel) {
-        addPropertiesInColumn(col, entityModel);
-        addCollectionsIfRequired(col, entityModel);
-    }
-
-    private void addPropertiesInColumn(
-            final MarkupContainer markupContainer,
-            final EntityModel entityModel) {
-
-        final Column columnMetaDataIfAny = entityModel.getColumnMetadata();
-        final Column.Hint hint = entityModel.getColumnHint();
-        final ObjectAdapter adapter = entityModel.getObject();
-        final ObjectSpecification objSpec = adapter.getSpecification();
-
-        final Map<String, List<ObjectAssociation>> associationsByGroup = PropUtil
-                .propertiesByMemberOrder(adapter);
-        final List<String> groupNames = columnMetaDataIfAny != null
-                ? FluentIterable
-                .from(columnMetaDataIfAny.getPropertyGroups())
-                .transform(PropertyGroup.Util.nameOf())
-                .toList()
-                : ObjectSpecifications.orderByMemberGroups(objSpec, associationsByGroup.keySet(), hint);
-
-        final RepeatingView memberGroupRv = new RepeatingView(ID_MEMBER_GROUP);
-        markupContainer.add(memberGroupRv);
-
-        for(final String groupName: groupNames) {
-            final List<ObjectAssociation> associationsInGroup = associationsByGroup.get(groupName);
-            if(associationsInGroup==null) {
-                continue;
-            }
-
-            final WebMarkupContainer memberGroupRvContainer = new WebMarkupContainer(memberGroupRv.newChildId());
-            memberGroupRv.add(memberGroupRvContainer);
-            memberGroupRvContainer.add(new Label(ID_MEMBER_GROUP_NAME, groupName));
-
-            final List<LinkAndLabel> memberGroupActions = Lists.newArrayList();
-
-            final RepeatingView propertyRv = new RepeatingView(ID_PROPERTIES);
-            memberGroupRvContainer.add(propertyRv);
-
-            @SuppressWarnings("unused")
-            Component component;
-            for (final ObjectAssociation association : associationsInGroup) {
-                final WebMarkupContainer propertyRvContainer = new UiHintPathSignificantWebMarkupContainer(propertyRv.newChildId());
-                propertyRv.add(propertyRvContainer);
-
-                addPropertyToForm(entityModel, (OneToOneAssociation) association, propertyRvContainer, memberGroupActions);
-            }
-
-            final List<LinkAndLabel> actionsPanel = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL);
-            final List<LinkAndLabel> actionsPanelDropDown = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL_DROPDOWN);
-
-            AdditionalLinksPanel.addAdditionalLinks(
-                    memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL,
-                    actionsPanel,
-                    AdditionalLinksPanel.Style.INLINE_LIST);
-            AdditionalLinksPanel.addAdditionalLinks(
-                    memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN,
-                    actionsPanelDropDown,
-                    AdditionalLinksPanel.Style.DROPDOWN);
-        }
-    }
-
-    private void addCollectionsIfRequired(
-            final MarkupContainer column,
-            final EntityModel entityModel) {
-
-        final Column columnMetaDataIfAny = entityModel.getColumnMetadata();
-
-        if(columnMetaDataIfAny != null) {
-            getComponentFactoryRegistry()
-                    .addOrReplaceComponent(column, "collections", ComponentType.ENTITY_COLLECTIONS, entityModel);
-        } else {
-            Components.permanentlyHide(column, "collections");
-        }
-    }
-
-    private void addPropertyToForm(
-            final EntityModel entityModel,
-            final OneToOneAssociation otoa,
-            final WebMarkupContainer container,
-            final List<LinkAndLabel> entityActions) {
-        final PropertyMemento pm = new PropertyMemento(otoa);
-
-        final ScalarModel scalarModel = entityModel.getPropertyModel(pm);
-        final Component component = getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
-
-        final List<ObjectAction> associatedActions = EntityActionUtil.getObjectActionsForAssociation(entityModel,
-                otoa, getDeploymentType());
-
-        entityActions.addAll(EntityActionUtil.asLinkAndLabelsForAdditionalLinksPanel(entityModel, associatedActions));
-    }
-
-
-
-    ///////////////////////////////////////////////////////
-    // Dependencies (from context)
-    ///////////////////////////////////////////////////////
-
-    protected DeploymentType getDeploymentType() {
-        return IsisContext.getDeploymentType();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index 94c191c..7981790 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -239,8 +239,8 @@ public class EntityPropertiesForm extends FormAbstract<ObjectAdapter> implements
 
         final EntityModel entityModelWithHints = entityModel.cloneWithColumnMetadata(columnMetaDataIfAny, hint);
 
-        final EntityColumnMembers columnMembers =
-                new EntityColumnMembers("entityMembers", entityModelWithHints, markupContainer);
+        final EntityColumn columnMembers =
+                new EntityColumn("entityMembers", entityModelWithHints, markupContainer);
         markupContainer.add(columnMembers);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.html
index 5b56f5d..7b172aa 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.html
@@ -25,11 +25,7 @@
 
         <div class="row">
             <div wicket:id="leftColumn" class = "leftColumn"/>
-            <div wicket:id="middleColumn" class="tabGroups">
-                <div class="row" wicket:id="tabGroups">
-                    <div wicket:id="tabGroup" class="col-xs-12">[tabbed panel will be here]</div>
-                </div>
-            </div>
+            <div wicket:id="middleColumn" class="middleColumn"/>
             <div wicket:id="rightColumn" class = "rightColumn"/>
         </div>
 	</div>

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.java
index b9cd46e..ba3a2ac 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/EntityTabGroupsPanel.java
@@ -20,40 +20,21 @@
 package org.apache.isis.viewer.wicket.ui.components.entity.tabgroups;
 
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
-import org.apache.wicket.extensions.markup.html.tabs.TabbedPanel;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.Model;
 
 import org.apache.isis.applib.layout.v1_0.Column;
 import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
-import org.apache.isis.applib.layout.v1_0.Tab;
 import org.apache.isis.applib.layout.v1_0.TabGroup;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.object.layoutmetadata.ObjectLayoutMetadataFacet;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.entity.properties.EntityColumnMembers;
+import org.apache.isis.viewer.wicket.ui.components.entity.properties.EntityColumn;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
-import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
-
 /**
  * {@link PanelAbstract Panel} to represent an entity on a single page made up
  * of several &lt;div&gt; regions.
@@ -62,8 +43,6 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
 
     private static final long serialVersionUID = 1L;
 
-    private static final String ID_TAB_GROUPS = "tabGroups";
-    private static final String ID_TAB_GROUP = "tabGroup";
     private static final String ID_LEFT_COLUMN = "leftColumn";
     private static final String ID_MIDDLE_COLUMN = "middleColumn";
     private static final String ID_RIGHT_COLUMN = "rightColumn";
@@ -91,107 +70,38 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
 
         final int leftSpan = addColumnIfRequired(ID_LEFT_COLUMN, objectLayoutMetadata.getLeft(), Column.Hint.LEFT);
 
-        final List<TabGroup> tabGroups = FluentIterable
-                .from(objectLayoutMetadata.getTabGroups())
-                .filter(TabGroup.Predicates.notEmpty())
-                .toList();
-        final AtomicInteger tabGroupRef = new AtomicInteger(0);
-        final ListView<TabGroup> tabGroupsList =
-                new ListView<TabGroup>(ID_TAB_GROUPS, tabGroups) {
-
-            @Override
-            protected void populateItem(final ListItem<TabGroup> item) {
-
-                final List<ITab> tabs = Lists.newArrayList();
-                final TabGroup tabGroup = item.getModelObject();
-                final List<Tab> tabList = FluentIterable
-                        .from(tabGroup.getTabs())
-                        .filter(Tab.Predicates.notEmpty())
-                        .toList();
-
-                for (final Tab tab : tabList) {
-                    tabs.add(new AbstractTab(Model.of(tab.getName())) {
-                        private static final long serialVersionUID = 1L;
-
-                        @Override
-                        public Panel getPanel(String panelId) {
-                            return new EntityTabPanel(panelId, model, tab);
-                        }
-                    });
-                }
-                final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel = newTabbedPanel(tabs, tabGroupRef.get());
-
-                item.add(ajaxBootstrapTabbedPanel);
-
-                tabGroupRef.incrementAndGet();
-            }
-
-            private AjaxBootstrapTabbedPanel newTabbedPanel(final List<ITab> tabs, final int tabGroupNumber) {
-                final AjaxBootstrapTabbedPanel tabbedPanel = new AjaxBootstrapTabbedPanel(ID_TAB_GROUP, tabs) {
-                    @Override
-                    public TabbedPanel setSelectedTab(final int index) {
-                        saveSelectedTabInSession(tabGroupNumber, index);
-                        return super.setSelectedTab(index);
-                    }
-                };
-                setSelectedTabFromSessionIfAny(tabbedPanel, tabGroupNumber);
-                return tabbedPanel;
-
-            }
-
-            private void setSelectedTabFromSessionIfAny(
-                    final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel,
-                    final int tabGroupNumber) {
-                final String key = buildKey(tabGroupNumber);
-                final String value = (String) getSession().getAttribute(key);
-                if(value != null) {
-                    final int tabIndex = Integer.parseInt(value);
-                    final int numTabs = ajaxBootstrapTabbedPanel.getTabs().size();
-                    if(tabIndex < numTabs) {
-                        // to support dynamic reloading; the data in the session might not be compatible with current layout.
-                        ajaxBootstrapTabbedPanel.setSelectedTab(tabIndex);
-                    }
-                }
-            }
-
-            private void saveSelectedTabInSession(final int tabGroupNumber, final int tabIndex) {
-                final String key = buildKey(tabGroupNumber);
-                getSession().setAttribute(key, "" + tabIndex);
-            }
-
-            private String buildKey(final int tabGroupNumber) {
-                final ObjectAdapterMemento objectAdapterMemento = EntityTabGroupsPanel.this.getModel().getObjectAdapterMemento();
-                final RootOid oid = (RootOid) objectAdapterMemento.getObjectAdapter(
-                        AdapterManager.ConcurrencyChecking.NO_CHECK).getOid();
-                final String key =
-                        IsisContext.getOidMarshaller().marshalNoVersion(oid) + "." + tabGroupNumber + ".selectedTab";
-                return key;
-            }
-
-        };
-
-        final MarkupContainer tabGroupsContainer = new WebMarkupContainer(ID_MIDDLE_COLUMN);
-        add(tabGroupsContainer);
-
-        tabGroupsContainer.add(tabGroupsList);
+        final ListOfTabGroupsPanel middleTabs = addTabGroups(ID_MIDDLE_COLUMN, objectLayoutMetadata.getTabGroups());
 
         final int rightSpan = addColumnIfRequired(ID_RIGHT_COLUMN, objectLayoutMetadata.getRight(), Column.Hint.RIGHT);
 
         final int columnSpans = leftSpan + rightSpan;
         int tabGroupSpan = columnSpans < 12 ? 12 - (columnSpans) : 12;
-        CssClassAppender.appendCssClassTo(tabGroupsContainer, "col-xs-" + tabGroupSpan);
+        CssClassAppender.appendCssClassTo(middleTabs, "col-xs-" + tabGroupSpan);
 
     }
 
+    private ListOfTabGroupsPanel addTabGroups(
+            final String id, final List<TabGroup> tabGroupList) {
+        final EntityModel model = getModel();
+        final List<TabGroup> tabGroups = FluentIterable
+                .from(tabGroupList)
+                .filter(TabGroup.Predicates.notEmpty())
+                .toList();
+        final EntityModel entityModelWitHints = model.cloneWithTabGroupListMetadata(tabGroups);
+        final ListOfTabGroupsPanel middleComponent = new ListOfTabGroupsPanel(id, entityModelWitHints);
+        addOrReplace(middleComponent);
+        return middleComponent;
+    }
+
     private int addColumnIfRequired(final String id, final Column col, final Column.Hint hint) {
         if(col != null) {
             final EntityModel entityModel =
                     getModel().cloneWithColumnMetadata(col, hint);
             final int span = entityModel.getColumnMetadata().getSpan();
             if(span > 0) {
-                final EntityColumnMembers entityColumnMembers = new EntityColumnMembers(id, entityModel, this);
-                addOrReplace(entityColumnMembers);
-                CssClassAppender.appendCssClassTo(entityColumnMembers, "col-xs-" + span);
+                final EntityColumn entityColumn = new EntityColumn(id, entityModel, this);
+                addOrReplace(entityColumn);
+                CssClassAppender.appendCssClassTo(entityColumn, "col-xs-" + span);
                 return span;
             }
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.html
new file mode 100644
index 0000000..6699518
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.html
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:panel>
+    <div wicket:id="tabGroups">
+        <div wicket:id="tabGroup">[tabbed panel will be here]</div>
+    </div>
+</wicket:panel>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/55c4ac75/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.java
new file mode 100644
index 0000000..c8cc961
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabgroups/ListOfTabGroupsPanel.java
@@ -0,0 +1,144 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.entity.tabgroups;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.extensions.markup.html.tabs.TabbedPanel;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+import org.apache.isis.applib.layout.v1_0.Tab;
+import org.apache.isis.applib.layout.v1_0.TabGroup;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+
+public class ListOfTabGroupsPanel extends PanelAbstract<EntityModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_TAB_GROUPS = "tabGroups";
+    private static final String ID_TAB_GROUP = "tabGroup";
+
+    public ListOfTabGroupsPanel(final String id, final EntityModel entityModel) {
+        super(id, entityModel);
+        buildGui();
+    }
+
+    private void buildGui() {
+        final EntityModel model = getModel();
+
+        final List<TabGroup> tabGroups = model.getTabGroupListMetadata();
+
+        final AtomicInteger tabGroupRef = new AtomicInteger(0);
+        final ListView<TabGroup> tabGroupsList =
+                new ListView<TabGroup>(ID_TAB_GROUPS, tabGroups) {
+
+            @Override
+            protected void populateItem(final ListItem<TabGroup> item) {
+
+                final List<ITab> tabs = Lists.newArrayList();
+                final TabGroup tabGroup = item.getModelObject();
+                final List<Tab> tabList = FluentIterable
+                        .from(tabGroup.getTabs())
+                        .filter(Tab.Predicates.notEmpty())
+                        .toList();
+
+                for (final Tab tab : tabList) {
+                    tabs.add(new AbstractTab(Model.of(tab.getName())) {
+                        private static final long serialVersionUID = 1L;
+
+                        @Override
+                        public Panel getPanel(String panelId) {
+                            return new EntityTabPanel(panelId, model, tab);
+                        }
+                    });
+                }
+                final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel = newTabbedPanel(tabs, tabGroupRef.get());
+
+                item.add(ajaxBootstrapTabbedPanel);
+
+                tabGroupRef.incrementAndGet();
+            }
+
+            private AjaxBootstrapTabbedPanel newTabbedPanel(final List<ITab> tabs, final int tabGroupNumber) {
+                final AjaxBootstrapTabbedPanel tabbedPanel = new AjaxBootstrapTabbedPanel(ID_TAB_GROUP, tabs) {
+                    @Override
+                    public TabbedPanel setSelectedTab(final int index) {
+                        saveSelectedTabInSession(tabGroupNumber, index);
+                        return super.setSelectedTab(index);
+                    }
+                };
+                setSelectedTabFromSessionIfAny(tabbedPanel, tabGroupNumber);
+                return tabbedPanel;
+
+            }
+
+            private void setSelectedTabFromSessionIfAny(
+                    final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel,
+                    final int tabGroupNumber) {
+                final String key = buildKey(tabGroupNumber);
+                final String value = (String) getSession().getAttribute(key);
+                if(value != null) {
+                    final int tabIndex = Integer.parseInt(value);
+                    final int numTabs = ajaxBootstrapTabbedPanel.getTabs().size();
+                    if(tabIndex < numTabs) {
+                        // to support dynamic reloading; the data in the session might not be compatible with current layout.
+                        ajaxBootstrapTabbedPanel.setSelectedTab(tabIndex);
+                    }
+                }
+            }
+
+            private void saveSelectedTabInSession(final int tabGroupNumber, final int tabIndex) {
+                final String key = buildKey(tabGroupNumber);
+                getSession().setAttribute(key, "" + tabIndex);
+            }
+
+            private String buildKey(final int tabGroupNumber) {
+                final ObjectAdapterMemento objectAdapterMemento = ListOfTabGroupsPanel.this.getModel().getObjectAdapterMemento();
+                final RootOid oid = (RootOid) objectAdapterMemento.getObjectAdapter(
+                        AdapterManager.ConcurrencyChecking.NO_CHECK).getOid();
+                final String key =
+                        IsisContext.getOidMarshaller().marshalNoVersion(oid) + "." + tabGroupNumber + ".selectedTab";
+                return key;
+            }
+
+        };
+
+        add(tabGroupsList);
+    }
+
+}