You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/06/24 09:45:43 UTC

[isis] branch master updated: ISIS-2340: JavaFX viewer: adds menu items

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new a8c9856  ISIS-2340: JavaFX viewer: adds menu items
a8c9856 is described below

commit a8c9856460b1ff989667cc916182b0c92bcb4090
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Jun 24 11:45:23 2020 +0200

    ISIS-2340: JavaFX viewer: adds menu items
---
 .../src/main/java/demoapp/dom/DemoModule.java      | 17 ++---
 .../java/demoapp/dom/viewmodels/ViewModels.java    | 14 -----
 .../main/java/demoapp/webapp/DemoAppManifest.java  | 19 ++++--
 .../main/java/demoapp/javafx/DemoAppJavaFx.java    |  2 +
 .../javafx/model/action/ActionLinkFactoryFx.java}  | 29 ++++-----
 .../viewer/javafx/model/action/ActionLinkFx.java}  | 21 ++++---
 .../viewer/javafx/model/menu/MenuItemFx.java       | 33 +++++++---
 .../javafx/ui/IsisModuleIncViewerJavaFxUi.java     | 15 +++--
 .../viewer/javafx/ui/main/MenuBuilderFx.java       | 68 ++++++++++++++++++++
 .../{PrimaryStageListener.java => UiBuilder.java}  |  6 +-
 .../viewer/javafx/ui/main/UiController.java        | 69 +++++++++++++++++++++
 .../viewers/javafx/ui/src/main/resources/ui.fxml   | 56 ++++-------------
 ...onFactoryVaa.java => ActionLinkFactoryVaa.java} | 16 ++---
 .../action/{ActionVaa.java => ActionLinkVaa.java}  |  6 +-
 .../viewer/vaadin/ui/pages/main/MainView.java      |  4 +-
 .../ui/pages/main/MainView_createHeader.java       | 10 +--
 ...kUiComponentFactory.java => HasUiMenuItem.java} | 17 ++---
 .../action/ActionLinkUiComponentDecorator.java     |  4 +-
 .../model/action/ActionLinkUiComponentFactory.java |  6 +-
 .../{ActionUiModel.java => ActionLinkUiModel.java} |  4 +-
 ...lFactory.java => ActionLinkUiModelFactory.java} |  8 +--
 .../MenuBuilder.java}                              | 22 +++----
 .../isis/viewer/common/model/menu/MenuUiModel.java | 72 +++++++++++++++++++++-
 .../model/menu/MenuUiModel_buildMenuItems.java     |  4 +-
 .../common/model/menuitem/MenuItemUiModel.java     |  6 +-
 .../common/model/object/SimpleObjectUiModel.java   |  5 +-
 .../viewer/wicket/model/links/LinkAndLabel.java    |  4 +-
 .../serviceactions/ServiceActionUtil.java          |  4 +-
 28 files changed, 356 insertions(+), 185 deletions(-)

diff --git a/examples/demo/domain/src/main/java/demoapp/dom/DemoModule.java b/examples/demo/domain/src/main/java/demoapp/dom/DemoModule.java
index 7283bea..d4b3103 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/DemoModule.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/DemoModule.java
@@ -19,6 +19,7 @@
 package demoapp.dom;
 
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.PropertySource;
@@ -30,26 +31,14 @@ import org.apache.isis.extensions.modelannotation.metamodel.IsisModuleExtModelAn
 import org.apache.isis.extensions.secman.api.SecurityModuleConfig;
 import org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationService;
 import org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationServiceAllowBeatsVeto;
-import org.apache.isis.extensions.secman.encryption.jbcrypt.IsisModuleExtSecmanEncryptionJbcrypt;
-import org.apache.isis.extensions.secman.jdo.IsisModuleExtSecmanPersistenceJdo;
-import org.apache.isis.extensions.secman.model.IsisModuleExtSecmanModel;
-import org.apache.isis.extensions.secman.shiro.IsisModuleExtSecmanRealmShiro;
 import org.apache.isis.persistence.jdo.datanucleus5.IsisModuleJdoDataNucleus5;
-import org.apache.isis.security.shiro.IsisModuleSecurityShiro;
 import org.apache.isis.testing.fixtures.applib.IsisModuleTestingFixturesApplib;
 
 @Configuration
 @Import({
     IsisModuleCoreRuntimeServices.class,
-    IsisModuleSecurityShiro.class,
     IsisModuleJdoDataNucleus5.class,
     
-    // Security Manager Extension (secman)
-    IsisModuleExtSecmanModel.class,
-    IsisModuleExtSecmanRealmShiro.class,
-    IsisModuleExtSecmanPersistenceJdo.class,
-    IsisModuleExtSecmanEncryptionJbcrypt.class,
-
     IsisModuleTestingFixturesApplib.class,
 
     IsisModuleExtModelAnnotation.class, // @Model support
@@ -61,6 +50,10 @@ import org.apache.isis.testing.fixtures.applib.IsisModuleTestingFixturesApplib;
     @PropertySource(IsisPresets.SilenceWicket),
     @PropertySource(IsisPresets.DataNucleusAutoCreate),
 })
+@ComponentScan(
+        basePackageClasses= {
+                DemoModule.class
+        })
 public class DemoModule {
     
     @Bean
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/viewmodels/ViewModels.java b/examples/demo/domain/src/main/java/demoapp/dom/viewmodels/ViewModels.java
index 62711ef..35f3156 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/viewmodels/ViewModels.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/viewmodels/ViewModels.java
@@ -18,26 +18,12 @@
  */
 package demoapp.dom.viewmodels;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
 import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.Editing;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Nature;
-import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.SemanticsOf;
 
-import lombok.Getter;
-import lombok.Setter;
 import lombok.val;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
 import demoapp.dom.viewmodels.jaxbrefentity.StatefulViewModelJaxbRefsEntity;
 import demoapp.dom.viewmodels.usingjaxb.StatefulViewModelUsingJaxb;
 
diff --git a/examples/demo/domain/src/main/java/demoapp/webapp/DemoAppManifest.java b/examples/demo/domain/src/main/java/demoapp/webapp/DemoAppManifest.java
index bbc57fc..e071b34 100644
--- a/examples/demo/domain/src/main/java/demoapp/webapp/DemoAppManifest.java
+++ b/examples/demo/domain/src/main/java/demoapp/webapp/DemoAppManifest.java
@@ -23,11 +23,15 @@ import java.util.Optional;
 import org.springframework.boot.web.server.WebServerFactoryCustomizer;
 import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
 import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
+import org.apache.isis.extensions.secman.encryption.jbcrypt.IsisModuleExtSecmanEncryptionJbcrypt;
+import org.apache.isis.extensions.secman.jdo.IsisModuleExtSecmanPersistenceJdo;
+import org.apache.isis.extensions.secman.model.IsisModuleExtSecmanModel;
+import org.apache.isis.extensions.secman.shiro.IsisModuleExtSecmanRealmShiro;
 import org.apache.isis.extensions.viewer.wicket.exceldownload.ui.IsisModuleExtExcelDownloadUi;
+import org.apache.isis.security.shiro.IsisModuleSecurityShiro;
 import org.apache.isis.testing.h2console.ui.IsisModuleTestingH2ConsoleUi;
 import org.apache.isis.viewer.restfulobjects.jaxrsresteasy4.IsisModuleViewerRestfulObjectsJaxrsResteasy4;
 import org.apache.isis.viewer.restfulobjects.viewer.IsisModuleViewerRestfulObjectsViewer;
@@ -45,7 +49,16 @@ import demoapp.dom._infra.LibraryPreloadingService;
 @Configuration
 @Import({
     DemoModule.class, // shared demo core module
+    
+    // SECURITY
+    IsisModuleSecurityShiro.class,
 
+    // Security Manager Extension (secman)
+    IsisModuleExtSecmanModel.class,
+    IsisModuleExtSecmanRealmShiro.class,
+    IsisModuleExtSecmanPersistenceJdo.class,
+    IsisModuleExtSecmanEncryptionJbcrypt.class,
+    
     // REST
     IsisModuleViewerRestfulObjectsViewer.class,
     IsisModuleViewerRestfulObjectsJaxrsResteasy4.class,
@@ -60,10 +73,6 @@ import demoapp.dom._infra.LibraryPreloadingService;
     AsciiDocReaderService.class,
 
 })
-@ComponentScan(
-        basePackageClasses= {
-                DemoModule.class
-        })
 @Log4j2
 public class DemoAppManifest {
 
diff --git a/examples/demo/javafx/src/main/java/demoapp/javafx/DemoAppJavaFx.java b/examples/demo/javafx/src/main/java/demoapp/javafx/DemoAppJavaFx.java
index 3eebb77..e18cdbd 100644
--- a/examples/demo/javafx/src/main/java/demoapp/javafx/DemoAppJavaFx.java
+++ b/examples/demo/javafx/src/main/java/demoapp/javafx/DemoAppJavaFx.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.runtimeservices.session.IsisInteractionFactoryDefaul
 import org.apache.isis.incubator.viewer.javafx.model.events.JavaFxViewerConfig;
 import org.apache.isis.incubator.viewer.javafx.viewer.IsisModuleIncViewerJavaFxViewer;
 import org.apache.isis.incubator.viewer.javafx.viewer.JavafxViewer;
+import org.apache.isis.security.bypass.IsisModuleSecurityBypass;
 
 import demoapp.dom.DemoModule;
 
@@ -39,6 +40,7 @@ import demoapp.dom.DemoModule;
     DemoModule.class,
     
     // INCUBATING
+    IsisModuleSecurityBypass.class,
     IsisModuleIncViewerJavaFxViewer.class,
   
 })
diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFactoryFx.java
similarity index 64%
copy from incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java
copy to incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFactoryFx.java
index ea7ba0d..8bccf20 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java
+++ b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFactoryFx.java
@@ -16,33 +16,33 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.incubator.viewer.vaadin.model.action;
+package org.apache.isis.incubator.viewer.javafx.model.action;
 
-import com.vaadin.flow.component.Component;
-import com.vaadin.flow.component.html.Label;
 
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.incubator.viewer.vaadin.model.decorator.Decorators;
-import org.apache.isis.incubator.viewer.vaadin.model.entity.ObjectVaa;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
-import org.apache.isis.viewer.common.model.action.ActionUiModelFactory;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModelFactory;
+import org.apache.isis.viewer.common.model.object.SimpleObjectUiModel;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+
 @RequiredArgsConstructor
-public class ActionFactoryVaa implements ActionUiModelFactory<Component> {
+public class ActionLinkFactoryFx implements ActionLinkUiModelFactory<Node> {
 
     @Override
-    public ActionUiModel<Component> newAction(
+    public ActionLinkFx newAction(
             IsisWebAppCommonContext commonContext, 
             String named,
             ManagedAction managedAction) {
         
-        val actionOwnerModel = new ObjectVaa(commonContext, managedAction.getOwner());
+        val actionOwnerModel = new SimpleObjectUiModel(commonContext, managedAction.getOwner());
         
-        val actionUiModel = new ActionVaa(
+        val actionUiModel = new ActionLinkFx(
                 this::createUiComponent,
                 named,
                 actionOwnerModel, 
@@ -53,13 +53,14 @@ public class ActionFactoryVaa implements ActionUiModelFactory<Component> {
     
     // -- HELPER
     
-    private Component createUiComponent(
-            final ActionUiModel<Component> actionUiModel) {
+    private Node createUiComponent(
+            final ActionLinkUiModel<Node> actionUiModel) {
         
         val actionMeta = actionUiModel.getActionUiMetaModel();
         val uiLabel = new Label(actionMeta.getLabel());
         
-        return Decorators.getIcon().decorate(uiLabel, actionMeta.getFontAwesomeUiModel());
+        return uiLabel;
+        //return Decorators.getIcon().decorate(uiLabel, actionMeta.getFontAwesomeUiModel());
                 
     }
 
diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFx.java
similarity index 70%
copy from incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java
copy to incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFx.java
index e281529..330a76c 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java
+++ b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/action/ActionLinkFx.java
@@ -16,24 +16,31 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.incubator.viewer.vaadin.model.action;
-
-import com.vaadin.flow.component.Component;
+package org.apache.isis.incubator.viewer.javafx.model.action;
 
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.common.model.HasUiMenuItem;
 import org.apache.isis.viewer.common.model.action.ActionLinkUiComponentFactory;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
 import org.apache.isis.viewer.common.model.object.ObjectUiModel;
 
-public class ActionVaa extends ActionUiModel<Component> {
+import javafx.scene.Node;
+import javafx.scene.control.Menu;
+
+public class ActionLinkFx extends ActionLinkUiModel<Node> implements HasUiMenuItem<Menu>{
 
-    public ActionVaa(
-            final ActionLinkUiComponentFactory<Component> uiComponentFactory,
+    public ActionLinkFx(
+            final ActionLinkUiComponentFactory<Node> uiComponentFactory,
             final String named,
             final ObjectUiModel actionHolder,
             final ObjectAction objectAction) {
         
         super(uiComponentFactory, named, actionHolder, objectAction);
     }
+
+    @Override
+    public Menu getUiMenuItem() {
+        return new Menu(super.getLabel());
+    }
     
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/menu/MenuItemFx.java
similarity index 57%
copy from viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
copy to incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/menu/MenuItemFx.java
index 53ee108..aacb1b8 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
+++ b/incubator/viewers/javafx/model/src/main/java/org/apache/isis/incubator/viewer/javafx/model/menu/MenuItemFx.java
@@ -16,19 +16,32 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.viewer.common.model.action;
+package org.apache.isis.incubator.viewer.javafx.model.menu;
+
+import org.apache.isis.viewer.common.model.menuitem.MenuItemUiModel;
+
+import lombok.val;
 
 /**
- * Creates a click-able UI component of type {@code <T>} based on an {@link ActionUiModel}.
- * eg. link, button, menu-item
- * 
- * @see ActionUiModel
- * 
  * @since 2.0.0
- * @param <T> - link component type, native to the viewer
  */
-public interface ActionLinkUiComponentFactory<T> {
+//@Log4j2
+public class MenuItemFx 
+extends MenuItemUiModel<javafx.scene.Node, MenuItemFx> {
+
+    public static MenuItemFx newMenuItem(final String label) {
+        return new MenuItemFx(label);
+    }
+
+    private MenuItemFx(final String label) {
+        super(label);
+    }
+    
+    @Override
+    protected MenuItemFx newSubMenuItem(final String label) {
+        val subMenuItem = newMenuItem(label);
+        subMenuItem.setParent(this);
+        return subMenuItem;
+    }
 
-    T newActionLinkUiComponent(ActionUiModel<T> actionUiModel);
-   
 }
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
index 2802fea..5f1cad2 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
@@ -22,7 +22,9 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.incubator.viewer.javafx.model.events.IsisModuleIncViewerJavaFxModel;
-import org.apache.isis.incubator.viewer.javafx.ui.main.PrimaryStageListener;
+import org.apache.isis.incubator.viewer.javafx.ui.main.UiBuilder;
+import org.apache.isis.incubator.viewer.javafx.ui.main.UiController;
+import org.apache.isis.viewer.common.model.IsisModuleViewerCommon;
 
 /**
  * 
@@ -31,11 +33,13 @@ import org.apache.isis.incubator.viewer.javafx.ui.main.PrimaryStageListener;
 @Configuration
 @Import({
         // modules
-    
+        IsisModuleViewerCommon.class,
         IsisModuleIncViewerJavaFxModel.class,
         
+        
         // @Components's
-        PrimaryStageListener.class,
+        UiBuilder.class,
+        UiController.class,
         
         // @Service's
 
@@ -44,9 +48,4 @@ import org.apache.isis.incubator.viewer.javafx.ui.main.PrimaryStageListener;
 
 public class IsisModuleIncViewerJavaFxUi {
 
-//    @Bean(name="uiMainLayout")
-//    public Resource uiMainLayout() {
-//        return new ClassPathResource("/ui.fxml");
-//    }
-    
 }
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/MenuBuilderFx.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/MenuBuilderFx.java
new file mode 100644
index 0000000..3cf7889
--- /dev/null
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/MenuBuilderFx.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.incubator.viewer.javafx.ui.main;
+
+import org.apache.isis.applib.layout.menubars.bootstrap3.BS3Menu;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
+import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
+import org.apache.isis.incubator.viewer.javafx.model.action.ActionLinkFactoryFx;
+import org.apache.isis.viewer.common.model.menu.MenuBuilder;
+
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
+
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuBar;
+
+@RequiredArgsConstructor(staticName = "of")
+@Log4j2
+public class MenuBuilderFx implements MenuBuilder {
+    
+    private final IsisWebAppCommonContext commonContext;
+    private final MenuBar menuBar;
+    
+    private Menu currentTopLevelMenu = null;
+    private ActionLinkFactoryFx actionLinkFactory = new ActionLinkFactoryFx();
+
+    
+    @Override
+    public void addTopLevel(BS3Menu menu) {
+        log.info("top level menu {}", menu.getNamed());
+        
+        menuBar.getMenus()
+        .add(currentTopLevelMenu = new Menu(menu.getNamed()));
+        
+    }
+    
+    @Override
+    public void addSectionSpacer() {
+        // TODO Auto-generated method stub
+        log.info("spacer");
+    }
+    
+    @Override
+    public void addSubMenu(String named, ManagedAction managedAction) {
+        log.info("top level menu {}", managedAction.getName());
+        
+        val actionLink = actionLinkFactory.newAction(commonContext, named, managedAction);
+        currentTopLevelMenu.getItems().add(actionLink.getUiMenuItem());
+    }
+    
+}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/PrimaryStageListener.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilder.java
similarity index 95%
rename from incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/PrimaryStageListener.java
rename to incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilder.java
index 600d70a..6630277 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/PrimaryStageListener.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilder.java
@@ -37,13 +37,13 @@ import javafx.scene.Scene;
 
 @Component
 @Log4j2
-public class PrimaryStageListener {
+public class UiBuilder {
     
     private final ApplicationContext springContext;
     private final JavaFxViewerConfig viewerConfig;
     
     @Inject
-    public PrimaryStageListener(
+    public UiBuilder(
             ApplicationContext springContext,
             JavaFxViewerConfig viewerConfig) {
         
@@ -59,7 +59,7 @@ public class PrimaryStageListener {
         val fxmlLoader = new FXMLLoader(layoutUrl);
         fxmlLoader.setControllerFactory(springContext::getBean);
         val uiRoot = (Parent)fxmlLoader.load();
-        val scene = new Scene(uiRoot, 800, 600);
+        val scene = new Scene(uiRoot);
         val stage = event.getStage();
         stage.setScene(scene);
         stage.setTitle(viewerConfig.getApplicationTitle());
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiController.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiController.java
new file mode 100644
index 0000000..b46b006
--- /dev/null
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiController.java
@@ -0,0 +1,69 @@
+/*
+ *  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.incubator.viewer.javafx.ui.main;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.core.metamodel.context.MetaModelContext;
+import org.apache.isis.core.runtime.iactn.IsisInteractionFactory;
+import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
+import org.apache.isis.viewer.common.model.header.HeaderUiModelProvider;
+
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.MenuBar;
+
+@Component
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+@Log4j2
+public class UiController {
+    
+    private final MetaModelContext metaModelContext;
+    private final HeaderUiModelProvider headerUiModelProvider;
+    private final IsisInteractionFactory isisInteractionFactory;
+
+    @FXML private MenuBar menuBarLeft;
+    @FXML private MenuBar menuBarRight;
+    
+    @FXML
+    public void initialize() {
+        log.info("about to initialize");
+        isisInteractionFactory.runAnonymous(this::buildMenu);
+    }
+    
+    private void buildMenu() {
+        val header = headerUiModelProvider.getHeader();
+        
+        val commonContext = IsisWebAppCommonContext.of(metaModelContext);
+        
+        val leftMenuBuilder = MenuBuilderFx.of(commonContext, menuBarLeft);
+        val rightMenuBuilder = MenuBuilderFx.of(commonContext, menuBarRight);
+        
+        header.getPrimary().buildMenuItems(commonContext, leftMenuBuilder);
+        header.getSecondary().buildMenuItems(commonContext, rightMenuBuilder);
+        header.getTertiary().buildMenuItems(commonContext, rightMenuBuilder);
+    }
+
+    
+}
diff --git a/incubator/viewers/javafx/ui/src/main/resources/ui.fxml b/incubator/viewers/javafx/ui/src/main/resources/ui.fxml
index fd5ee3f..ea25941 100644
--- a/incubator/viewers/javafx/ui/src/main/resources/ui.fxml
+++ b/incubator/viewers/javafx/ui/src/main/resources/ui.fxml
@@ -1,61 +1,29 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
 <?import javafx.scene.control.Label?>
-<?import javafx.scene.control.Menu?>
 <?import javafx.scene.control.MenuBar?>
-<?import javafx.scene.control.MenuItem?>
 <?import javafx.scene.control.ScrollPane?>
-<?import javafx.scene.control.SeparatorMenuItem?>
 <?import javafx.scene.control.SplitPane?>
+<?import javafx.scene.control.TextArea?>
 <?import javafx.scene.layout.AnchorPane?>
 <?import javafx.scene.layout.HBox?>
 <?import javafx.scene.layout.Pane?>
+<?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.VBox?>
 <?import javafx.scene.paint.Color?>
 <?import javafx.scene.text.Font?>
 
-<VBox prefHeight="600.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
+<VBox prefHeight="800.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.apache.isis.incubator.viewer.javafx.ui.main.UiController">
   <children>
-    <MenuBar VBox.vgrow="NEVER">
-      <menus>
-        <Menu mnemonicParsing="false" text="File">
-          <items>
-            <MenuItem mnemonicParsing="false" text="New" />
-            <MenuItem mnemonicParsing="false" text="Open…" />
-            <Menu mnemonicParsing="false" text="Open Recent" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem mnemonicParsing="false" text="Close" />
-            <MenuItem mnemonicParsing="false" text="Save" />
-            <MenuItem mnemonicParsing="false" text="Save As…" />
-            <MenuItem mnemonicParsing="false" text="Revert" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem mnemonicParsing="false" text="Preferences…" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem mnemonicParsing="false" text="Quit" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="Edit">
-          <items>
-            <MenuItem mnemonicParsing="false" text="Undo" />
-            <MenuItem mnemonicParsing="false" text="Redo" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem mnemonicParsing="false" text="Cut" />
-            <MenuItem mnemonicParsing="false" text="Copy" />
-            <MenuItem mnemonicParsing="false" text="Paste" />
-            <MenuItem mnemonicParsing="false" text="Delete" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem mnemonicParsing="false" text="Select All" />
-            <MenuItem mnemonicParsing="false" text="Unselect All" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="Help">
-          <items>
-            <MenuItem mnemonicParsing="false" text="About MyHelloApp" />
-          </items>
-        </Menu>
-      </menus>
-    </MenuBar>
+    <HBox VBox.vgrow="NEVER">
+      <children>
+    		<MenuBar fx:id="menuBarLeft" />
+            <Region fx:id="topLevelMenuSpacer" styleClass="menu-bar" HBox.hgrow="SOMETIMES" />
+    		<MenuBar fx:id="menuBarRight" />
+   	  </children>
+    </HBox>
     <SplitPane dividerPositions="0.2505567928730512, 0.7505567928730512" focusTraversable="true" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
       <items>
         <AnchorPane>
@@ -68,6 +36,8 @@
                 <Color blue="0.624" green="0.624" red="0.624" fx:id="x2" />
               </textFill>
             </Label>
+                  <Button layoutX="11.0" layoutY="88.0" mnemonicParsing="false" text="Button" />
+                  <TextArea layoutX="11.0" layoutY="122.0" prefHeight="200.0" prefWidth="200.0" />
           </children>
         </AnchorPane>
         <ScrollPane prefHeight="-1.0" prefWidth="-1.0">
diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkFactoryVaa.java
similarity index 77%
rename from incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java
rename to incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkFactoryVaa.java
index ea7ba0d..8972e3e 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionFactoryVaa.java
+++ b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkFactoryVaa.java
@@ -24,25 +24,25 @@ import com.vaadin.flow.component.html.Label;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
 import org.apache.isis.incubator.viewer.vaadin.model.decorator.Decorators;
-import org.apache.isis.incubator.viewer.vaadin.model.entity.ObjectVaa;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
-import org.apache.isis.viewer.common.model.action.ActionUiModelFactory;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModelFactory;
+import org.apache.isis.viewer.common.model.object.SimpleObjectUiModel;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @RequiredArgsConstructor
-public class ActionFactoryVaa implements ActionUiModelFactory<Component> {
+public class ActionLinkFactoryVaa implements ActionLinkUiModelFactory<Component> {
 
     @Override
-    public ActionUiModel<Component> newAction(
+    public ActionLinkUiModel<Component> newAction(
             IsisWebAppCommonContext commonContext, 
             String named,
             ManagedAction managedAction) {
         
-        val actionOwnerModel = new ObjectVaa(commonContext, managedAction.getOwner());
+        val actionOwnerModel = new SimpleObjectUiModel(commonContext, managedAction.getOwner());
         
-        val actionUiModel = new ActionVaa(
+        val actionUiModel = new ActionLinkVaa(
                 this::createUiComponent,
                 named,
                 actionOwnerModel, 
@@ -54,7 +54,7 @@ public class ActionFactoryVaa implements ActionUiModelFactory<Component> {
     // -- HELPER
     
     private Component createUiComponent(
-            final ActionUiModel<Component> actionUiModel) {
+            final ActionLinkUiModel<Component> actionUiModel) {
         
         val actionMeta = actionUiModel.getActionUiMetaModel();
         val uiLabel = new Label(actionMeta.getLabel());
diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkVaa.java
similarity index 89%
rename from incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java
rename to incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkVaa.java
index e281529..011f230 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionVaa.java
+++ b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/action/ActionLinkVaa.java
@@ -22,12 +22,12 @@ import com.vaadin.flow.component.Component;
 
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.common.model.action.ActionLinkUiComponentFactory;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
 import org.apache.isis.viewer.common.model.object.ObjectUiModel;
 
-public class ActionVaa extends ActionUiModel<Component> {
+public class ActionLinkVaa extends ActionLinkUiModel<Component> {
 
-    public ActionVaa(
+    public ActionLinkVaa(
             final ActionLinkUiComponentFactory<Component> uiComponentFactory,
             final String named,
             final ObjectUiModel actionHolder,
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView.java
index 35ab841..216a2f0 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView.java
@@ -36,7 +36,7 @@ import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.interactions.InteractionHead;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.incubator.viewer.vaadin.model.action.ActionVaa;
+import org.apache.isis.incubator.viewer.vaadin.model.action.ActionLinkVaa;
 import org.apache.isis.incubator.viewer.vaadin.ui.components.UiComponentFactoryVaa;
 import org.apache.isis.incubator.viewer.vaadin.ui.components.collection.TableView;
 import org.apache.isis.incubator.viewer.vaadin.ui.components.object.ObjectFormView;
@@ -97,7 +97,7 @@ implements BeforeEnterObserver {
         setDrawerOpened(false);
     }
 
-    private void onMenuAction(ActionVaa menuActionModel) {
+    private void onMenuAction(ActionLinkVaa menuActionModel) {
         
         pageContent.removeAll();
 
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
index 6964d1c..2ef7094 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
@@ -32,8 +32,8 @@ import com.vaadin.flow.component.orderedlayout.FlexComponent.Alignment;
 import com.vaadin.flow.component.orderedlayout.FlexLayout;
 
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.incubator.viewer.vaadin.model.action.ActionFactoryVaa;
-import org.apache.isis.incubator.viewer.vaadin.model.action.ActionVaa;
+import org.apache.isis.incubator.viewer.vaadin.model.action.ActionLinkFactoryVaa;
+import org.apache.isis.incubator.viewer.vaadin.model.action.ActionLinkVaa;
 import org.apache.isis.incubator.viewer.vaadin.model.decorator.Decorators;
 import org.apache.isis.incubator.viewer.vaadin.model.menu.MenuItemVaa;
 import org.apache.isis.viewer.common.model.branding.BrandingUiModel;
@@ -48,7 +48,7 @@ final class MainView_createHeader {
     static Component createHeader(
             final IsisWebAppCommonContext commonContext, 
             final HeaderUiModel headerUiModel,
-            final Consumer<ActionVaa> subMenuEventHandler) {
+            final Consumer<ActionLinkVaa> subMenuEventHandler) {
         
         val titleOrLogo = createTitleOrLogo(commonContext, headerUiModel.getBranding());
         val leftMenuBar = new MenuBar();
@@ -80,7 +80,7 @@ final class MainView_createHeader {
                             .decorateTopLevel(new Label(menuSectionUiModel.getName())));
             val subMenu = menuItem.getSubMenu();
             menuSectionUiModel.getSubMenuItems().forEach(menuItemModel -> {
-                val menuActionModel = (ActionVaa)menuItemModel.getMenuActionUiModel();
+                val menuActionModel = (ActionLinkVaa)menuItemModel.getMenuActionUiModel();
                 
                 if(menuItemModel.isFirstInSection() 
                         && subMenu.getItems().size()>0) {
@@ -142,7 +142,7 @@ final class MainView_createHeader {
         
         menuUiModel.buildMenuItems(
                 commonContext, 
-                new ActionFactoryVaa(),
+                new ActionLinkFactoryVaa(),
                 MenuItemVaa::newMenuItem,
                 onNewMenuItem);
     }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/HasUiMenuItem.java
similarity index 67%
copy from viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
copy to viewers/common/src/main/java/org/apache/isis/viewer/common/model/HasUiMenuItem.java
index 53ee108..0e2b033 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/HasUiMenuItem.java
@@ -16,19 +16,10 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.viewer.common.model.action;
+package org.apache.isis.viewer.common.model;
 
-/**
- * Creates a click-able UI component of type {@code <T>} based on an {@link ActionUiModel}.
- * eg. link, button, menu-item
- * 
- * @see ActionUiModel
- * 
- * @since 2.0.0
- * @param <T> - link component type, native to the viewer
- */
-public interface ActionLinkUiComponentFactory<T> {
+public interface HasUiMenuItem<T> {
 
-    T newActionLinkUiComponent(ActionUiModel<T> actionUiModel);
-   
+    T getUiMenuItem();
+    
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentDecorator.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentDecorator.java
index 119ac34..6becab5 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentDecorator.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentDecorator.java
@@ -28,9 +28,9 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
 /**
- * Decorates a click-able UI component of type {@code <T>} based on an {@link ActionUiModel}.
+ * Decorates a click-able UI component of type {@code <T>} based on an {@link ActionLinkUiModel}.
  * 
- * @see ActionUiModel
+ * @see ActionLinkUiModel
  * 
  * @since 2.0.0
  * @param <T> - link component type, native to the viewer
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
index 53ee108..7aa8777 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
@@ -19,16 +19,16 @@
 package org.apache.isis.viewer.common.model.action;
 
 /**
- * Creates a click-able UI component of type {@code <T>} based on an {@link ActionUiModel}.
+ * Creates a click-able UI component of type {@code <T>} based on an {@link ActionLinkUiModel}.
  * eg. link, button, menu-item
  * 
- * @see ActionUiModel
+ * @see ActionLinkUiModel
  * 
  * @since 2.0.0
  * @param <T> - link component type, native to the viewer
  */
 public interface ActionLinkUiComponentFactory<T> {
 
-    T newActionLinkUiComponent(ActionUiModel<T> actionUiModel);
+    T newActionLinkUiComponent(ActionLinkUiModel<T> actionUiModel);
    
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModel.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModel.java
similarity index 97%
rename from viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModel.java
rename to viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModel.java
index 4fd5351..82c8b2a 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModel.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModel.java
@@ -36,12 +36,12 @@ import lombok.RequiredArgsConstructor;
 /**
  * Holder of the <em>Action's</em> meta-model and a click-able UI action component; eg. link, button, menu-items.
  * 
- * @see ActionUiModelFactory
+ * @see ActionLinkUiModelFactory
  * @since 2.0.0
  * @param <T> - link component type, native to the viewer
  */
 @RequiredArgsConstructor
-public abstract class ActionUiModel<T> implements HasUiComponent<T> {
+public abstract class ActionLinkUiModel<T> implements HasUiComponent<T> {
 
     protected final ActionLinkUiComponentFactory<T> uiComponentFactory;
     
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModelFactory.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModelFactory.java
similarity index 88%
rename from viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModelFactory.java
rename to viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModelFactory.java
index 39e97ee..3a41c0b 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionUiModelFactory.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiModelFactory.java
@@ -22,15 +22,15 @@ import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
 
 /**
- * Creates an {@link ActionUiModel}, a holder of the <em>Action's</em> meta-model 
+ * Creates an {@link ActionLinkUiModel}, a holder of the <em>Action's</em> meta-model 
  * and a click-able UI action component; eg. link, button, menu-items.
  * 
- * @see ActionUiModel
+ * @see ActionLinkUiModel
  * 
  * @since 2.0.0
  * @param <T> - link component type, native to the viewer
  */
-public interface ActionUiModelFactory<T> {
+public interface ActionLinkUiModelFactory<T> {
     
     /**
      * 
@@ -39,7 +39,7 @@ public interface ActionUiModelFactory<T> {
      * @param managedAction
      * @return
      */
-    ActionUiModel<T> newAction(
+    ActionLinkUiModel<T> newAction(
             IsisWebAppCommonContext commonContext, 
             String named,
             ManagedAction managedAction);
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuBuilder.java
similarity index 67%
copy from viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
copy to viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuBuilder.java
index 53ee108..f120d89 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/ActionLinkUiComponentFactory.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuBuilder.java
@@ -16,19 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.viewer.common.model.action;
+package org.apache.isis.viewer.common.model.menu;
 
-/**
- * Creates a click-able UI component of type {@code <T>} based on an {@link ActionUiModel}.
- * eg. link, button, menu-item
- * 
- * @see ActionUiModel
- * 
- * @since 2.0.0
- * @param <T> - link component type, native to the viewer
- */
-public interface ActionLinkUiComponentFactory<T> {
+import org.apache.isis.applib.layout.menubars.bootstrap3.BS3Menu;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
+
+public interface MenuBuilder {
 
-    T newActionLinkUiComponent(ActionUiModel<T> actionUiModel);
-   
+    void addTopLevel(BS3Menu menu);
+    void addSectionSpacer();
+    void addSubMenu(String named, ManagedAction managedAction);
+    
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel.java
index 7ed5392..1e0ac5e 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel.java
@@ -21,22 +21,26 @@ package org.apache.isis.viewer.common.model.menu;
 import java.io.Serializable;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.atomic.LongAdder;
 import java.util.function.Consumer;
 import java.util.function.Function;
 
 import org.apache.isis.applib.annotation.DomainServiceLayout;
 import org.apache.isis.applib.layout.menubars.bootstrap3.BS3MenuBar;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.viewer.common.model.action.ActionUiModelFactory;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModelFactory;
 import org.apache.isis.viewer.common.model.menuitem.MenuItemUiModel;
 
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
+import lombok.extern.log4j.Log4j2;
 
 @Getter
 @RequiredArgsConstructor(staticName = "of")
+@Log4j2
 public class MenuUiModel implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -51,7 +55,7 @@ public class MenuUiModel implements Serializable {
     public <T, M extends MenuItemUiModel<T, M>> 
     void buildMenuItems(
             final IsisWebAppCommonContext commonContext,
-            final ActionUiModelFactory<T> menuActionFactory,
+            final ActionLinkUiModelFactory<T> menuActionFactory,
             final Function<String, M> menuItemFactory,
             final Consumer<M> onNewMenuItem) {
         
@@ -69,5 +73,69 @@ public class MenuUiModel implements Serializable {
         
     }
     
+    public void buildMenuItems(
+            final IsisWebAppCommonContext commonContext,
+            final MenuBuilder menuBuilder) {
+        
+        val menuBars = commonContext.getMenuBarsService().menuBars();
+
+        // TODO: remove hard-coded dependency on BS3
+        final BS3MenuBar menuBar = (BS3MenuBar) menuBars.menuBarFor(getMenuBarSelect());
+        
+        val itemsPerSectionCounter = new LongAdder();
+        
+        for (val menu : menuBar.getMenus()) {
+            
+            menuBuilder.addTopLevel(menu);
+
+            for (val menuSection : menu.getSections()) {
+
+                itemsPerSectionCounter.reset();
+                
+                for (val actionLayoutData : menuSection.getServiceActions()) {
+                    val serviceSpecId = actionLayoutData.getObjectType();
+
+                    val serviceAdapter = commonContext.lookupServiceAdapterById(serviceSpecId);
+                    if(serviceAdapter == null) {
+                        // service not recognized, presumably the menu layout is out of sync with actual configured modules
+                        continue;
+                    }
+
+                    val managedAction = ManagedAction.lookupAction(serviceAdapter, actionLayoutData.getId())
+                            .orElse(null);
+                    if (managedAction == null) {
+                        log.warn("No such action {}", actionLayoutData.getId());
+                        continue;
+                    }
+                    
+                    val isFirstInSection = itemsPerSectionCounter.intValue()==0; 
+                    
+                    //TODO call this only, if visible and usable 
+                    menuBuilder.addSubMenu(actionLayoutData.getNamed(), managedAction);
+                    
+//                    val menuActionUiModel = menuActionFactory.newAction(
+//                            commonContext,
+//                            actionLayoutData.getNamed(),
+//                            managedAction);
+
+                    // Optionally creates a sub-menu item based on visibility and usability
+//                    menuItemModel.addSubMenuItemFor(
+//                            menuActionUiModel, 
+//                            isFirstInSection,
+//                            newSubMenuItem->{
+//                                // increment counter only when a sub item was actually added
+//                                itemsPerSectionCounter.increment();
+//                                newSubMenuItem.setMenuActionUiModel(menuActionUiModel);
+//                    });
+                    
+                }
+            }
+//            if (menuItemModel.hasSubMenuItems()) {
+//                onNewMenuItem.accept(menuItemModel);
+//            }
+        }
+        
+    }
+    
 
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel_buildMenuItems.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel_buildMenuItems.java
index 5d7dae0..ae020cd 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel_buildMenuItems.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menu/MenuUiModel_buildMenuItems.java
@@ -27,7 +27,7 @@ import org.apache.isis.applib.layout.menubars.bootstrap3.BS3MenuBar;
 import org.apache.isis.core.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.viewer.common.model.action.ActionUiModelFactory;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModelFactory;
 import org.apache.isis.viewer.common.model.menuitem.MenuItemUiModel;
 import org.apache.isis.viewer.common.model.userprofile.UserProfileUiModelProvider;
 
@@ -41,7 +41,7 @@ final class MenuUiModel_buildMenuItems {
     void buildMenuItems(
             final IsisWebAppCommonContext commonContext,
             final BS3MenuBar menuBar,
-            final ActionUiModelFactory<T> menuActionFactory,
+            final ActionLinkUiModelFactory<T> menuActionFactory,
             final Function<String, M> menuItemFactory,
             final Consumer<M> onNewMenuItem) {
 
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menuitem/MenuItemUiModel.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menuitem/MenuItemUiModel.java
index a289db1..89e6fe0 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menuitem/MenuItemUiModel.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/menuitem/MenuItemUiModel.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
 
 import org.apache.isis.core.commons.internal.base._Casts;
 import org.apache.isis.core.commons.internal.collections._Lists;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -56,7 +56,7 @@ public abstract class MenuItemUiModel<T, U extends MenuItemUiModel<T, U>> {
     
     @Getter @Setter private boolean isTertiaryRoot = false; // unless set otherwise
 
-    @Getter @Setter private ActionUiModel<T> menuActionUiModel;
+    @Getter @Setter private ActionLinkUiModel<T> menuActionUiModel;
     
     private final List<U> subMenuItems = _Lists.newArrayList();
     protected void addSubMenuItem(final U cssMenuItem) {
@@ -93,7 +93,7 @@ public abstract class MenuItemUiModel<T, U extends MenuItemUiModel<T, U>> {
      * {@link MenuActionWkt action model}, based on visibility and usability.
      */
     public void addSubMenuItemFor(
-            @NonNull final ActionUiModel<T> actionModel,
+            @NonNull final ActionLinkUiModel<T> actionModel,
             final boolean isFirstInSection,
             @Nullable final Consumer<U> onNewSubMenuItem) {
 
diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/entity/ObjectVaa.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/object/SimpleObjectUiModel.java
similarity index 87%
rename from incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/entity/ObjectVaa.java
rename to viewers/common/src/main/java/org/apache/isis/viewer/common/model/object/SimpleObjectUiModel.java
index fb46d31..b7580b3 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/entity/ObjectVaa.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/object/SimpleObjectUiModel.java
@@ -16,18 +16,17 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.incubator.viewer.vaadin.model.entity;
+package org.apache.isis.viewer.common.model.object;
 
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.viewer.common.model.object.ObjectUiModel;
 
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor
-public class ObjectVaa implements ObjectUiModel {
+public class SimpleObjectUiModel implements ObjectUiModel {
 
     private final IsisWebAppCommonContext commonContext;
     
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/links/LinkAndLabel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/links/LinkAndLabel.java
index fd2a386..6814365 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/links/LinkAndLabel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/links/LinkAndLabel.java
@@ -34,14 +34,14 @@ import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.common.model.action.ActionUiMetaModel;
-import org.apache.isis.viewer.common.model.action.ActionUiModel;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModel;
 import org.apache.isis.viewer.wicket.model.common.CommonContextUtils;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 
 import lombok.NonNull;
 import lombok.val;
 
-public final class LinkAndLabel extends ActionUiModel<AbstractLink> implements Serializable  {
+public final class LinkAndLabel extends ActionLinkUiModel<AbstractLink> implements Serializable  {
 
     private static final long serialVersionUID = 1L;
     
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 4907766..0e8a7d0 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -31,7 +31,7 @@ import org.apache.wicket.markup.html.panel.Fragment;
 
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
-import org.apache.isis.viewer.common.model.action.ActionUiModelFactory;
+import org.apache.isis.viewer.common.model.action.ActionLinkUiModelFactory;
 import org.apache.isis.viewer.common.model.menu.MenuUiModel;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -106,7 +106,7 @@ public final class ServiceActionUtil {
     }
 
 
-    private static class MenuActionFactoryWkt implements ActionUiModelFactory<AbstractLink> {
+    private static class MenuActionFactoryWkt implements ActionLinkUiModelFactory<AbstractLink> {
 
         @Override
         public LinkAndLabel newAction(