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 2014/12/03 08:53:07 UTC

[1/5] isis git commit: ISIS-537: minor CSS tidy up.

Repository: isis
Updated Branches:
  refs/heads/master 3444afc56 -> 8aaa166ff


ISIS-537: minor CSS tidy up.


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

Branch: refs/heads/master
Commit: 992e388a2ba996dfe278d1cdc2d5c330719c6195
Parents: 3444afc
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Dec 3 00:19:10 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Dec 3 00:19:10 2014 +0000

----------------------------------------------------------------------
 .../ui/pages/bootstrap-overrides-flatly.css     | 28 ++++++++++++++++++++
 .../wicket/ui/pages/bootstrap-overrides.css     | 27 +++++++++++++++++--
 2 files changed, 53 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/992e388a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
new file mode 100644
index 0000000..626f843
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+.select2-container.input-sm .select2-choice,
+.input-group-sm .select2-container .select2-choice {
+    height: 33px;
+}
+
+.select2-container.select2-container-disabled .select2-choice,
+.select2-container.select2-container-disabled .select2-choices {
+    background-color: #ecf0f1;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/992e388a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
index b486641..09e1cea 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -600,8 +600,8 @@ div.label-left .choicesPlaceholder {
 }
 
 
-.modal-body textarea {
-    resize: none;
+.scalarValueWrapper textarea {
+    resize: vertical;
 }
 
 
@@ -649,3 +649,26 @@ div.label-left .choicesPlaceholder {
     display: inline-block;
     margin-left: 5px;
 }
+
+
+.scalarValueWrapper ul.additionalLinkList {
+    padding-bottom: 5px;
+}
+
+.scalarValueWrapper ul.additionalLinkListInline li.additionalLinkItem {
+    padding-bottom: 5px;
+}
+
+.scalarValueWrapper .help-block {
+    margin-bottom: 5px;
+}
+
+.scalarValueWrapper .help-block ul {
+    margin-bottom: 0px;
+}
+
+.scalarValueWrapper .help-block .alert {
+    margin-bottom: 0px;
+}
+
+


[2/5] isis git commit: ISIS-963: primary, secondary and tertiary menu support.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
new file mode 100644
index 0000000..c9bb75f
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/AjaxDeferredBehaviour.java
@@ -0,0 +1,84 @@
+/*
+ *  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.widgets.linkandlabel;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.behavior.AbstractAjaxBehavior;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.UrlRenderer;
+import org.apache.wicket.request.cycle.RequestCycle;
+
+import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseHandlingStrategy;
+
+public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
+    private static final long serialVersionUID = 1L;
+
+    public static enum OpenUrlStrategy {
+        NEW_WINDOW {
+            @Override
+            public String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
+                final Url parsedUrl = Url.parse(url);
+                final RequestCycle requestCycle = deferredBehaviour.getComponent().getRequestCycle();
+                final UrlRenderer urlRenderer = requestCycle.getUrlRenderer();
+                String fullUrl = urlRenderer.renderFullUrl(parsedUrl);
+                return "function(){Wicket.Event.publish(Isis.Topic.OPEN_IN_NEW_TAB, '" + fullUrl + "');}";
+            }
+        },
+        SAME_WINDOW {
+            @Override
+            public String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
+                return "\"window.location.href='" + url + "'\"";
+            }
+        };
+
+        public abstract String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url);
+    }
+    
+    private final OpenUrlStrategy openUrlStrategy;
+    
+    protected AjaxDeferredBehaviour(final OpenUrlStrategy openUrlStrategy) {
+        this.openUrlStrategy = openUrlStrategy;
+    }
+
+    /**
+     * Call this method to initiate the download.
+     */
+    public void initiate(AjaxRequestTarget target) {
+        String url = getCallbackUrl().toString();
+
+        url = ActionResultResponseHandlingStrategy.expanded(url);
+        String func = openUrlStrategy.javascriptFor(this, url);
+
+        // the timeout is needed to let Wicket release the channel
+        String javascriptFor = "setTimeout(" + func + ", 100);";
+        target.appendJavaScript(javascriptFor);
+    }
+
+    @Override
+    public void onRequest() {
+        IRequestHandler handler = getRequestHandler();
+        if(handler != null) {
+            getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
+        }
+    }
+
+    protected abstract IRequestHandler getRequestHandler();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/valuechoices/ValueChoicesSelect2Panel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/valuechoices/ValueChoicesSelect2Panel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/valuechoices/ValueChoicesSelect2Panel.java
index 2f6b442..f5b3b17 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/valuechoices/ValueChoicesSelect2Panel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/valuechoices/ValueChoicesSelect2Panel.java
@@ -37,7 +37,7 @@ import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.ObjectAdapterMementoProviderAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract-old.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract-old.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract-old.css
deleted file mode 100644
index b7e215e..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract-old.css
+++ /dev/null
@@ -1,962 +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.
- */
- 
- 
-/*
-TODO mgrigorov: Remove this file once the new styling based on Bootstrap is finished
-
-
-colors
-------
-
-#E4E4DB - page background
-
-#00477F   rich blue
-          h1,h2,h3 {color}
-          a {color}
-
-#20B5C2 - light blue
-          .ok {background-color}
-          .links{color}
-
-#40C0CB - highlight blue
-          .a:hover {background-color}
-
-#F0EFEA   light (bookmark background)
-          .select2-choice {background-color}
-
-#407098   muted blue
-          th {color}
-
-
-#454545   dark brown/grey
-          body {color}
-
-#413D37   dark brown/banner
-          legend {color}
-
-#E4E4DB   very pale beige
-.cancel {background-color}
-
-#46423C   dark brown
-          .cancel {color}
-
-#888      medium grey
-          p.disabled {color}
-
-#F0EFEA   very light grey
-          p.disabled {background-color}
-
-#E3E3D9   light grey
-          body {background-color}
-
-
-#BF0B0B - jgrowl error
-
-
-
-#46413B   dark brown
-          .scalarName {color}
-
-#7F7F7F   (medium grey)
-          .select2-choice {color}
-
-#46423C - dark (writing?)
-
-
-#CCCBC7   (medium)
-          input[disabled]  {border-top}
-
-#EEEEEE   light grey
-          th{background}
-
-#FFFFFF   white
-          .ok {color}
-
-*/
- 
-/********** ID's **********/
-
-#header {
-	width: 73%;
-	float: left;
-	height: 60px;
-	margin-left: 5px;
-	background: transparent url("images/logo.png") left center no-repeat;
-}
-
-#header .applicationName {
-	display:none;
-}
-.headerContainer {
-	background: url("images/bg_header_brown.png") left top repeat;
-	height: 100px;
-}
-
-.headerContainer .links>span:first-child {
-	background: url("/images/icon_appuser.png") no-repeat scroll left
-		center transparent;
-	line-height: 30px;
-	padding: 5px 0 5px 20px;
-	margin-left: 10px;
-}
-
-.headerContainer .links {
-	font-size: 0.9em;
-}
-
-.headerContainer .links a {
-	margin-left: 10px;
-}
-
-#secondaryMenu {
-    width: 25%;
-}
-
-#tertiaryMenu {
-    width: 3%;
-    float: right;
-    padding-right: 20px;
-}
-#breadcrumbsMenu {
-    width: 18%;
-    float: right;
-}
-#tertiaryMenu .imgLinks {
-	line-height: 30px;
-	font-size: 3em;
-	margin-right:20px;
-}
-
-#tertiaryMenu  a.copyLink:hover,
-#tertiaryMenu  a.copyLink.hover {
-    cursor: pointer;
-}
-
-#tertiaryMenu  a.copyLink:active,
-#tertiaryMenu  a.copyLink.active {
-    cursor: pointer;
-}
-
-
-#secondaryMenu,
-#tertiaryMenu {
-	display: inline-block;
-	float: right;
-	text-align: right;
-    margin-right: 5px;
-}
-
-#tertiaryMenu a {
-	font-size:3em;
-	line-height: 30px;
-}
-
-#header h1 {
-	margin: 10px 10px 10px 0px;
-	font-size: xx-large;
-}
-
-.clear {
-	clear: both; 
-}
-
-.links {
-	clear: both;
-	height: 60px;
-	line-height:60px;
-	color:#20B5C2;
-	text-transform: uppercase;
-	font-size:1.0em;
-    font-weight:bold;
-    padding:0px 20px 0px 0px;
-}
-
-	.links a {
-		color:#FFFFFF;
-    	font-weight:bold;
-	}
-	
-		
-#container {
-	/*width: 800px;*/
-}
-
-
-/* Buttons */
-
-.edit,
-.ok,
-.okButton {
-	display:inline-block;
-	background-color:#20B5C2;
-	color:#FFFFFF;
-	text-transform:uppercase;
-	font-size:0.9em;
-	border:0px;
-	padding:5px 10px;
-	border-radius:4px;
-	cursor:pointer;
-}
-
-.edit:focus,
-.ok:focus,
-.okButton:focus {
-	background-color: #40C0CB;
-	font-style: italic;
-}
-
-.cancel {
-	display:inline-block;
-	background-color:#E4E4DB;
-	color:#46423C;
-	text-transform:uppercase;
-	font-size:0.9em;
-	border:0px;
-	padding:5px 10px;
-	border-radius:4px;
-	cursor:pointer;	
-}
-
-.cancel:focus {
-    font-style: italic;
-}
-
-
-/********** CLASSes **********/
-
-.feedbackPanel li {
-	list-style: none;	
-}
-
-.leftSide {
-	float: left;
-	width: 220px;
-	height: 500px;
-}
-
-.rightSide {
-	float: right;
-	width: 520px;
-}
-
-/**************** APPLICATION MENU **************/
-
-#applicationActions {
-    padding-left: 10px;
-    height:40px;
-    margin-left: 10px;
-    width: 73%;
-    float: left;
-}
-
-#applicationActions .menuh {
-	background-color: transparent;
-	position:relative;
-	z-index:501;
-}
-
-#applicationActions .menuh ul.cssMenuItems {
-	line-height:30px;
-}
-
-#applicationActions .cssMenuPanel .menuh a:link, 
-#applicationActions .cssMenuPanel .menuh a:visited, 
-#applicationActions .cssMenuPanel .menuh a:active, 
-#applicationActions .cssMenuPanel .menuh p {
-	background-color: transparent;
-   	color: #FFFFFF;
-   	text-decoration: none;
-   	text-transform:uppercase;
-   	font-size:0.9em;
-   	font-weight:bold;
-}
-
-#applicationActions .cssMenuPanel .menuh a.prototype span {
-    color: #DBDB4D;
-    font-style: italic;
-}
-
-
-#applicationActions .cssMenuPanel .menuh li a:link, 
-#applicationActions .cssMenuPanel .menuh li a:visited, 
-#applicationActions .cssMenuPanel .menuh li a:active, 
-#applicationActions .cssMenuPanel .menuh li p {
-	border-radius:4px 4px 0px 0px;
-   	-moz-border-radius:4px 4px 0px 0px;
-   	-webkit-border-radius:4px 4px 0px 0px;
-}
-
-#applicationActions .cssMenuPanel .menuh li li a:link, 
-#applicationActions .cssMenuPanel .menuh li li a:visited, 
-#applicationActions .cssMenuPanel .menuh li li a:active, 
-#applicationActions .cssMenuPanel .menuh li li p {
-	border-radius:0px;
-   	-moz-border-radius:0px;
-   	-webkit-border-radius:0px;
-	background-color: #20B5C2;
-}
-
-#applicationActions .cssMenuPanel .menuh li li:last-child a:link, 
-#applicationActions .cssMenuPanel .menuh li li:last-child a:visited, 
-#applicationActions .cssMenuPanel .menuh li li:last-child a:active, 
-#applicationActions .cssMenuPanel .menuh li li:last-child p {
-	border-radius:0px 0px 4px 4px;
-	-webkit-border-radius:0px 0px 4px 4px;
-	-moz-border-radius:0px 0px 4px 4px;
-	background-color: #20B5C2;
-}
-
-#applicationActions .cssMenuPanel .menuh li li:first-child a:link, 
-#applicationActions .cssMenuPanel .menuh li li:first-child a:visited, 
-#applicationActions .cssMenuPanel .menuh li li:first-child a:active, 
-#applicationActions .cssMenuPanel .menuh li li:first-child p {
-	border-radius:0px 4px 0px 0px;
-	-webkit-border-radius:0px 4px 0px 0px;
-	-moz-border-radius:0px 4px 0px 0px;
-	background-color: #20B5C2;
-}
-
-#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:link, 
-#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:visited, 
-#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:active, 
-#applicationActions .cssMenuPanel .menuh li li:first-child:last-child p {
-	border-radius:0px 4px 4px 4px;
-	-webkit-border-radius:0px 4px 4px 4px;
-	-moz-border-radius:0px 4px 4px 4px;
-	background-color: #20B5C2;
-}
-
-
-#applicationActions .menuh a, 
-#applicationActions .menuh p {
-    border: 0px solid #00477F;
-    padding: 0px 1em 0px 1em;
-    background-image:none !important;
-}
-
-#applicationActions .cssMenuPanel .menuh li:hover a, 
-#applicationActions .cssMenuPanel .menuh li:hover p {
-	color: #FFFFFF;
-	background-color: #20B5C2;
-}
-
-#applicationActions .cssMenuPanel .menuh a:hover, 
-#applicationActions .cssMenuPanel .menuh p:hover {
-	color: #FFFFFF;
-	background-color: #20B5C2;
-}
-
-#applicationActions .cssMenuPanel .menuh li li a:hover, 
-#applicationActions .cssMenuPanel .menuh li li p:hover {
-	color: #FFFFFF;
-	background-color: #40C0CB !important;
-}
-
-#applicationActions ul.cssSubMenuItemsPanel {
-	min-width:220px;
-}
-
-   #applicationActions ul.cssSubMenuItemsPanel li.cssSubMenuItem p.disabled {
-       color: lightgray;
-       /*background-color: #F0EFEA;*/
-       
-   } 
-
-
-/**************** ELEMENTS **************/
-
-body {
-	background-color: #E3E3D9;
-	color: #454545;
-	font-family: Arial,'Sans-serif',  'Helvetica', 'Sans-serif', 'sans';
-	font-size: 0.8em;
-	line-height: 1.4em;
-	padding: 0px;
-	margin:0px;
-}
-
-.panel, fieldset {
-	margin: 3px 0px;
-}
-
-.scalarNameAndValueComponentType .panel {
-	padding: 4px;
-}
-
-
-div {
-	margin: 0;
-	padding: 0;
-}
-
-#body {
-	min-height: 400px;
-	margin:20px;
-}
-
-#footer {
-}
-
-	#footer .links {
-		height:auto;
-		padding:0px 20px;
-		line-height:20px;
-		height:20px;
-		color:#46423C;
-	}
-	
-	#footer .links a {
-		color:#20B5C2;
-		text-decoration:none;
-	}
-
-h3 {
-	margin-top: 9px;
-	margin-bottom: 0px;
-}
-
-p {
-	margin-top: 0px;
-	margin-bottom: 0px;
-}
-
-form fieldset .okButton {
-	margin-top: 2em;
-}
-
-.myBlockContainer {
-	background-color:#FFFFFF;
-	padding:10px;
-	border-radius:4px;
-	-moz-border-radius:4px;
-	-webkit-border-radius:4px;
-	margin-bottom:1%;
-	position:relative;
-	clear:both;
-}
-
-.myBlockContainer fieldset {
-	border:0px;
-	margin:0px;
-	padding:0px;
-}
-.myBlockContainer fieldset:not(:first-child) {
-    margin-top: 30px
-}
-
-
-.myBlockContainer legend {
-	color:#423D37;
-	font-size:1.6em;
-	margin-bottom:10px;
-	line-height:120%;
-	padding:0px;
-	float:left;
-	display:block;
-}
-
-
-/************************************************************ *********/
-
-
-
-h1,h2,h3,h4,h5,h6,h7,h8 {
-	color: #00477F;
-	font-weight: normal;
-}
-
-h1,h2 {
-	letter-spacing: -1px;
-}
-
-#extitle {
-	font-size: 12pt;
-	font-weight: bold;
-	color: #454545;
-	padding: 10px 10px 10px 10px;
-}
-
-.mark {
-	background-color: yellow;
-	margin: 5px;	
-}
-
-.nospam {
-	display : none;
-}
-
-.block {
-	padding: 10px;
-}
-
-
-h2 {
-	font-size: 1.25em;
-}
-
-h3 {
-	font-size: 1em;
-}
-
-a {
-	color: #00477F;
-	font-weight: bold;
-	text-decoration: none;
-}
-
-a:hover {
-	text-decoration: underline;
-	cursor: pointer;
-}
-
-img {
-	border: none;
-}
-
-pre {
-	font-family: 'Lucida Sans', 'Helvetica', 'Sans serif', 'sans';
-}
-
-th {
-	background: #EEEEEE;
-	color: #407098;
-	font-weight: bold;
-}
-
-tr.b {
-	background: #EEEEEE;
-}
-
-tr.a {
-	background: #E6E6E5;
-}
-
-tr.none {
-	background: transparent;
-}
-
-a.none {
-	background: transparent;
-	padding-right: 0px;
-}
-
-.inputForm label.non {
-	display: inline !important;
-}
-
-.inputFormTable td {
-	padding: 2px;
-}
-
-div.tabRowContent {
-	border-style: solid;
-	border-width: 1px;
-	margin: 4px;
-	padding: 4px;
-}
-
-tr.section td {
-	padding-top: 0.75em;
-}
-
-table.contents td,
-table.contents th {
-	border-left: 1px solid #DDD;
-	border-right: 1px solid #DDD;
-}
-
-/*************** Styling Entity Forms and Parameters ********************/
-
-
-
-
-.property, .propertyOrCollection, .parameter {
-	clear: both;
-}
-
-.scalarNameAndValueComponentType {
-}
-
-.scalarName {
-	padding:6px 0px;
-	margin-bottom:5px;
-}
-
-
-
-.scalarValue {
-	margin-bottom:10px;
-}
-
-.collectionName, 
-.collectionContents {
-
-}
-
-.scalarName, .collectionName {
-	float: left;
-	font-style: normal;
-	text-align: left;
-	text-transform:uppercase;
-	font-weight:bold !important;
-	font-size:0.9em;
-	color:#46413B;
-}
-
-.mandatory .scalarName:after, 
-.mandatory  .collectionName:after {
-	content: " *";
-	font-weight:bold;
-	color:#20B5C2;
-}
-
-.scalarValue,.collectionContents  {
-	float: left;
-}
-
-.scalarValue  {
-}
-
-.collectionContents {
-	width: 100%;
-}
-
-.scalarName {
-	width: 160px;
-}
-.scalarValue {
-}
-
-div.scalarPanel {
-	display: inline;
-}
-	
-.buttons {
-	padding: 1em 0em 1em 0em;
-	clear: both;
-	display: block;
-}	
-
-.mandatory {
-	font-weight: bold;
-}
-
-.number input {
- 	text-align: right;
-}
-
-
-
-/********************* Select2 component styling *****************************/
-
-
-.actionPromptPage .select2-container .select2-choice,
-.entityPage       .select2-container .select2-choice {
-    padding: 4px;
-}
-
-
-
-.actionPromptPage .select2-container .select2-choice,
-.entityPage       .select2-container .select2-choice {
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-	height: 20px;
-    line-height: 20px;
-	color:#7F7F7F;
-	background:#FFFFFF none;
-	border:1px solid #F0EFEA;
-	border-top:1px solid #CCCBC7;
-}
-
-.actionPromptPage .select2-container .select2-choice span,
-.entityPage       .select2-container .select2-choice span {
-    font-size:13px;
-}
-
-.actionPromptPage .select2-container.select2-drop-above .select2-choice,
-.entityPage       .select2-container.select2-drop-above .select2-choice {
-    -webkit-border-radius:0px;
-    -moz-border-radius:0px;
-    border-radius:0px;
-}
-
-.actionPromptPage .select2-drop,
-.entityPage       .select2-drop {
-    -webkit-border-radius:0px;
-    -moz-border-radius:0px;
-    border-radius:0px;
-}
-
-.actionPromptPage .select2-drop.select2-drop-above,
-.entityPage       .select2-drop.select2-drop-above {
-    -webkit-border-radius:0px;
-    -moz-border-radius:0px;
-    border-radius:0px;
-}
-
-.actionPromptPage .select2-container .select2-choice div,
-.entityPage       .select2-container .select2-choice div {
-    -webkit-border-radius:0px;
-    -moz-border-radius:0px;
-    border-radius:0px;
-    background: #EBEBE4;
-}
-
-.actionPromptPage .select2-container.select2-container-disabled .select2-choice,
-.entityPage       .select2-container.select2-container-disabled .select2-choice {
-	background-color:#F0EFEA;
-	border:1px solid #F0EFEA;
-	border-top:1px solid #CCCBC7;
-}
-
-.actionPromptPage .select2-container a,
-.entityPage       .select2-container a {
-	font-weight: normal;
-}
-
-/******** fix for select2 on ModalWindow ********/
-/* http://osdir.com/ml/users-wicket.apache.org/2013-09/msg00165.html */
-
-div.select2-drop {
-	z-index: 30001
-}
-
-.select2-drop-mask {
-    z-index: 30000
-}
-
-
-/******** action prompt modal dialog ********/
-
-
-.wicket-modal .w_content_container {
-  background-color: #E4E4DB;
-}
-
-.actionPanel {
-    width: 680px;
-}
-
-.actionPanel .myBlockContainer {
-    margin:19px;
-    padding: 20px;
-    width: 600px;
-    min-height: 200px;
-}
-
-.wicket-modal .w_caption {
-	display: none;
-}
-
-div.wicket-modal div.w_content_3 {
-	border: 0px;
-}
-
-div.wicket-modal div.w_content_3,
-div.wicket-modal div.w_content_2,
-div.wicket-modal div.w_content_1,
-div.wicket-modal div.w_content,
-.wicket-modal .w_content_container,
-.w_isis,
-.actionPanel {
-  border-radius:4px;
-  -moz-border-radius:4px;
-  -webkit-border-radius:4px;
-}
-
-/******** FORM STYLES ********/
-
-form input[type=text][disabled] {
-	border-radius:4px;
-	-moz-border-radius:4px;
-	-webkit-border-radius:4px;
-	padding:6px;
-	background-color:#F0EFEA;
-	border:1px solid #F0EFEA;
-	border-top:1px solid #CCCBC7;
-}
-
-form input[type=text] {
-	border-radius:4px;
-	-moz-border-radius:4px;
-	-webkit-border-radius:4px;
-	padding:6px;
-	background-color:#FFFFFF;
-	border:1px solid #F0EFEA;
-	border-top:1px solid #CCCBC7;
-}
-
-
-
-.inputForm {
-	clear:both;
-}
-
-.actionPanelHeaderNew {
-	clear:both;
-	display:block;
-}
-
-.actionPanelHeaderNew .entityIconAndTitlePanel {
-	padding-bottom:10px;
-	line-height:150%;
-	float:left;
-}
-
-div.actionPanelHeaderNew .iconAndTitle {
-	float: left;
-    padding:0em;
-}
-
-div.actionPanelHeaderNew .actions {
-	float: right;
-    padding:0em 0em;
-}
-
-.actionPanelHeaderNew .entityImage {
-	width: 32px;
-	height: 32px;
-	vertical-align:text-bottom;
-	padding-right:5px;
-}
-
-.actionPanelHeaderNew .entityTitle  {
-	font-size: 1.8em;
-	font-weight:normal;
-	color:#413D37;
-	text-decoration:none;
-}
-
-/* Feedback Error Styling */
-
-.feedbackPanel {
-	clear:both;
-	display:block;
-	color:#990000;
-	font-weight:normal;
-	font-size:12px;
-	line-height:150%;
-}
-
-
-.feedbackPanelERROR {
-	color:#CC0000;
-	list-style: none;
-	font-weight: normal;
-}
-
-.feedbackPanelINFO {
-	color: green;
-	list-style: none;
-	font-weight: normal;
-}
-
-
-
-div#jGrowl {
- margin-top: 55px;
- margin-right: 25px;
- color: white;
- font-size: larger;
- opacity: .90;
- filter: alpha(opacity = 90);
-}
-
-div#jGrowl div.jgrowl-ERROR {
- background-color: #BF0B0B;
-}
-div#jGrowl div.jgrowl-WARNING {
- background-color: orange;
-}
-div#jGrowl div.jgrowl-INFO {
- background-color: #20B5C2;
-}
-div#jGrowl div.jgrowl-WARNING {
- background-color: orange;
-}
-div#jGrowl div.jGrowl-closer {
- background-color: #F0EFEA;
- color: #46423C;
- font-size: small;
-}
-
-
-
-
-/* ModalWindow tweaks */
-
-div.wicket-mask-dark {  
-    filter: alpha(opacity=40);
-    opacity: 0.4; 
-}
-
-
-/* action buttons in properties */
-
-.properties .property .additionalLinkList {
-    float:none;
-    padding-top: 5px;
-    padding-bottom: 20px;
-}
-
-.properties .property .isisBlobPanel .additionalLinkList {
-    padding-top: 0px;
-}
-
-
-
-/** general **/
-
-.hidden {
-	display: none;
-}
-
-
-
-
-/**
-zero clipboard
-(for some reason - perhaps to do with Flash - this CSS doesn't seem to 
- do anything if within the ZeroClipboard.css)
-*/
-.zeroClipboardPanel a {
-    background-image: url("copy-26.png"); 
-    background-position: right;
-    background-repeat: no-repeat;
-    cursor: pointer;
-}
-
-
-/**
-for some reason the containedToggleboxPanel.css is not being picked up...
-*/
-.containedToggleboxPanel .containedToggleboxPanelForm {
-    display: inline;
-}
-
-
-
-
-.collectionContentsAsAjaxTablePanel table.contents tbody td div.FixtureResult-className label,
-.collectionContentsAsAjaxTablePanel table.contents tbody td div.FixtureResult-fixtureScriptClassName label {
-    text-transform: none;
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
deleted file mode 100644
index 60c8e2c..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
+++ /dev/null
@@ -1,20 +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.
- */
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
index 5cd3c10..400cca7 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
@@ -50,16 +50,16 @@
                                     <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                         <i class="fa fa-fw fa-user"></i> <span wicket:id="userName"></span><span class="caret"></span>
                                     </a>
-                                    <ul class="dropdown-menu" role="menu" style="min-width: 0px;">
-                                        <li class="navbar-right">
-                                            <a wicket:id="logoutLink"><i class="fa fa-fw fa-sign-out"></i><wicket:message key="logoutLabel"></wicket:message></a>
-                                        </li>
+                                    <ul wicket:id="tertiaryMenuBar" class="dropdown-menu" role="menu" style="min-width: 0px;">
                                     </ul>
                                 </li>
                             </ul>
                         </div>
+                        <div class="navbar-collapse app-actions collapse navbar-right">
+                            <ul class="nav navbar-nav" wicket:id="secondaryMenuBar"></ul>
+                        </div>
                         <div class="navbar-collapse app-actions collapse">
-                            <ul class="nav navbar-nav" wicket:id="applicationActions"></ul>
+                            <ul class="nav navbar-nav" wicket:id="primaryMenuBar"></ul>
                         </div>
                     </div>
                 </header>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
index 0d7b129..424b23f 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
@@ -47,7 +47,6 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
@@ -61,6 +60,7 @@ import org.apache.wicket.request.resource.PackageResource;
 import org.apache.wicket.request.resource.ResourceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -74,11 +74,11 @@ import org.apache.isis.viewer.wicket.model.hints.IsisEnvelopeEvent;
 import org.apache.isis.viewer.wicket.model.hints.IsisEventLetterAbstract;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
-import org.apache.isis.viewer.wicket.model.models.ApplicationActionsModel;
 import org.apache.isis.viewer.wicket.model.models.BookmarkableModel;
 import org.apache.isis.viewer.wicket.model.models.BookmarkedPagesModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.PageType;
+import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
@@ -89,7 +89,6 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.themepicker.ThemeChoo
 import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 import org.apache.isis.viewer.wicket.ui.pages.about.AboutPage;
-import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
 /**
@@ -156,6 +155,15 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
     @Inject
     private PageClassRegistry pageClassRegistry;
 
+    /**
+     * Top-level &lt;div&gt; to which all content is added.
+     *
+     * <p>
+     *     Has <code>protected</code> visibility so that subclasses can also add directly to this div.
+     * </p>
+     */
+    protected MarkupContainer themeDiv;
+
     public PageAbstract(
             final PageParameters pageParameters,
             final String title,
@@ -172,14 +180,15 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
                 themeDiv.add(new CssClassAppender(CssClassAppender.asCssStyle(applicationName)));
             }
 
-            addApplicationActions(themeDiv);
+            addActionPromptModalWindow(themeDiv);
+            addServiceActionMenuBars(themeDiv);
 
             this.childComponentIds = Collections.unmodifiableList(Arrays.asList(childComponentIds));
             this.pageParameters = pageParameters;
 
             addApplicationName(themeDiv);
             addUserName(themeDiv);
-            addLogoutLink(themeDiv);
+            //addLogoutLink(themeDiv);
             addAboutLink(themeDiv);
 
             addBreadcrumbs();
@@ -237,7 +246,6 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         response.render(CssHeaderItem.forReference(FontAwesomeCssReference.instance()));
         response.render(CssHeaderItem.forReference(new BootstrapOverridesCssResourceReference()));
         contributeThemeSpecificOverrides(response);
-        PanelUtil.renderHead(response, PageAbstract.class);
 
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_LIVEQUERY_JS));
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_ISIS_WICKET_VIEWER_JS));
@@ -282,17 +290,6 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         themeDiv.add(userName);
     }
 
-    private void addLogoutLink(MarkupContainer themeDiv) {
-        Link logoutLink = new Link("logoutLink") {
-
-            @Override
-            public void onClick() {
-                getSession().invalidate();
-                setResponsePage(getSignInPage());
-            }
-        };
-        themeDiv.add(logoutLink);
-    }
 
     private void addAboutLink(MarkupContainer themeDiv) {
         BookmarkablePageLink<Void> aboutLink = new BookmarkablePageLink<>("aboutLink", AboutPage.class);
@@ -335,11 +332,15 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         return pageParameters;
     }
 
-    private void addApplicationActions(MarkupContainer container) {
-        addActionPromptModalWindow();
-        final ApplicationActionsModel model = new ApplicationActionsModel();
-        model.setActionPromptProvider(this);
-        addComponent(container, ComponentType.APPLICATION_ACTIONS, model);
+    private void addServiceActionMenuBars(MarkupContainer container) {
+        addMenuBar(container, "primaryMenuBar", DomainService.MenuBar.PRIMARY);
+        addMenuBar(container, "secondaryMenuBar", DomainService.MenuBar.SECONDARY);
+        addMenuBar(container, "tertiaryMenuBar", DomainService.MenuBar.TERTIARY);
+    }
+
+    private void addMenuBar(MarkupContainer container, String id, DomainService.MenuBar menuBar) {
+        final ServiceActionsModel model = new ServiceActionsModel(menuBar);
+        getComponentFactoryRegistry().addOrReplaceComponent(container, id, ComponentType.SERVICE_ACTIONS, model);
     }
 
     /**
@@ -395,12 +396,11 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
     
     private ActionPromptModalWindow actionPromptModalWindow;
 
-    protected MarkupContainer themeDiv;
     public ActionPrompt getActionPrompt() {
         return ActionPromptModalWindow.getActionPromptModalWindowIfEnabled(actionPromptModalWindow);
     }
 
-    private void addActionPromptModalWindow() {
+    private void addActionPromptModalWindow(final MarkupContainer themeDiv) {
         actionPromptModalWindow = ActionPromptModalWindow.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW); 
         themeDiv.addOrReplace(actionPromptModalWindow);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
index 064910a..670361f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
@@ -33,12 +33,23 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.RUNTIME)
 public @interface DomainService {
 
+    public enum MenuBar {
+        PRIMARY,
+        SECONDARY,
+        TERTIARY
+    }
+
     /**
      * If this domain service acts as a repository for an entity type, specify that entity type.
      */
     Class<?> repositoryFor() default Object.class;
 
     /**
+     * The menubar in which the menu that hold's this service's actions should reside.
+     */
+    MenuBar menuBar() default MenuBar.PRIMARY;
+
+    /**
      * Number in Dewey Decimal format representing the order.
      *
      * <p>
@@ -47,4 +58,5 @@ public @interface DomainService {
      */
     String menuOrder() default "" + Integer.MAX_VALUE;
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
index 73ca140..250aba4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice;
 
 
+import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 
 
@@ -28,6 +29,11 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 public interface DomainServiceFacet extends Facet {
 
     /**
+     * Corresponds to {@link org.apache.isis.applib.annotation.DomainService#menuBar()}.
+     */
+    public DomainService.MenuBar getMenuBar();
+
+    /**
      * Corresponds to {@link org.apache.isis.applib.annotation.DomainService#menuOrder()}.
      *
      * <p>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
index e39bb3b..d1aa190 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice;
 
 
+import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -32,15 +33,21 @@ public abstract class DomainServiceFacetAbstract
         return DomainServiceFacet.class;
     }
 
+    private final DomainService.MenuBar menuBar;
     private final String menuOrder;
     private final Class<?> repositoryFor;
 
-    public DomainServiceFacetAbstract(final FacetHolder facetHolder, final String menuOrder, final Class<?> repositoryFor) {
+    public DomainServiceFacetAbstract(final FacetHolder facetHolder, final DomainService.MenuBar menuBar, final String menuOrder, final Class<?> repositoryFor) {
         super(DomainServiceFacetAbstract.type(), facetHolder, Derivation.NOT_DERIVED);
+        this.menuBar = menuBar;
         this.menuOrder = menuOrder;
         this.repositoryFor = repositoryFor;
     }
 
+    public DomainService.MenuBar getMenuBar() {
+        return menuBar;
+    }
+
     public String getMenuOrder() {
         return menuOrder;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
index 460b5cd..9448bf8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
@@ -19,13 +19,18 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice.annotation;
 
 
+import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacetAbstract;
 
 
 public class DomainServiceFacetAnnotation extends DomainServiceFacetAbstract {
 
-    public DomainServiceFacetAnnotation(FacetHolder facetHolder, String menuOrder, Class<?> repositoryFor) {
-        super(facetHolder, menuOrder, repositoryFor);
+    public DomainServiceFacetAnnotation(
+            final FacetHolder facetHolder,
+            final DomainService.MenuBar menubar,
+            final String menuOrder,
+            final Class<?> repositoryFor) {
+        super(facetHolder, menubar, menuOrder, repositoryFor);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
index 036ebd8..78f42b6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
@@ -41,8 +41,8 @@ public class DomainServiceFacetAnnotationFactory extends FacetFactoryAbstract {
         }
         FacetUtil.addFacet(
                 new DomainServiceFacetAnnotation(
-                        processClassContext.getFacetHolder(), 
-                        annotation.menuOrder(), annotation.repositoryFor()));
+                        processClassContext.getFacetHolder(),
+                        annotation.menuBar(), annotation.menuOrder(), annotation.repositoryFor()));
         if(annotation.repositoryFor() != null) {
             FacetUtil.addFacet(
                     new IconFacetDerivedFromDomainServiceAnnotation(


[4/5] isis git commit: ISIS-963: primary, secondary and tertiary menu support.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.css
new file mode 100644
index 0000000..87a8864
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.css
@@ -0,0 +1,340 @@
+/*
+ *  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.
+ */
+
+
+/* copied from CssMenuPanel.css (since deleted that panel */
+
+
+
+.cssMenuPanel span.clear {
+    line-height: 3px;
+}
+
+.cssMenuPanel .menuh .small {
+    float: none;
+    display: inline;
+}
+
+.cssMenuPanel .menuh p .small {
+    float: none;
+    display: inline;
+}
+
+.menuh a,.menuh p {
+    text-align: left;
+    display: block;
+    white-space: nowrap;
+    margin: 0;
+    padding: 1px;
+    padding-right: 1.6em;
+    padding-left: 0.4em;
+    font-weight: normal;
+    cursor: default;
+}
+
+.cssMenuPanel .menuh a:hover {
+    text-decoration: underline;
+}
+
+.cssMenuPanel .menuh a.top-parent,.cssMenuPanel .menuh p.top-parent {
+    background-position: right center;
+    background-repeat: no-repeat;
+}
+
+.cssMenuPanel .menuh a.top-parent:hover,.cssMenuPanel .menuh p.top-parent:hover	{
+    background-position: right center;
+    background-repeat: no-repeat;
+}
+
+.cssMenuPanel .menuh a.parent,.cssMenuPanel .menuh p.parent {
+    background-position: right center;
+    background-repeat: no-repeat;
+}
+
+.cssMenuPanel .menuh a.parent:hover,.cssMenuPanel .menuh p.parent:hover	{
+    background-position: right center;
+    background-repeat: no-repeat;
+}
+
+.cssMenuPanel .menuh ul {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    float: left;
+    display: inline;
+}
+
+.cssMenuPanel .menuh li {
+    position: relative;
+    min-height: 1px;
+}
+
+.cssMenuPanel .menuh ul ul {
+    position: absolute;
+    z-index: 500;
+    top: auto;
+    display: none;
+    padding: 1em;
+    margin: -1em 0 0 -1em;
+}
+
+.cssMenuPanel .menuh ul ul ul {
+    top: 0;
+    left: 100%;
+}
+
+.cssMenuPanel span.menuh a:hover {
+    cursor: pointer;
+    z-index: 100;
+}
+
+.cssMenuPanel span.menuh li:hover ul ul,.cssMenuPanel span.menuh li li:hover ul ul,.cssMenuPanel span.menuh li li li:hover ul ul,.cssMenuPanel span.menuh li li li li:hover ul ul {
+    display: none;
+}
+
+.cssMenuPanel span.menuh li:hover ul,.cssMenuPanel span.menuh li li:hover ul,.cssMenuPanel span.menuh li li li:hover ul,.cssMenuPanel span.menuh li li li li:hover ul {
+    display: block;
+}
+
+.cssMenuPanel li.cssSubMenuItem p.disabled {
+    cursor: not-allowed;
+}
+
+.cssMenuPanel li.cssSubMenuItem {
+    margin-left:0;
+}
+
+/******** overrides for grouped actions and entity actions ***************/
+.groupedActions .cssMenuPanel li.cssMenuItemPanel>p.top-parent {
+    display: none;
+}
+
+.groupedActions .cssMenuPanel .menuh ul {
+    position: relative;
+    display: block;
+    float: right;
+    margin: 0;
+    padding: 0;
+}
+
+.groupedActions .cssMenuPanel .menuh ul ul {
+    position: relative;
+    display: block;
+    float: right;
+    margin: 0;
+    padding: 0;
+}
+
+.groupedActions .cssMenuPanel .menuh li,
+.groupedActions .cssMenuPanel .menuh li p	{
+    float:left;
+    display:block;
+    margin-left:10px;
+}
+
+.groupedActions .cssMenuPanel .menuh a,.groupedActions .cssMenuPanel .menuh p
+{
+    display: inline-block;
+    border: none;
+}
+
+.groupedActions .cssMenuPanel .menuh a:link,
+.groupedActions .cssMenuPanel .menuh a:visited,
+.groupedActions .cssMenuPanel .menuh a:active,
+.groupedActions .cssMenuPanel .menuh p {
+    display: block;
+    float: left;
+    height: 30px;
+    line-height: 30px;
+    padding: 0 10px;
+    font-weight: bold;
+    /*font-size: 0.85em;*/
+    border-radius: 4px;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+    text-decoration: none;
+}
+
+.entityActions .cssMenuPanel li.cssMenuItemPanel>p.top-parent {
+    display: none;
+}
+
+.entityActions .cssMenuPanel .menuh ul {
+    position: relative;
+    display: block;
+    float: right;
+    margin: 0 0 10px;
+    padding: 0;
+}
+
+.entityActions .cssMenuPanel .menuh ul ul {
+    position: relative;
+    display: block;
+    float: right;
+    margin: 0;
+    padding: 0;
+}
+
+.entityActions .cssMenuPanel .menuh li {
+    float:left;
+    display:block;
+    margin-left:10px;
+}
+
+.entityActions .cssMenuPanel .menuh li p {
+    float:left;
+    display:block;
+    margin-left:0;
+}
+
+.entityActions .cssMenuPanel .menuh a,
+.entityActions .cssMenuPanel .menuh p {
+    display: inline-block;
+    /*border: none;*/
+}
+
+.entityActions .cssMenuPanel .menuh a,
+.entityActions .cssMenuPanel .menuh a:link,
+.entityActions .cssMenuPanel .menuh a:visited,
+.entityActions .cssMenuPanel .menuh a:active,
+.entityActions .cssMenuPanel .menuh p {
+    display: block;
+    float: left;
+    height: 30px;
+    /*line-height: 30px;*/
+    padding: 4px 10px 0;
+    /*font-size:0.85em;*/
+    border-radius:4px;
+    -moz-border-radius:4px;
+    -webkit-border-radius:4px;
+    text-decoration:none;
+}
+
+.additionalLinkList {
+    float:left;
+    margin:0;
+    padding:0;
+    list-style:none;
+}
+
+.entityCollectionsPanel .panel-heading .additionalLinkList {
+    margin-right: 10px;
+}
+
+.additionalLinkList li {
+    float:left;
+    margin-right:10px;
+    /*	margin-bottom: 2px;*/
+}
+.entityPropertiesPanel .additionalLinkList li {
+    margin-right:0px;
+}
+.entityPropertiesPanel .properties .panel-heading .additionalLinkList {
+    margin-right: -5px;
+}
+
+
+
+
+
+/**
+ * Borrowed from http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3
+ */
+
+.dropdown-submenu {
+    position: relative;
+}
+
+.dropdown-submenu>.dropdown-menu {
+    top: 0;
+    left: 100%;
+    margin-top: -6px;
+    margin-left: -1px;
+    -webkit-border-radius: 0 6px 6px 6px;
+    -moz-border-radius: 0 6px 6px;
+    border-radius: 0 6px 6px 6px;
+}
+
+.dropdown-submenu:hover>.dropdown-menu {
+    display: block;
+}
+
+.dropdown-submenu>a:after {
+    display: block;
+    content: " ";
+    float: right;
+    width: 0;
+    height: 0;
+    border-color: transparent;
+    border-style: solid;
+    border-width: 5px 0 5px 5px;
+    border-left-color: #ccc;
+    margin-top: 5px;
+    margin-right: -10px;
+}
+
+.dropdown-submenu:hover>a:after {
+    border-left-color: #fff;
+}
+
+.dropdown-submenu.pull-left {
+    float: none;
+}
+
+.dropdown-submenu.pull-left>.dropdown-menu {
+    left: -100%;
+    margin-left: 10px;
+    -webkit-border-radius: 6px 0 6px 6px;
+    -moz-border-radius: 6px 0 6px 6px;
+    border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu > li > a.menuLink {
+    padding-left: 0;
+}
+
+.dropdown-menu > li > span.fa {
+    padding-left: 3px;
+}
+
+.dropdown-menu .fontAwesomeIcon {
+    min-width: 20px;
+}
+
+.dropdown-menu > li > a.menuLink.btn-warning:hover {
+    background-color: inherit;
+    background-image: inherit;
+}
+
+.dropdown-menu > li > a.menuLink.menuLinkSpacer {
+    padding-left: 24px;
+}
+
+.dropdown-menu > li > a.btn.btn-warning {
+    text-align: start;
+    border-radius: 0;
+    color: initial;
+}
+
+.scrollable-menu {
+    min-width: 250px;
+    height: auto;
+    max-height: 600px;
+    overflow-x: hidden;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.html
new file mode 100644
index 0000000..3a6dd5d
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+    <body>
+        <wicket:panel>
+            <li class="dropdown" wicket:id="menuItems">
+                <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><span wicket:id="name"></span> <span class="caret"></span></a>
+                <ul wicket:id="topMenu" class="dropdown-menu scrollable-menu multi-level" role="menu">
+                    <li wicket:id="subMenuItems">
+                        <wicket:container wicket:id="content"></wicket:container>
+                    </li>
+                </ul>
+            </li>
+
+            <wicket:fragment wicket:id="leafItem">
+                <a class="menuLink" wicket:id="menuLink">
+                    <span class="fontAwesomeIcon" wicket:id="menuLinkFontAwesome"></span> <span class="menuLinkLabel" wicket:id="menuLinkLabel"></span>
+                </a>
+            </wicket:fragment>
+
+            <wicket:fragment wicket:id="folderItem">
+                <a wicket:id="folderName" tabindex="-1"></a>
+                <ul class="dropdown-menu">
+                    <li wicket:id="subMenuItems">
+                        <wicket:container wicket:id="content"></wicket:container>
+                    </li>
+                </ul>
+            </wicket:fragment>
+
+            <wicket:fragment wicket:id="empty">
+            </wicket:fragment>
+
+
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
new file mode 100644
index 0000000..b2324cd
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
@@ -0,0 +1,179 @@
+package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipBehavior;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.button.DropdownAutoOpenJavaScriptReference;
+
+import java.util.List;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.resource.CssResourceReference;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+/**
+ * A panel responsible to render the application actions as menu in a navigation bar.
+ *
+ * <p>
+ *     The multi-level sub menu support is borrowed from
+ *     <a href="http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3">Bootsnip</a>
+ * </p>
+ */
+public class ServiceActionsPanel extends Panel {
+
+    public ServiceActionsPanel(String id, List<CssMenuItem> menuItems) {
+        super(id);
+
+        ListView<CssMenuItem> menuItemsView = new ListView<CssMenuItem>("menuItems", menuItems) {
+
+            @Override
+            protected void populateItem(ListItem<CssMenuItem> listItem) {
+                CssMenuItem menuItem = listItem.getModelObject();
+                listItem.add(new Label("name", menuItem.getName()));
+
+                MarkupContainer topMenu = new WebMarkupContainer("topMenu");
+
+                topMenu.add(new CssClassAppender("top-menu-" + CssClassAppender.asCssStyle(menuItem.getName())));
+                listItem.add(topMenu);
+                List<CssMenuItem> subMenuItems = withSeparators(menuItem);
+
+// fake data to test multi-level menus
+//                if (menuItem.getName().equals("ToDos")) {
+//                    CssMenuItem fakeItem = menuItem.newSubMenuItem("Fake item").build();
+//
+//                    fakeItem.newSubMenuItem("Fake item 1").link(new ExternalLink("menuLink", "http://abv.bg")).build();
+//                    CssMenuItem fakeMenu12 = fakeItem.newSubMenuItem("Fake item 2").link(new ExternalLink("menuLink", "http://google.com")).build();
+//
+//                    fakeMenu12.newSubMenuItem("Fake item 2.1").link(new ExternalLink("menuLink", "http://web.de")).build();
+//                }
+
+                ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems", subMenuItems) {
+                    @Override
+                    protected void populateItem(ListItem<CssMenuItem> listItem) {
+                        CssMenuItem subMenuItem = listItem.getModelObject();
+
+                        if (subMenuItem.hasSubMenuItems()) {
+                            addFolderItem(subMenuItem, listItem);
+                        } else {
+                            addLeafItem(subMenuItem, listItem);
+                        }
+                    }
+                };
+                topMenu.add(subMenuItemsView);
+            }
+        };
+        add(menuItemsView);
+    }
+
+    private void addFolderItem(CssMenuItem subMenuItem, ListItem<CssMenuItem> listItem) {
+
+        listItem.add(new CssClassAppender("dropdown-submenu"));
+
+        Fragment folderItem = new Fragment("content", "folderItem", ServiceActionsPanel.this);
+        listItem.add(folderItem);
+
+        folderItem.add(new Label("folderName", subMenuItem.getName()));
+        final List<CssMenuItem> menuItems = withSeparators(subMenuItem);
+        ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems",
+                menuItems) {
+            @Override
+            protected void populateItem(ListItem<CssMenuItem> listItem) {
+                CssMenuItem subMenuItem = listItem.getModelObject();
+
+                if (subMenuItem.hasSubMenuItems()) {
+                    addFolderItem(subMenuItem, listItem);
+                } else {
+                    addLeafItem(subMenuItem, listItem);
+                }
+            }
+        };
+        folderItem.add(subMenuItemsView);
+    }
+
+    private static List<CssMenuItem> withSeparators(CssMenuItem subMenuItem) {
+        final List<CssMenuItem> subMenuItems = subMenuItem.getSubMenuItems();
+        return withSeparators(subMenuItems);
+    }
+
+    private static List<CssMenuItem> withSeparators(List<CssMenuItem> subMenuItems) {
+        final List<CssMenuItem> itemsWithSeparators = Lists.newArrayList();
+        for (CssMenuItem menuItem : subMenuItems) {
+            if(menuItem.isSeparator() ) {
+                if(!itemsWithSeparators.isEmpty()) {
+                    // bit nasty... we add a new separator item
+                    itemsWithSeparators.add(
+                            CssMenuItem.newMenuItem(menuItem.getName() + "-separator")
+                                    .separator(menuItem.isSeparator())
+                                    .prototyping(menuItem.isPrototyping())
+                                    .build());
+                }
+                menuItem.setSeparator(false);
+            }
+            itemsWithSeparators.add(menuItem);
+        }
+        return itemsWithSeparators;
+    }
+
+    private void addLeafItem(
+            final CssMenuItem menuItem,
+            final ListItem<CssMenuItem> listItem) {
+
+        Fragment leafItem;
+        if (!menuItem.isSeparator()) {
+            leafItem = new Fragment("content", "leafItem", ServiceActionsPanel.this);
+
+            AbstractLink subMenuItemLink = menuItem.getLink();
+
+            Label menuItemLabel = new Label("menuLinkLabel", menuItem.getName());
+            subMenuItemLink.addOrReplace(menuItemLabel);
+
+            if (!menuItem.isEnabled()) {
+                listItem.add(new CssClassAppender("disabled"));
+                subMenuItemLink.setEnabled(false);
+                TooltipBehavior tooltipBehavior = new TooltipBehavior(Model.of(menuItem.getDisabledReason()));
+                listItem.add(tooltipBehavior);
+            }
+            if (menuItem.isPrototyping()) {
+                subMenuItemLink.add(new CssClassAppender("prototype"));
+            }
+            leafItem.add(subMenuItemLink);
+
+            String cssClassFa = menuItem.getCssClassFa();
+            if (Strings.isNullOrEmpty(cssClassFa)) {
+                Components.permanentlyHide(subMenuItemLink, "menuLinkFontAwesome");
+                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
+            } else {
+                Label dummy = new Label("menuLinkFontAwesome", "");
+                dummy.add(new CssClassAppender(cssClassFa));
+                subMenuItemLink.addOrReplace(dummy);
+            }
+        } else {
+            leafItem = new Fragment("content", "empty", ServiceActionsPanel.this);
+            listItem.add(new CssClassAppender("divider"));
+        }
+        listItem.add(leafItem);
+
+    }
+
+    @Override
+    public void renderHead(IHeaderResponse response) {
+        super.renderHead(response);
+
+        response.render(CssHeaderItem.forReference(new CssResourceReference(ServiceActionsPanel.class, "ServiceActionsPanel.css")));
+        response.render(JavaScriptHeaderItem.forReference(DropdownAutoOpenJavaScriptReference.instance()));
+        response.render(OnDomReadyHeaderItem.forScript("$('.dropdown-toggle').dropdownHover();"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanelFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanelFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanelFactory.java
new file mode 100644
index 0000000..d60dce1
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanelFactory.java
@@ -0,0 +1,60 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * {@link ComponentFactory} for a {@link ServiceActionsPanel} to represent the
+ * {@link org.apache.isis.viewer.wicket.model.models.ServiceActionsModel application action}s.
+ */
+public class ServiceActionsPanelFactory extends ComponentFactoryAbstract {
+
+    private final static long serialVersionUID = 1L;
+
+    public ServiceActionsPanelFactory() {
+        super(ComponentType.SERVICE_ACTIONS, ServiceActionsPanel.class);
+    }
+
+    /**
+     * Applies to primary and secondary service action models.
+     */
+    @Override
+    protected ApplicationAdvice appliesTo(final IModel<?> model) {
+        if(!(model instanceof ServiceActionsModel)) {
+            return ApplicationAdvice.DOES_NOT_APPLY;
+        }
+        final ServiceActionsModel serviceActionsModel = (ServiceActionsModel) model;
+        return appliesIf(serviceActionsModel.getMenuBar() != DomainService.MenuBar.TERTIARY);
+    }
+
+    @Override
+    public Component createComponent(final String id, final IModel<?> model) {
+        final ServiceActionsModel serviceActionsModel = (ServiceActionsModel) model;
+        return new ServiceActionsPanel(id, ServiceActionUtil.buildMenu(serviceActionsModel));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.css
new file mode 100644
index 0000000..eaeea17
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.css
@@ -0,0 +1,18 @@
+/*
+ *  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.
+ */

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.html
new file mode 100644
index 0000000..94b4870
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+    <body>
+        <wicket:panel>
+
+            <li wicket:id="subMenuItems">
+                <wicket:container wicket:id="content"></wicket:container>
+            </li>
+
+            <li class="divider"></li>
+            <li>
+                <a class="menuLink" wicket:id="logoutLink" >
+                    <span class="fontAwesomeIcon fa fa-fw fa-sign-out"></span>
+                    <span class="menuLinkLabel">
+                        <wicket:message key="logoutLabel"></wicket:message>
+                    </span>
+                </a>
+            </li>
+
+            <wicket:fragment wicket:id="leafItem">
+                <a class="menuLink" wicket:id="menuLink">
+                    <span class="fontAwesomeIcon" wicket:id="menuLinkFontAwesome"></span>
+                    <span class="menuLinkLabel" wicket:id="menuLinkLabel"></span>
+                </a>
+            </wicket:fragment>
+
+
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
new file mode 100644
index 0000000..94402ca
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
@@ -0,0 +1,164 @@
+package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipBehavior;
+
+import java.util.List;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.resource.CssResourceReference;
+import org.apache.isis.viewer.wicket.model.models.PageType;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+/**
+ * A panel responsible to render the application actions as menu in a navigation bar.
+ *
+ * <p>
+ *     The multi-level sub menu support is borrowed from
+ *     <a href="http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3">Bootsnip</a>
+ * </p>
+ */
+public class TertiaryActionsPanel extends Panel {
+
+    public TertiaryActionsPanel(String id, List<CssMenuItem> menuItems) {
+        super(id);
+
+        addLogoutLink(this);
+
+        List<CssMenuItem> subMenuItems = flatten(menuItems);
+
+        ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems", subMenuItems) {
+            @Override
+            protected void populateItem(ListItem<CssMenuItem> listItem) {
+                CssMenuItem subMenuItem = listItem.getModelObject();
+
+                if (subMenuItem.hasSubMenuItems()) {
+                    addFolderItem(subMenuItem, listItem);
+                } else {
+                    addLeafItem(subMenuItem, listItem);
+                }
+            }
+        };
+        add(subMenuItemsView);
+    }
+
+    protected List<CssMenuItem> flatten(List<CssMenuItem> menuItems) {
+        List<CssMenuItem> subMenuItems = Lists.newArrayList();
+        for (CssMenuItem menuItem : menuItems) {
+            subMenuItems.addAll(menuItem.getSubMenuItems());
+        }
+        return subMenuItems;
+    }
+
+    private void addLogoutLink(MarkupContainer themeDiv) {
+        Link logoutLink = new Link("logoutLink") {
+
+            @Override
+            public void onClick() {
+                getSession().invalidate();
+                setResponsePage(getSignInPage());
+            }
+        };
+        themeDiv.add(logoutLink);
+    }
+
+    private Class<? extends Page> getSignInPage() {
+        return pageClassRegistry.getPageClass(PageType.SIGN_IN);
+    }
+
+
+    private void addFolderItem(CssMenuItem subMenuItem, ListItem<CssMenuItem> listItem) {
+
+        listItem.add(new CssClassAppender("dropdown-submenu"));
+
+        Fragment folderItem = new Fragment("content", "folderItem", TertiaryActionsPanel.this);
+        listItem.add(folderItem);
+
+        folderItem.add(new Label("folderName", subMenuItem.getName()));
+        final List<CssMenuItem> subMenuItems = subMenuItem.getSubMenuItems();
+        final List<CssMenuItem> menuItems = subMenuItems;
+        ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems",
+                menuItems) {
+            @Override
+            protected void populateItem(ListItem<CssMenuItem> listItem) {
+                CssMenuItem subMenuItem = listItem.getModelObject();
+
+                if (subMenuItem.hasSubMenuItems()) {
+                    addFolderItem(subMenuItem, listItem);
+                } else {
+                    addLeafItem(subMenuItem, listItem);
+                }
+            }
+        };
+        folderItem.add(subMenuItemsView);
+    }
+
+    private void addLeafItem(
+            final CssMenuItem menuItem,
+            final ListItem<CssMenuItem> listItem) {
+
+        Fragment leafItem;
+        if (!menuItem.isSeparator()) {
+            leafItem = new Fragment("content", "leafItem", TertiaryActionsPanel.this);
+
+            AbstractLink subMenuItemLink = menuItem.getLink();
+
+            Label menuItemLabel = new Label("menuLinkLabel", menuItem.getName());
+            subMenuItemLink.addOrReplace(menuItemLabel);
+
+            if (!menuItem.isEnabled()) {
+                listItem.add(new CssClassAppender("disabled"));
+                subMenuItemLink.setEnabled(false);
+                TooltipBehavior tooltipBehavior = new TooltipBehavior(Model.of(menuItem.getDisabledReason()));
+                listItem.add(tooltipBehavior);
+            }
+            if (menuItem.isPrototyping()) {
+                subMenuItemLink.add(new CssClassAppender("prototype"));
+            }
+            leafItem.add(subMenuItemLink);
+
+            String cssClassFa = menuItem.getCssClassFa();
+            if (Strings.isNullOrEmpty(cssClassFa)) {
+                Components.permanentlyHide(subMenuItemLink, "menuLinkFontAwesome");
+                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
+            } else {
+                Label dummy = new Label("menuLinkFontAwesome", "");
+                dummy.add(new CssClassAppender(cssClassFa));
+                subMenuItemLink.addOrReplace(dummy);
+            }
+        } else {
+            leafItem = new Fragment("content", "empty", TertiaryActionsPanel.this);
+            listItem.add(new CssClassAppender("divider"));
+        }
+        listItem.add(leafItem);
+
+    }
+
+    @Override
+    public void renderHead(IHeaderResponse response) {
+        super.renderHead(response);
+
+        response.render(CssHeaderItem.forReference(new CssResourceReference(TertiaryActionsPanel.class, "TertiaryActionsPanel.css")));
+    }
+
+    /**
+     * {@link com.google.inject.Inject}ed when {@link #init() initialized}.
+     */
+    @Inject
+    private PageClassRegistry pageClassRegistry;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryMenuPanelFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryMenuPanelFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryMenuPanelFactory.java
new file mode 100644
index 0000000..0e303ec
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryMenuPanelFactory.java
@@ -0,0 +1,59 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
+import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * {@link org.apache.isis.viewer.wicket.ui.ComponentFactory} for a {@link org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.ServiceActionsPanel} to represent the
+ * {@link org.apache.isis.viewer.wicket.model.models.ServiceActionsModel application action}s.
+ */
+public class TertiaryMenuPanelFactory extends ComponentFactoryAbstract {
+
+    private final static long serialVersionUID = 1L;
+
+    public TertiaryMenuPanelFactory() {
+        super(ComponentType.SERVICE_ACTIONS, ServiceActionsPanel.class);
+    }
+
+    /**
+     * Applies only to tertiary service action models.
+     */
+    @Override
+    protected ApplicationAdvice appliesTo(final IModel<?> model) {
+        if(!(model instanceof ServiceActionsModel)) {
+            return ApplicationAdvice.DOES_NOT_APPLY;
+        }
+        final ServiceActionsModel serviceActionsModel = (ServiceActionsModel) model;
+        return appliesIf(serviceActionsModel.getMenuBar() == DomainService.MenuBar.TERTIARY);
+    }
+
+    @Override
+    public Component createComponent(final String id, final IModel<?> model) {
+        final ServiceActionsModel serviceActionsModel = (ServiceActionsModel) model;
+        return new TertiaryActionsPanel(id, ServiceActionUtil.buildMenu(serviceActionsModel));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.html
deleted file mode 100644
index 3667116..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.html
+++ /dev/null
@@ -1,44 +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.
--->
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"  
-      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
-      xml:lang="en"  
-      lang="en">
-    <body>
-        <wicket:panel>
-            <div wicket:id="additionalLinkList" class="additionalLinkList additionalLinkListDropDown">
-                <div class="btn-group">
-                    <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
-                        <span class="fa fa-ellipsis-v"></span>
-                    </button>
-                    <ul class="dropdown-menu" role="menu">
-                        <li wicket:id="additionalLinkItem" class="additionalLinkItem">
-                            <a href="#" wicket:id="additionalLink">
-                                <span wicket:id="additionalLinkFontAwesome"></span>
-                                <span wicket:id="additionalLinkTitle" class="additionalLinkItem">[link title]</span>
-                            </a>
-                        </li>
-                    </ul>
-                </div>
-            </div>
-        </wicket:panel>
-    </body>
-</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.java
deleted file mode 100644
index 3e971eb..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsDropDownPanel.java
+++ /dev/null
@@ -1,32 +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.additionallinks;
-
-import java.util.List;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-
-public class AdditionalLinksAsDropDownPanel extends AdditionalLinksPanel {
-
-    private static final long serialVersionUID = 1L;
-
-    public AdditionalLinksAsDropDownPanel(String id, List<LinkAndLabel> links) {
-        super(id, links);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.html
deleted file mode 100644
index 9fcacee..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.html
+++ /dev/null
@@ -1,37 +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.
--->
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"  
-      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
-      xml:lang="en"  
-      lang="en">
-    <body>
-        <wicket:panel>
-            <ul wicket:id="additionalLinkList" class="additionalLinkList additionalLinkListInline list-unstyled list-inline">
-                <li wicket:id="additionalLinkItem" class="additionalLinkItem">
-                    <a href="#" wicket:id="additionalLink" class="btn btn-sm btn-default">
-                        <span wicket:id="additionalLinkFontAwesome"></span>
-                        <span wicket:id="additionalLinkTitle" class="additionalLinkItem">[link title]</span>
-                    </a>
-                </li>
-            </ul>
-        </wicket:panel>
-    </body>
-</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.java
deleted file mode 100644
index bde760f..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksAsListInlinePanel.java
+++ /dev/null
@@ -1,32 +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.additionallinks;
-
-import java.util.List;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-
-public class AdditionalLinksAsListInlinePanel extends AdditionalLinksPanel {
-
-    private static final long serialVersionUID = 1L;
-
-    public AdditionalLinksAsListInlinePanel(String id, List<LinkAndLabel> links) {
-        super(id, links);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksPanel.java
deleted file mode 100644
index b5f2b23..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/AdditionalLinksPanel.java
+++ /dev/null
@@ -1,149 +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.additionallinks;
-
-import java.util.List;
-import com.google.common.base.Strings;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.behavior.AttributeAppender;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.isis.core.commons.lang.StringExtensions;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.links.ListOfLinksModel;
-import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
-import org.apache.isis.viewer.wicket.ui.util.Components;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
-
-public class AdditionalLinksPanel extends PanelAbstract<ListOfLinksModel> {
-
-    private static final long serialVersionUID = 1L;
-
-    private static final String ID_ADDITIONAL_LINK_LIST = "additionalLinkList";
-    private static final String ID_ADDITIONAL_LINK_ITEM = "additionalLinkItem";
-    private static final String ID_ADDITIONAL_LINK_FONT_AWESOME = "additionalLinkFontAwesome";
-    private static final String ID_ADDITIONAL_LINK_TITLE = "additionalLinkTitle";
-
-    public static final String ID_ADDITIONAL_LINK = "additionalLink";
-
-    public enum Style {
-        INLINE_LIST {
-            @Override
-            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) {
-                return new AdditionalLinksAsListInlinePanel(id, links);
-            }
-        },
-        DROPDOWN {
-            @Override
-            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) {
-                return new AdditionalLinksAsDropDownPanel(id, links);
-            }
-        };
-        abstract AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links);
-    }
-
-    public static AdditionalLinksPanel addAdditionalLinks(
-            final MarkupContainer markupContainer,
-            final String id,
-            final List<LinkAndLabel> links,
-            final Style style) {
-        if(links.isEmpty()) {
-            Components.permanentlyHide(markupContainer, id);
-            return null;
-        }
-
-        final AdditionalLinksPanel additionalLinksPanel =  style.newPanel(id, links);
-        markupContainer.addOrReplace(additionalLinksPanel);
-        return additionalLinksPanel;
-    }
-
-
-    private List<LinkAndLabel> linkAndLabels;
-    
-    protected AdditionalLinksPanel(final String id, final List<LinkAndLabel> links) {
-        super(id, new ListOfLinksModel(links));
-
-        this.linkAndLabels = getModel().getObject();
-        
-        final WebMarkupContainer container = new WebMarkupContainer(ID_ADDITIONAL_LINK_LIST);
-        addOrReplace(container);
-        
-        container.setOutputMarkupId(true);
-        
-        setOutputMarkupId(true);
-        
-        final ListView<LinkAndLabel> listView = new ListView<LinkAndLabel>(ID_ADDITIONAL_LINK_ITEM, this.linkAndLabels) {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void populateItem(ListItem<LinkAndLabel> item) {
-                final LinkAndLabel linkAndLabel = item.getModelObject();
-                
-                final AbstractLink link = linkAndLabel.getLink();
-
-                final String cssClassFa = linkAndLabel.getCssClassFa();
-                if(Strings.isNullOrEmpty(cssClassFa)) {
-                    Components.permanentlyHide(link, ID_ADDITIONAL_LINK_FONT_AWESOME);
-                } else {
-                    Label dummy = new Label(ID_ADDITIONAL_LINK_FONT_AWESOME, "");
-                    link.addOrReplace(dummy);
-                    dummy.add(new CssClassAppender(cssClassFa));
-                }
-
-                final String itemTitle = first(linkAndLabel.getDisabledReasonIfAny(), linkAndLabel.getDescriptionIfAny());
-                if(itemTitle != null) {
-                    item.add(new AttributeAppender("title", itemTitle));
-                }
-
-                final Label viewTitleLabel = new Label(ID_ADDITIONAL_LINK_TITLE, linkAndLabel.getLabel());
-                if(linkAndLabel.isBlobOrClob()) {
-                    link.add(new CssClassAppender("noVeil"));
-                }
-                if(linkAndLabel.isPrototype()) {
-                    link.add(new CssClassAppender("prototype"));
-                }
-                link.add(new CssClassAppender(linkAndLabel.getActionIdentifier()));
-
-                final String cssClass = linkAndLabel.getCssClass();
-                if(cssClass != null) {
-                    link.add(new CssClassAppender(cssClass));
-                }
-                viewTitleLabel.add(new CssClassAppender(StringExtensions.asLowerDashed(linkAndLabel.getLabel())));
-
-                link.addOrReplace(viewTitleLabel);
-                item.addOrReplace(link);
-            }
-        };
-        container.addOrReplace(listView);
-    }
-
-    private static String first(String... str) {
-        for (String s : str) {
-            if(s != null) return s;
-        }
-        return null;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
deleted file mode 100644
index bd44fbc..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
+++ /dev/null
@@ -1,175 +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.additionallinks;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import org.apache.wicket.Session;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.filter.Filter;
-import org.apache.isis.applib.filter.Filters;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
-import org.apache.isis.core.metamodel.layout.memberorderfacet.MemberOrderFacetComparator;
-import org.apache.isis.core.metamodel.spec.ActionType;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-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.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-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.components.entity.EntityActionLinkFactory;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
-
-public final class EntityActionUtil {
-
-    private EntityActionUtil(){}
-
-    private final static MemberOrderFacetComparator memberOrderFacetComparator = new MemberOrderFacetComparator(false);
-
-    public static List<LinkAndLabel> getEntityActionLinksForAssociation(
-            final ScalarModel scalarModel,
-            final DeploymentType deploymentType) {
-        final List<LinkAndLabel> entityActions = Lists.newArrayList();
-
-        if (scalarModel.getKind() != ScalarModel.Kind.PROPERTY) {
-            return entityActions;
-        } else {
-            final ObjectAdapterMemento parentMemento = scalarModel.getParentObjectAdapterMemento();
-            final EntityModel parentEntityModel = new EntityModel(parentMemento);
-            final OneToOneAssociation oneToOneAssociation = scalarModel.getPropertyMemento().getProperty();
-
-            final List<ObjectAction> associatedActions = getObjectActionsForAssociation(parentEntityModel, oneToOneAssociation, deploymentType);
-
-            entityActions.addAll(asLinkAndLabelsForAdditionalLinksPanel(parentEntityModel, associatedActions));
-            return entityActions;
-        }
-    }
-
-    public static List<ObjectAction> getObjectActionsForAssociation(
-            final EntityModel entityModel,
-            final ObjectAssociation association,
-            final DeploymentType deploymentType) {
-        final List<ObjectAction> associatedActions = Lists.newArrayList();
-
-        addActions(ActionType.USER, entityModel, association, associatedActions);
-        if(deploymentType.isPrototyping()) {
-            addActions(ActionType.EXPLORATION, entityModel, association, associatedActions);
-            addActions(ActionType.PROTOTYPE, entityModel, association, associatedActions);
-        }
-
-        Collections.sort(associatedActions, new Comparator<ObjectAction>() {
-
-            @Override
-            public int compare(ObjectAction o1, ObjectAction o2) {
-                final MemberOrderFacet m1 = o1.getFacet(MemberOrderFacet.class);
-                final MemberOrderFacet m2 = o2.getFacet(MemberOrderFacet.class);
-                return memberOrderFacetComparator.compare(m1, m2);
-            }
-        });
-        return associatedActions;
-    }
-
-    /**
-     * Converts an {@link org.apache.isis.viewer.wicket.model.models.EntityModel} and a (subset of its) {@link org.apache.isis.core.metamodel.spec.feature.ObjectAction}s into a
-     * list of {@link org.apache.isis.viewer.wicket.model.links.LinkAndLabel}s intended to be apassed
-     * to the {@link org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel}.
-     */
-    public static List<LinkAndLabel> asLinkAndLabelsForAdditionalLinksPanel(
-            final EntityModel entityModel,
-            final List<ObjectAction> actions) {
-
-        final String linkId = AdditionalLinksPanel.ID_ADDITIONAL_LINK;
-        final ActionLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
-
-        final ObjectAdapterMemento adapterMemento = entityModel.getObjectAdapterMemento();
-        return Lists.transform(actions, new Function<ObjectAction, LinkAndLabel>() {
-
-            @Override
-            public LinkAndLabel apply(ObjectAction objectAction) {
-                return linkFactory.newLink(adapterMemento, objectAction, linkId);
-            }
-        });
-    }
-
-    private static List<ObjectAction> addActions(
-            final ActionType type,
-            final EntityModel entityModel,
-            final ObjectAssociation association,
-            final List<ObjectAction> associatedActions) {
-        final ObjectSpecification adapterSpec = entityModel.getTypeOfSpecification();
-        final ObjectAdapter adapter = entityModel.load(ConcurrencyChecking.NO_CHECK);
-
-        final AuthenticationSessionProvider asa = (AuthenticationSessionProvider) Session.get();
-        AuthenticationSession authSession = asa.getAuthenticationSession();
-
-        final ObjectSpecification objectSpecification = entityModel.getTypeOfSpecification();
-        @SuppressWarnings({ "unchecked", "deprecation" })
-        Filter<ObjectAction> filter = Filters.and(
-                    ObjectAction.Filters.memberOrderOf(association),
-                    ObjectAction.Filters.dynamicallyVisible(authSession, adapter, Where.ANYWHERE),
-                    ObjectAction.Filters.notBulkOnly(),
-                    ObjectAction.Filters.excludeWizardActions(objectSpecification));
-
-        final List<ObjectAction> userActions = adapterSpec.getObjectActions(type, Contributed.INCLUDED, filter);
-        associatedActions.addAll(userActions);
-        return userActions;
-    }
-
-
-    public static void addTopLevelActions(
-            final ObjectAdapter adapter,
-            final ActionType actionType,
-            final List<ObjectAction> topLevelActions,
-            final AuthenticationSession authenticationSession) {
-
-        final ObjectSpecification adapterSpec = adapter.getSpecification();
-
-        @SuppressWarnings({ "unchecked", "deprecation" })
-        Filter<ObjectAction> filter = Filters.and(
-                ObjectAction.Filters.memberOrderNotAssociationOf(adapterSpec),
-                ObjectAction.Filters.dynamicallyVisible(authenticationSession, adapter, Where.ANYWHERE),
-                ObjectAction.Filters.notBulkOnly(),
-                ObjectAction.Filters.excludeWizardActions(adapterSpec));
-
-        final List<ObjectAction> userActions = adapterSpec.getObjectActions(actionType, Contributed.INCLUDED, filter);
-        topLevelActions.addAll(userActions);
-    }
-
-    public static List<ObjectAction> getTopLevelActions(final ObjectAdapter adapter, final DeploymentType deploymentType, final AuthenticationSession authenticationSession) {
-        final List<ObjectAction> topLevelActions = Lists.newArrayList();
-
-        addTopLevelActions(adapter, ActionType.USER, topLevelActions, authenticationSession);
-        if(deploymentType.isPrototyping()) {
-            addTopLevelActions(adapter, ActionType.EXPLORATION, topLevelActions, authenticationSession);
-            addTopLevelActions(adapter, ActionType.PROTOTYPE, topLevelActions, authenticationSession);
-        }
-        return topLevelActions;
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
deleted file mode 100644
index 125c301..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
+++ /dev/null
@@ -1,225 +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.appactions.cssmenu;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.apache.wicket.Component;
-import org.apache.wicket.model.IModel;
-import org.apache.isis.applib.filter.Filters;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
-import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
-import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
-import org.apache.isis.core.metamodel.spec.ActionType;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.model.models.ApplicationActionsModel;
-import org.apache.isis.viewer.wicket.ui.ComponentFactory;
-import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
-import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ApplicationActionsPanel;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem.Builder;
-
-/**
- * {@link ComponentFactory} for a {@link org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ApplicationActionsPanel} to represent the
- * {@link ApplicationActionsModel application action}s.
- */
-public class AppActionsCssMenuFactory extends ComponentFactoryAbstract {
-
-    private final static long serialVersionUID = 1L;
-
-    
-    static class LogicalServiceAction {
-        private final String serviceName;
-        private final ObjectAdapter serviceAdapter;
-        private final ObjectAdapterMemento serviceAdapterMemento;
-        private final ObjectAction objectAction;
-        public boolean separator;
-
-        LogicalServiceAction(final String serviceName, final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
-            this.serviceName = serviceName;
-            this.serviceAdapter = serviceAdapter;
-            this.serviceAdapterMemento = ObjectAdapterMemento.createOrNull(serviceAdapter);
-            this.objectAction = objectAction;
-        }
-        @Override
-        public String toString() {
-            return serviceName + " ~ " + objectAction.getIdentifier().toFullIdentityString();
-        }
-    }
-
-    private final static ActionLinkFactory cssMenuLinkFactory = new AppActionsCssMenuLinkFactory();
-
-    public AppActionsCssMenuFactory() {
-        super(ComponentType.APPLICATION_ACTIONS, ApplicationActionsPanel.class);
-    }
-
-    /**
-     * Generic, so applies to all models.
-     */
-    @Override
-    protected ApplicationAdvice appliesTo(final IModel<?> model) {
-        return appliesIf(model instanceof ApplicationActionsModel);
-    }
-
-    @Override
-    public Component createComponent(final String id, final IModel<?> model) {
-        final ApplicationActionsModel applicationActionsModel = (ApplicationActionsModel) model;
-        return new ApplicationActionsPanel(id, buildMenu(applicationActionsModel));
-    }
-
-    private List<CssMenuItem> buildMenu(final ApplicationActionsModel appActionsModel) {
-
-        final List<ObjectAdapter> serviceAdapters = appActionsModel.getObject();
-
-        final List<LogicalServiceAction> serviceActions = Lists.newArrayList();
-        for (final ObjectAdapter serviceAdapter : serviceAdapters) {
-            collateServiceActions(serviceAdapter, ActionType.USER, serviceActions);
-            collateServiceActions(serviceAdapter, ActionType.PROTOTYPE, serviceActions);
-        }
-        
-        final Set<String> serviceNamesInOrder = serviceNamesInOrder(serviceAdapters, serviceActions);
-        final Map<String, List<LogicalServiceAction>> serviceActionsByName = groupByServiceName(serviceActions);
-        
-        // prune any service names that have no service actions
-        serviceNamesInOrder.retainAll(serviceActionsByName.keySet());
-        
-        return buildMenuItems(serviceNamesInOrder, serviceActionsByName, cssMenuLinkFactory);
-    }
-
-    /**
-     * Builds a hierarchy of {@link CssMenuItem}s, following the provided map of {@link LogicalServiceAction}s (keyed by their service Name).
-     */
-    private List<CssMenuItem> buildMenuItems(
-            final Set<String> serviceNamesInOrder,
-            final Map<String, List<LogicalServiceAction>> serviceActionsByName,
-            final ActionLinkFactory actionLinkFactory) {
-        
-        final List<CssMenuItem> menuItems = Lists.newArrayList();
-        for (String serviceName : serviceNamesInOrder) {
-            final CssMenuItem serviceMenuItem = CssMenuItem.newMenuItem(serviceName).build();
-            final List<LogicalServiceAction> serviceActionsForName = serviceActionsByName.get(serviceName);
-            for (LogicalServiceAction logicalServiceAction : serviceActionsForName) {
-                final ObjectAdapter serviceAdapter = logicalServiceAction.serviceAdapter;
-                final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
-                if (serviceSpec.isHidden()) {
-                    continue;
-                }
-                final ObjectAdapterMemento serviceAdapterMemento = logicalServiceAction.serviceAdapterMemento;
-                final ObjectAction objectAction = logicalServiceAction.objectAction;
-                final boolean separator = logicalServiceAction.separator;
-                final Builder subMenuItemBuilder = serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, separator, actionLinkFactory);
-                if (subMenuItemBuilder == null) {
-                    // not visible
-                    continue;
-                } 
-                subMenuItemBuilder.build();
-            }
-            if (serviceMenuItem.hasSubMenuItems()) {
-                menuItems.add(serviceMenuItem);
-            }
-        }
-        return menuItems;
-    }
-
-
-    // //////////////////////////////////////
-
-    /**
-     * Spin through all object actions of the service adapter, and add to the provided List of {@link LogicalServiceAction}s. 
-     */
-    private static void collateServiceActions(final ObjectAdapter serviceAdapter, ActionType actionType, List<LogicalServiceAction> serviceActions) {
-        final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
-        for (final ObjectAction objectAction : serviceSpec.getObjectActions(
-                actionType, Contributed.INCLUDED, Filters.<ObjectAction>any())) {
-            // skip if annotated to not be included in repository menu
-            if (objectAction.getFacet(NotInServiceMenuFacet.class) != null) {
-                continue;
-            }
-
-            final MemberOrderFacet memberOrderFacet = objectAction.getFacet(MemberOrderFacet.class);
-            String serviceName = memberOrderFacet != null? memberOrderFacet.name(): null;
-            if(Strings.isNullOrEmpty(serviceName)){
-                serviceName = serviceSpec.getFacet(NamedFacet.class).value();
-            }
-            serviceActions.add(new LogicalServiceAction(serviceName, serviceAdapter, objectAction));
-        }
-    }
-
-    /**
-     * The unique service names, as they appear in order of the provided List of {@link LogicalServiceAction}s.
-     * @param serviceAdapters 
-     */
-    private Set<String> serviceNamesInOrder(
-            final List<ObjectAdapter> serviceAdapters, final List<LogicalServiceAction> serviceActions) {
-        final Set<String> serviceNameOrder = Sets.newLinkedHashSet();
-
-        // first, order as defined in isis.properties
-        for (ObjectAdapter serviceAdapter : serviceAdapters) {
-            final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
-            String serviceName = serviceSpec.getFacet(NamedFacet.class).value();
-            serviceNameOrder.add(serviceName);
-        }
-        // then, any other services (eg due to misspellings, at the end)
-        for (LogicalServiceAction serviceAction : serviceActions) {
-            if(!serviceNameOrder.contains(serviceAction.serviceName)) {
-                serviceNameOrder.add(serviceAction.serviceName);
-            }
-        }
-        return serviceNameOrder;
-    }
-
-    /**
-     * Group the provided {@link LogicalServiceAction}s by their service name. 
-     */
-    private static Map<String, List<LogicalServiceAction>> groupByServiceName(final List<LogicalServiceAction> serviceActions) {
-        final Map<String, List<LogicalServiceAction>> serviceActionsByName = Maps.newTreeMap();
-        
-        // map available services
-        ObjectAdapter lastServiceAdapter = null;
-        for (LogicalServiceAction serviceAction : serviceActions) {
-            List<LogicalServiceAction> serviceActionsForName = serviceActionsByName.get(serviceAction.serviceName);
-            if(serviceActionsForName == null) {
-                serviceActionsForName = Lists.newArrayList();
-                serviceActionsByName.put(serviceAction.serviceName, serviceActionsForName);
-            } else {
-                // capture whether this action is from a different service
-                serviceAction.separator = lastServiceAdapter != serviceAction.serviceAdapter;
-            }
-            serviceActionsForName.add(serviceAction);
-            lastServiceAdapter = serviceAction.serviceAdapter;
-        }
-        
-        return serviceActionsByName;
-    }
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
deleted file mode 100644
index c25d0dc..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
+++ /dev/null
@@ -1,50 +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.appactions.cssmenu;
-
-import org.apache.wicket.markup.html.link.AbstractLink;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactoryAbstract;
-
-class AppActionsCssMenuLinkFactory extends ActionLinkFactoryAbstract {
-
-    private static final long serialVersionUID = 1L;
-    
-    @Override
-    public LinkAndLabel newLink(
-            final ObjectAdapterMemento adapterMemento,
-            final ObjectAction action,
-            final String linkId) {
-        
-        ObjectAdapter objectAdapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-
-        final AbstractLink link = newLink(linkId, objectAdapter, action);
-
-        return newLinkAndLabel(action, link, null);
-    }
-
-
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
index 5609289..1ae3b3b 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -34,7 +34,7 @@ import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 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.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorPanel;
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorProvider;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
index f628014..8ba0c16 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
@@ -49,7 +49,7 @@ import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponse;
 import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseType;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 
 public final class BulkActionsLinkFactory implements ActionLinkFactory {

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
deleted file mode 100644
index 17a55e4..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ /dev/null
@@ -1,95 +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;
-
-import org.apache.wicket.markup.html.link.AbstractLink;
-
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.consent.Consent;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.model.models.*;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactoryAbstract;
-
-public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
-
-    private static final long serialVersionUID = 1L;
-
-    @SuppressWarnings("unused")
-    private final EntityModel entityModel;
-
-    public EntityActionLinkFactory(final EntityModel entityModel) {
-        this.entityModel = entityModel;
-    }
-
-    @Override
-    public LinkAndLabel newLink(
-            final ObjectAdapterMemento adapterMemento,
-            final ObjectAction action,
-            final String linkId) {
-
-        final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-        
-        final Boolean persistent = adapter.representsPersistent();
-        if (!persistent) {
-            throw new IllegalArgumentException("Object '" + adapter.titleString(null) + "' is not persistent.");
-        }
-
-        // check visibility and whether enabled
-        final AuthenticationSession session = getAuthenticationSession();
-        
-        final Consent visibility = action.isVisible(session, adapter, Where.OBJECT_FORMS);
-        if (visibility.isVetoed()) {
-            return null;
-        }
-
-        
-        final AbstractLink link = newLink(linkId, adapter, action);
-        
-        final Consent usability = action.isUsable(session, adapter, Where.OBJECT_FORMS);
-        final String disabledReasonIfAny = usability.getReason();
-        if(disabledReasonIfAny != null) {
-            link.setEnabled(false);
-        }
-
-        return newLinkAndLabel(action, link, disabledReasonIfAny);
-    }
-
-    
-
-    // ///////////////////////////////////////////////////////////////////
-    // Dependencies (from IsisContext)
-    // ///////////////////////////////////////////////////////////////////
-
-    protected PersistenceSession getPersistenceSession() {
-        return IsisContext.getPersistenceSession();
-    }
-
-    protected AuthenticationSession getAuthenticationSession() {
-        return IsisContext.getAuthenticationSession();
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
index 74f9617..04a669e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
@@ -37,7 +37,7 @@ import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanel;
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorHelper;
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorPanel;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
index ec86034..e1ab0c1 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
@@ -30,9 +30,9 @@ 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.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
-import org.apache.isis.viewer.wicket.ui.components.entity.EntityActionLinkFactory;
+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.actionmenu.entityactions.EntityActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 
 /**

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
index 36e7f44..54f64f4 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
@@ -36,7 +36,7 @@ import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ImageResourceCache;
 import org.apache.isis.viewer.wicket.model.models.PageType;
-import org.apache.isis.viewer.wicket.ui.components.entity.EntityActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;


[3/5] isis git commit: ISIS-963: primary, secondary and tertiary menu support.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index aa40774..b7f1127 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -75,8 +75,8 @@ import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
 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.additionallinks.AdditionalLinksPanel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+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.components.widgets.formcomponent.CancelHintRequired;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
index ed4389a..2bd7cf1 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
@@ -50,7 +50,7 @@ import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.CollectionContentsAsFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.Components;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index ad93822..5aaeddc 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -43,7 +43,7 @@ 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.models.EntityModel.RenderingHint;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.TextFieldValueModel.ScalarModelProvider;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
@@ -168,7 +168,7 @@ public abstract class ScalarPanelAbstract extends PanelAbstract<ScalarModel> imp
      * Bit of a hack, but is an API to force the eager building of this component such that focus can be placed on it.
      *
      * <p>
-     *     This is used in {@link org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactoryAbstract}
+     *     This is used in {@link org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract}
      *     when creating the action prompt parameters panel.
      * </p>
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index f47e54d..6e41fd5 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -38,7 +38,7 @@ import org.apache.isis.core.metamodel.facets.objpropparam.typicallen.TypicalLeng
 import org.apache.isis.core.metamodel.facets.propparam.maxlen.MaxLengthFacet;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/isisapplib/IsisBlobOrClobPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/isisapplib/IsisBlobOrClobPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/isisapplib/IsisBlobOrClobPanelAbstract.java
index b6c6c8e..617f24d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/isisapplib/IsisBlobOrClobPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/isisapplib/IsisBlobOrClobPanelAbstract.java
@@ -51,7 +51,7 @@ import org.apache.isis.core.commons.lang.CloseableExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.util.Components;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
index cd57534..ff670f9 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
@@ -33,7 +33,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
index e580d77..7f925dc 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
@@ -46,7 +46,7 @@ import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending.Util;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.ObjectAdapterMementoProviderAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
index 89e7b50..101f26e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
@@ -37,7 +37,7 @@ import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.components.actionprompt.ActionPromptModalWindow;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
 import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsHelper;
 import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsLinkFactory;
 import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsProvider;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
deleted file mode 100644
index 9e3ca0a..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
+++ /dev/null
@@ -1,33 +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.widgets.cssmenu;
-
-import java.io.Serializable;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-
-public interface ActionLinkFactory extends Serializable {
-
-    LinkAndLabel newLink(
-            final ObjectAdapterMemento adapter,
-            final ObjectAction noAction,
-            final String linkId);
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
deleted file mode 100644
index 1142d14..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
+++ /dev/null
@@ -1,233 +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.widgets.cssmenu;
-
-import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.form.FormComponent;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.request.IRequestHandler;
-import org.apache.wicket.util.visit.IVisit;
-import org.apache.wicket.util.visit.IVisitor;
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.models.ActionModel;
-import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
-import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
-import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
-import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
-import org.apache.isis.viewer.wicket.ui.components.actionprompt.ActionPromptHeaderPanel;
-import org.apache.isis.viewer.wicket.ui.components.actions.ActionPanel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.AjaxDeferredBehaviour.OpenUrlStrategy;
-import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
-import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
-
-public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
-
-    private static final long serialVersionUID = 1L;
-
-    protected AbstractLink newLink(
-            final String linkId,
-            final ObjectAdapter objectAdapter,
-            final ObjectAction action) {
-        
-        final ActionModel actionModel = ActionModel.create(objectAdapter, action);
-
-        final AjaxDeferredBehaviour ajaxDeferredBehaviour = determineDeferredBehaviour(action, actionModel);
-
-        final AbstractLink link = new AjaxLink<Object>(linkId) {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public void onClick(AjaxRequestTarget target) {
-
-                if(ajaxDeferredBehaviour != null) {
-                    ajaxDeferredBehaviour.initiate(target);
-                } else {
-                    final ActionPromptProvider promptProvider = ActionPromptProvider.Util.getFrom(getPage());
-                    final ActionPrompt actionPrompt = promptProvider.getActionPrompt();
-                    ActionPromptHeaderPanel titlePanel = new ActionPromptHeaderPanel(actionPrompt.getTitleId(), actionModel);
-                    final ActionPanel actionPanel =
-                            (ActionPanel) getComponentFactoryRegistry().createComponent(
-                                    ComponentType.ACTION_PROMPT, actionPrompt.getContentId(), actionModel);
-
-                    actionPanel.setShowHeader(false);
-
-                    actionPrompt.setTitle(titlePanel, target);
-                    actionPrompt.setPanel(actionPanel, target);
-                    actionPanel.setActionPrompt(actionPrompt);
-                    actionPrompt.showPrompt(target);
-
-                    focusOnFirstParameter(target, actionPanel);
-                }
-            }
-
-            private void focusOnFirstParameter(AjaxRequestTarget target, ActionPanel actionPanel) {
-
-                // first, force all parameters to build themselves...
-                actionPanel.visitChildren(new IVisitor<Component, Component>() {
-                    @Override
-                    public void component(Component object, IVisit<Component> visit) {
-                        if (object instanceof ScalarPanelAbstract) {
-                            ScalarPanelAbstract spa = (ScalarPanelAbstract) object;
-                            spa.forceBuildGui();
-                            visit.dontGoDeeper();
-                        }
-                    }
-                });
-
-                // second, go searching for the first <input> in the action panel.
-                final Component actionPanelFirstParam = actionPanel.visitChildren(new IVisitor<Component, Component>() {
-                    @Override
-                    public void component(Component object, IVisit<Component> visit) {
-                        if (object instanceof FormComponent &&
-                            !"scalarIfCompact".equals(object.getId()) &&
-                            object.getOutputMarkupId()) {
-                            // there are components for 'compact' and 'regular'; we want the 'regular' one
-                            // also double check that has outputMarkupId enabled (prereq for setting focus)
-                            visit.stop(object);
-                        }
-                    }
-                });
-
-                // third, if found then use Wicket API to focus on this component
-                if(actionPanelFirstParam != null) {
-                    target.focusComponent(actionPanelFirstParam);
-                }
-            }
-
-            @Override
-            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
-                super.updateAjaxAttributes(attributes);
-
-                // allow the event to bubble so the menu is hidden after click on an item
-                attributes.setEventPropagation(AjaxRequestAttributes.EventPropagation.BUBBLE);
-            }
-
-            @Override
-            protected void onComponentTag(ComponentTag tag) {
-                super.onComponentTag(tag);
-
-                Buttons.fixDisabledState(this, tag);
-            }
-        };
-
-        if(ajaxDeferredBehaviour != null) {
-            link.add(ajaxDeferredBehaviour);
-        }
-
-        link.add(new CssClassAppender("noVeil"));
-
-        return link;
-    }
-
-    private static AjaxDeferredBehaviour determineDeferredBehaviour(final ObjectAction action, final ActionModel actionModel) {
-        // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
-        if(isNoArgReturnTypeRedirect(action)) {
-            /**
-             * adapted from:
-             * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
-             */
-            return new AjaxDeferredBehaviour(OpenUrlStrategy.NEW_WINDOW) {
-                
-                private static final long serialVersionUID = 1L;
-
-                @Override
-                protected IRequestHandler getRequestHandler() {
-                    ObjectAdapter resultAdapter = actionModel.executeHandlingApplicationExceptions();
-                    final Object value = resultAdapter.getObject();
-                    return ActionModel.redirectHandler(value);
-                }
-            };
-        } 
-        if(isNoArgReturnTypeDownload(action)) {
-
-            /**
-             * adapted from:
-             * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
-             */
-            return new AjaxDeferredBehaviour(OpenUrlStrategy.SAME_WINDOW) {
-                
-                private static final long serialVersionUID = 1L;
-   
-                @Override
-                protected IRequestHandler getRequestHandler() {
-                    final ObjectAdapter resultAdapter = actionModel.executeHandlingApplicationExceptions();
-                    final Object value = resultAdapter.getObject();
-                    return ActionModel.downloadHandler(value);
-                }
-            };
-        } 
-        return null;
-    }
-
-    // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
-    private static boolean isNoArgReturnTypeRedirect(final ObjectAction action) {
-        return action.getParameterCount() == 0 &&
-               action.getReturnType() != null && 
-               action.getReturnType().getCorrespondingClass() == java.net.URL.class;
-    }
-
-    // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
-    private static boolean isNoArgReturnTypeDownload(final ObjectAction action) {
-        return action.getParameterCount() == 0 && action.getReturnType() != null && 
-                (action.getReturnType().getCorrespondingClass() == org.apache.isis.applib.value.Blob.class ||
-                action.getReturnType().getCorrespondingClass() == org.apache.isis.applib.value.Clob.class);
-    }
-
-    protected LinkAndLabel newLinkAndLabel(final ObjectAction objectAction, final AbstractLink link, final String disabledReasonIfAny) {
-
-        final String label = ObjectAction.Utils.nameFor(objectAction);
-        final boolean blobOrClob = ObjectAction.Utils.returnsBlobOrClob(objectAction);
-        final boolean prototype = ObjectAction.Utils.isExplorationOrPrototype(objectAction);
-        final String actionIdentifier = ObjectAction.Utils.actionIdentifierFor(objectAction);
-        final String description = ObjectAction.Utils.descriptionOf(objectAction);
-        final ActionLayout.Position position = ObjectAction.Utils.actionLayoutPositionOf(objectAction);
-        final String cssClass = ObjectAction.Utils.cssClassFor(objectAction);
-        final String cssClassFa = ObjectAction.Utils.cssClassFaFor(objectAction);
-
-        return new LinkAndLabel(link, label, disabledReasonIfAny, description, blobOrClob, prototype, actionIdentifier, cssClass, cssClassFa, position);
-    }
-
-
-    // ////////////////////////////////////////////////////////////
-    // Dependencies
-    // ////////////////////////////////////////////////////////////
-    
-    protected ComponentFactoryRegistry getComponentFactoryRegistry() {
-        return ((ComponentFactoryRegistryAccessor)Application.get()).getComponentFactoryRegistry();
-    }
-    
-    protected PageClassRegistry getPageClassRegistry() {
-        return ((PageClassRegistryAccessor) Application.get()).getPageClassRegistry();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/AjaxDeferredBehaviour.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/AjaxDeferredBehaviour.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/AjaxDeferredBehaviour.java
deleted file mode 100644
index cdf06ca..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/AjaxDeferredBehaviour.java
+++ /dev/null
@@ -1,84 +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.widgets.cssmenu;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.behavior.AbstractAjaxBehavior;
-import org.apache.wicket.request.IRequestHandler;
-import org.apache.wicket.request.Url;
-import org.apache.wicket.request.UrlRenderer;
-import org.apache.wicket.request.cycle.RequestCycle;
-
-import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseHandlingStrategy;
-
-public abstract class AjaxDeferredBehaviour extends AbstractAjaxBehavior {
-    private static final long serialVersionUID = 1L;
-
-    public static enum OpenUrlStrategy {
-        NEW_WINDOW {
-            @Override
-            public String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
-                final Url parsedUrl = Url.parse(url);
-                final RequestCycle requestCycle = deferredBehaviour.getComponent().getRequestCycle();
-                final UrlRenderer urlRenderer = requestCycle.getUrlRenderer();
-                String fullUrl = urlRenderer.renderFullUrl(parsedUrl);
-                return "function(){Wicket.Event.publish(Isis.Topic.OPEN_IN_NEW_TAB, '" + fullUrl + "');}";
-            }
-        },
-        SAME_WINDOW {
-            @Override
-            public String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url) {
-                return "\"window.location.href='" + url + "'\"";
-            }
-        };
-
-        public abstract String javascriptFor(AjaxDeferredBehaviour deferredBehaviour, String url);
-    }
-    
-    private final OpenUrlStrategy openUrlStrategy;
-    
-    protected AjaxDeferredBehaviour(final OpenUrlStrategy openUrlStrategy) {
-        this.openUrlStrategy = openUrlStrategy;
-    }
-
-    /**
-     * Call this method to initiate the download.
-     */
-    public void initiate(AjaxRequestTarget target) {
-        String url = getCallbackUrl().toString();
-
-        url = ActionResultResponseHandlingStrategy.expanded(url);
-        String func = openUrlStrategy.javascriptFor(this, url);
-
-        // the timeout is needed to let Wicket release the channel
-        String javascriptFor = "setTimeout(" + func + ", 100);";
-        target.appendJavaScript(javascriptFor);
-    }
-
-    @Override
-    public void onRequest() {
-        IRequestHandler handler = getRequestHandler();
-        if(handler != null) {
-            getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
-        }
-    }
-
-    protected abstract IRequestHandler getRequestHandler();
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.css
deleted file mode 100644
index 87a8864..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.css
+++ /dev/null
@@ -1,340 +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.
- */
-
-
-/* copied from CssMenuPanel.css (since deleted that panel */
-
-
-
-.cssMenuPanel span.clear {
-    line-height: 3px;
-}
-
-.cssMenuPanel .menuh .small {
-    float: none;
-    display: inline;
-}
-
-.cssMenuPanel .menuh p .small {
-    float: none;
-    display: inline;
-}
-
-.menuh a,.menuh p {
-    text-align: left;
-    display: block;
-    white-space: nowrap;
-    margin: 0;
-    padding: 1px;
-    padding-right: 1.6em;
-    padding-left: 0.4em;
-    font-weight: normal;
-    cursor: default;
-}
-
-.cssMenuPanel .menuh a:hover {
-    text-decoration: underline;
-}
-
-.cssMenuPanel .menuh a.top-parent,.cssMenuPanel .menuh p.top-parent {
-    background-position: right center;
-    background-repeat: no-repeat;
-}
-
-.cssMenuPanel .menuh a.top-parent:hover,.cssMenuPanel .menuh p.top-parent:hover	{
-    background-position: right center;
-    background-repeat: no-repeat;
-}
-
-.cssMenuPanel .menuh a.parent,.cssMenuPanel .menuh p.parent {
-    background-position: right center;
-    background-repeat: no-repeat;
-}
-
-.cssMenuPanel .menuh a.parent:hover,.cssMenuPanel .menuh p.parent:hover	{
-    background-position: right center;
-    background-repeat: no-repeat;
-}
-
-.cssMenuPanel .menuh ul {
-    list-style: none;
-    margin: 0;
-    padding: 0;
-    float: left;
-    display: inline;
-}
-
-.cssMenuPanel .menuh li {
-    position: relative;
-    min-height: 1px;
-}
-
-.cssMenuPanel .menuh ul ul {
-    position: absolute;
-    z-index: 500;
-    top: auto;
-    display: none;
-    padding: 1em;
-    margin: -1em 0 0 -1em;
-}
-
-.cssMenuPanel .menuh ul ul ul {
-    top: 0;
-    left: 100%;
-}
-
-.cssMenuPanel span.menuh a:hover {
-    cursor: pointer;
-    z-index: 100;
-}
-
-.cssMenuPanel span.menuh li:hover ul ul,.cssMenuPanel span.menuh li li:hover ul ul,.cssMenuPanel span.menuh li li li:hover ul ul,.cssMenuPanel span.menuh li li li li:hover ul ul {
-    display: none;
-}
-
-.cssMenuPanel span.menuh li:hover ul,.cssMenuPanel span.menuh li li:hover ul,.cssMenuPanel span.menuh li li li:hover ul,.cssMenuPanel span.menuh li li li li:hover ul {
-    display: block;
-}
-
-.cssMenuPanel li.cssSubMenuItem p.disabled {
-    cursor: not-allowed;
-}
-
-.cssMenuPanel li.cssSubMenuItem {
-    margin-left:0;
-}
-
-/******** overrides for grouped actions and entity actions ***************/
-.groupedActions .cssMenuPanel li.cssMenuItemPanel>p.top-parent {
-    display: none;
-}
-
-.groupedActions .cssMenuPanel .menuh ul {
-    position: relative;
-    display: block;
-    float: right;
-    margin: 0;
-    padding: 0;
-}
-
-.groupedActions .cssMenuPanel .menuh ul ul {
-    position: relative;
-    display: block;
-    float: right;
-    margin: 0;
-    padding: 0;
-}
-
-.groupedActions .cssMenuPanel .menuh li,
-.groupedActions .cssMenuPanel .menuh li p	{
-    float:left;
-    display:block;
-    margin-left:10px;
-}
-
-.groupedActions .cssMenuPanel .menuh a,.groupedActions .cssMenuPanel .menuh p
-{
-    display: inline-block;
-    border: none;
-}
-
-.groupedActions .cssMenuPanel .menuh a:link,
-.groupedActions .cssMenuPanel .menuh a:visited,
-.groupedActions .cssMenuPanel .menuh a:active,
-.groupedActions .cssMenuPanel .menuh p {
-    display: block;
-    float: left;
-    height: 30px;
-    line-height: 30px;
-    padding: 0 10px;
-    font-weight: bold;
-    /*font-size: 0.85em;*/
-    border-radius: 4px;
-    -moz-border-radius: 4px;
-    -webkit-border-radius: 4px;
-    text-decoration: none;
-}
-
-.entityActions .cssMenuPanel li.cssMenuItemPanel>p.top-parent {
-    display: none;
-}
-
-.entityActions .cssMenuPanel .menuh ul {
-    position: relative;
-    display: block;
-    float: right;
-    margin: 0 0 10px;
-    padding: 0;
-}
-
-.entityActions .cssMenuPanel .menuh ul ul {
-    position: relative;
-    display: block;
-    float: right;
-    margin: 0;
-    padding: 0;
-}
-
-.entityActions .cssMenuPanel .menuh li {
-    float:left;
-    display:block;
-    margin-left:10px;
-}
-
-.entityActions .cssMenuPanel .menuh li p {
-    float:left;
-    display:block;
-    margin-left:0;
-}
-
-.entityActions .cssMenuPanel .menuh a,
-.entityActions .cssMenuPanel .menuh p {
-    display: inline-block;
-    /*border: none;*/
-}
-
-.entityActions .cssMenuPanel .menuh a,
-.entityActions .cssMenuPanel .menuh a:link,
-.entityActions .cssMenuPanel .menuh a:visited,
-.entityActions .cssMenuPanel .menuh a:active,
-.entityActions .cssMenuPanel .menuh p {
-    display: block;
-    float: left;
-    height: 30px;
-    /*line-height: 30px;*/
-    padding: 4px 10px 0;
-    /*font-size:0.85em;*/
-    border-radius:4px;
-    -moz-border-radius:4px;
-    -webkit-border-radius:4px;
-    text-decoration:none;
-}
-
-.additionalLinkList {
-    float:left;
-    margin:0;
-    padding:0;
-    list-style:none;
-}
-
-.entityCollectionsPanel .panel-heading .additionalLinkList {
-    margin-right: 10px;
-}
-
-.additionalLinkList li {
-    float:left;
-    margin-right:10px;
-    /*	margin-bottom: 2px;*/
-}
-.entityPropertiesPanel .additionalLinkList li {
-    margin-right:0px;
-}
-.entityPropertiesPanel .properties .panel-heading .additionalLinkList {
-    margin-right: -5px;
-}
-
-
-
-
-
-/**
- * Borrowed from http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3
- */
-
-.dropdown-submenu {
-    position: relative;
-}
-
-.dropdown-submenu>.dropdown-menu {
-    top: 0;
-    left: 100%;
-    margin-top: -6px;
-    margin-left: -1px;
-    -webkit-border-radius: 0 6px 6px 6px;
-    -moz-border-radius: 0 6px 6px;
-    border-radius: 0 6px 6px 6px;
-}
-
-.dropdown-submenu:hover>.dropdown-menu {
-    display: block;
-}
-
-.dropdown-submenu>a:after {
-    display: block;
-    content: " ";
-    float: right;
-    width: 0;
-    height: 0;
-    border-color: transparent;
-    border-style: solid;
-    border-width: 5px 0 5px 5px;
-    border-left-color: #ccc;
-    margin-top: 5px;
-    margin-right: -10px;
-}
-
-.dropdown-submenu:hover>a:after {
-    border-left-color: #fff;
-}
-
-.dropdown-submenu.pull-left {
-    float: none;
-}
-
-.dropdown-submenu.pull-left>.dropdown-menu {
-    left: -100%;
-    margin-left: 10px;
-    -webkit-border-radius: 6px 0 6px 6px;
-    -moz-border-radius: 6px 0 6px 6px;
-    border-radius: 6px 0 6px 6px;
-}
-
-.dropdown-menu > li > a.menuLink {
-    padding-left: 0;
-}
-
-.dropdown-menu > li > span.fa {
-    padding-left: 3px;
-}
-
-.dropdown-menu .fontAwesomeIcon {
-    min-width: 20px;
-}
-
-.dropdown-menu > li > a.menuLink.btn-warning:hover {
-    background-color: inherit;
-    background-image: inherit;
-}
-
-.dropdown-menu > li > a.menuLink.menuLinkSpacer {
-    padding-left: 24px;
-}
-
-.dropdown-menu > li > a.btn.btn-warning {
-    text-align: start;
-    border-radius: 0;
-    color: initial;
-}
-
-.scrollable-menu {
-    min-width: 250px;
-    height: auto;
-    max-height: 600px;
-    overflow-x: hidden;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.html
deleted file mode 100644
index 3a6dd5d..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:wicket="http://wicket.apache.org">
-    <body>
-        <wicket:panel>
-            <li class="dropdown" wicket:id="menuItems">
-                <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><span wicket:id="name"></span> <span class="caret"></span></a>
-                <ul wicket:id="topMenu" class="dropdown-menu scrollable-menu multi-level" role="menu">
-                    <li wicket:id="subMenuItems">
-                        <wicket:container wicket:id="content"></wicket:container>
-                    </li>
-                </ul>
-            </li>
-
-            <wicket:fragment wicket:id="leafItem">
-                <a class="menuLink" wicket:id="menuLink">
-                    <span class="fontAwesomeIcon" wicket:id="menuLinkFontAwesome"></span> <span class="menuLinkLabel" wicket:id="menuLinkLabel"></span>
-                </a>
-            </wicket:fragment>
-
-            <wicket:fragment wicket:id="folderItem">
-                <a wicket:id="folderName" tabindex="-1"></a>
-                <ul class="dropdown-menu">
-                    <li wicket:id="subMenuItems">
-                        <wicket:container wicket:id="content"></wicket:container>
-                    </li>
-                </ul>
-            </wicket:fragment>
-
-            <wicket:fragment wicket:id="empty">
-            </wicket:fragment>
-
-
-        </wicket:panel>
-    </body>
-</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.java
deleted file mode 100644
index 5208189..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ApplicationActionsPanel.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu;
-
-import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipBehavior;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.button.DropdownAutoOpenJavaScriptReference;
-
-import java.util.List;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.markup.head.CssHeaderItem;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.JavaScriptHeaderItem;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.markup.html.link.ExternalLink;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.resource.CssResourceReference;
-import org.apache.isis.viewer.wicket.ui.util.Components;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
-
-/**
- * A panel responsible to render the application actions as menu in a navigation bar.
- *
- * <p>
- *     The multi-level sub menu support is borrowed from
- *     <a href="http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3">Bootsnip</a>
- * </p>
- */
-public class ApplicationActionsPanel extends Panel {
-
-    /**
-     * Constructor.
-     *
-     * @param id
-     *          the Wicket component id
-     * @param menuItems
-     *          the menu items with their sub menu items
-     */
-    public ApplicationActionsPanel(String id, List<CssMenuItem> menuItems) {
-        super(id);
-
-        ListView<CssMenuItem> menuItemsView = new ListView<CssMenuItem>("menuItems", menuItems) {
-
-            @Override
-            protected void populateItem(ListItem<CssMenuItem> listItem) {
-                CssMenuItem menuItem = listItem.getModelObject();
-                listItem.add(new Label("name", menuItem.getName()));
-
-                MarkupContainer topMenu = new WebMarkupContainer("topMenu");
-
-                topMenu.add(new CssClassAppender("top-menu-" + CssClassAppender.asCssStyle(menuItem.getName())));
-                listItem.add(topMenu);
-                List<CssMenuItem> subMenuItems = withSeparators(menuItem);
-
-// fake data to test multi-level menus
-//                if (menuItem.getName().equals("ToDos")) {
-//                    CssMenuItem fakeItem = menuItem.newSubMenuItem("Fake item").build();
-//
-//                    fakeItem.newSubMenuItem("Fake item 1").link(new ExternalLink("menuLink", "http://abv.bg")).build();
-//                    CssMenuItem fakeMenu12 = fakeItem.newSubMenuItem("Fake item 2").link(new ExternalLink("menuLink", "http://google.com")).build();
-//
-//                    fakeMenu12.newSubMenuItem("Fake item 2.1").link(new ExternalLink("menuLink", "http://web.de")).build();
-//                }
-
-                ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems", subMenuItems) {
-                    @Override
-                    protected void populateItem(ListItem<CssMenuItem> listItem) {
-                        CssMenuItem subMenuItem = listItem.getModelObject();
-
-                        if (subMenuItem.hasSubMenuItems()) {
-                            addFolderItem(subMenuItem, listItem);
-                        } else {
-                            addLeafItem(subMenuItem, listItem);
-                        }
-                    }
-                };
-                topMenu.add(subMenuItemsView);
-            }
-        };
-        add(menuItemsView);
-    }
-
-    private void addFolderItem(CssMenuItem subMenuItem, ListItem<CssMenuItem> listItem) {
-
-        listItem.add(new CssClassAppender("dropdown-submenu"));
-
-        Fragment folderItem = new Fragment("content", "folderItem", ApplicationActionsPanel.this);
-        listItem.add(folderItem);
-
-        folderItem.add(new Label("folderName", subMenuItem.getName()));
-        final List<CssMenuItem> menuItems = withSeparators(subMenuItem);
-        ListView<CssMenuItem> subMenuItemsView = new ListView<CssMenuItem>("subMenuItems",
-                menuItems) {
-            @Override
-            protected void populateItem(ListItem<CssMenuItem> listItem) {
-                CssMenuItem subMenuItem = listItem.getModelObject();
-
-                if (subMenuItem.hasSubMenuItems()) {
-                    addFolderItem(subMenuItem, listItem);
-                } else {
-                    addLeafItem(subMenuItem, listItem);
-                }
-            }
-        };
-        folderItem.add(subMenuItemsView);
-    }
-
-    private List<CssMenuItem> withSeparators(CssMenuItem subMenuItem) {
-        final List<CssMenuItem> subMenuItems = subMenuItem.getSubMenuItems();
-        final List<CssMenuItem> itemsWithSeparators = Lists.newArrayList();
-        for (CssMenuItem menuItem : subMenuItems) {
-            if(menuItem.isSeparator() ) {
-                if(!itemsWithSeparators.isEmpty()) {
-                    // bit nasty... we add a new separator item
-                    itemsWithSeparators.add(
-                            CssMenuItem.newMenuItem(menuItem.getName() + "-separator")
-                                    .separator(menuItem.isSeparator())
-                                    .prototyping(menuItem.isPrototyping())
-                                    .build());
-                }
-                menuItem.setSeparator(false);
-            }
-            itemsWithSeparators.add(menuItem);
-        }
-        return itemsWithSeparators;
-    }
-
-    private void addLeafItem(
-            final CssMenuItem menuItem,
-            final ListItem<CssMenuItem> listItem) {
-
-        Fragment leafItem;
-        if (!menuItem.isSeparator()) {
-            leafItem = new Fragment("content", "leafItem", ApplicationActionsPanel.this);
-
-            AbstractLink subMenuItemLink = menuItem.getLink();
-
-            Label menuItemLabel = new Label("menuLinkLabel", menuItem.getName());
-            subMenuItemLink.addOrReplace(menuItemLabel);
-
-            if (!menuItem.isEnabled()) {
-                listItem.add(new CssClassAppender("disabled"));
-                subMenuItemLink.setEnabled(false);
-                TooltipBehavior tooltipBehavior = new TooltipBehavior(Model.of(menuItem.getDisabledReason()));
-                listItem.add(tooltipBehavior);
-            }
-            if (menuItem.isPrototyping()) {
-                subMenuItemLink.add(new CssClassAppender("prototype"));
-            }
-            leafItem.add(subMenuItemLink);
-
-            String cssClassFa = menuItem.getCssClassFa();
-            if (Strings.isNullOrEmpty(cssClassFa)) {
-                Components.permanentlyHide(subMenuItemLink, "menuLinkFontAwesome");
-                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
-            } else {
-                Label dummy = new Label("menuLinkFontAwesome", "");
-                dummy.add(new CssClassAppender(cssClassFa));
-                subMenuItemLink.addOrReplace(dummy);
-            }
-        } else {
-            leafItem = new Fragment("content", "empty", ApplicationActionsPanel.this);
-            listItem.add(new CssClassAppender("divider"));
-        }
-        listItem.add(leafItem);
-
-    }
-
-    @Override
-    public void renderHead(IHeaderResponse response) {
-        super.renderHead(response);
-
-        response.render(CssHeaderItem.forReference(new CssResourceReference(ApplicationActionsPanel.class, "ApplicationActionsPanel.css")));
-        response.render(JavaScriptHeaderItem.forReference(DropdownAutoOpenJavaScriptReference.instance()));
-        response.render(OnDomReadyHeaderItem.forScript("$('.dropdown-toggle').dropdownHover();"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
deleted file mode 100644
index 88caef5..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
+++ /dev/null
@@ -1,441 +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.widgets.cssmenu;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.Component;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.Page;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.SubmitLink;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.model.Model;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.ensure.Ensure;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.consent.Consent;
-import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
-import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
-import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaFacet;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-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.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.model.models.ActionModel;
-import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
-import org.apache.isis.viewer.wicket.ui.util.Components;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
-
-import static org.hamcrest.CoreMatchers.is;
-
-;
-
-public class CssMenuItem implements Serializable {
-
-
-    private static final long serialVersionUID = 1L;
-
-    public static final String ID_MENU_LINK = "menuLink";
-
-    public static class Builder {
-        private final CssMenuItem cssMenuItem;
-
-        private Builder(final String name) {
-            cssMenuItem = new CssMenuItem(name);
-        }
-
-        public Builder parent(final CssMenuItem parent) {
-            cssMenuItem.setParent(parent);
-            return this;
-        }
-
-        public <T extends Page> Builder link() {
-            final AbstractLink link = new SubmitLink(ID_MENU_LINK); 
-            return link(link);
-        }
-
-        public <T extends Page> Builder link(final AbstractLink link) {
-            Ensure.ensureThatArg(link.getId(), is(ID_MENU_LINK));
-            cssMenuItem.setLink(link);
-            return this;
-        }
-
-        public <T extends Page> Builder enabled(final String disabledReasonIfAny) {
-            cssMenuItem.setEnabled(disabledReasonIfAny == null);
-            cssMenuItem.setDisabledReason(disabledReasonIfAny);
-            return this;
-        }
-
-        public Builder describedAs(String descriptionIfAny) {
-            cssMenuItem.setDescription(descriptionIfAny);
-            return this;
-        }
-
-        public Builder returnsBlobOrClob(boolean blobOrClob) {
-            cssMenuItem.setReturnsBlobOrClob(blobOrClob);
-            return this;
-        }
-
-        public Builder prototyping(boolean prototype) {
-            cssMenuItem.setPrototyping(prototype);
-            return this;
-        }
-
-        public Builder separator(boolean separator) {
-            cssMenuItem.setSeparator(separator);
-            return this;
-        }
-
-        public Builder withActionIdentifier(String actionIdentifier) {
-            cssMenuItem.setActionIdentifier(actionIdentifier);
-            return this;
-        }
-
-        public Builder withFacet(CssClassFacet facet) {
-            if(facet != null) {
-                withCssClass(facet.value());
-            }
-            return this;
-        }
-
-        public Builder withCssClass(String cssClass) {
-            cssMenuItem.setCssClass(cssClass);
-            return this;
-        }
-
-        public Builder withFacet(CssClassFaFacet facet) {
-            if(facet != null) {
-                withCssClassFa(facet.value());
-            }
-            return this;
-        }
-
-        public Builder withCssClassFa(String cssClassFa) {
-            cssMenuItem.setCssClassFa(cssClassFa);
-            return this;
-        }
-
-        /**
-         * Returns the built {@link CssMenuItem}, associating with
-         * {@link #parent(CssMenuItem) parent} (if specified).
-         */
-        public CssMenuItem build() {
-            if (cssMenuItem.parent != null) {
-                cssMenuItem.parent.subMenuItems.add(cssMenuItem);
-            }
-            return cssMenuItem;
-        }
-
-    }
-
-    private final String name;
-    private final List<CssMenuItem> subMenuItems = Lists.newArrayList();
-    private CssMenuItem parent;
-
-    private AbstractLink link;
-    private boolean enabled = true; // unless disabled
-    private String disabledReason;
-    private boolean blobOrClob = false; // unless set otherwise
-    private boolean prototype = false; // unless set otherwise
-    private boolean separator = false; // unless set otherwise
-
-    static final String ID_MENU_LABEL = "menuLabel";
-
-    static final String ID_SUB_MENU_ITEMS = "subMenuItems";
-
-    private String actionIdentifier;
-    private String cssClass;
-    private String cssClassFa;
-
-    private String description;
-
-
-
-    /**
-     * Factory method returning {@link Builder builder}.
-     */
-    public static Builder newMenuItem(final String name) {
-        return new Builder(name);
-    }
-
-
-    public void setActionIdentifier(String actionIdentifier) {
-        this.actionIdentifier = actionIdentifier;
-    }
-
-    public void setPrototyping(boolean prototype) {
-        this.prototype = prototype;
-    }
-
-    public boolean isPrototyping() {
-        return prototype;
-    }
-
-    public void setSeparator(boolean separator) {
-        this.separator = separator;
-    }
-
-    /**
-     * Requires a separator before it
-     * @return
-     */
-    public boolean isSeparator() {
-        return separator;
-    }
-
-    private CssMenuItem(final String name) {
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public boolean hasParent() {
-        return parent != null;
-    }
-
-    private void setParent(final CssMenuItem parent) {
-        this.parent = parent;
-    }
-
-    public Builder newSubMenuItem(final String name) {
-        return CssMenuItem.newMenuItem(name).parent(this);
-    }
-
-    public List<CssMenuItem> getSubMenuItems() {
-        return Collections.unmodifiableList(subMenuItems);
-    }
-
-    public boolean hasSubMenuItems() {
-        return subMenuItems.size() > 0;
-    }
-
-    public AbstractLink getLink() {
-        return link;
-    }
-
-    private void setLink(final AbstractLink link) {
-        this.link = link;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    private void setEnabled(final boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public void setReturnsBlobOrClob(boolean blobOrClob) {
-        this.blobOrClob = blobOrClob;
-    }
-
-    public void setCssClass(String cssClass) {
-        this.cssClass = cssClass;
-    }
-
-    public void setCssClassFa(String cssClassFa) {
-        this.cssClassFa = cssClassFa;
-    }
-
-    public String getCssClassFa() {
-        return cssClassFa;
-    }
-
-
-    /**
-     * Only populated if not {@link #isEnabled() enabled}.
-     */
-    public String getDisabledReason() {
-        return disabledReason;
-    }
-
-    public void setDisabledReason(final String disabledReason) {
-        this.disabledReason = disabledReason;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // To add submenu items
-    // //////////////////////////////////////////////////////////////
-
-    /**
-     * Creates a {@link Builder} for a submenu item invoking an action on the provided
-     * {@link ObjectAdapterMemento target adapter}.
-     */
-    public Builder newSubMenuItem(
-            final ObjectAdapterMemento targetAdapterMemento,
-            final ObjectAction objectAction,
-            final boolean separator,
-            final ActionLinkFactory actionLinkFactory) {
-
-        // check visibility
-        final AuthenticationSession session = getAuthenticationSession();
-        final ObjectAdapter adapter = targetAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
-        final Consent visibility = objectAction.isVisible(session, adapter, ActionModel.WHERE_FOR_ACTION_INVOCATION);
-        if (visibility.isVetoed()) {
-            return null;
-        }
-
-        // build the link
-        final LinkAndLabel linkAndLabel = actionLinkFactory.newLink(
-                targetAdapterMemento, objectAction, PageAbstract.ID_MENU_LINK
-        );
-        if(linkAndLabel==null) {
-            // can only get a null if invisible, so this should not happen given guard above
-            return null;
-        }
-        final AbstractLink link = linkAndLabel.getLink();
-        final String actionLabel = linkAndLabel.getLabel();
-
-        final Consent usability = objectAction.isUsable(session, adapter, ActionModel.WHERE_FOR_ACTION_INVOCATION);
-        final String reasonDisabledIfAny = usability.getReason();
-        
-        final DescribedAsFacet describedAsFacet = objectAction.getFacet(DescribedAsFacet.class);
-        final String descriptionIfAny = describedAsFacet != null? describedAsFacet.value(): null;
-
-        Builder builder = newSubMenuItem(actionLabel)
-                .link(link)
-                .describedAs(descriptionIfAny)
-                .enabled(reasonDisabledIfAny)
-                .returnsBlobOrClob(ObjectAction.Utils.returnsBlobOrClob(objectAction))
-                .prototyping(ObjectAction.Utils.isExplorationOrPrototype(objectAction))
-                .separator(separator)
-                .withActionIdentifier(ObjectAction.Utils.actionIdentifierFor(objectAction))
-                .withCssClass(ObjectAction.Utils.cssClassFor(objectAction))
-                .withCssClassFa(ObjectAction.Utils.cssClassFaFor(objectAction));
-
-        return builder;
-    }
-
-
-    // //////////////////////////////////////////////////////////////
-    // Build wicket components from the menu item.
-    // //////////////////////////////////////////////////////////////
-
-    void addTo(final MarkupContainer markupContainer) {
-
-        final Component menuItemComponent = addMenuItemComponentTo(markupContainer);
-        addSubMenuItemComponentsIfAnyTo(markupContainer);
-
-        addCssClassAttributesIfRequired(menuItemComponent);
-    }
-
-    private Component addMenuItemComponentTo(final MarkupContainer markupContainer) {
-        final AbstractLink link = getLink();
-        final Label label = new Label(CssMenuItem.ID_MENU_LABEL, Model.of(this.getName()));
-
-        if (link != null) {
-
-            // show link...
-            markupContainer.add(link);
-            link.add(label);
-
-            if(this.description != null) {
-                label.add(new AttributeModifier("title", Model.of(description)));
-            }
-            if(this.blobOrClob) {
-                link.add(new CssClassAppender("noVeil"));
-            }
-            if(this.prototype) {
-                link.add(new CssClassAppender("prototype"));
-            }
-
-
-            if(this.cssClass != null) {
-                link.add(new CssClassAppender(this.cssClass));
-            }
-            link.add(new CssClassAppender(this.actionIdentifier));
-
-            String cssClassFa = getCssClassFa();
-            if (Strings.isNullOrEmpty(cssClassFa)) {
-                Components.permanentlyHide(link, "menuLinkFontAwesome");
-            } else {
-                Label dummy = new Label("menuLinkFontAwesome", "");
-                dummy.add(new CssClassAppender(cssClassFa));
-                link.add(dummy);
-            }
-
-            if(! this.isEnabled()) {
-                link.add(new AttributeModifier("title", Model.of(this.getDisabledReason())));
-                link.add(new CssClassAppender("disabled"));
-
-                link.setEnabled(false);
-            }
-
-            // .. and hide label
-            Components.permanentlyHide(markupContainer, CssMenuItem.ID_MENU_LABEL);
-            return link;
-        } else {
-            // hide link...
-            Components.permanentlyHide(markupContainer, ID_MENU_LINK);
-            // ... and show label, along with disabled reason
-            label.add(new AttributeModifier("title", Model.of(this.getDisabledReason())));
-            label.add(new AttributeModifier("class", Model.of("disabled")));
-
-            markupContainer.add(label);
-
-            return label;
-        }
-    }
-
-    private void addSubMenuItemComponentsIfAnyTo(final MarkupContainer menuItemMarkup) {
-        final List<CssMenuItem> subMenuItems = getSubMenuItems();
-        if (subMenuItems.isEmpty()) {
-            Components.permanentlyHide(menuItemMarkup, CssMenuItem.ID_SUB_MENU_ITEMS);
-        } else {
-            menuItemMarkup.add(new CssSubMenuItemsPanel(CssMenuItem.ID_SUB_MENU_ITEMS, subMenuItems));
-        }
-    }
-
-    private void addCssClassAttributesIfRequired(final Component linkComponent) {
-        if (!hasSubMenuItems()) {
-            return;
-        }
-        if (this.hasParent()) {
-            linkComponent.add(new CssClassAppender("parent"));
-        } else {
-            linkComponent.add(new CssClassAppender("top-parent"));
-        }
-    }
-
-    // //////////////////////////////////////////////////////////////
-    // dependencies
-    // //////////////////////////////////////////////////////////////
-
-    protected AuthenticationSession getAuthenticationSession() {
-        return IsisContext.getAuthenticationSession();
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItemPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItemPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItemPanelAbstract.java
deleted file mode 100644
index 832515b..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItemPanelAbstract.java
+++ /dev/null
@@ -1,47 +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.widgets.cssmenu;
-
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.model.IModel;
-
-import org.apache.isis.viewer.wicket.ui.ComponentFactory;
-import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
-import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
-
-/**
- * Package-level adapter for menu items and submenu-items.
- */
-abstract class CssMenuItemPanelAbstract<T extends IModel<?>> extends PanelAbstract<T> {
-
-    private static final long serialVersionUID = 1L;
-
-    public CssMenuItemPanelAbstract(final String id, final T model) {
-        super(id, model);
-        setRenderBodyOnly(true);
-    }
-
-    protected void addSubMenuItems(final WebMarkupContainer markupContainer, final CssMenuItem cssMenuItem) {
-        cssMenuItem.addTo(markupContainer);
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.html
deleted file mode 100644
index 9c1e14f..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.html
+++ /dev/null
@@ -1,35 +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>
-    <ul class="cssSubMenuItemsPanel">
-        <li wicket:id="subMenuItems" class="cssSubMenuItem">
-            <a wicket:id="menuLink" class="btn btn-primary btn-sm">
-                <span class="fontAwesomeIcon" wicket:id="menuLinkFontAwesome"></span>
-                <span class="menuLabel" wicket:id="menuLabel">[menu label]</span>
-            </a>
-            <p wicket:id="menuLabel">[menu label]</p>
-            <span wicket:id="subMenuItems">[subMenuItems]</span>
-        </li>
-    </ul>
-</wicket:panel>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.java
deleted file mode 100644
index 092e1fe..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssSubMenuItemsPanel.java
+++ /dev/null
@@ -1,59 +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.widgets.cssmenu;
-
-import java.util.List;
-
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.repeater.RepeatingView;
-import org.apache.wicket.model.util.ListModel;
-
-/**
- * Panel containing a list of {@link CssMenuItem}s acting as submenus of a
- * parent {@link CssMenuItem}.
- */
-public class CssSubMenuItemsPanel extends CssMenuItemPanelAbstract<CssSubMenuItemsPanel.MyModel> {
-
-    private static final long serialVersionUID = 1L;
-
-    static class MyModel extends ListModel<CssMenuItem> {
-
-        private static final long serialVersionUID = 1L;
-
-        public MyModel(final List<CssMenuItem> cssMenuItems) {
-            super(cssMenuItems);
-        }
-    }
-
-    public CssSubMenuItemsPanel(final String id, final List<CssMenuItem> subMenuItems) {
-        super(id, new MyModel(subMenuItems));
-        setRenderBodyOnly(true);
-
-        final RepeatingView menuItemRv = new RepeatingView(getId());
-        add(menuItemRv);
-        for (final CssMenuItem cssMenuItem : getModel().getObject()) {
-            final WebMarkupContainer menuItemMarkup = new WebMarkupContainer(menuItemRv.newChildId());
-            menuItemRv.add(menuItemMarkup);
-
-            addSubMenuItems(menuItemMarkup, cssMenuItem);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
new file mode 100644
index 0000000..6c07221
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
@@ -0,0 +1,33 @@
+/*
+ *  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.widgets.linkandlabel;
+
+import java.io.Serializable;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+
+public interface ActionLinkFactory extends Serializable {
+
+    LinkAndLabel newLink(
+            final ObjectAdapterMemento adapter,
+            final ObjectAction noAction,
+            final String linkId);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
new file mode 100644
index 0000000..dff6cd9
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
@@ -0,0 +1,232 @@
+/*
+ *  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.widgets.linkandlabel;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
+import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
+import org.apache.isis.viewer.wicket.ui.components.actionprompt.ActionPromptHeaderPanel;
+import org.apache.isis.viewer.wicket.ui.components.actions.ActionPanel;
+import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    protected AbstractLink newLink(
+            final String linkId,
+            final ObjectAdapter objectAdapter,
+            final ObjectAction action) {
+        
+        final ActionModel actionModel = ActionModel.create(objectAdapter, action);
+
+        final AjaxDeferredBehaviour ajaxDeferredBehaviour = determineDeferredBehaviour(action, actionModel);
+
+        final AbstractLink link = new AjaxLink<Object>(linkId) {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public void onClick(AjaxRequestTarget target) {
+
+                if(ajaxDeferredBehaviour != null) {
+                    ajaxDeferredBehaviour.initiate(target);
+                } else {
+                    final ActionPromptProvider promptProvider = ActionPromptProvider.Util.getFrom(getPage());
+                    final ActionPrompt actionPrompt = promptProvider.getActionPrompt();
+                    ActionPromptHeaderPanel titlePanel = new ActionPromptHeaderPanel(actionPrompt.getTitleId(), actionModel);
+                    final ActionPanel actionPanel =
+                            (ActionPanel) getComponentFactoryRegistry().createComponent(
+                                    ComponentType.ACTION_PROMPT, actionPrompt.getContentId(), actionModel);
+
+                    actionPanel.setShowHeader(false);
+
+                    actionPrompt.setTitle(titlePanel, target);
+                    actionPrompt.setPanel(actionPanel, target);
+                    actionPanel.setActionPrompt(actionPrompt);
+                    actionPrompt.showPrompt(target);
+
+                    focusOnFirstParameter(target, actionPanel);
+                }
+            }
+
+            private void focusOnFirstParameter(AjaxRequestTarget target, ActionPanel actionPanel) {
+
+                // first, force all parameters to build themselves...
+                actionPanel.visitChildren(new IVisitor<Component, Component>() {
+                    @Override
+                    public void component(Component object, IVisit<Component> visit) {
+                        if (object instanceof ScalarPanelAbstract) {
+                            ScalarPanelAbstract spa = (ScalarPanelAbstract) object;
+                            spa.forceBuildGui();
+                            visit.dontGoDeeper();
+                        }
+                    }
+                });
+
+                // second, go searching for the first <input> in the action panel.
+                final Component actionPanelFirstParam = actionPanel.visitChildren(new IVisitor<Component, Component>() {
+                    @Override
+                    public void component(Component object, IVisit<Component> visit) {
+                        if (object instanceof FormComponent &&
+                            !"scalarIfCompact".equals(object.getId()) &&
+                            object.getOutputMarkupId()) {
+                            // there are components for 'compact' and 'regular'; we want the 'regular' one
+                            // also double check that has outputMarkupId enabled (prereq for setting focus)
+                            visit.stop(object);
+                        }
+                    }
+                });
+
+                // third, if found then use Wicket API to focus on this component
+                if(actionPanelFirstParam != null) {
+                    target.focusComponent(actionPanelFirstParam);
+                }
+            }
+
+            @Override
+            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+                super.updateAjaxAttributes(attributes);
+
+                // allow the event to bubble so the menu is hidden after click on an item
+                attributes.setEventPropagation(AjaxRequestAttributes.EventPropagation.BUBBLE);
+            }
+
+            @Override
+            protected void onComponentTag(ComponentTag tag) {
+                super.onComponentTag(tag);
+
+                Buttons.fixDisabledState(this, tag);
+            }
+        };
+
+        if(ajaxDeferredBehaviour != null) {
+            link.add(ajaxDeferredBehaviour);
+        }
+
+        link.add(new CssClassAppender("noVeil"));
+
+        return link;
+    }
+
+    private static AjaxDeferredBehaviour determineDeferredBehaviour(final ObjectAction action, final ActionModel actionModel) {
+        // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
+        if(isNoArgReturnTypeRedirect(action)) {
+            /**
+             * adapted from:
+             * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
+             */
+            return new AjaxDeferredBehaviour(AjaxDeferredBehaviour.OpenUrlStrategy.NEW_WINDOW) {
+                
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                protected IRequestHandler getRequestHandler() {
+                    ObjectAdapter resultAdapter = actionModel.executeHandlingApplicationExceptions();
+                    final Object value = resultAdapter.getObject();
+                    return ActionModel.redirectHandler(value);
+                }
+            };
+        } 
+        if(isNoArgReturnTypeDownload(action)) {
+
+            /**
+             * adapted from:
+             * @see https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
+             */
+            return new AjaxDeferredBehaviour(AjaxDeferredBehaviour.OpenUrlStrategy.SAME_WINDOW) {
+                
+                private static final long serialVersionUID = 1L;
+   
+                @Override
+                protected IRequestHandler getRequestHandler() {
+                    final ObjectAdapter resultAdapter = actionModel.executeHandlingApplicationExceptions();
+                    final Object value = resultAdapter.getObject();
+                    return ActionModel.downloadHandler(value);
+                }
+            };
+        } 
+        return null;
+    }
+
+    // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
+    private static boolean isNoArgReturnTypeRedirect(final ObjectAction action) {
+        return action.getParameterCount() == 0 &&
+               action.getReturnType() != null && 
+               action.getReturnType().getCorrespondingClass() == java.net.URL.class;
+    }
+
+    // TODO: should unify with ActionResultResponseType (as used in ActionPanel)
+    private static boolean isNoArgReturnTypeDownload(final ObjectAction action) {
+        return action.getParameterCount() == 0 && action.getReturnType() != null && 
+                (action.getReturnType().getCorrespondingClass() == org.apache.isis.applib.value.Blob.class ||
+                action.getReturnType().getCorrespondingClass() == org.apache.isis.applib.value.Clob.class);
+    }
+
+    protected LinkAndLabel newLinkAndLabel(final ObjectAction objectAction, final AbstractLink link, final String disabledReasonIfAny) {
+
+        final String label = ObjectAction.Utils.nameFor(objectAction);
+        final boolean blobOrClob = ObjectAction.Utils.returnsBlobOrClob(objectAction);
+        final boolean prototype = ObjectAction.Utils.isExplorationOrPrototype(objectAction);
+        final String actionIdentifier = ObjectAction.Utils.actionIdentifierFor(objectAction);
+        final String description = ObjectAction.Utils.descriptionOf(objectAction);
+        final ActionLayout.Position position = ObjectAction.Utils.actionLayoutPositionOf(objectAction);
+        final String cssClass = ObjectAction.Utils.cssClassFor(objectAction);
+        final String cssClassFa = ObjectAction.Utils.cssClassFaFor(objectAction);
+
+        return new LinkAndLabel(link, label, disabledReasonIfAny, description, blobOrClob, prototype, actionIdentifier, cssClass, cssClassFa, position);
+    }
+
+
+    // ////////////////////////////////////////////////////////////
+    // Dependencies
+    // ////////////////////////////////////////////////////////////
+    
+    protected ComponentFactoryRegistry getComponentFactoryRegistry() {
+        return ((ComponentFactoryRegistryAccessor)Application.get()).getComponentFactoryRegistry();
+    }
+    
+    protected PageClassRegistry getPageClassRegistry() {
+        return ((PageClassRegistryAccessor) Application.get()).getPageClassRegistry();
+    }
+
+}


[5/5] isis git commit: ISIS-963: primary, secondary and tertiary menu support.

Posted by da...@apache.org.
ISIS-963: primary, secondary and tertiary menu support.

Included the refactoring of AppActions (renamed to ServiceActions).


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

Branch: refs/heads/master
Commit: 8aaa166ff14751d81e9c8897fe4b9625e151ae50
Parents: 992e388
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Dec 3 07:51:45 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Dec 3 07:51:45 2014 +0000

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java    |   2 +-
 .../ComponentFactoryRegistrarDefault.java       |   6 +-
 .../model/models/ApplicationActionsModel.java   |  48 -
 .../wicket/model/models/ModelAbstract.java      |   6 +-
 .../model/models/ServiceActionsModel.java       |  68 ++
 .../isis/viewer/wicket/ui/ComponentType.java    |   2 +-
 .../AdditionalLinksAsDropDownPanel.html         |  44 +
 .../AdditionalLinksAsDropDownPanel.java         |  32 +
 .../AdditionalLinksAsListInlinePanel.html       |  37 +
 .../AdditionalLinksAsListInlinePanel.java       |  32 +
 .../entityactions/AdditionalLinksPanel.java     | 149 +++
 .../entityactions/EntityActionLinkFactory.java  |  95 ++
 .../entityactions/EntityActionUtil.java         | 174 ++++
 .../actionmenu/serviceactions/CssMenuItem.java  | 439 +++++++++
 .../CssMenuItemPanelAbstract.java               |  44 +
 .../serviceactions/CssSubMenuItemsPanel.html    |  35 +
 .../serviceactions/CssSubMenuItemsPanel.java    |  59 ++
 .../ServiceActionLinkFactory.java               |  48 +
 .../serviceactions/ServiceActionUtil.java       | 192 ++++
 .../serviceactions/ServiceActionsPanel.css      | 340 +++++++
 .../serviceactions/ServiceActionsPanel.html     |  35 +
 .../serviceactions/ServiceActionsPanel.java     | 179 ++++
 .../ServiceActionsPanelFactory.java             |  60 ++
 .../serviceactions/TertiaryActionsPanel.css     |  18 +
 .../serviceactions/TertiaryActionsPanel.html    |  30 +
 .../serviceactions/TertiaryActionsPanel.java    | 164 ++++
 .../TertiaryMenuPanelFactory.java               |  59 ++
 .../AdditionalLinksAsDropDownPanel.html         |  44 -
 .../AdditionalLinksAsDropDownPanel.java         |  32 -
 .../AdditionalLinksAsListInlinePanel.html       |  37 -
 .../AdditionalLinksAsListInlinePanel.java       |  32 -
 .../additionallinks/AdditionalLinksPanel.java   | 149 ---
 .../additionallinks/EntityActionUtil.java       | 175 ----
 .../cssmenu/AppActionsCssMenuFactory.java       | 225 -----
 .../cssmenu/AppActionsCssMenuLinkFactory.java   |  50 -
 .../components/collection/CollectionPanel.java  |   2 +-
 .../collection/bulk/BulkActionsLinkFactory.java |   2 +-
 .../entity/EntityActionLinkFactory.java         |  95 --
 .../collections/EntityCollectionsPanel.java     |   2 +-
 .../entity/header/EntityHeaderPanel.java        |   6 +-
 .../icontitle/EntityIconAndTitlePanel.java      |   2 +-
 .../entity/properties/EntityPropertiesForm.java |   4 +-
 .../links/EntityLinksSelectorPanel.java         |   2 +-
 .../components/scalars/ScalarPanelAbstract.java |   4 +-
 .../scalars/ScalarPanelTextFieldAbstract.java   |   2 +-
 .../isisapplib/IsisBlobOrClobPanelAbstract.java |   2 +-
 .../scalars/primitive/BooleanPanel.java         |   2 +-
 .../scalars/reference/ReferencePanel.java       |   2 +-
 .../StandaloneCollectionPanel.java              |   2 +-
 .../widgets/cssmenu/ActionLinkFactory.java      |  33 -
 .../cssmenu/ActionLinkFactoryAbstract.java      | 233 -----
 .../widgets/cssmenu/AjaxDeferredBehaviour.java  |  84 --
 .../widgets/cssmenu/ApplicationActionsPanel.css | 340 -------
 .../cssmenu/ApplicationActionsPanel.html        |  35 -
 .../cssmenu/ApplicationActionsPanel.java        | 183 ----
 .../components/widgets/cssmenu/CssMenuItem.java | 441 ---------
 .../cssmenu/CssMenuItemPanelAbstract.java       |  47 -
 .../widgets/cssmenu/CssSubMenuItemsPanel.html   |  35 -
 .../widgets/cssmenu/CssSubMenuItemsPanel.java   |  59 --
 .../widgets/linkandlabel/ActionLinkFactory.java |  33 +
 .../linkandlabel/ActionLinkFactoryAbstract.java | 232 +++++
 .../linkandlabel/AjaxDeferredBehaviour.java     |  84 ++
 .../valuechoices/ValueChoicesSelect2Panel.java  |   2 +-
 .../viewer/wicket/ui/pages/PageAbstract-old.css | 962 -------------------
 .../viewer/wicket/ui/pages/PageAbstract.css     |  20 -
 .../viewer/wicket/ui/pages/PageAbstract.html    |  10 +-
 .../viewer/wicket/ui/pages/PageAbstract.java    |  48 +-
 .../isis/applib/annotation/DomainService.java   |  12 +
 .../domainservice/DomainServiceFacet.java       |   6 +
 .../DomainServiceFacetAbstract.java             |   9 +-
 .../DomainServiceFacetAnnotation.java           |   9 +-
 .../DomainServiceFacetAnnotationFactory.java    |   4 +-
 72 files changed, 2771 insertions(+), 3420 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index 332a7d7..11a1f9f 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -92,7 +92,7 @@ import org.apache.isis.viewer.wicket.model.models.PageType;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
-import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.string.MultiLineStringPanel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.Select2BootstrapCssReference;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.Select2JsReference;

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
index ed48dea..07fc9c8 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
@@ -25,10 +25,11 @@ import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistrar;
 import org.apache.isis.viewer.wicket.ui.components.about.AboutPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actionlink.ActionLinkPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.TertiaryMenuPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionInfoPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionParametersFormPanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.appactions.cssmenu.AppActionsCssMenuFactory;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.ServiceActionsPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.bookmarkedpages.BookmarkedPagesPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory;
@@ -239,7 +240,8 @@ public class ComponentFactoryRegistrarDefault implements ComponentFactoryRegistr
     }
 
     protected void addComponentFactoriesForApplicationActions(final ComponentFactoryList componentFactories) {
-        componentFactories.add(new AppActionsCssMenuFactory());
+        componentFactories.add(new ServiceActionsPanelFactory());
+        componentFactories.add(new TertiaryMenuPanelFactory());
     }
 
     protected void addComponentFactoriesForBreadcrumbs(ComponentFactoryList componentFactories) {

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
deleted file mode 100644
index c7d1c48..0000000
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
+++ /dev/null
@@ -1,48 +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.model.models;
-
-import java.util.List;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-
-/**
- * Backing model for actions of application services menu bar (typically, as
- * displayed along the top or side of the page).
- */
-public class ApplicationActionsModel extends ModelAbstract<List<ObjectAdapter>> {
-
-    private static final long serialVersionUID = 1L;
-    private ActionPromptProvider actionPromptProvider;
-
-    @Override
-    protected List<ObjectAdapter> load() {
-        return getServiceAdapters();
-    }
-
-    public void setActionPromptProvider(ActionPromptProvider actionPromptProvider) {
-        this.actionPromptProvider = actionPromptProvider;
-    }
-    
-    public ActionPromptProvider getActionPromptProvider() {
-        return actionPromptProvider;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ModelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ModelAbstract.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ModelAbstract.java
index 1ae3735..00c4512 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ModelAbstract.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ModelAbstract.java
@@ -124,12 +124,8 @@ public abstract class ModelAbstract<T> extends LoadableDetachableModel<T> implem
         return IsisContext.getPersistenceSession();
     }
 
-    protected List<ObjectAdapter> getServiceAdapters() {
-        return IsisContext.getPersistenceSession().getServices();
-    }
-
     protected AdapterManager getAdapterManager() {
-        return IsisContext.getPersistenceSession().getAdapterManager();
+        return getPersistenceSession().getAdapterManager();
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
new file mode 100644
index 0000000..2a816de
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
@@ -0,0 +1,68 @@
+/*
+ *  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.model.models;
+
+import java.util.List;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+
+/**
+ * Backing model for actions of application services menu bar (typically, as
+ * displayed along the top or side of the page).
+ */
+public class ServiceActionsModel extends ModelAbstract<List<ObjectAdapter>> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final DomainService.MenuBar menuBar;
+
+    private static Predicate<ObjectAdapter> with(final DomainService.MenuBar menuBar) {
+        return new Predicate<ObjectAdapter>() {
+            @Override
+            public boolean apply(ObjectAdapter input) {
+              final DomainServiceFacet facet = input.getSpecification().getFacet
+                  (DomainServiceFacet.class);
+                return facet != null && facet.getMenuBar() == menuBar;
+            }
+        };
+    }
+
+    public ServiceActionsModel(DomainService.MenuBar menuBar) {
+        this.menuBar = menuBar;
+    }
+
+    public DomainService.MenuBar getMenuBar() {
+        return menuBar;
+    }
+
+    protected List<ObjectAdapter> load() {
+        return Lists.newArrayList(Iterables.filter(getServiceAdapters(), with(menuBar)));
+    }
+
+    protected List<ObjectAdapter> getServiceAdapters() {
+        return getPersistenceSession().getServices();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
index c91c753..ac99173 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
@@ -51,7 +51,7 @@ public enum ComponentType {
      * Could be rendered using a JavaScript or DHTML menu, an accordion, or a
      * tree view.
      */
-    APPLICATION_ACTIONS,
+    SERVICE_ACTIONS,
     /**
      * A single domain entity.
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
new file mode 100644
index 0000000..3667116
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
@@ -0,0 +1,44 @@
+<?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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:panel>
+            <div wicket:id="additionalLinkList" class="additionalLinkList additionalLinkListDropDown">
+                <div class="btn-group">
+                    <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+                        <span class="fa fa-ellipsis-v"></span>
+                    </button>
+                    <ul class="dropdown-menu" role="menu">
+                        <li wicket:id="additionalLinkItem" class="additionalLinkItem">
+                            <a href="#" wicket:id="additionalLink">
+                                <span wicket:id="additionalLinkFontAwesome"></span>
+                                <span wicket:id="additionalLinkTitle" class="additionalLinkItem">[link title]</span>
+                            </a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
new file mode 100644
index 0000000..9b5d793
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.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.viewer.wicket.ui.components.actionmenu.entityactions;
+
+import java.util.List;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+
+public class AdditionalLinksAsDropDownPanel extends AdditionalLinksPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public AdditionalLinksAsDropDownPanel(String id, List<LinkAndLabel> links) {
+        super(id, links);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
new file mode 100644
index 0000000..9fcacee
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
@@ -0,0 +1,37 @@
+<?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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:panel>
+            <ul wicket:id="additionalLinkList" class="additionalLinkList additionalLinkListInline list-unstyled list-inline">
+                <li wicket:id="additionalLinkItem" class="additionalLinkItem">
+                    <a href="#" wicket:id="additionalLink" class="btn btn-sm btn-default">
+                        <span wicket:id="additionalLinkFontAwesome"></span>
+                        <span wicket:id="additionalLinkTitle" class="additionalLinkItem">[link title]</span>
+                    </a>
+                </li>
+            </ul>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
new file mode 100644
index 0000000..049c1a6
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.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.viewer.wicket.ui.components.actionmenu.entityactions;
+
+import java.util.List;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+
+public class AdditionalLinksAsListInlinePanel extends AdditionalLinksPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public AdditionalLinksAsListInlinePanel(String id, List<LinkAndLabel> links) {
+        super(id, links);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
new file mode 100644
index 0000000..aa3cec9
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
@@ -0,0 +1,149 @@
+/*
+ *  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.actionmenu.entityactions;
+
+import java.util.List;
+import com.google.common.base.Strings;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.isis.core.commons.lang.StringExtensions;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.links.ListOfLinksModel;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+public class AdditionalLinksPanel extends PanelAbstract<ListOfLinksModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_ADDITIONAL_LINK_LIST = "additionalLinkList";
+    private static final String ID_ADDITIONAL_LINK_ITEM = "additionalLinkItem";
+    private static final String ID_ADDITIONAL_LINK_FONT_AWESOME = "additionalLinkFontAwesome";
+    private static final String ID_ADDITIONAL_LINK_TITLE = "additionalLinkTitle";
+
+    public static final String ID_ADDITIONAL_LINK = "additionalLink";
+
+    public enum Style {
+        INLINE_LIST {
+            @Override
+            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) {
+                return new AdditionalLinksAsListInlinePanel(id, links);
+            }
+        },
+        DROPDOWN {
+            @Override
+            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) {
+                return new AdditionalLinksAsDropDownPanel(id, links);
+            }
+        };
+        abstract AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links);
+    }
+
+    public static AdditionalLinksPanel addAdditionalLinks(
+            final MarkupContainer markupContainer,
+            final String id,
+            final List<LinkAndLabel> links,
+            final Style style) {
+        if(links.isEmpty()) {
+            Components.permanentlyHide(markupContainer, id);
+            return null;
+        }
+
+        final AdditionalLinksPanel additionalLinksPanel =  style.newPanel(id, links);
+        markupContainer.addOrReplace(additionalLinksPanel);
+        return additionalLinksPanel;
+    }
+
+
+    private List<LinkAndLabel> linkAndLabels;
+    
+    protected AdditionalLinksPanel(final String id, final List<LinkAndLabel> links) {
+        super(id, new ListOfLinksModel(links));
+
+        this.linkAndLabels = getModel().getObject();
+        
+        final WebMarkupContainer container = new WebMarkupContainer(ID_ADDITIONAL_LINK_LIST);
+        addOrReplace(container);
+        
+        container.setOutputMarkupId(true);
+        
+        setOutputMarkupId(true);
+        
+        final ListView<LinkAndLabel> listView = new ListView<LinkAndLabel>(ID_ADDITIONAL_LINK_ITEM, this.linkAndLabels) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(ListItem<LinkAndLabel> item) {
+                final LinkAndLabel linkAndLabel = item.getModelObject();
+                
+                final AbstractLink link = linkAndLabel.getLink();
+
+                final String cssClassFa = linkAndLabel.getCssClassFa();
+                if(Strings.isNullOrEmpty(cssClassFa)) {
+                    Components.permanentlyHide(link, ID_ADDITIONAL_LINK_FONT_AWESOME);
+                } else {
+                    Label dummy = new Label(ID_ADDITIONAL_LINK_FONT_AWESOME, "");
+                    link.addOrReplace(dummy);
+                    dummy.add(new CssClassAppender(cssClassFa));
+                }
+
+                final String itemTitle = first(linkAndLabel.getDisabledReasonIfAny(), linkAndLabel.getDescriptionIfAny());
+                if(itemTitle != null) {
+                    item.add(new AttributeAppender("title", itemTitle));
+                }
+
+                final Label viewTitleLabel = new Label(ID_ADDITIONAL_LINK_TITLE, linkAndLabel.getLabel());
+                if(linkAndLabel.isBlobOrClob()) {
+                    link.add(new CssClassAppender("noVeil"));
+                }
+                if(linkAndLabel.isPrototype()) {
+                    link.add(new CssClassAppender("prototype"));
+                }
+                link.add(new CssClassAppender(linkAndLabel.getActionIdentifier()));
+
+                final String cssClass = linkAndLabel.getCssClass();
+                if(cssClass != null) {
+                    link.add(new CssClassAppender(cssClass));
+                }
+                viewTitleLabel.add(new CssClassAppender(StringExtensions.asLowerDashed(linkAndLabel.getLabel())));
+
+                link.addOrReplace(viewTitleLabel);
+                item.addOrReplace(link);
+            }
+        };
+        container.addOrReplace(listView);
+    }
+
+    private static String first(String... str) {
+        for (String s : str) {
+            if(s != null) return s;
+        }
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
new file mode 100644
index 0000000..654cf02
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
@@ -0,0 +1,95 @@
+/*
+ *  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.actionmenu.entityactions;
+
+import org.apache.wicket.markup.html.link.AbstractLink;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.*;
+import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
+
+public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unused")
+    private final EntityModel entityModel;
+
+    public EntityActionLinkFactory(final EntityModel entityModel) {
+        this.entityModel = entityModel;
+    }
+
+    @Override
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento adapterMemento,
+            final ObjectAction action,
+            final String linkId) {
+
+        final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+        
+        final Boolean persistent = adapter.representsPersistent();
+        if (!persistent) {
+            throw new IllegalArgumentException("Object '" + adapter.titleString(null) + "' is not persistent.");
+        }
+
+        // check visibility and whether enabled
+        final AuthenticationSession session = getAuthenticationSession();
+        
+        final Consent visibility = action.isVisible(session, adapter, Where.OBJECT_FORMS);
+        if (visibility.isVetoed()) {
+            return null;
+        }
+
+        
+        final AbstractLink link = newLink(linkId, adapter, action);
+        
+        final Consent usability = action.isUsable(session, adapter, Where.OBJECT_FORMS);
+        final String disabledReasonIfAny = usability.getReason();
+        if(disabledReasonIfAny != null) {
+            link.setEnabled(false);
+        }
+
+        return newLinkAndLabel(action, link, disabledReasonIfAny);
+    }
+
+    
+
+    // ///////////////////////////////////////////////////////////////////
+    // Dependencies (from IsisContext)
+    // ///////////////////////////////////////////////////////////////////
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
new file mode 100644
index 0000000..c987980
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
@@ -0,0 +1,174 @@
+/*
+ *  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.actionmenu.entityactions;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import org.apache.wicket.Session;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+import org.apache.isis.core.metamodel.layout.memberorderfacet.MemberOrderFacetComparator;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+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.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+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.components.widgets.linkandlabel.ActionLinkFactory;
+
+public final class EntityActionUtil {
+
+    private EntityActionUtil(){}
+
+    private final static MemberOrderFacetComparator memberOrderFacetComparator = new MemberOrderFacetComparator(false);
+
+    public static List<LinkAndLabel> getEntityActionLinksForAssociation(
+            final ScalarModel scalarModel,
+            final DeploymentType deploymentType) {
+        final List<LinkAndLabel> entityActions = Lists.newArrayList();
+
+        if (scalarModel.getKind() != ScalarModel.Kind.PROPERTY) {
+            return entityActions;
+        } else {
+            final ObjectAdapterMemento parentMemento = scalarModel.getParentObjectAdapterMemento();
+            final EntityModel parentEntityModel = new EntityModel(parentMemento);
+            final OneToOneAssociation oneToOneAssociation = scalarModel.getPropertyMemento().getProperty();
+
+            final List<ObjectAction> associatedActions = getObjectActionsForAssociation(parentEntityModel, oneToOneAssociation, deploymentType);
+
+            entityActions.addAll(asLinkAndLabelsForAdditionalLinksPanel(parentEntityModel, associatedActions));
+            return entityActions;
+        }
+    }
+
+    public static List<ObjectAction> getObjectActionsForAssociation(
+            final EntityModel entityModel,
+            final ObjectAssociation association,
+            final DeploymentType deploymentType) {
+        final List<ObjectAction> associatedActions = Lists.newArrayList();
+
+        addActions(ActionType.USER, entityModel, association, associatedActions);
+        if(deploymentType.isPrototyping()) {
+            addActions(ActionType.EXPLORATION, entityModel, association, associatedActions);
+            addActions(ActionType.PROTOTYPE, entityModel, association, associatedActions);
+        }
+
+        Collections.sort(associatedActions, new Comparator<ObjectAction>() {
+
+            @Override
+            public int compare(ObjectAction o1, ObjectAction o2) {
+                final MemberOrderFacet m1 = o1.getFacet(MemberOrderFacet.class);
+                final MemberOrderFacet m2 = o2.getFacet(MemberOrderFacet.class);
+                return memberOrderFacetComparator.compare(m1, m2);
+            }
+        });
+        return associatedActions;
+    }
+
+    /**
+     * Converts an {@link org.apache.isis.viewer.wicket.model.models.EntityModel} and a (subset of its) {@link org.apache.isis.core.metamodel.spec.feature.ObjectAction}s into a
+     * list of {@link org.apache.isis.viewer.wicket.model.links.LinkAndLabel}s intended to be apassed
+     * to the {@link AdditionalLinksPanel}.
+     */
+    public static List<LinkAndLabel> asLinkAndLabelsForAdditionalLinksPanel(
+            final EntityModel entityModel,
+            final List<ObjectAction> actions) {
+
+        final String linkId = AdditionalLinksPanel.ID_ADDITIONAL_LINK;
+        final ActionLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
+
+        final ObjectAdapterMemento adapterMemento = entityModel.getObjectAdapterMemento();
+        return Lists.transform(actions, new Function<ObjectAction, LinkAndLabel>() {
+
+            @Override
+            public LinkAndLabel apply(ObjectAction objectAction) {
+                return linkFactory.newLink(adapterMemento, objectAction, linkId);
+            }
+        });
+    }
+
+    private static List<ObjectAction> addActions(
+            final ActionType type,
+            final EntityModel entityModel,
+            final ObjectAssociation association,
+            final List<ObjectAction> associatedActions) {
+        final ObjectSpecification adapterSpec = entityModel.getTypeOfSpecification();
+        final ObjectAdapter adapter = entityModel.load(ConcurrencyChecking.NO_CHECK);
+
+        final AuthenticationSessionProvider asa = (AuthenticationSessionProvider) Session.get();
+        AuthenticationSession authSession = asa.getAuthenticationSession();
+
+        final ObjectSpecification objectSpecification = entityModel.getTypeOfSpecification();
+        @SuppressWarnings({ "unchecked", "deprecation" })
+        Filter<ObjectAction> filter = Filters.and(
+                    ObjectAction.Filters.memberOrderOf(association),
+                    ObjectAction.Filters.dynamicallyVisible(authSession, adapter, Where.ANYWHERE),
+                    ObjectAction.Filters.notBulkOnly(),
+                    ObjectAction.Filters.excludeWizardActions(objectSpecification));
+
+        final List<ObjectAction> userActions = adapterSpec.getObjectActions(type, Contributed.INCLUDED, filter);
+        associatedActions.addAll(userActions);
+        return userActions;
+    }
+
+
+    public static void addTopLevelActions(
+            final ObjectAdapter adapter,
+            final ActionType actionType,
+            final List<ObjectAction> topLevelActions,
+            final AuthenticationSession authenticationSession) {
+
+        final ObjectSpecification adapterSpec = adapter.getSpecification();
+
+        @SuppressWarnings({ "unchecked", "deprecation" })
+        Filter<ObjectAction> filter = Filters.and(
+                ObjectAction.Filters.memberOrderNotAssociationOf(adapterSpec),
+                ObjectAction.Filters.dynamicallyVisible(authenticationSession, adapter, Where.ANYWHERE),
+                ObjectAction.Filters.notBulkOnly(),
+                ObjectAction.Filters.excludeWizardActions(adapterSpec));
+
+        final List<ObjectAction> userActions = adapterSpec.getObjectActions(actionType, Contributed.INCLUDED, filter);
+        topLevelActions.addAll(userActions);
+    }
+
+    public static List<ObjectAction> getTopLevelActions(final ObjectAdapter adapter, final DeploymentType deploymentType, final AuthenticationSession authenticationSession) {
+        final List<ObjectAction> topLevelActions = Lists.newArrayList();
+
+        addTopLevelActions(adapter, ActionType.USER, topLevelActions, authenticationSession);
+        if(deploymentType.isPrototyping()) {
+            addTopLevelActions(adapter, ActionType.EXPLORATION, topLevelActions, authenticationSession);
+            addTopLevelActions(adapter, ActionType.PROTOTYPE, topLevelActions, authenticationSession);
+        }
+        return topLevelActions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
new file mode 100644
index 0000000..3e8914d
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
@@ -0,0 +1,439 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.SubmitLink;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.model.Model;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.ensure.Ensure;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
+import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
+import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+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.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+import static org.hamcrest.CoreMatchers.is;
+
+class CssMenuItem implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final String ID_MENU_LINK = "menuLink";
+
+    public static class Builder {
+        private final CssMenuItem cssMenuItem;
+
+        private Builder(final String name) {
+            cssMenuItem = new CssMenuItem(name);
+        }
+
+        public Builder parent(final CssMenuItem parent) {
+            cssMenuItem.setParent(parent);
+            return this;
+        }
+
+        public <T extends Page> Builder link() {
+            final AbstractLink link = new SubmitLink(ID_MENU_LINK); 
+            return link(link);
+        }
+
+        public <T extends Page> Builder link(final AbstractLink link) {
+            Ensure.ensureThatArg(link.getId(), is(ID_MENU_LINK));
+            cssMenuItem.setLink(link);
+            return this;
+        }
+
+        public <T extends Page> Builder enabled(final String disabledReasonIfAny) {
+            cssMenuItem.setEnabled(disabledReasonIfAny == null);
+            cssMenuItem.setDisabledReason(disabledReasonIfAny);
+            return this;
+        }
+
+        public Builder describedAs(String descriptionIfAny) {
+            cssMenuItem.setDescription(descriptionIfAny);
+            return this;
+        }
+
+        public Builder returnsBlobOrClob(boolean blobOrClob) {
+            cssMenuItem.setReturnsBlobOrClob(blobOrClob);
+            return this;
+        }
+
+        public Builder prototyping(boolean prototype) {
+            cssMenuItem.setPrototyping(prototype);
+            return this;
+        }
+
+        public Builder separator(boolean separator) {
+            cssMenuItem.setSeparator(separator);
+            return this;
+        }
+
+        public Builder withActionIdentifier(String actionIdentifier) {
+            cssMenuItem.setActionIdentifier(actionIdentifier);
+            return this;
+        }
+
+        public Builder withFacet(CssClassFacet facet) {
+            if(facet != null) {
+                withCssClass(facet.value());
+            }
+            return this;
+        }
+
+        public Builder withCssClass(String cssClass) {
+            cssMenuItem.setCssClass(cssClass);
+            return this;
+        }
+
+        public Builder withFacet(CssClassFaFacet facet) {
+            if(facet != null) {
+                withCssClassFa(facet.value());
+            }
+            return this;
+        }
+
+        public Builder withCssClassFa(String cssClassFa) {
+            cssMenuItem.setCssClassFa(cssClassFa);
+            return this;
+        }
+
+        /**
+         * Returns the built {@link CssMenuItem}, associating with
+         * {@link #parent(CssMenuItem) parent} (if specified).
+         */
+        public CssMenuItem build() {
+            if (cssMenuItem.parent != null) {
+                cssMenuItem.parent.subMenuItems.add(cssMenuItem);
+            }
+            return cssMenuItem;
+        }
+
+    }
+
+    private final String name;
+    private final List<CssMenuItem> subMenuItems = Lists.newArrayList();
+    private CssMenuItem parent;
+
+    private AbstractLink link;
+    private boolean enabled = true; // unless disabled
+    private String disabledReason;
+    private boolean blobOrClob = false; // unless set otherwise
+    private boolean prototype = false; // unless set otherwise
+    private boolean separator = false; // unless set otherwise
+
+    static final String ID_MENU_LABEL = "menuLabel";
+
+    static final String ID_SUB_MENU_ITEMS = "subMenuItems";
+
+    private String actionIdentifier;
+    private String cssClass;
+    private String cssClassFa;
+
+    private String description;
+
+
+
+    /**
+     * Factory method returning {@link Builder builder}.
+     */
+    public static Builder newMenuItem(final String name) {
+        return new Builder(name);
+    }
+
+
+    public void setActionIdentifier(String actionIdentifier) {
+        this.actionIdentifier = actionIdentifier;
+    }
+
+    public void setPrototyping(boolean prototype) {
+        this.prototype = prototype;
+    }
+
+    public boolean isPrototyping() {
+        return prototype;
+    }
+
+    public void setSeparator(boolean separator) {
+        this.separator = separator;
+    }
+
+    /**
+     * Requires a separator before it
+     * @return
+     */
+    public boolean isSeparator() {
+        return separator;
+    }
+
+    private CssMenuItem(final String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean hasParent() {
+        return parent != null;
+    }
+
+    private void setParent(final CssMenuItem parent) {
+        this.parent = parent;
+    }
+
+    public Builder newSubMenuItem(final String name) {
+        return CssMenuItem.newMenuItem(name).parent(this);
+    }
+
+    public List<CssMenuItem> getSubMenuItems() {
+        return Collections.unmodifiableList(subMenuItems);
+    }
+
+    public boolean hasSubMenuItems() {
+        return subMenuItems.size() > 0;
+    }
+
+    public AbstractLink getLink() {
+        return link;
+    }
+
+    private void setLink(final AbstractLink link) {
+        this.link = link;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    private void setEnabled(final boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public void setReturnsBlobOrClob(boolean blobOrClob) {
+        this.blobOrClob = blobOrClob;
+    }
+
+    public void setCssClass(String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+    public void setCssClassFa(String cssClassFa) {
+        this.cssClassFa = cssClassFa;
+    }
+
+    public String getCssClassFa() {
+        return cssClassFa;
+    }
+
+
+    /**
+     * Only populated if not {@link #isEnabled() enabled}.
+     */
+    public String getDisabledReason() {
+        return disabledReason;
+    }
+
+    public void setDisabledReason(final String disabledReason) {
+        this.disabledReason = disabledReason;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    // //////////////////////////////////////////////////////////////
+    // To add submenu items
+    // //////////////////////////////////////////////////////////////
+
+    /**
+     * Creates a {@link Builder} for a submenu item invoking an action on the provided
+     * {@link ObjectAdapterMemento target adapter}.
+     */
+    public Builder newSubMenuItem(
+            final ObjectAdapterMemento targetAdapterMemento,
+            final ObjectAction objectAction,
+            final boolean separator,
+            final ActionLinkFactory actionLinkFactory) {
+
+        // check visibility
+        final AuthenticationSession session = getAuthenticationSession();
+        final ObjectAdapter adapter = targetAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
+        final Consent visibility = objectAction.isVisible(session, adapter, ActionModel.WHERE_FOR_ACTION_INVOCATION);
+        if (visibility.isVetoed()) {
+            return null;
+        }
+
+        // build the link
+        final LinkAndLabel linkAndLabel = actionLinkFactory.newLink(
+                targetAdapterMemento, objectAction, PageAbstract.ID_MENU_LINK
+        );
+        if(linkAndLabel==null) {
+            // can only get a null if invisible, so this should not happen given guard above
+            return null;
+        }
+        final AbstractLink link = linkAndLabel.getLink();
+        final String actionLabel = linkAndLabel.getLabel();
+
+        final Consent usability = objectAction.isUsable(session, adapter, ActionModel.WHERE_FOR_ACTION_INVOCATION);
+        final String reasonDisabledIfAny = usability.getReason();
+        
+        final DescribedAsFacet describedAsFacet = objectAction.getFacet(DescribedAsFacet.class);
+        final String descriptionIfAny = describedAsFacet != null? describedAsFacet.value(): null;
+
+        Builder builder = newSubMenuItem(actionLabel)
+                .link(link)
+                .describedAs(descriptionIfAny)
+                .enabled(reasonDisabledIfAny)
+                .returnsBlobOrClob(ObjectAction.Utils.returnsBlobOrClob(objectAction))
+                .prototyping(ObjectAction.Utils.isExplorationOrPrototype(objectAction))
+                .separator(separator)
+                .withActionIdentifier(ObjectAction.Utils.actionIdentifierFor(objectAction))
+                .withCssClass(ObjectAction.Utils.cssClassFor(objectAction))
+                .withCssClassFa(ObjectAction.Utils.cssClassFaFor(objectAction));
+
+        return builder;
+    }
+
+
+    // //////////////////////////////////////////////////////////////
+    // Build wicket components from the menu item.
+    // //////////////////////////////////////////////////////////////
+
+    void addTo(final MarkupContainer markupContainer) {
+
+        final Component menuItemComponent = addMenuItemComponentTo(markupContainer);
+        addSubMenuItemComponentsIfAnyTo(markupContainer);
+
+        addCssClassAttributesIfRequired(menuItemComponent);
+    }
+
+    private Component addMenuItemComponentTo(final MarkupContainer markupContainer) {
+        final AbstractLink link = getLink();
+        final Label label = new Label(CssMenuItem.ID_MENU_LABEL, Model.of(this.getName()));
+
+        if (link != null) {
+
+            // show link...
+            markupContainer.add(link);
+            link.add(label);
+
+            if(this.description != null) {
+                label.add(new AttributeModifier("title", Model.of(description)));
+            }
+            if(this.blobOrClob) {
+                link.add(new CssClassAppender("noVeil"));
+            }
+            if(this.prototype) {
+                link.add(new CssClassAppender("prototype"));
+            }
+
+
+            if(this.cssClass != null) {
+                link.add(new CssClassAppender(this.cssClass));
+            }
+            link.add(new CssClassAppender(this.actionIdentifier));
+
+            String cssClassFa = getCssClassFa();
+            if (Strings.isNullOrEmpty(cssClassFa)) {
+                Components.permanentlyHide(link, "menuLinkFontAwesome");
+            } else {
+                Label dummy = new Label("menuLinkFontAwesome", "");
+                dummy.add(new CssClassAppender(cssClassFa));
+                link.add(dummy);
+            }
+
+            if(! this.isEnabled()) {
+                link.add(new AttributeModifier("title", Model.of(this.getDisabledReason())));
+                link.add(new CssClassAppender("disabled"));
+
+                link.setEnabled(false);
+            }
+
+            // .. and hide label
+            Components.permanentlyHide(markupContainer, CssMenuItem.ID_MENU_LABEL);
+            return link;
+        } else {
+            // hide link...
+            Components.permanentlyHide(markupContainer, ID_MENU_LINK);
+            // ... and show label, along with disabled reason
+            label.add(new AttributeModifier("title", Model.of(this.getDisabledReason())));
+            label.add(new AttributeModifier("class", Model.of("disabled")));
+
+            markupContainer.add(label);
+
+            return label;
+        }
+    }
+
+    private void addSubMenuItemComponentsIfAnyTo(final MarkupContainer menuItemMarkup) {
+        final List<CssMenuItem> subMenuItems = getSubMenuItems();
+        if (subMenuItems.isEmpty()) {
+            Components.permanentlyHide(menuItemMarkup, CssMenuItem.ID_SUB_MENU_ITEMS);
+        } else {
+            menuItemMarkup.add(new CssSubMenuItemsPanel(CssMenuItem.ID_SUB_MENU_ITEMS, subMenuItems));
+        }
+    }
+
+    private void addCssClassAttributesIfRequired(final Component linkComponent) {
+        if (!hasSubMenuItems()) {
+            return;
+        }
+        if (this.hasParent()) {
+            linkComponent.add(new CssClassAppender("parent"));
+        } else {
+            linkComponent.add(new CssClassAppender("top-parent"));
+        }
+    }
+
+    // //////////////////////////////////////////////////////////////
+    // dependencies
+    // //////////////////////////////////////////////////////////////
+
+    protected AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItemPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItemPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItemPanelAbstract.java
new file mode 100644
index 0000000..4069731
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItemPanelAbstract.java
@@ -0,0 +1,44 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+
+/**
+ * Package-level adapter for menu items and submenu-items.
+ */
+abstract class CssMenuItemPanelAbstract<T extends IModel<?>> extends PanelAbstract<T> {
+
+    private static final long serialVersionUID = 1L;
+
+    public CssMenuItemPanelAbstract(final String id, final T model) {
+        super(id, model);
+        setRenderBodyOnly(true);
+    }
+
+    protected void addSubMenuItems(final WebMarkupContainer markupContainer, final CssMenuItem cssMenuItem) {
+        cssMenuItem.addTo(markupContainer);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.html
new file mode 100644
index 0000000..9c1e14f
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.html
@@ -0,0 +1,35 @@
+<?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>
+    <ul class="cssSubMenuItemsPanel">
+        <li wicket:id="subMenuItems" class="cssSubMenuItem">
+            <a wicket:id="menuLink" class="btn btn-primary btn-sm">
+                <span class="fontAwesomeIcon" wicket:id="menuLinkFontAwesome"></span>
+                <span class="menuLabel" wicket:id="menuLabel">[menu label]</span>
+            </a>
+            <p wicket:id="menuLabel">[menu label]</p>
+            <span wicket:id="subMenuItems">[subMenuItems]</span>
+        </li>
+    </ul>
+</wicket:panel>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.java
new file mode 100644
index 0000000..2ac948d
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssSubMenuItemsPanel.java
@@ -0,0 +1,59 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import java.util.List;
+
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.model.util.ListModel;
+
+/**
+ * Panel containing a list of {@link CssMenuItem}s acting as submenus of a
+ * parent {@link CssMenuItem}.
+ */
+class CssSubMenuItemsPanel extends CssMenuItemPanelAbstract<CssSubMenuItemsPanel.MyModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    static class MyModel extends ListModel<CssMenuItem> {
+
+        private static final long serialVersionUID = 1L;
+
+        public MyModel(final List<CssMenuItem> cssMenuItems) {
+            super(cssMenuItems);
+        }
+    }
+
+    public CssSubMenuItemsPanel(final String id, final List<CssMenuItem> subMenuItems) {
+        super(id, new MyModel(subMenuItems));
+        setRenderBodyOnly(true);
+
+        final RepeatingView menuItemRv = new RepeatingView(getId());
+        add(menuItemRv);
+        for (final CssMenuItem cssMenuItem : getModel().getObject()) {
+            final WebMarkupContainer menuItemMarkup = new WebMarkupContainer(menuItemRv.newChildId());
+            menuItemRv.add(menuItemMarkup);
+
+            addSubMenuItems(menuItemMarkup, cssMenuItem);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
new file mode 100644
index 0000000..d9b3b6d
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
@@ -0,0 +1,48 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import org.apache.wicket.markup.html.link.AbstractLink;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
+
+class ServiceActionLinkFactory extends ActionLinkFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+    
+    @Override
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento adapterMemento,
+            final ObjectAction action,
+            final String linkId) {
+        
+        ObjectAdapter objectAdapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+
+        final AbstractLink link = newLink(linkId, objectAdapter, action);
+
+        return newLinkAndLabel(action, link, null);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8aaa166f/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
new file mode 100644
index 0000000..6dd2156
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -0,0 +1,192 @@
+/*
+ *  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.actionmenu.serviceactions;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
+import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
+
+public final class ServiceActionUtil {
+
+    private ServiceActionUtil(){}
+
+    private final static ActionLinkFactory linkAndLabelFactory = new ServiceActionLinkFactory();
+
+    static class LogicalServiceAction {
+        private final String serviceName;
+        private final ObjectAdapter serviceAdapter;
+        private final ObjectAdapterMemento serviceAdapterMemento;
+        private final ObjectAction objectAction;
+        public boolean separator;
+
+        LogicalServiceAction(final String serviceName, final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
+            this.serviceName = serviceName;
+            this.serviceAdapter = serviceAdapter;
+            this.serviceAdapterMemento = ObjectAdapterMemento.createOrNull(serviceAdapter);
+            this.objectAction = objectAction;
+        }
+        @Override
+        public String toString() {
+            return serviceName + " ~ " + objectAction.getIdentifier().toFullIdentityString();
+        }
+    }
+
+    public static List<CssMenuItem> buildMenu(final ServiceActionsModel appActionsModel) {
+
+        final List<ObjectAdapter> serviceAdapters = appActionsModel.getObject();
+
+        final List<LogicalServiceAction> serviceActions = Lists.newArrayList();
+        for (final ObjectAdapter serviceAdapter : serviceAdapters) {
+            collateServiceActions(serviceAdapter, ActionType.USER, serviceActions);
+            collateServiceActions(serviceAdapter, ActionType.PROTOTYPE, serviceActions);
+        }
+
+        final Set<String> serviceNamesInOrder = serviceNamesInOrder(serviceAdapters, serviceActions);
+        final Map<String, List<LogicalServiceAction>> serviceActionsByName = groupByServiceName(serviceActions);
+
+        // prune any service names that have no service actions
+        serviceNamesInOrder.retainAll(serviceActionsByName.keySet());
+
+        return buildMenuItems(serviceNamesInOrder, serviceActionsByName, linkAndLabelFactory);
+    }
+
+    /**
+     * Builds a hierarchy of {@link CssMenuItem}s, following the provided map of {@link LogicalServiceAction}s (keyed by their service Name).
+     */
+    private static List<CssMenuItem> buildMenuItems(
+            final Set<String> serviceNamesInOrder,
+            final Map<String, List<LogicalServiceAction>> serviceActionsByName,
+            final ActionLinkFactory actionLinkFactory) {
+
+        final List<CssMenuItem> menuItems = Lists.newArrayList();
+        for (String serviceName : serviceNamesInOrder) {
+            final CssMenuItem serviceMenuItem = CssMenuItem.newMenuItem(serviceName).build();
+            final List<LogicalServiceAction> serviceActionsForName = serviceActionsByName.get(serviceName);
+            for (LogicalServiceAction logicalServiceAction : serviceActionsForName) {
+                final ObjectAdapter serviceAdapter = logicalServiceAction.serviceAdapter;
+                final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
+                if (serviceSpec.isHidden()) {
+                    continue;
+                }
+                final ObjectAdapterMemento serviceAdapterMemento = logicalServiceAction.serviceAdapterMemento;
+                final ObjectAction objectAction = logicalServiceAction.objectAction;
+                final boolean separator = logicalServiceAction.separator;
+                final CssMenuItem.Builder subMenuItemBuilder = serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, separator, actionLinkFactory);
+                if (subMenuItemBuilder == null) {
+                    // not visible
+                    continue;
+                }
+                subMenuItemBuilder.build();
+            }
+            if (serviceMenuItem.hasSubMenuItems()) {
+                menuItems.add(serviceMenuItem);
+            }
+        }
+        return menuItems;
+    }
+
+
+    // //////////////////////////////////////
+
+    /**
+     * Spin through all object actions of the service adapter, and add to the provided List of {@link LogicalServiceAction}s.
+     */
+    private static void collateServiceActions(final ObjectAdapter serviceAdapter, ActionType actionType, List<LogicalServiceAction> serviceActions) {
+        final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
+        for (final ObjectAction objectAction : serviceSpec.getObjectActions(
+                actionType, Contributed.INCLUDED, Filters.<ObjectAction>any())) {
+            // skip if annotated to not be included in repository menu
+            if (objectAction.getFacet(NotInServiceMenuFacet.class) != null) {
+                continue;
+            }
+
+            final MemberOrderFacet memberOrderFacet = objectAction.getFacet(MemberOrderFacet.class);
+            String serviceName = memberOrderFacet != null? memberOrderFacet.name(): null;
+            if(Strings.isNullOrEmpty(serviceName)){
+                serviceName = serviceSpec.getFacet(NamedFacet.class).value();
+            }
+            serviceActions.add(new LogicalServiceAction(serviceName, serviceAdapter, objectAction));
+        }
+    }
+
+    /**
+     * The unique service names, as they appear in order of the provided List of {@link LogicalServiceAction}s.
+     * @param serviceAdapters
+     */
+    private static Set<String> serviceNamesInOrder(
+            final List<ObjectAdapter> serviceAdapters, final List<LogicalServiceAction> serviceActions) {
+        final Set<String> serviceNameOrder = Sets.newLinkedHashSet();
+
+        // first, order as defined in isis.properties
+        for (ObjectAdapter serviceAdapter : serviceAdapters) {
+            final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
+            String serviceName = serviceSpec.getFacet(NamedFacet.class).value();
+            serviceNameOrder.add(serviceName);
+        }
+        // then, any other services (eg due to misspellings, at the end)
+        for (LogicalServiceAction serviceAction : serviceActions) {
+            if(!serviceNameOrder.contains(serviceAction.serviceName)) {
+                serviceNameOrder.add(serviceAction.serviceName);
+            }
+        }
+        return serviceNameOrder;
+    }
+
+    /**
+     * Group the provided {@link LogicalServiceAction}s by their service name.
+     */
+    private static Map<String, List<LogicalServiceAction>> groupByServiceName(final List<LogicalServiceAction> serviceActions) {
+        final Map<String, List<LogicalServiceAction>> serviceActionsByName = Maps.newTreeMap();
+
+        // map available services
+        ObjectAdapter lastServiceAdapter = null;
+        for (LogicalServiceAction serviceAction : serviceActions) {
+            List<LogicalServiceAction> serviceActionsForName = serviceActionsByName.get(serviceAction.serviceName);
+            if(serviceActionsForName == null) {
+                serviceActionsForName = Lists.newArrayList();
+                serviceActionsByName.put(serviceAction.serviceName, serviceActionsForName);
+            } else {
+                // capture whether this action is from a different service
+                serviceAction.separator = lastServiceAdapter != serviceAction.serviceAdapter;
+            }
+            serviceActionsForName.add(serviceAction);
+            lastServiceAdapter = serviceAction.serviceAdapter;
+        }
+
+        return serviceActionsByName;
+    }
+
+}