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 2015/07/24 19:48:20 UTC

[2/2] isis git commit: ISIS-1175: fixing issue with menu separators disappearing in do force reload in Wicket viewer.

ISIS-1175: fixing issue with menu separators disappearing in do force reload in Wicket viewer.

In addition, refactored ServiceActionsPanel and TertiaryActionsPanel, remove some of the duplication of code (moved to ServiceActionUtil class instead).


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

Branch: refs/heads/master
Commit: b86aa5506029b344869edcc3651f03888663c2f7
Parents: 18bfb6d
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 24 18:48:06 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 24 18:48:06 2015 +0100

----------------------------------------------------------------------
 .../actionmenu/serviceactions/CssMenuItem.java  |  57 +++++----
 .../serviceactions/ServiceActionUtil.java       | 119 +++++++++++++++++++
 .../serviceactions/ServiceActionsPanel.java     | 116 ++----------------
 .../serviceactions/TertiaryActionsPanel.java    |  87 +-------------
 4 files changed, 171 insertions(+), 208 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b86aa550/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
index b14d616..f6d847b 100644
--- a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
+++ b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
@@ -17,19 +17,29 @@
 
 package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
 
-import static org.hamcrest.CoreMatchers.is;
-
 import java.io.Serializable;
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaPosition;
+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.cssclassfa.CssClassFaPosition;
 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;
@@ -40,17 +50,8 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLi
 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 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 com.google.common.base.Strings;
-import com.google.common.collect.Lists;
+import static org.hamcrest.CoreMatchers.is;
 
 class CssMenuItem implements Serializable {
 
@@ -102,8 +103,8 @@ class CssMenuItem implements Serializable {
             return this;
         }
 
-        public Builder separator(boolean separator) {
-            cssMenuItem.setSeparator(separator);
+        public Builder requiresSeparator(boolean separator) {
+            cssMenuItem.setRequiresSeparator(separator);
             return this;
         }
 
@@ -148,7 +149,7 @@ class CssMenuItem implements Serializable {
     private String disabledReason;
     private boolean blobOrClob = false; // unless set otherwise
     private boolean prototype = false; // unless set otherwise
-    private boolean separator = false; // unless set otherwise
+    private boolean requiresSeparator = false; // unless set otherwise
 
     static final String ID_MENU_LABEL = "menuLabel";
 
@@ -180,17 +181,24 @@ class CssMenuItem implements Serializable {
         return prototype;
     }
 
-    public void setSeparator(boolean separator) {
+    private boolean separator;
+
+    public boolean isSeparator() {
+        return separator;
+    }
+    public void setSeparator(final boolean separator) {
         this.separator = separator;
     }
 
+    public void setRequiresSeparator(boolean requiresSeparator) {
+        this.requiresSeparator = requiresSeparator;
+    }
+
     /**
      * Requires a separator before it
-     *
-     * @return
      */
-    public boolean isSeparator() {
-        return separator;
+    public boolean requiresSeparator() {
+        return requiresSeparator;
     }
 
     private CssMenuItem(final String name) {
@@ -217,6 +225,11 @@ class CssMenuItem implements Serializable {
         return Collections.unmodifiableList(subMenuItems);
     }
 
+    public void replaceSubMenuItems(List<CssMenuItem> menuItems) {
+        subMenuItems.clear();
+        subMenuItems.addAll(menuItems);
+    }
+
     public boolean hasSubMenuItems() {
         return subMenuItems.size() > 0;
     }
@@ -329,7 +342,7 @@ class CssMenuItem implements Serializable {
                 .enabled(reasonDisabledIfAny)
                 .returnsBlobOrClob(ObjectAction.Utils.returnsBlobOrClob(objectAction))
                 .prototyping(ObjectAction.Utils.isExplorationOrPrototype(objectAction))
-                .separator(separator)
+                .requiresSeparator(separator)
                 .withActionIdentifier(ObjectAction.Utils.actionIdentifierFor(objectAction))
                 .withCssClass(ObjectAction.Utils.cssClassFor(objectAction, adapter))
                 .withCssClassFa(ObjectAction.Utils.cssClassFaFor(objectAction))

http://git-wip-us.apache.org/repos/asf/isis/blob/b86aa550/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index dfce331..4931ea2 100644
--- a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -28,6 +28,14 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+import org.apache.wicket.MarkupContainer;
+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.model.Model;
+
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.filter.Filters;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -41,7 +49,11 @@ 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.actionmenu.CssClassFaBehavior;
 import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipBehavior;
 
 public final class ServiceActionUtil {
 
@@ -49,6 +61,113 @@ public final class ServiceActionUtil {
 
     private final static ActionLinkFactory linkAndLabelFactory = new ServiceActionLinkFactory();
 
+    static void addLeafItem(final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem, final MarkupContainer parent) {
+        Fragment leafItem;
+        if (!menuItem.isSeparator()) {
+            leafItem = new Fragment("content", "leafItem", parent);
+
+            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)) {
+                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
+            } else {
+                menuItemLabel.add(new CssClassFaBehavior(cssClassFa, menuItem.getCssClassFaPosition()));
+            }
+
+            String cssClass = menuItem.getCssClass();
+            if (!Strings.isNullOrEmpty(cssClass)) {
+                subMenuItemLink.add(new CssClassAppender(cssClass));
+            }
+        } else {
+            leafItem = new Fragment("content", "empty", parent);
+            listItem.add(new CssClassAppender("divider"));
+        }
+        listItem.add(leafItem);
+    }
+
+
+    enum SeparatorStrategy {
+        WITH_SEPARATORS {
+            List<CssMenuItem> applySeparatorStrategy(final CssMenuItem subMenuItem) {
+                return withSeparators(subMenuItem);
+            }
+
+        },
+        WITHOUT_SEPARATORS {
+            List<CssMenuItem> applySeparatorStrategy(final CssMenuItem subMenuItem) {
+                final List<CssMenuItem> subMenuItems = subMenuItem.getSubMenuItems();
+                return subMenuItems;
+            }
+        };
+
+        abstract List<CssMenuItem> applySeparatorStrategy(final CssMenuItem subMenuItem);
+    }
+
+    static List<CssMenuItem> withSeparators(CssMenuItem subMenuItem) {
+        final List<CssMenuItem> subMenuItems = subMenuItem.getSubMenuItems();
+        final List<CssMenuItem> cssMenuItemsWithSeparators = withSeparators(subMenuItems);
+        subMenuItem.replaceSubMenuItems(cssMenuItemsWithSeparators);
+        return cssMenuItemsWithSeparators;
+    }
+
+    static List<CssMenuItem> withSeparators(List<CssMenuItem> subMenuItems) {
+        final List<CssMenuItem> itemsWithSeparators = Lists.newArrayList();
+        for (CssMenuItem menuItem : subMenuItems) {
+            if(menuItem.requiresSeparator()) {
+                if(!itemsWithSeparators.isEmpty()) {
+                    // bit nasty... we add a new separator item
+                    final CssMenuItem separatorItem = CssMenuItem.newMenuItem(menuItem.getName() + "-separator")
+                            .prototyping(menuItem.isPrototyping())
+                            .build();
+                    separatorItem.setSeparator(true);
+                    itemsWithSeparators.add(separatorItem);
+                }
+                menuItem.setRequiresSeparator(false);
+            }
+            itemsWithSeparators.add(menuItem);
+        }
+        return itemsWithSeparators;
+    }
+
+    static void addFolderItem(final CssMenuItem subMenuItem, final ListItem<CssMenuItem> listItem, final MarkupContainer parent, final SeparatorStrategy separatorStrategy) {
+        listItem.add(new CssClassAppender("dropdown-submenu"));
+
+        Fragment folderItem = new Fragment("content", "folderItem", parent);
+        listItem.add(folderItem);
+
+        folderItem.add(new Label("folderName", subMenuItem.getName()));
+        final List<CssMenuItem> menuItems = separatorStrategy.applySeparatorStrategy(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, parent, SeparatorStrategy.WITHOUT_SEPARATORS);
+                } else {
+                    addLeafItem(subMenuItem, listItem, parent);
+                }
+            }
+        };
+        folderItem.add(subMenuItemsView);
+    }
+
     static class LogicalServiceAction {
         private final String serviceName;
         private final ObjectAdapter serviceAdapter;

http://git-wip-us.apache.org/repos/asf/isis/blob/b86aa550/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
index 25e2a69..e024e5c 100644
--- a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
+++ b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionsPanel.java
@@ -18,12 +18,8 @@
  */
 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;
@@ -31,16 +27,15 @@ 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.components.actionmenu.CssClassFaBehavior;
+
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.button.DropdownAutoOpenJavaScriptReference;
+
 /**
  * A panel responsible to render the application actions as menu in a navigation bar.
  *
@@ -53,19 +48,15 @@ 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);
+                List<CssMenuItem> subMenuItems = ServiceActionUtil.withSeparators(menuItem);
 
 // fake data to test multi-level menus
 //                if (menuItem.getName().equals("ToDos")) {
@@ -85,7 +76,10 @@ public class ServiceActionsPanel extends Panel {
                         if (subMenuItem.hasSubMenuItems()) {
                             addFolderItem(subMenuItem, listItem);
                         } else {
-                            addLeafItem(subMenuItem, listItem);
+
+                            final MarkupContainer parent = ServiceActionsPanel.this;
+                            ServiceActionUtil.addLeafItem(subMenuItem, listItem, parent);
+
                         }
                     }
                 };
@@ -96,101 +90,13 @@ public class ServiceActionsPanel extends Panel {
     }
 
     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)) {
-                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
-            } else {
-                menuItemLabel.add(new CssClassFaBehavior(cssClassFa, menuItem.getCssClassFaPosition()));
-            }
-            
-            String cssClass = menuItem.getCssClass();
-            if (!Strings.isNullOrEmpty(cssClass)) {
-                subMenuItemLink.add(new CssClassAppender(cssClass));
-            }
-        } else {
-            leafItem = new Fragment("content", "empty", ServiceActionsPanel.this);
-            listItem.add(new CssClassAppender("divider"));
-        }
-        listItem.add(leafItem);
-
+        final MarkupContainer parent = ServiceActionsPanel.this;
+        ServiceActionUtil.addFolderItem(subMenuItem, listItem, parent, ServiceActionUtil.SeparatorStrategy.WITH_SEPARATORS);
     }
 
     @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/b86aa550/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
index 28ebb34..c6f112c 100644
--- a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
+++ b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/TertiaryActionsPanel.java
@@ -18,30 +18,24 @@
  */
 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.WebComponent;
-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.components.actionmenu.CssClassFaBehavior;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
 /**
  * A panel responsible to render the application actions as menu in a navigation bar.
@@ -55,20 +49,16 @@ public class TertiaryActionsPanel extends Panel {
 
     public TertiaryActionsPanel(String id, List<CssMenuItem> menuItems) {
         super(id);
-
         addLogoutLink(this);
-
         final List<CssMenuItem> subMenuItems = flatten(menuItems);
-
         final 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);
+                    ServiceActionUtil.addLeafItem(subMenuItem, listItem, TertiaryActionsPanel.this);
                 }
             }
         };
@@ -112,78 +102,13 @@ public class TertiaryActionsPanel extends Panel {
 
 
     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)) {
-                subMenuItemLink.add(new CssClassAppender("menuLinkSpacer"));
-            } else {
-                menuItemLabel.add(new CssClassFaBehavior(cssClassFa, menuItem.getCssClassFaPosition()));
-            }
-
-            String cssClass = menuItem.getCssClass();
-            if (!Strings.isNullOrEmpty(cssClass)) {
-                subMenuItemLink.add(new CssClassAppender(cssClass));
-            }
-        } else {
-            leafItem = new Fragment("content", "empty", TertiaryActionsPanel.this);
-            listItem.add(new CssClassAppender("divider"));
-        }
-        listItem.add(leafItem);
-
+        final MarkupContainer parent = TertiaryActionsPanel.this;
+        ServiceActionUtil.addFolderItem(subMenuItem, listItem, parent, ServiceActionUtil.SeparatorStrategy.WITHOUT_SEPARATORS);
     }
 
     @Override
     public void renderHead(IHeaderResponse response) {
         super.renderHead(response);
-
         response.render(CssHeaderItem.forReference(new CssResourceReference(TertiaryActionsPanel.class, "TertiaryActionsPanel.css")));
     }