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:07:57 UTC

[36/50] [abbrv] isis git commit: ISIS-993: optional left and right columns either side of tab groups; tweaks to CSS; HasPath for all elements of the layout metadata classes (working towards support for persistence of widget state and hints)

ISIS-993: optional left and right columns either side of tab groups; tweaks to CSS; HasPath for all elements of the layout metadata classes (working towards support for persistence of widget state and hints)


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

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

----------------------------------------------------------------------
 .../schema/applib/layout/layout-1.0.xsd         | 38 ++++-----
 .../asciidoc/schema/applib/layout/layout.xsd    | 38 ++++-----
 .../isis/applib/layout/v1_0/ActionHolder.java   | 25 ------
 .../layout/v1_0/ActionLayoutMetadata.java       | 26 +++++-
 .../isis/applib/layout/v1_0/ActionOwner.java    | 25 ++++++
 .../layout/v1_0/CollectionLayoutMetadata.java   | 20 ++++-
 .../apache/isis/applib/layout/v1_0/Column.java  | 27 ++++++-
 .../isis/applib/layout/v1_0/ColumnHolder.java   | 23 ------
 .../isis/applib/layout/v1_0/ColumnOwner.java    | 23 ++++++
 .../apache/isis/applib/layout/v1_0/HasPath.java | 32 ++++++++
 .../layout/v1_0/ObjectLayoutMetadata.java       | 67 +++++++++++----
 .../apache/isis/applib/layout/v1_0/Owned.java   | 23 ++++++
 .../apache/isis/applib/layout/v1_0/Owner.java   | 24 ++++++
 .../isis/applib/layout/v1_0/PropertyGroup.java  | 21 ++++-
 .../layout/v1_0/PropertyLayoutMetadata.java     | 20 ++++-
 .../org/apache/isis/applib/layout/v1_0/Tab.java | 20 ++++-
 .../isis/applib/layout/v1_0/TabGroup.java       | 45 +++++++----
 .../isis/applib/layout/v1_0/TabGroupOwner.java  | 23 ++++++
 .../ObjectLayoutMetadataFacetDefault.java       | 85 +++++++++++++++++---
 .../v1_0/ObjectLayoutMetadataTest.java          |  2 +
 .../properties/EntityPropertiesPanel.html       |  2 +-
 .../entity/tabgroups/EntityTabGroupsPanel.html  | 10 ++-
 .../entity/tabgroups/EntityTabGroupsPanel.java  | 51 ++++++++++--
 .../wicket/ui/pages/bootstrap-overrides.css     | 26 +++++-
 .../dom/simple/SimpleObject.layout.xml          | 30 +++----
 25 files changed, 558 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout-1.0.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout-1.0.xsd b/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout-1.0.xsd
index 7a3e949..9628c78 100644
--- a/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout-1.0.xsd
+++ b/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout-1.0.xsd
@@ -12,7 +12,9 @@
           </xs:sequence>
         </xs:complexType>
       </xs:element>
+      <xs:element name="left" type="tns:column" minOccurs="0"/>
       <xs:element name="tabGroup" type="tns:tabGroup" maxOccurs="unbounded"/>
+      <xs:element name="right" type="tns:column" minOccurs="0"/>
     </xs:sequence>
   </xs:complexType>
 
@@ -32,25 +34,10 @@
     <xs:attribute name="position" type="tns:position"/>
   </xs:complexType>
 
-  <xs:complexType name="tabGroup">
-    <xs:sequence>
-      <xs:element name="tab" type="tns:tab" maxOccurs="unbounded"/>
-    </xs:sequence>
-  </xs:complexType>
-
-  <xs:complexType name="tab">
-    <xs:sequence>
-      <xs:element name="left" type="tns:column"/>
-      <xs:element name="middle" type="tns:column" minOccurs="0"/>
-      <xs:element name="right" type="tns:column" minOccurs="0"/>
-    </xs:sequence>
-    <xs:attribute name="name" type="xs:string" use="required"/>
-  </xs:complexType>
-
   <xs:complexType name="column">
     <xs:sequence>
       <xs:element name="propertyGroup" type="tns:propertyGroup" minOccurs="0" maxOccurs="unbounded"/>
-      <xs:element name="collection" type="tns:collectionLayoutXml" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="collection" type="tns:collectionLayoutMetadata" minOccurs="0" maxOccurs="unbounded"/>
     </xs:sequence>
     <xs:attribute name="span" type="xs:int" use="required"/>
   </xs:complexType>
@@ -92,7 +79,7 @@
     <xs:attribute name="typicalLength" type="xs:int"/>
   </xs:complexType>
 
-  <xs:complexType name="collectionLayoutXml">
+  <xs:complexType name="collectionLayoutMetadata">
     <xs:sequence>
       <xs:element name="named" type="xs:string" minOccurs="0"/>
       <xs:element name="describedAs" type="xs:string" minOccurs="0"/>
@@ -114,6 +101,21 @@
     <xs:attribute name="paged" type="xs:int"/>
   </xs:complexType>
 
+  <xs:complexType name="tabGroup">
+    <xs:sequence>
+      <xs:element name="tab" type="tns:tab" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="tab">
+    <xs:sequence>
+      <xs:element name="left" type="tns:column"/>
+      <xs:element name="middle" type="tns:column" minOccurs="0"/>
+      <xs:element name="right" type="tns:column" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
   <xs:simpleType name="bookmarkPolicy">
     <xs:restriction base="xs:string">
       <xs:enumeration value="AS_ROOT"/>
@@ -162,4 +164,4 @@
       <xs:enumeration value="NONE"/>
     </xs:restriction>
   </xs:simpleType>
-</xs:schema>
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout.xsd b/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout.xsd
index 7a3e949..9628c78 100644
--- a/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout.xsd
+++ b/adocs/documentation/src/main/asciidoc/schema/applib/layout/layout.xsd
@@ -12,7 +12,9 @@
           </xs:sequence>
         </xs:complexType>
       </xs:element>
+      <xs:element name="left" type="tns:column" minOccurs="0"/>
       <xs:element name="tabGroup" type="tns:tabGroup" maxOccurs="unbounded"/>
+      <xs:element name="right" type="tns:column" minOccurs="0"/>
     </xs:sequence>
   </xs:complexType>
 
@@ -32,25 +34,10 @@
     <xs:attribute name="position" type="tns:position"/>
   </xs:complexType>
 
-  <xs:complexType name="tabGroup">
-    <xs:sequence>
-      <xs:element name="tab" type="tns:tab" maxOccurs="unbounded"/>
-    </xs:sequence>
-  </xs:complexType>
-
-  <xs:complexType name="tab">
-    <xs:sequence>
-      <xs:element name="left" type="tns:column"/>
-      <xs:element name="middle" type="tns:column" minOccurs="0"/>
-      <xs:element name="right" type="tns:column" minOccurs="0"/>
-    </xs:sequence>
-    <xs:attribute name="name" type="xs:string" use="required"/>
-  </xs:complexType>
-
   <xs:complexType name="column">
     <xs:sequence>
       <xs:element name="propertyGroup" type="tns:propertyGroup" minOccurs="0" maxOccurs="unbounded"/>
-      <xs:element name="collection" type="tns:collectionLayoutXml" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="collection" type="tns:collectionLayoutMetadata" minOccurs="0" maxOccurs="unbounded"/>
     </xs:sequence>
     <xs:attribute name="span" type="xs:int" use="required"/>
   </xs:complexType>
@@ -92,7 +79,7 @@
     <xs:attribute name="typicalLength" type="xs:int"/>
   </xs:complexType>
 
-  <xs:complexType name="collectionLayoutXml">
+  <xs:complexType name="collectionLayoutMetadata">
     <xs:sequence>
       <xs:element name="named" type="xs:string" minOccurs="0"/>
       <xs:element name="describedAs" type="xs:string" minOccurs="0"/>
@@ -114,6 +101,21 @@
     <xs:attribute name="paged" type="xs:int"/>
   </xs:complexType>
 
+  <xs:complexType name="tabGroup">
+    <xs:sequence>
+      <xs:element name="tab" type="tns:tab" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="tab">
+    <xs:sequence>
+      <xs:element name="left" type="tns:column"/>
+      <xs:element name="middle" type="tns:column" minOccurs="0"/>
+      <xs:element name="right" type="tns:column" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
   <xs:simpleType name="bookmarkPolicy">
     <xs:restriction base="xs:string">
       <xs:enumeration value="AS_ROOT"/>
@@ -162,4 +164,4 @@
       <xs:enumeration value="NONE"/>
     </xs:restriction>
   </xs:simpleType>
-</xs:schema>
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionHolder.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionHolder.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionHolder.java
deleted file mode 100644
index d5a6b37..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionHolder.java
+++ /dev/null
@@ -1,25 +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.applib.layout.v1_0;
-
-import java.util.List;
-
-public interface ActionHolder {
-    List<ActionLayoutMetadata> getActions();
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionLayoutMetadata.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionLayoutMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionLayoutMetadata.java
index bf454d1..5c07ffa 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionLayoutMetadata.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionLayoutMetadata.java
@@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.isis.applib.annotation.BookmarkPolicy;
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Where;
 
 /**
@@ -44,7 +45,7 @@ import org.apache.isis.applib.annotation.Where;
         , "metadataError"
     }
 )
-public class ActionLayoutMetadata implements Serializable {
+public class ActionLayoutMetadata implements Serializable, HasPath, Owned<ActionOwner> {
 
     private static final long serialVersionUID = 1L;
 
@@ -188,7 +189,7 @@ public class ActionLayoutMetadata implements Serializable {
 
 
 
-    private ActionHolder owner;
+    private ActionOwner owner;
     /**
      * Owner.
      *
@@ -197,11 +198,11 @@ public class ActionLayoutMetadata implements Serializable {
      * </p>
      */
     @XmlTransient
-    public ActionHolder getOwner() {
+    public ActionOwner getOwner() {
         return owner;
     }
 
-    public void setOwner(final ActionHolder owner) {
+    public void setOwner(final ActionOwner owner) {
         this.owner = owner;
     }
 
@@ -220,4 +221,21 @@ public class ActionLayoutMetadata implements Serializable {
         this.metadataError = metadataError;
     }
 
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionOwner.java
new file mode 100644
index 0000000..4dde062
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ActionOwner.java
@@ -0,0 +1,25 @@
+/*
+ *  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.applib.layout.v1_0;
+
+import java.util.List;
+
+public interface ActionOwner extends Owner {
+    List<ActionLayoutMetadata> getActions();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/CollectionLayoutMetadata.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/CollectionLayoutMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/CollectionLayoutMetadata.java
index 7aa17f6..e6ce973 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/CollectionLayoutMetadata.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/CollectionLayoutMetadata.java
@@ -29,6 +29,7 @@ import javax.xml.bind.annotation.XmlType;
 
 import com.google.common.base.Function;
 
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Where;
 
 /**
@@ -48,7 +49,7 @@ import org.apache.isis.applib.annotation.Where;
                 , "metadataError"
         }
 )
-public class CollectionLayoutMetadata implements ColumnContent, ActionHolder, Serializable {
+public class CollectionLayoutMetadata implements ColumnContent, ActionOwner, Serializable, HasPath, Owned<Column> {
 
     private static final long serialVersionUID = 1L;
 
@@ -226,6 +227,23 @@ public class CollectionLayoutMetadata implements ColumnContent, ActionHolder, Se
     }
 
 
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
     public static class Functions {
         private Functions(){}
 

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Column.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Column.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Column.java
index fc8ec6d..6ff7527 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Column.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Column.java
@@ -29,6 +29,7 @@ import javax.xml.bind.annotation.XmlType;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.annotation.MemberGroupLayout;
+import org.apache.isis.applib.annotation.Programmatic;
 
 @XmlType(
         propOrder = {
@@ -36,7 +37,7 @@ import org.apache.isis.applib.annotation.MemberGroupLayout;
                 , "collections"
         }
 )
-public class Column implements Serializable {
+public class Column implements Serializable, Owner, Owned<ColumnOwner> {
 
     private static final long serialVersionUID = 1L;
 
@@ -86,7 +87,7 @@ public class Column implements Serializable {
     }
 
 
-    private ColumnHolder owner;
+    private ColumnOwner owner;
     /**
      * Owner.
      *
@@ -95,14 +96,32 @@ public class Column implements Serializable {
      * </p>
      */
     @XmlTransient
-    public ColumnHolder getOwner() {
+    public ColumnOwner getOwner() {
         return owner;
     }
 
-    public void setOwner(final ColumnHolder owner) {
+    public void setOwner(final ColumnOwner owner) {
         this.owner = owner;
     }
 
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
+
     public enum Hint {
         LEFT,
         MIDDLE,

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnHolder.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnHolder.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnHolder.java
deleted file mode 100644
index 8211750..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnHolder.java
+++ /dev/null
@@ -1,23 +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.applib.layout.v1_0;
-
-public interface ColumnHolder {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnOwner.java
new file mode 100644
index 0000000..62f6007
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnOwner.java
@@ -0,0 +1,23 @@
+/*
+ *  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.applib.layout.v1_0;
+
+public interface ColumnOwner extends Owner {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/HasPath.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/HasPath.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/HasPath.java
new file mode 100644
index 0000000..39cdb85
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/HasPath.java
@@ -0,0 +1,32 @@
+/*
+ *  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.applib.layout.v1_0;
+
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface HasPath {
+
+    @Programmatic
+    @XmlTransient
+    String getPath();
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ObjectLayoutMetadata.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ObjectLayoutMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ObjectLayoutMetadata.java
index 727bba2..6cbf901 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ObjectLayoutMetadata.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ObjectLayoutMetadata.java
@@ -19,7 +19,6 @@
 package org.apache.isis.applib.layout.v1_0;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 
@@ -41,10 +40,12 @@ import org.apache.isis.applib.services.dto.Dto;
         name = "objectLayout"
         , propOrder = {
                 "actions"
+                , "left"
                 , "tabGroups"
+                , "right"
         }
 )
-public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
+public class ObjectLayoutMetadata implements Dto, ActionOwner, Serializable, ColumnOwner, HasPath, TabGroupOwner {
 
     private static final long serialVersionUID = 1L;
 
@@ -61,16 +62,23 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
     }
 
 
-    // must have at least one tab group
-    private List<TabGroup> tabGroups = new ArrayList<TabGroup>() {{
-        add(new TabGroup());
-    }};
 
-    // no wrapper
+    private Column left;
 
-    /**
-     * Must have at least one tab group; no wrapper.
-     */
+    @XmlElement(required = false)
+    public Column getLeft() {
+        return left;
+    }
+
+    public void setLeft(final Column left) {
+        this.left = left;
+    }
+
+
+
+    private List<TabGroup> tabGroups;
+
+    // no wrapper
     @XmlElement(name = "tabGroup", required = true)
     public List<TabGroup> getTabGroups() {
         return tabGroups;
@@ -81,6 +89,19 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
     }
 
 
+
+    private Column right;
+
+    @XmlElement(required = false)
+    public Column getRight() {
+        return right;
+    }
+
+    public void setRight(final Column right) {
+        this.right = right;
+    }
+    
+
     public interface Visitor {
         void visit(final ObjectLayoutMetadata objectLayoutMetadata);
         void visit(final TabGroup tabGroup);
@@ -119,6 +140,7 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
     public void visit(final Visitor visitor) {
         visitor.visit(this);
         traverseActions(this, visitor);
+        traverseColumn(getLeft(), this, visitor);
         final List<TabGroup> tabGroups = getTabGroups();
         for (final TabGroup tabGroup : tabGroups) {
             tabGroup.setOwner(this);
@@ -132,13 +154,14 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
                 traverseColumn(tab.getRight(), tab, visitor);
             }
         }
+        traverseColumn(getRight(), this, visitor);
     }
 
-    private void traverseColumn(final Column column, final Tab tab, final Visitor visitor) {
+    private void traverseColumn(final Column column, final ColumnOwner columnOwner, final Visitor visitor) {
         if(column == null) {
             return;
         }
-        column.setOwner(tab);
+        column.setOwner(columnOwner);
         visitor.visit(column);
         traversePropertyGroups(column, visitor);
         traverseCollections(column, visitor);
@@ -166,13 +189,13 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
         }
     }
 
-    private void traverseActions(final ActionHolder actionHolder, final Visitor visitor) {
-        final List<ActionLayoutMetadata> actionLayoutMetadatas = actionHolder.getActions();
+    private void traverseActions(final ActionOwner actionOwner, final Visitor visitor) {
+        final List<ActionLayoutMetadata> actionLayoutMetadatas = actionOwner.getActions();
         if(actionLayoutMetadatas == null) {
             return;
         }
         for (final ActionLayoutMetadata actionLayoutMetadata : actionLayoutMetadatas) {
-            actionLayoutMetadata.setOwner(actionHolder);
+            actionLayoutMetadata.setOwner(actionOwner);
             visitor.visit(actionLayoutMetadata);
         }
     }
@@ -251,6 +274,20 @@ public class ObjectLayoutMetadata implements Dto, ActionHolder, Serializable {
     }
 
 
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
     private boolean normalized;
 
     @Programmatic

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owned.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owned.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owned.java
new file mode 100644
index 0000000..a209293
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owned.java
@@ -0,0 +1,23 @@
+/*
+ *  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.applib.layout.v1_0;
+
+public interface Owned<T extends Owner> {
+    T getOwner();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owner.java
new file mode 100644
index 0000000..7b8940c
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Owner.java
@@ -0,0 +1,24 @@
+/*
+ *  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.applib.layout.v1_0;
+
+public interface Owner extends HasPath {
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyGroup.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyGroup.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyGroup.java
index 2fb52e3..a91deea 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyGroup.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyGroup.java
@@ -32,6 +32,7 @@ import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Programmatic;
 
 @XmlType(
         propOrder = {
@@ -40,7 +41,7 @@ import org.apache.isis.applib.annotation.MemberOrder;
                 , "properties"
         }
 )
-public class PropertyGroup implements ColumnContent, ActionHolder, Serializable {
+public class PropertyGroup implements ColumnContent, ActionOwner, Serializable, HasPath, Owned<Column> {
 
     private static final long serialVersionUID = 1L;
 
@@ -111,6 +112,24 @@ public class PropertyGroup implements ColumnContent, ActionHolder, Serializable
     }
 
 
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
+
     public static class Util {
         private Util(){}
         public static Function<? super PropertyGroup, String> nameOf() {

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyLayoutMetadata.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyLayoutMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyLayoutMetadata.java
index 5f6b3b1..dccf7b8 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyLayoutMetadata.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/PropertyLayoutMetadata.java
@@ -28,6 +28,7 @@ import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.isis.applib.annotation.LabelPosition;
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Where;
 
 /**
@@ -42,7 +43,7 @@ import org.apache.isis.applib.annotation.Where;
                 , "metadataError"
         }
 )
-public class PropertyLayoutMetadata implements ActionHolder, Serializable {
+public class PropertyLayoutMetadata implements ActionOwner, Serializable, HasPath, Owned<PropertyGroup> {
 
     private static final long serialVersionUID = 1L;
 
@@ -224,4 +225,21 @@ public class PropertyLayoutMetadata implements ActionHolder, Serializable {
         this.metadataError = metadataError;
     }
 
+
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Tab.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Tab.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Tab.java
index 4f0a5c3..1a8f652 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Tab.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/Tab.java
@@ -40,7 +40,7 @@ import org.apache.isis.applib.annotation.Programmatic;
                 , "right"
         }
 )
-public class Tab implements ColumnHolder, Serializable {
+public class Tab implements ColumnOwner, Serializable, HasPath, Owned<TabGroup> {
 
     private static final long serialVersionUID = 1L;
 
@@ -123,6 +123,24 @@ public class Tab implements ColumnHolder, Serializable {
         return contents;
     }
 
+
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
     private static void appendContent(final List<ColumnContent> contents, final Column column) {
         if(column == null) {
             return;

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroup.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroup.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroup.java
index 6fb93ee..acb91c3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroup.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroup.java
@@ -29,8 +29,15 @@ import javax.xml.bind.annotation.XmlType;
 import com.google.common.base.Predicate;
 import com.google.common.collect.FluentIterable;
 
-@XmlType()
-public class TabGroup implements ColumnHolder, Serializable {
+import org.apache.isis.applib.annotation.Programmatic;
+
+@XmlType(
+        propOrder = {
+                "tabs"
+        }
+
+)
+public class TabGroup implements ColumnOwner, Serializable, HasPath, Owned<TabGroupOwner> {
 
     private static final long serialVersionUID = 1L;
 
@@ -53,18 +60,7 @@ public class TabGroup implements ColumnHolder, Serializable {
 
 
 
-    private Column fixed;
-
-    @XmlElement(required = false)
-    public Column getFixed() {
-        return fixed;
-    }
-
-    public void setFixed(final Column fixed) {
-        this.fixed = fixed;
-    }
-
-    private ObjectLayoutMetadata owner;
+    private TabGroupOwner owner;
 
     /**
      * Owner.
@@ -74,15 +70,32 @@ public class TabGroup implements ColumnHolder, Serializable {
      * </p>
      */
     @XmlTransient
-    public ObjectLayoutMetadata getOwner() {
+    public TabGroupOwner getOwner() {
         return owner;
     }
 
-    public void setOwner(final ObjectLayoutMetadata owner) {
+    public void setOwner(final TabGroupOwner owner) {
         this.owner = owner;
     }
 
 
+
+
+    private String path;
+
+    @Programmatic
+    @XmlTransient
+    public String getPath() {
+        return path;
+    }
+
+    @Programmatic
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+
+
     public static class Predicates {
         public static Predicate<TabGroup> notEmpty() {
             return new Predicate<TabGroup>() {

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroupOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroupOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroupOwner.java
new file mode 100644
index 0000000..12dc645
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/TabGroupOwner.java
@@ -0,0 +1,23 @@
+/*
+ *  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.applib.layout.v1_0;
+
+public interface TabGroupOwner extends Owner {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutmetadata/ObjectLayoutMetadataFacetDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutmetadata/ObjectLayoutMetadataFacetDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutmetadata/ObjectLayoutMetadataFacetDefault.java
index fdc12ef..6137a53 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutmetadata/ObjectLayoutMetadataFacetDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutmetadata/ObjectLayoutMetadataFacetDefault.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 import com.google.common.base.Strings;
@@ -31,12 +32,13 @@ import com.google.common.collect.Maps;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.applib.layout.v1_0.ActionHolder;
 import org.apache.isis.applib.layout.v1_0.ActionLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.ActionOwner;
 import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.applib.layout.v1_0.Column;
-import org.apache.isis.applib.layout.v1_0.ColumnHolder;
+import org.apache.isis.applib.layout.v1_0.ColumnOwner;
 import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.Owned;
 import org.apache.isis.applib.layout.v1_0.PropertyGroup;
 import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.applib.layout.v1_0.Tab;
@@ -273,6 +275,65 @@ public class ObjectLayoutMetadataFacetDefault
                 actions.add(new ActionLayoutMetadata(actionId));
             }
         }
+
+        // set paths
+        metadata.visit(new ObjectLayoutMetadata.Visitor() {
+
+            private final Map<String,AtomicInteger> sequenceByPath = Maps.newHashMap();
+
+            @Override
+            public void visit(final ObjectLayoutMetadata objectLayoutMetadata) {
+                objectLayoutMetadata.setPath("/layout");
+            }
+
+            @Override
+            public void visit(final TabGroup tabGroup) {
+                tabGroup.setPath(pathFor(tabGroup, "tabGroup"));
+            }
+
+            @Override
+            public void visit(final Tab tab) {
+                tab.setPath(pathFor(tab, "tab"));
+            }
+
+            @Override
+            public void visit(final Column column) {
+                column.setPath(pathFor(column, "column"));
+            }
+
+            @Override
+            public void visit(final PropertyGroup propertyGroup) {
+                propertyGroup.setPath(pathFor(propertyGroup, "propertyGroup"));
+            }
+
+            @Override
+            public void visit(final PropertyLayoutMetadata propertyLayoutMetadata) {
+                propertyLayoutMetadata.setPath(pathFor(propertyLayoutMetadata, "property"));
+            }
+
+            @Override
+            public void visit(final CollectionLayoutMetadata collectionLayoutMetadata) {
+                collectionLayoutMetadata.setPath(pathFor(collectionLayoutMetadata, "collection"));
+            }
+
+            @Override
+            public void visit(final ActionLayoutMetadata actionLayoutMetadata) {
+                actionLayoutMetadata.setPath(pathFor(actionLayoutMetadata, "action"));
+            }
+
+            private String pathFor(final Owned<?> owned, final String type) {
+                final String ownerPath = owned.getOwner().getPath();
+                final String prefix = ownerPath + "/" + type;
+                AtomicInteger atomicInteger = sequenceByPath.get(prefix);
+                if(atomicInteger == null) {
+                    atomicInteger = new AtomicInteger(-1);
+                    sequenceByPath.put(prefix, atomicInteger);
+                }
+                final int seq = atomicInteger.incrementAndGet();
+                return prefix + seq;
+            }
+
+        });
     }
 
     static class Tuple<T> {
@@ -314,7 +375,7 @@ public class ObjectLayoutMetadataFacetDefault
 
             @Override
             public void visit(final ActionLayoutMetadata actionLayoutMetadata) {
-                final ActionHolder actionHolder = actionLayoutMetadata.getOwner();
+                final ActionOwner actionOwner = actionLayoutMetadata.getOwner();
                 final ObjectAction objectAction = objectActionById.get(actionLayoutMetadata.getId());
                 if(objectAction == null) {
                     return;
@@ -322,18 +383,18 @@ public class ObjectLayoutMetadataFacetDefault
 
                 final String memberOrderName;
                 final int memberOrderSequence;
-                if(actionHolder instanceof PropertyGroup) {
-                    final PropertyGroup propertyGroup = (PropertyGroup) actionHolder;
+                if(actionOwner instanceof PropertyGroup) {
+                    final PropertyGroup propertyGroup = (PropertyGroup) actionOwner;
                     final List<PropertyLayoutMetadata> properties = propertyGroup.getProperties();
                     final PropertyLayoutMetadata propertyLayoutMetadata = properties.get(0); // any will do
                     memberOrderName = propertyLayoutMetadata.getId();
                     memberOrderSequence = actionPropertyGroupSequence++;
-                } else if(actionHolder instanceof PropertyLayoutMetadata) {
-                    final PropertyLayoutMetadata propertyLayoutMetadata = (PropertyLayoutMetadata) actionHolder;
+                } else if(actionOwner instanceof PropertyLayoutMetadata) {
+                    final PropertyLayoutMetadata propertyLayoutMetadata = (PropertyLayoutMetadata) actionOwner;
                     memberOrderName = propertyLayoutMetadata.getId();
                     memberOrderSequence = actionPropertySequence++;
-                } else if(actionHolder instanceof CollectionLayoutMetadata) {
-                    final CollectionLayoutMetadata collectionLayoutMetadata = (CollectionLayoutMetadata) actionHolder;
+                } else if(actionOwner instanceof CollectionLayoutMetadata) {
+                    final CollectionLayoutMetadata collectionLayoutMetadata = (CollectionLayoutMetadata) actionOwner;
                     memberOrderName = collectionLayoutMetadata.getId();
                     memberOrderSequence = actionCollectionSequence++;
                 } else {
@@ -345,13 +406,13 @@ public class ObjectLayoutMetadataFacetDefault
                         new MemberOrderFacetXml(memberOrderName, ""+memberOrderSequence, translationService, objectAction));
 
 
-                if(actionHolder instanceof PropertyGroup) {
+                if(actionOwner instanceof PropertyGroup) {
                     if(actionLayoutMetadata.getPosition() == null ||
                             actionLayoutMetadata.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.BELOW ||
                             actionLayoutMetadata.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.RIGHT) {
                         actionLayoutMetadata.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.PANEL);
                     }
-                } else if(actionHolder instanceof PropertyLayoutMetadata) {
+                } else if(actionOwner instanceof PropertyLayoutMetadata) {
                     if(actionLayoutMetadata.getPosition() == null ||
                             actionLayoutMetadata.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.PANEL_DROPDOWN ||
                             actionLayoutMetadata.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.PANEL) {
@@ -421,7 +482,7 @@ public class ObjectLayoutMetadataFacetDefault
 
                 // if there is only a single column and no other contents, then copy the collection Id onto the tab'
                 final Column column = collectionLayoutMetadata.getOwner();
-                final ColumnHolder holder = column.getOwner();
+                final ColumnOwner holder = column.getOwner();
                 if(holder instanceof Tab) {
                     final Tab tab = (Tab) holder;
                     if(tab.getContents().size() == 1 && Strings.isNullOrEmpty(tab.getName()) ) {

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/ObjectLayoutMetadataTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/ObjectLayoutMetadataTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/ObjectLayoutMetadataTest.java
index c5e8c1b..7e72c7a 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/ObjectLayoutMetadataTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/ObjectLayoutMetadataTest.java
@@ -62,6 +62,8 @@ public class ObjectLayoutMetadataTest {
 
         final ObjectLayoutMetadata objectLayoutMetadata = new ObjectLayoutMetadata();
 
+        objectLayoutMetadata.setTabGroups(Lists.<TabGroup>newArrayList());
+        objectLayoutMetadata.getTabGroups().add(new TabGroup());
         TabGroup tabGroup = objectLayoutMetadata.getTabGroups().get(0);
         Tab tab = tabGroup.getTabs().get(0);
         tab.setName("Common");

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesPanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesPanel.html
index 8fbcfb4..e204c12 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesPanel.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesPanel.html
@@ -22,7 +22,7 @@
         <wicket:panel>
             <div class="entityPropertiesPanel entityPropertiesComponentType">
                 <form wicket:id="entityProperties" class="inputForm" role="form">
-                    <div class="row" style="padding-bottom: 20px">
+                    <div class="row">
                         <div wicket:id="leftColumn">
                             <div wicket:id="entityMembers"/>
                             <div class="feedbackPanel">

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/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 4e45e96..f954e5d 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
@@ -23,12 +23,14 @@
 	<div class="entityTabbed">
 		<div wicket:id="entitySummary"></div>
 
-        <div wicket:id="tabGroups">
-            <div class="row">
-                <div wicket:id="tabGroup" class="col-xs-12">[tabbed panel will be here]</div>
-                <div XXXXwicket:id="entityColumnMembers" class = "fixedColumn col-xs-4">
+        <div class="row">
+            <div wicket:id="leftColumn" class = "leftColumn"/>
+            <div wicket:id="tabGroupsContainer" 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="rightColumn" class = "rightColumn"/>
         </div>
 	</div>
 </wicket:panel>

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/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 671ccd1..a729188 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,18 +20,22 @@
 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;
@@ -44,6 +48,7 @@ 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.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
@@ -60,6 +65,8 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
     private static final String ID_ENTITY_PROPERTIES_AND_COLLECTIONS = "entityPropertiesAndCollections";
     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_RIGHT_COLUMN = "rightColumn";
 
     public EntityTabGroupsPanel(final String id, final EntityModel entityModel) {
         super(id, entityModel);
@@ -82,11 +89,13 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
 
         addOrReplace(ComponentType.ENTITY_SUMMARY, model);
 
+        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 int[] tabGroupCount = new int[]{0};
+        final AtomicInteger tabGroupRef = new AtomicInteger(0);
         final ListView<TabGroup> tabGroupsList =
                 new ListView<TabGroup>(ID_TAB_GROUPS, tabGroups) {
 
@@ -110,11 +119,11 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
                         }
                     });
                 }
-                final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel = newTabbedPanel(tabs, tabGroupCount[0]);
+                final AjaxBootstrapTabbedPanel ajaxBootstrapTabbedPanel = newTabbedPanel(tabs, tabGroupRef.get());
 
                 item.add(ajaxBootstrapTabbedPanel);
 
-                tabGroupCount[0]++;
+                tabGroupRef.incrementAndGet();
             }
 
             private AjaxBootstrapTabbedPanel newTabbedPanel(final List<ITab> tabs, final int tabGroupNumber) {
@@ -137,7 +146,11 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
                 final String value = (String) getSession().getAttribute(key);
                 if(value != null) {
                     final int tabIndex = Integer.parseInt(value);
-                    ajaxBootstrapTabbedPanel.setSelectedTab(tabIndex);
+                    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);
+                    }
                 }
             }
 
@@ -157,11 +170,34 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
 
         };
 
-        add(tabGroupsList);
+        final MarkupContainer tabGroupsContainer = new WebMarkupContainer("tabGroupsContainer");
+        add(tabGroupsContainer);
+
+        tabGroupsContainer.add(tabGroupsList);
+
+        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);
 
     }
 
+    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);
+                return span;
+            }
+        }
+        permanentlyHide(id);
+        return 0;
+    }
 
     private static class EntityTabPanel extends PanelAbstract {
         private static final long serialVersionUID = 1L;
@@ -171,7 +207,10 @@ public class EntityTabGroupsPanel extends PanelAbstract<EntityModel> {
 
             final EntityModel modelWithTabHints = model.cloneWithTabMetadata(tab);
 
-            getComponentFactoryRegistry().addOrReplaceComponent(this, ID_ENTITY_PROPERTIES_AND_COLLECTIONS, ComponentType.ENTITY_PROPERTIES, modelWithTabHints);
+            getComponentFactoryRegistry()
+                    .addOrReplaceComponent(this,
+                            ID_ENTITY_PROPERTIES_AND_COLLECTIONS, ComponentType.ENTITY_PROPERTIES, modelWithTabHints);
+
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
index ace0e00..dd192d1 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -724,4 +724,28 @@ tr.headers th form input {
 
 #aboutLink {
     padding-right: 30px;
-}
\ No newline at end of file
+}
+
+/*
+.entityTabbed > .row > .leftColumn,
+.entityTabbed > .row > .rightColumn {
+    margin-top: 41px;
+}
+*/
+
+.tab-content {
+    border-left: 1px solid #ddd;
+    border-right: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    padding-top: 10px;
+    padding-left: 10px;
+    padding-right: 10px;
+}
+
+.nav-tabs {
+    margin-bottom: 0;
+}
+
+.tabGroups > .row {
+    padding-bottom: 10px;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b709b9aa/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
index 1c56232..79bc6a5 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
@@ -3,19 +3,10 @@
     <actions>
         <action id="delete"/>
     </actions>
+    <left span="0">
+    </left>
     <tabGroup>
-        <tab name="Metadata">
-            <left span="6">
-                <propertyGroup name="Persistence">
-                    <actions>
-                        <action id="downloadJdoMetadata"/>
-                        <action id="downloadLayoutXml"/>
-                    </actions>
-                    <property id="versionSequence"/>
-                </propertyGroup>
-            </left>
-        </tab>
-        <tab name="Common">
+        <tab name="General">
             <left span="6">
                 <propertyGroup name="General">
                     <property id="name" labelPosition="TOP">
@@ -24,19 +15,24 @@
                         </actions>
                     </property>
                 </propertyGroup>
-                <collection id="similarTo" defaultView="table"/>
             </left>
             <right span="6">
-                <collection id="others" defaultView="hide"/>
+                <propertyGroup name="Metadata">
+                    <actions>
+                        <action id="downloadJdoMetadata" position="PANEL_DROPDOWN"/>
+                        <action id="downloadLayoutXml" position="PANEL_DROPDOWN"/>
+                    </actions>
+                    <property id="versionSequence"/>
+                </propertyGroup>
             </right>
         </tab>
     </tabGroup>
-<!--
     <tabGroup>
         <tab name="Collections">
-            <left span="6">
+            <left span="12">
+                <collection id="others" defaultView="table"/>
+                <collection id="similarTo" defaultView="hide"/>
             </left>
         </tab>
     </tabGroup>
--->
 </objectLayout>
\ No newline at end of file