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 2017/11/07 22:31:45 UTC
[isis] branch master updated: ISIS-1766: updates docs for menubars,
and fixes an NPE
This is an automated email from the ASF dual-hosted git repository.
danhaywood 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 56c0195 ISIS-1766: updates docs for menubars, and fixes an NPE
56c0195 is described below
commit 56c0195f891c6639696fd63fe1a72f49bc5dcf76
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Nov 7 22:29:16 2017 +0000
ISIS-1766: updates docs for menubars, and fixes an NPE
---
.../guides/rgcms/_rgcms_classes_menubars.adoc | 56 +++----
.../main/asciidoc/guides/ugvw/_ugvw_layout.adoc | 6 +-
.../guides/ugvw/_ugvw_layout_application-menu.adoc | 165 ---------------------
.../guides/ugvw/_ugvw_layout_file-based.adoc | 62 ++++----
.../guides/ugvw/_ugvw_menubars-layout.adoc | 39 +++++
.../_ugvw_menubars-layout_annotation-based.adoc | 126 ++++++++++++++++
.../ugvw/_ugvw_menubars-layout_file-based.adoc | 105 +++++++++++++
.../guides/ugvw/images/menubars/010-download.png | Bin 0 -> 21017 bytes
.../guides/ugvw/images/menubars/020-download.png | Bin 0 -> 15727 bytes
.../src/main/asciidoc/guides/ugvw/ugvw.adoc | 1 +
.../menubars/bootstrap3/MenuBarsServiceBS3.java | 2 +
.../application/manifest/menubars.layout.xml | 91 ++++++++++++
12 files changed, 426 insertions(+), 227 deletions(-)
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_classes_menubars.adoc b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_classes_menubars.adoc
index 28613db..83ba17c 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_classes_menubars.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_classes_menubars.adoc
@@ -5,64 +5,64 @@
:_imagesdir: images/
-The `org.apache.isis.applib.layout.menus` package defines a number of classes that allow the layout of domain service actions to be organised across menu bars, menus and menu sections.
+The `org.apache.isis.applib.layout.menubars` package and subpackages define a number of interfaces classes that allow the layout of domain service actions to be organised across menu bars, menus and menu sections.
-These classes fall into two main categories:
+The classes define a hierarchical structure of menu bars, menus and menu sections.
+Similar to the xref:rgcms.adoc#_rgcms_classes_layout[object layout] classes, the concrete menu classes support bootstrap3; support for other layout systems is possible.
-* menu classes, that define a hierarchical structure of menu bars, menus and menu sections, and;
+The component class `ServiceActionLayoutData` defines action metadata, being broadly equivalent to the "layout" annotations for actions, ie xref:../rgant/rgant.adoc#_rgant-ActionLayout[`@ActionLayout`].
+This is similar to the `ActionLayoutData` component class used for object layouts, but also captures the identity of the "owning" domain service.
+Service actions are grouped into menu sections.
-+
-Unlike the xref:rgcms.adoc#_rgcms_classes_layout[object layout] classes, the menu classes have no dependency on any particular layout architecture (that is, they don't attempt to model some particular grid system such as bootstrap3).
-
-* a component class `(ServiceActionLayoutData`) that captures the layout metadata for a domain services action.
-These are grouped into menu sections.
-
-+
-The component class is broadly equivalent to the "layout" annotations for actions, ie xref:../rgant/rgant.adoc#_rgant-ActionLayout[`@ActionLayout`].
-
-The menu classes and the component class should be reusable across all any and all UI implementations, so this is a less abstract (though equally general) design as compared to the xref:rgcms.adoc#_rgcms_classes_layout[object layout] design.
-
-All of the classes in this package are JAXB-annotated, meaning that they can be serialized to/from XML (in the `http://isis.apache.org/applib/layout/menus` XSD namespace).
+All of the classes in this package are JAXB-annotated, meaning that they can be serialized to/from XML (in the `http://isis.apache.org/applib/layout/menubars/bootstrap3` XSD namespace).
This ability to serialize to/from XML is used by the xref:../rgsvc/rgsvc.adoc#_rgsvc_presentation-layer-spi_MenuBarsLoaderService[`MenuBarsLoaderService`], the default implementation of which reads the grid layout for a domain class from a `.layout.xml` file on the classpath.
It also allows the menu bars to be exposed through the REST API provided by the xref:../ugvro/ugvro.adoc#[Restful Objects viewer], as either XML or JSON.
-The service action component also allow a link to be associated with it.
+The service action component also allows a link to be associated with it.
Each such link is populated by the framework automatically when exposing the menu bars layout through the REST API, pointing back to the standard Restful Objects resources.
This design greatly assists in the implementation of generic REST clients.
-[[_rgcms_classes_menubars]]
+[[_rgcms_classes_menubars_menus]]
== Menus
-Both the menu and component classes reside in the `org.apache.isis.applib.layout.menus` package, consisting of:
+The menu classes reside in the `org.apache.isis.applib.layout.menubars.bootstrap3` package, consisting of:
-* `MenuBars`
+* `BS3MenuBars`
+
-The top-level structure that define three fields: a primary `MenuBar`, secondary `MenuBar` and tertiary `MenuBar`.
-The xref:../ugvw/ugvw.adoc#[Wicket viewer] places the primary bar to the left, the secondary bar aligned right, and the tertiary bar (expected to consist of just one `Menu`) under the user names.
+The top-level structure that define three fields: a primary `BS3MenuBar`, secondary `BS3MenuBar` and tertiary `BS3MenuBar`.
+The xref:../ugvw/ugvw.adoc#[Wicket viewer] places the primary bar to the left, the secondary bar aligned right, and the tertiary bar (expected to consist of just one `BS3Menu`) under the user names.
-* `MenuBar`
+* `BS3MenuBar`
+
-consisting of one or many ``Menu``s.
+consisting of one or many ``BS3Menu``s.
-* `Menu`
+* `BS3Menu`
+
-consisting of one or many ``MenuSection``s.
+consisting of one or many ``BS3MenuSection``s.
The xref:../ugvw/ugvw.adoc#[Wicket viewer] renders a separator between each section.
-* `MenuSection`
+* `BS3MenuSection`
+
consisting of one or many actions (``ServiceActionLayoutData``s)
-* `ServiceActionLayoutData` class, which correspond to the xref:../rgant/rgant.adoc#_rgant-ActionLayout[`@ActionLayout`] annotation.
+
+[[_rgcms_classes_menubars_components]]
+== Components
+
+The service action class reside in the `org.apache.isis.applib.layout.component` package, consisting of just:
+
+* `ServiceActionLayoutData` class
+
+which correspond to the xref:../rgant/rgant.adoc#_rgant-ActionLayout[`@ActionLayout`] annotation.
+
This is similar to `ActionLayoutData` (of the xref:rgcms.adoc#_rgcms_classes_layout[object layout] classes), however it also identifies the domain service to which it belongs.
-(This isn't required for the object layouts because that is implicit).
+(This isn't required for the object layouts because the owner in that case is implicit).
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc
index d3fb6dc..0139a0b 100644
--- a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc
@@ -5,17 +5,15 @@
:_imagesdir: images/
-
-
In implementing the http://en.wikipedia.org/wiki/Naked_objects[naked objects pattern], Apache Isis aims to infer as much information from the domain classes as possible.
Nevertheless, some metadata relating solely to the UI is inevitably required.
This chapter describes how this is done both for domain objects using either annotations or using an associated layout file.
-It also describes how to layout the application menu items (containing domain service' actions), as more well as more advanced topics such as customising which columns appear in tables.
+The chapter also describes how to customising which columns of associated objects appear in tables.
+The layout of application menu items is described in a xref:ugvw.adoc#_ugvw_menubars-layout[separate chapter].
include::_ugvw_layout_annotation-based.adoc[leveloffset=+1]
include::_ugvw_layout_file-based.adoc[leveloffset=+1]
-include::_ugvw_layout_application-menu.adoc[leveloffset=+1]
include::_ugvw_layout_table-columns.adoc[leveloffset=+1]
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_application-menu.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_application-menu.adoc
deleted file mode 100644
index 02a83e5..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_application-menu.adoc
+++ /dev/null
@@ -1,165 +0,0 @@
-[[_ugvw_layout_application-menu]]
-= Application Menu Layout
-:Notice: 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 ag [...]
-:_basedir: ../../
-:_imagesdir: images/
-
-
-
-The actions of domain services are made available as an application menu bar. By default each domain service
-corresponds to a single menu on this menu bar, with its actions as the drop-down menu items. This is rarely exactly
-what is required, however. The `@MemberOrder` and `@DomainServiceLayout` annotations can be used to rearrange the
-placement of menu items.
-
-The screenshots below are taken from http://github.com/estatio/estatio[Estatio], an open source estate management
-application built using Apache Isis.
-
-== @DomainServiceLayout
-
-Menus for domain services can be placed either on a primary, secondary or tertiary menu bar.
-
-image::{_imagesdir}application-menu/layout-menus.png[width="800px",link="{_imagesdir}application-menu/layout-menus.png"]
-
-Within a single top-level menu (eg "Fixed Assets") there can be actions from multiple services. The Wicket viewer
-automatically adds a divider between each:
-
-image::{_imagesdir}application-menu/dividers.png[width="400px",link="{_imagesdir}application-menu/dividers.png"]
-
-In the example above the top-level menu combines the actions from the `Properties`, `Units` and `FixedAssetRegistrations`
-services. The `Properties` service is annotated:
-
-[source,java]
-----
-@DomainServiceLayout(
- named="Fixed Assets",
- menuBar = DomainServiceLayout.MenuBar.PRIMARY,
- menuOrder = "10.1"
-)
-public class Properties ... { ... }
-----
-
-while the `Units` service is annotated:
-
-[source,java]
-----
-@DomainServiceLayout(
- named="Fixed Assets",
- menuBar = DomainServiceLayout.MenuBar.PRIMARY,
- menuOrder = "10.2"
-)
-public class Units ... { ... }
-----
-
-and similarly `FixedAssetRegistrations` is annotated:
-
-[source,java]
-----
-@DomainServiceLayout(
- named="Fixed Assets",
- menuBar = DomainServiceLayout.MenuBar.PRIMARY,
- menuOrder = "10.3"
-)
-public class FixedAssetRegistrations ... { ... }
-----
-
-Note that in all three cases the value of the `named` attribute and the `menuBar` attribute is the same: "Fixed Assets"
-and PRIMARY. This means that all will appear on a "Fixed Assets" menu in the primary menu bar.
-
-Meanwhile the value of `menuOrder` attribute is significant for two reasons:
-
-* for these three services on the same ("Fixed Assets") top-level menu, it determines the relative order of their sections (`Properties` first, then `Units`, then `FixedAssetRegistrations`)
-* it determines the placement of the top-level menu itself ("Fixed Assets") with respect to other top-level menus on the menu bar.
-
-To illustrate this latter point, the next top-level menu on the menu bar, "Parties", is placed after "Fixed Assets"
- because the `menuOrder` of the first of its domain services, namely the `Parties` service, is higher than that for
- "Fixed Assets":
-
-[source,java]
-----
-@DomainServiceLayout(
- named="Parties",
- menuBar = DomainServiceLayout.MenuBar.PRIMARY,
- menuOrder = "20.1"
-)
-public class Parties ... { ... }
-----
-
-Note that only the `menuOrder` of the _first_ domain service is significant in placing the menus along the menu bar;
-thereafter the purpose of the `menuOrder` is to order the menu services sections on the menu itself.
-
-== Ordering menu actions
-
-For a given service, the actions within a section on a menu is determined by the `@MemberOrder` annotation. Thus, for
-the `Units` domain service, its actions are annotated:
-
-[source,java]
-----
-public class Units extends EstatioDomainService<Unit> {
-
- @MemberOrder(sequence = "1")
- public Unit newUnit( ... ) { ... }
-
- @MemberOrder(sequence = "2")
- public List<Unit> findUnits( ... ) { ... }
-
- @ActionLayout( prototype = true )
- @MemberOrder(sequence = "99")
- public List<Unit> allUnits() { ... }
- ...
-}
-----
-
-Note that the last is also a prototype action (meaning it is only displayed in SERVER_PROTOTYPE (=Wicket Development) mode).
-In the UI it is rendered in italics.
-
-(It is possible to override this place of a given action by specifying `@MemberOrder(name="...")` where the name is
-that of a top-level menu. Prior to `1.8.0` this was the only way of doing things, as of `1.8.0` its use
-is not recommended).
-
-== Tertiary menubar
-
-The tertiary menu bar consists of a single unnamed menu, rendered underneath the user's login, top right. This is
-intended primarily for actions pertaining to the user themselves, eg their account, profile or settings:
-
-image::{_imagesdir}application-menu/tertiary.png[width="300px",link="{_imagesdir}application-menu/tertiary.png"]
-
-Domain services' actions can be associated with the tertiary menu using the same `@DomainServiceLayout` annotation. For
-example, the `updateEpochDate(...)` and `listAllSettings(...)` actions come from the following service:
-
-[source,java]
-----
-@DomainServiceLayout(
- menuBar = DomainServiceLayout.MenuBar.TERTIARY,
- menuOrder = "10.1"
-)
-public class EstatioAdministrationService ... {
-
- @MemberOrder(sequence = "1")
- public void updateEpochDate( ... ) { ... }
-
- @MemberOrder(sequence = "2")
- public List<ApplicationSetting> listAllSettings() { ... }
- ...
-}
-----
-
-Because the number of items on the tertiary menu is expected to be small and most will pertain to the current user, the
-viewer does _not_ place dividers between actions from different services on the tertiary menu.
-
-
-== Incode Platform modules
-
-Some of the (non-ASF) link:http://platform.incode.org[Incode Platform^] modules also provide services whose actions appear in top-level menus.
-
-The security's module places its domain service menus in three
-top-level menus:
-
-* its `ApplicationUsers`, `ApplicationRoles`, `ApplicationPermission`, `ApplicationFeatureViewModels` and
- `ApplicationTenancies` domain services are all grouped together in a single "Security" top-level menu, on the
- SECONDARY menu bar
-
-* its `MeService` domain service, which provides the `me()` action, is placed on the TERTIARY menu bar.
-
-Currently there is no facility to alter the placement of these services. However, their UI can be suppressed
-using security or using a xref:../ugbtb/ugbtb.adoc#_ugbtb_hints-and-tips_vetoing-visibility[vetoing subscriber].
-
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc
index ff94776..36c56cd 100644
--- a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc
@@ -20,14 +20,15 @@ It is also possible to download an initial `.layout.xml` - capturing any existin
There are some downsides, though:
-* file-based layouts are not type: a typo will result in the metadata not being picked up for the element.
-They also suffer from syntactic fragility: an invalid XML document will result in no metadata for the entire class.
+* file-based layouts are not typesafe: a typo will result in the metadata not being picked up for the element.
-* there is no notion of inheritance, so a `.layout.xml` is required for all concrete classes and also for any abstract classes (if used as a collection type)
+* they suffer from syntactic fragility: an invalid XML document will result in no metadata for the entire class.
+
+* there is no notion of inheritance, so a `.layout.xml` is required for all concrete classes and also for any abstract classes (if used as a collection type).
In contrast, the dewey-decimal format `@MemberOrder` annotation allows the metadata of the subclass its superclasses to fit together relatively seamlessly.
-The `Xxx.layout.xml` file is just the serialized form of a xref:../rgcms/rgcms.adoc#_rgcms_classes_layout[`Grid`] layout class defined within Apache Isis' applib. These are JAXB-annotated classes with corresponding XSD schemas; the upshot of that
-is that IDEs such as IntelliJ and Eclipse can provide "intellisense", making iteasy to author such layout files.
+The `Xxx.layout.xml` file is just the serialized form of a xref:../rgcms/rgcms.adoc#_rgcms_classes_layout[`Grid`] layout class defined within Apache Isis' applib.
+These are JAXB-annotated classes with corresponding XSD schemas; the upshot of that is that IDEs such as IntelliJ and Eclipse can provide "intellisense", making iteasy to author such layout files.
[NOTE]
@@ -62,15 +63,16 @@ This link:https://www.youtube.com/watch?v=MxewC5Pve5k[screencast] describes the
== Examples
-Probably the easiest way to understand dynamic XML layouts is by example. For this we'll use the `ToDoItem` from the
-(non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp]:
+Probably the easiest way to understand dynamic XML layouts is by example.
+For this we'll use the `ToDoItem` from the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp]:
image::{_imagesdir}layout-dynamic-xml/ToDoItem.png[width="940px",link="{_imagesdir}layout-dynamic-xml/ToDoItem.png"]
=== Namespaces
-First things first; every `.layout.xml` file must properly declare the XSD namespaces and schemas. There are two: one for the grid classes, and one for the common component classes:
+First things first; every `.layout.xml` file must properly declare the XSD namespaces and schemas.
+There are two: one for the grid classes, and one for the common component classes:
[source,xml]
----
@@ -177,7 +179,7 @@ Note also the `unreferencedProperties` attribute for the fieldset; this topic is
[NOTE]
====
-(As of `1.15.0`) the ``<fieldset>``'s "name" attribute is optional.
+The ``<fieldset>``'s "name" attribute is optional.
If omitted, then the title panel is suppressed, freeing more real estate.
Do be aware though that if there are any actions that have been placed on the fieldset's panel, then these _will *not* be displayed_.
@@ -191,23 +193,23 @@ In the final row the collections are placed in tabs, simply one collection per t
[source,xml]
----
- <bs3:tab name="Similar to">
- <bs3:row>
- <bs3:col span="12">
- <c:collection defaultView="table" id="similarTo"/>
- </bs3:col>
- </bs3:row>
- </bs3:tab>
- <bs3:tab name="Dependencies">
- <bs3:row>
- <bs3:col span="12">
- <c:collection defaultView="table" id="dependencies">
- <c:action id="add"/>
- <c:action id="remove"/>
- </c:collection>
- </bs3:col>
- </bs3:row>
- </bs3:tab>
+<bs3:tab name="Similar to">
+ <bs3:row>
+ <bs3:col span="12">
+ <c:collection defaultView="table" id="similarTo"/>
+ </bs3:col>
+ </bs3:row>
+</bs3:tab>
+<bs3:tab name="Dependencies">
+ <bs3:row>
+ <bs3:col span="12">
+ <c:collection defaultView="table" id="dependencies">
+ <c:action id="add"/>
+ <c:action id="remove"/>
+ </c:collection>
+ </bs3:col>
+ </bs3:row>
+</bs3:tab>
----
As with properties, actions can be associated with collections; this indicates that they should be rendered in the collection's header.
@@ -283,13 +285,13 @@ This is accomplished using the following (slightly abbreviated) layout:
<1> render the collection in "calendar" view
<2> also render the collection in "table" view
-In the middle column the `notYetComplete` collection is rendered in "calendar" view, while in the right-most column
-it is rendered in "table" view.
+In the middle column the `notYetComplete` collection is rendered in "calendar" view, while in the right-most column it is rendered in "table" view.
It is also possible to reference object properties and actions more than once.
This might be useful for a complex domain object with multiple tabs; certain properties or actions might appear on a summary tab (that shows the most commonly used info), but also on detail tabs.
+
=== Custom CSS
The ToDoApp's dashboard (above) also shows how custom CSS styles can be associated with specific regions of the layout:
@@ -320,8 +322,8 @@ The ToDoApp's dashboard (above) also shows how custom CSS styles can be associat
<2> Render the column with the `custom-padding-top-20` CSS class.
<3> Ditto
-For example the `custom-width-100` style is used to "stretch" the button for the `exportToWordDoc` action in the
-left-most column. This is accomplished with the following CSS in `application.css`:
+For example the `custom-width-100` style is used to "stretch" the button for the `exportToWordDoc` action in the left-most column.
+This is accomplished with the following CSS in `application.css`:
[source,css]
----
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc
new file mode 100644
index 0000000..6e4ca6f
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc
@@ -0,0 +1,39 @@
+[[_ugvw_menubars-layout]]
+= Menu Bars Layout
+:Notice: 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 ag [...]
+:_basedir: ../../
+:_imagesdir: images/
+
+
+
+The actions of domain services are made available as menu items on menus.
+By default each domain service corresponds to a single menu on this menu bar, with its actions as the drop-down menu items.
+This is rarely exactly what is required, however; it often makes sense to group menu items for similar domain services together.
+
+For example, the (non-ASF) link:http://platform.incode.org[Incode Platform^] modules provides services whose actions appear into two top-level menus:
+
+* its `ApplicationUsers`, `ApplicationRoles`, `ApplicationPermission`, `ApplicationFeatureViewModels` and `ApplicationTenancies` domain services are all grouped together in a single "Security" top-level menu, on the SECONDARY menu bar
+
+* its `MeService` domain service, which provides the `me()` action, is placed on the TERTIARY menu bar.
+
+
+The menus themselves can be placed either on a primary, secondary or tertiary menu bar, as shown in this screenshot (taken from http://github.com/estatio/estatio[Estatio], an open source estate management application built using Apache Isis):
+
+image::{_imagesdir}application-menu/layout-menus.png[width="800px",link="{_imagesdir}application-menu/layout-menus.png"]
+
+Within a single top-level menu (eg "Fixed Assets") there can be actions from multiple services.
+The Wicket viewer shows these as separate sections, with a divider between each:
+
+image::{_imagesdir}application-menu/dividers.png[width="400px",link="{_imagesdir}application-menu/dividers.png"]
+
+
+The tertiary menu bar consists of a single unnamed menu, rendered underneath the user's login, top right.
+This is intended primarily for actions pertaining to the user themselves, eg their account, profile or settings:
+
+image::{_imagesdir}application-menu/tertiary.png[width="300px",link="{_imagesdir}application-menu/tertiary.png"]
+
+
+The Apache Isis framework provides two mechanisms to control the arrangement of domain service actions across menubars and menus, either using annotations or (as of `1.16.0-SNAPSHOT`) using a file-based layout.
+
+include::_ugvw_menubars-layout_annotation-based.adoc[leveloffset=+1]
+include::_ugvw_menubars-layout_file-based.adoc[leveloffset=+1]
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc
new file mode 100644
index 0000000..54f468b
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc
@@ -0,0 +1,126 @@
+[[_ugvw_menubars-layout_annotation-based]]
+= Annotation-based Menu Bars
+:Notice: 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 ag [...]
+:_basedir: ../../
+:_imagesdir: images/
+
+
+
+The annotations-based approach for arranging the placement of menu items is achieved through the xref:../rgant/rgant.adoc#_rgant-MemberOrder[`@MemberOrder`] and xref:../rgant/rgant.adoc#_rgant-DomainServiceLayout[`@DomainServiceLayout`] annotations.
+
+== @DomainServiceLayout
+
+In the example from Estatio shown above the top-level menu combines the actions from the `Properties`, `Units` and `FixedAssetRegistrations` services.
+The `Properties` service is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.1"
+)
+public class Properties ... { ... }
+----
+
+while the `Units` service is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.2"
+)
+public class Units ... { ... }
+----
+
+and similarly `FixedAssetRegistrations` is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.3"
+)
+public class FixedAssetRegistrations ... { ... }
+----
+
+Note that in all three cases the value of the `named` attribute and the `menuBar` attribute is the same: "Fixed Assets" and PRIMARY.
+This means that all will appear on a "Fixed Assets" menu in the primary menu bar.
+
+Meanwhile the value of `menuOrder` attribute is significant for two reasons:
+
+* for these three services on the same ("Fixed Assets") top-level menu, it determines the relative order of their sections (`Properties` first, then `Units`, then `FixedAssetRegistrations`)
+
+* it determines the placement of the top-level menu itself ("Fixed Assets") with respect to other top-level menus on the menu bar.
+
+To illustrate this latter point, the next top-level menu on the menu bar, "Parties", is placed after "Fixed Assets" because the `menuOrder` of the first of its domain services, namely the `Parties` service, is higher than that for "Fixed Assets":
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Parties",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "20.1"
+)
+public class Parties ... { ... }
+----
+
+Note that only the `menuOrder` of the _first_ domain service is significant in placing the menus along the menu bar; thereafter the purpose of the `menuOrder` is to order the menu services sections on the menu itself.
+
+
+
+== Ordering menu actions
+
+For a given service, the actions within a section on a menu is determined by the `@MemberOrder` annotation.
+Thus, for the `Units` domain service, its actions are annotated:
+
+[source,java]
+----
+public class Units extends EstatioDomainService<Unit> {
+
+ @MemberOrder(sequence = "1")
+ public Unit newUnit( ... ) { ... }
+
+ @MemberOrder(sequence = "2")
+ public List<Unit> findUnits( ... ) { ... }
+
+ @ActionLayout( prototype = true )
+ @MemberOrder(sequence = "99")
+ public List<Unit> allUnits() { ... }
+ ...
+}
+----
+
+Note that the last is also a prototype action (meaning it is only displayed in SERVER_PROTOTYPE (=Wicket Development) mode).
+In the UI it is rendered in italics.
+
+
+
+== Tertiary Menu
+
+
+Domain services' actions can be associated with the tertiary menu using the same `@DomainServiceLayout` annotation, but be aware that the `@DomainServiceLayout#name()` attribute will be ignored (there is only one effective menu).
+
+For example, the `updateEpochDate(...)` and `listAllSettings(...)` actions come from the following service:
+
+[source,java]
+----
+@DomainServiceLayout(
+ menuBar = DomainServiceLayout.MenuBar.TERTIARY,
+ menuOrder = "10.1"
+)
+public class EstatioAdministrationService ... {
+
+ @MemberOrder(sequence = "1")
+ public void updateEpochDate( ... ) { ... }
+
+ @MemberOrder(sequence = "2")
+ public List<ApplicationSetting> listAllSettings() { ... }
+ ...
+}
+----
+
+Because the number of items on the tertiary menu is expected to be small and most will pertain to the current user, the viewer does _not_ place dividers between actions from different services on the tertiary menu.
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc
new file mode 100644
index 0000000..ae972a5
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc
@@ -0,0 +1,105 @@
+[[_ugvw_menubars-layout_file-based]]
+= File-based Menu Bars (`1.16.0-SNAPSHOT`)
+:Notice: 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 ag [...]
+:_basedir: ../../
+:_imagesdir: images/
+
+
+(As of `1.16.0-SNAPSHOT`) the domain service actions can be arranged across menu items using the `menubars.layout.xml` file.
+Not only is this easier to work with, it also can be reloaded dynamically (if in prototype mode), substantially redu.
+
+As for xref:ugvw.adoc#_ugvw_layout_file-based[file-based object layouts], this offers a number of benefits:
+
+* Probably most significantly, the layout can be updated without requiring a recompile of the code and redeploy of the app; fine-tuning the layout with your end users is easy to do
+
+* Many developers also find it easier to rationalize about menu bars layout when all the hints are collated together in a single place (rather than scattered across the domain service classes as annotations).
+
+There are some disadvantages to using file-based layouts:
+
+* file-based layouts are not typesafe: a typo will result in the metadata not being picked up for the element.
+
+* they also suffer from syntactic fragility: an invalid XML document will result in no metadata for the entire class.
+
+The `menubars.layout.xml` file is just the serialized form of a xref:../rgcms/rgcms.adoc#_rgcms_classes_layout[`MenuBars`] layout class defined within Apache Isis' applib.
+These are JAXB-annotated classes with corresponding XSD schemas; the upshot of that
+is that IDEs such as IntelliJ and Eclipse can provide "intellisense", making it easy to author such layout files.
+
+
+== Obtaining an initial layout
+
+An initial `menubars.layout.xml` - capturing any existing metadata either implicit or explicitly specified through annotations can be downloaded from the xref:../rgsvc/rgsvc.adoc#_rgsvc_metadata-api_MenuBarsService[`MenuBarsService`] (exposed on the prototyping menu):
+
+image::{_imagesdir}/menubars/010-download.png[width="300px",link="{_imagesdir}/menubars/010-download.png"]
+
+
+This action allows either the "Default" or the "Fallback" layout to be downloaded.
+
+image::{_imagesdir}/menubars/020-download.png[width="400px",link="{_imagesdir}/menubars/020-download.png"]
+
+The "Default" layout is that currently in use, while the "Fallback" layout is that provided only from the annotations.
+Initially these are identical.
+
+For example, here's a fragment of that provided by the simpleapp archetype:
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<mb3:menuBars
+ xsi:schemaLocation="..."
+ xmlns:cpt="http://isis.apache.org/applib/layout/component"
+ xmlns:lnk="http://isis.apache.org/applib/layout/links"
+ xmlns:mb3="http://isis.apache.org/applib/layout/menubars/bootstrap3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <mb3:primary>
+ <mb3:menu>
+ <mb3:named>Simple Objects</mb3:named>
+ <mb3:section>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="listAll">
+ <cpt:named>List All</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="findByName">
+ <cpt:named>Find By Name</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="create">
+ <cpt:named>Create</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ </mb3:menu>
+ <mb3:menu unreferencedActions="true">
+ <mb3:named>Other</mb3:named>
+ </mb3:menu>
+ </mb3:primary>
+ <mb3:secondary>
+ <mb3:menu>
+ <mb3:named>Prototyping</mb3:named>
+ ...
+ </mb3:secondary>
+ <mb3:tertiary>
+ <mb3:menu>
+ ...
+ </mb3:menu>
+ </mb3:tertiary>
+</mb3:menuBars>
+----
+
+Note the "Other" menu, with `unreferencedActions` attribute set to `true`.
+For a layout file to be valid there must be exactly one `<menu>` with this attribute set.
+Any domain service actions that are not explicitly listed will be placed under this menu.
+
+
+== Adjusting the layout
+
+The downloaded `menubars.layout.xml` file can be adjusted as necessary, creating new menus and menu sections.
+Once done, it can be saved in the same package as the `AppManifest` used to bootstrap the application.
+Subsequently, the file is then parsed and used when the application is started.
+
+If running in prototype mode, the file will be dynamically reloaded from the classpath.
+
+Once the application has bootstrapped with a layout file, downloading the "Default" layout (from the prototyping menu) in essence just returns this file.
+
+[TIP]
+====
+If, when the application is run, unwanted service actions are shown in the "Other" menu (which you would like to place elsewhere), then download the "Default" layout again.
+The downloaded file will list out all these domain service actions, so that they can easily be moved elsewhere.
+====
+
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/010-download.png b/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/010-download.png
new file mode 100644
index 0000000..4c79f73
Binary files /dev/null and b/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/010-download.png differ
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/020-download.png b/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/020-download.png
new file mode 100644
index 0000000..52100ec
Binary files /dev/null and b/adocs/documentation/src/main/asciidoc/guides/ugvw/images/menubars/020-download.png differ
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc
index a39199f..8c69e40 100644
--- a/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc
@@ -52,6 +52,7 @@ The remaining guides are:
include::_ugvw_features.adoc[leveloffset=+1]
include::_ugvw_layout.adoc[leveloffset=+1]
+include::_ugvw_menubars-layout.adoc[leveloffset=+1]
include::_ugvw_configuration-properties.adoc[leveloffset=+1]
include::_ugvw_customisation.adoc[leveloffset=+1]
include::_ugvw_extending.adoc[leveloffset=+1]
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/menubars/bootstrap3/MenuBarsServiceBS3.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/menubars/bootstrap3/MenuBarsServiceBS3.java
index e4f81c4..cae713f 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/menubars/bootstrap3/MenuBarsServiceBS3.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/menubars/bootstrap3/MenuBarsServiceBS3.java
@@ -101,6 +101,8 @@ public class MenuBarsServiceBS3 implements MenuBarsService {
BS3MenuBars menuBars = menuBarsLoaderService.menuBars();
+ menuBars.setTnsAndSchemaLocation(tnsAndSchemaLocation());
+
final BS3Menu unreferencedActionsMenu = validate(menuBars);
if (unreferencedActionsMenu != null) {
diff --git a/example/application/simpleapp/application/src/main/java/domainapp/application/manifest/menubars.layout.xml b/example/application/simpleapp/application/src/main/java/domainapp/application/manifest/menubars.layout.xml
new file mode 100644
index 0000000..d81b269
--- /dev/null
+++ b/example/application/simpleapp/application/src/main/java/domainapp/application/manifest/menubars.layout.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<mb3:menuBars xsi:schemaLocation="http://isis.apache.org/applib/layout/menubars/bootstrap3 http://isis.apache.org/applib/layout/menubars/bootstrap3/menubars.xsd http://isis.apache.org/applib/layout/component http://isis.apache.org/applib/layout/component/component.xsd http://isis.apache.org/applib/layout/links http://isis.apache.org/applib/layout/links/links.xsd" xmlns:cpt="http://isis.apache.org/applib/layout/component" xmlns:lnk="http://isis.apache.org/applib/layout/links" xmlns:mb3="h [...]
+ <mb3:primary>
+ <mb3:menu>
+ <mb3:named>Simple Objects</mb3:named>
+ <mb3:section>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="create">
+ <cpt:named>Create</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="findByName">
+ <cpt:named>Find By Name</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="simple.SimpleObjectMenu" id="listAll">
+ <cpt:named>List All</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ </mb3:menu>
+ <mb3:menu unreferencedActions="true">
+ <mb3:named>Other</mb3:named>
+ </mb3:menu>
+ </mb3:primary>
+ <mb3:secondary>
+ <mb3:menu>
+ <mb3:named>Prototyping</mb3:named>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.FixtureScriptsDefault" id="runFixtureScript">
+ <cpt:named>Run Fixture Script</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.FixtureScriptsDefault" id="runFixtureScriptWithAutoComplete">
+ <cpt:named>Run Fixture Script</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.FixtureScriptsDefault" id="recreateObjectsAndReturnFirst">
+ <cpt:named>Recreate Objects And Return First</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.LayoutServiceMenu" id="downloadLayouts">
+ <cpt:named>Download Object Layouts (ZIP)</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.LayoutServiceMenu" id="downloadMenuBarsLayout">
+ <cpt:named>Download Menu Bars Layout (XML)</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.MetaModelServicesMenu" id="downloadMetaModel">
+ <cpt:named>Download Meta Model (CSV)</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.SwaggerServiceMenu" id="openSwaggerUi">
+ <cpt:named>Open Swagger Ui</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.SwaggerServiceMenu" id="openRestApi">
+ <cpt:named>Open Rest Api</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.SwaggerServiceMenu" id="downloadSwaggerSchemaDefinition">
+ <cpt:named>Download Swagger Schema Definition</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.TranslationServicePoMenu" id="downloadTranslations">
+ <cpt:named>Download Translations</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.TranslationServicePoMenu" id="resetTranslationCache">
+ <cpt:named>Clear translation cache</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.TranslationServicePoMenu" id="switchToReadingTranslations">
+ <cpt:named>Switch To Reading Translations</cpt:named>
+ </mb3:serviceAction>
+ <mb3:serviceAction objectType="isisApplib.TranslationServicePoMenu" id="switchToWritingTranslations">
+ <cpt:named>Switch To Writing Translations</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.HsqlDbManagerMenu" id="hsqlDbManager">
+ <cpt:named>HSQL DB Manager</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ </mb3:menu>
+ </mb3:secondary>
+ <mb3:tertiary>
+ <mb3:menu>
+ <mb3:named>Configuration Service Menu</mb3:named>
+ <mb3:section>
+ <mb3:serviceAction objectType="isisApplib.ConfigurationServiceMenu" id="configuration">
+ <cpt:named>Configuration</cpt:named>
+ </mb3:serviceAction>
+ </mb3:section>
+ </mb3:menu>
+ </mb3:tertiary>
+</mb3:menuBars>
--
To stop receiving notification emails like this one, please contact
['"commits@isis.apache.org" <co...@isis.apache.org>'].