content/versions/1.17.0/guides/ugvw/ugvw.html (5,441 lines of code) (raw):
<!doctype html>
<html>
<head>
<!--
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.
-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- No caching headers -->
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="-1">
<title>Wicket Viewer</title>
<link rel="icon" type="image/png" href="../../images/isis-favicon.png">
<!--
Based on DataNucleus' template,
that was in turn based on an earlier version of Apache Isis' template,
that was in turn based on Apache Deltaspike's template.
This template uses
* Bootstrap v3.3.7 (https://getbootstrap.com/) for navbar.
* Bootstrap TOC plugin v0.4.1 (https://afeld.github.io/bootstrap-toc/)
for the table of contents.
* jQuery (necessary for Bootstrap's JavaScript plugins)
* Font-Awesome for some icons used by Asciidoctor
Also:
* Bootswatch "flatly" theme for Bootstrap (https://bootswatch.com/flatly).
* slick.js (carousel)
* add a link to all headers (home-grown, adapted from blog posts)
* integration of elasticlunr.js (home-grown, adapted from blog posts)
-->
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/flatly/bootstrap.min.css" rel="stylesheet">
<link href="../../css/bootstrap-toc/0.4.1/bootstrap-toc.min.css" rel="stylesheet">
<link href="../../css/asciidoctor/foundation.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link href="../../css/slick/1.5.0/slick.css" rel="stylesheet">
<link href="../../css/slick/1.5.0/slick-theme.css" rel="stylesheet">
<link href="../../css/search-panel/search-panel.css" rel="stylesheet">
<link href="../../css/header-links/header-links.css" rel="stylesheet">
<link href="../../css/sticky-header/sticky-header.css" rel="stylesheet">
<link href="../../css/customisations.css" rel="stylesheet">
<!-- Coderay syntax formatter -->
<style type="text/css">
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
/*pre.CodeRay {background-color:#f7f7f8;}*/
.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
table.CodeRay td{vertical-align: top;line-height:1.45}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
table.CodeRay td.code{padding:0 0 0 .5em}
table.CodeRay td.code>pre{padding:0}
.CodeRay .debug{color:#fff !important;background:#000080 !important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:#000080}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:#008080}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:#008080}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:#008080}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
</style>
</head>
<body data-spy="scroll" data-target="#toc">
<div id="basedir" style="display:none;">
../../
</div>
<div id="docname" style="display:none;">
ugvw
</div>
<div id="filetype" style="display:none;">
html
</div>
<!-- Navbar -->
<nav class="navbar navbar-default navbar-static-top header">
<div class="container">
<div class="navbar-header">
<!-- Three line menu button for use on mobile screens -->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button>
<a class="navbar-brand" href="../../index.html"> <img alt="Brand" src="../../images/isis-logo-48x48.png"> </a>
<a class="navbar-brand" href="../../index.html">Apache Isis</a>
</div>
<!-- Navbar that will collapse on mobile screens -->
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentation<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="../../documentation.html">Table of Contents</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">User Guides</li>
<li><a href="../../guides/ugfun/ugfun.html">Fundamentals</a></li>
<li><a href="../../guides/ugvw/ugvw.html">Wicket Viewer</a></li>
<li><a href="../../guides/ugvro/ugvro.html">Restful Objects Viewer</a></li>
<li><a href="../../guides/ugodn/ugodn.html">DataNucleus Object Store</a></li>
<li><a href="../../guides/ugsec/ugsec.html">Security</a></li>
<li><a href="../../guides/ugtst/ugtst.html">Testing</a></li>
<li><a href="../../guides/ugbtb/ugbtb.html">Beyond the Basics</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Reference Guides</li>
<li><a href="../../guides/rgant/rgant.html">Annotations</a></li>
<li><a href="../../guides/rgsvc/rgsvc.html">Domain Services</a></li>
<li><a href="../../guides/rgcfg/rgcfg.html">Core Config' Properties</a></li>
<li><a href="../../guides/rgcms/rgcms.html">Classes, Methods and Schema</a></li>
<li><a href="../../guides/rgmvn/rgmvn.html">Maven plugin</a></li>
<li><a href="../../guides/rgfis/rgfis.html">Framework Internal Services</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Javadoc</li>
<li><a href="http://javadoc.io/doc/org.apache.isis.core/isis-core-applib">Applib</a></li>
</ul> </li>
<li class="dropdown hidden-sm hidden-md"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Downloads<span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-header">Maven archetypes</li>
<li><a href="../../guides/ugfun/ugfun.html#_ugfun_getting-started_helloworld-archetype">helloworld</a></li>
<li><a href="../../guides/ugfun/ugfun.html#_ugfun_getting-started_simpleapp-archetype">simpleapp</a></li>
<li role="separator" class="divider"></li>
<li><a href="../../downloads.html">Downloads</a></li>
<li><a href="../../release-notes/release-notes.html">Release Notes</a></li>
<li><a href="../../migration-notes/migration-notes.html">Migration Notes</a></li>
<li role="separator" class="divider"></li>
<li><a href="https://github.com/apache/isis">Github mirror</a></li>
</ul> </li>
<li class="dropdown hidden-sm"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Support<span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-header">Guides</li>
<li><a href="../../guides/dg/dg.html">Developers' Guide</a></li>
<li><a href="../../guides/cgcom/cgcom.html">Committers' Guide</a></li>
<li><a href="../../guides/htg.html">Hints-n-Tips Guide</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Mailing Lists</li>
<li><a href="../../support.html">How to subscribe</a></li>
<li><a href="https://lists.apache.org/list.html?users@isis.apache.org">Archives (ASF Pony mail)</a></li>
<li><a href="http://isis.markmail.org/search/?q=">Archives (Markmail)</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Other Resources</li>
<li><a href="https://issues.apache.org/jira/browse/ISIS">ASF JIRA</a></li>
<li><a href="https://stackoverflow.com/questions/tagged/isis">Stack Overflow</a></li>
<li><a href="../../help.html">Wiki, Fisheye etc.</a></li>
</ul> </li>
<li class="dropdown hidden-sm hidden-md"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">@ASF<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://www.apache.org/">Apache Homepage</a></li>
<li><a href="https://www.apache.org/events/current-event">Events</a></li>
<li><a href="https://www.apache.org/licenses/">Licenses</a></li>
<li><a href="https://www.apache.org/security/">Security</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li role="separator" class="divider"></li>
<li><a href="https://whimsy.apache.org/board/minutes/Isis.html">PMC board minutes</a></li>
</ul> </li>
</ul>
<div class="nav navbar-nav navbar-right">
<!-- 'style' added to fix height of input box. FIX THIS -->
<form class="navbar-form" role="search" id="search-form" style="padding: 1px 15px;">
<div class="form-group">
<input class="form-control" id="search-field" type="text" size="30" placeholder="Search">
</div>
</form>
</div>
<p class="nav navbar-text navbar-right small">v1.17.0</p>
</div>
</div>
</nav>
<div class="container">
<div class="row-fluid">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-9">
<div id="search-panel">
<div id="search-results"></div>
<div>
<br>
<a href="#" id="search-results-clear">clear</a>
</div>
</div>
<span class="pdf-link"><a href="ugvw.pdf"><img src="../../images/PDF-50.png"></a></span>
<div class="page-title">
<h1>Wicket Viewer</h1>
</div>
<div id="doc-content">
<div class="btn-group" style="float: right; font-size: small; padding: 6px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/ugvw.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sect1">
<h2 id="__ugvw">1. Wicket Viewer</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Wicket Viewer automatically exposes an Apache Isis domain object model for use by end-users. The viewer is implemented using <a href="http://wicket.apache.org">Apache Wicket</a>.</p>
</div>
<div class="paragraph">
<p>This user guide discuss end-user features, configuration and customization of the Wicket viewer.</p>
</div>
<div class="paragraph">
<p>It also discusses how to extend the viewer, and the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a> wicket components.</p>
</div>
<div class="sect2">
<h3 id="_other_guides">1.1. Other Guides</h3>
<div class="paragraph">
<p>Apache Isis documentation is broken out into a number of user and reference guides.</p>
</div>
<div class="paragraph">
<p>The user guides available are:</p>
</div>
<div class="ulist">
<ul>
<li> <p><a href="../ugfun/ugfun.html">Fundamentals</a></p> </li>
<li> <p><a href="../ugvw/ugvw.html">Wicket viewer</a> (this guide)</p> </li>
<li> <p><a href="../ugvro/ugvro.html">Restful Objects viewer</a></p> </li>
<li> <p><a href="../ugodn/ugodn.html">DataNucleus object store</a></p> </li>
<li> <p><a href="../ugsec/ugsec.html">Security</a></p> </li>
<li> <p><a href="../ugtst/ugtst.html">Testing</a></p> </li>
<li> <p><a href="../ugbtb/ugbtb.html">Beyond the Basics</a></p> </li>
</ul>
</div>
<div class="paragraph">
<p>The reference guides are:</p>
</div>
<div class="ulist">
<ul>
<li> <p><a href="../rgant/rgant.html">Annotations</a></p> </li>
<li> <p><a href="../rgsvc/rgsvc.html">Domain Services</a></p> </li>
<li> <p><a href="../rgcfg/rgcfg.html">Configuration Properties</a></p> </li>
<li> <p><a href="../rgcms/rgcms.html">Classes, Methods and Schema</a></p> </li>
<li> <p><a href="../rgmvn/rgmvn.html">Apache Isis Maven plugin</a></p> </li>
<li> <p><a href="../rgfis/rgfis.html">Framework Internal Services</a></p> </li>
</ul>
</div>
<div class="paragraph">
<p>The remaining guides are:</p>
</div>
<div class="ulist">
<ul>
<li> <p><a href="../dg/dg.html">Developers' Guide</a> (how to set up a development environment for Apache Isis and contribute back to the project)</p> </li>
<li> <p><a href="../cgcom/cgcom.html">Committers' Guide</a> (release procedures and related practices)</p> </li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ugvw_features">2. Features/end-user usage</h2>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sectionbody">
<div class="paragraph">
<p>This section discusses features of the wicket viewer from the perspective of an end-user actually using your Apache Isis application.</p>
</div>
<div class="sect2">
<h3 id="_ugvw_features_recent-pages">2.1. Recent pages (drop down)</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_recent-pages.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_recent-pages.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_recent-pages.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_recent-pages.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_recent-pages.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The Wicket viewer provides a recent pages drop-down that acts as a breadcrumb trail. Using it, the user can quickly open a recently accessed domain object.</p>
</div>
<div class="sect3">
<h4 id="_screenshots">2.1.1. Screenshots</h4>
<div class="paragraph">
<p>The following screenshot, taken from the <a href="https://github.com/estatio/estatio">Estatio</a> application, shows the recent pages drop-down after a number of pages have been accessed.</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/recent-pages/recent-pages.png"><img src="images/recent-pages/recent-pages.png" alt="recent pages" width="800px"></a>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Note that this screenshot show an earlier version of the <a href="../ugvw/ugvw.html">Wicket viewer</a> UI (specifically, pre 1.8.0).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_domain_code">2.1.2. Domain Code</h4>
<div class="paragraph">
<p>The recent pages drop-down is automatically populated; no changes need to be made to the domain classes.</p>
</div>
</div>
<div class="sect3">
<h4 id="_user_experience">2.1.3. User Experience</h4>
<div class="paragraph">
<p>Selecting the domain object from the list causes the viewer to automatically navigate to the page for the selected object.</p>
</div>
</div>
<div class="sect3">
<h4 id="_related_functionality">2.1.4. Related functionality</h4>
<div class="paragraph">
<p>The <a href="../ugvw/ugvw.html#_ugvw_features_bookmarked-pages">bookmarked pages</a> (sliding panel) also provides links to recently visited objects, but only those explicitly marked as <code>@DomainObject(bookmarking=…)</code>. The bookmarks panel also nests related objects together hierarchically (the recent pages drop-down does not).</p>
</div>
</div>
<div class="sect3">
<h4 id="_configuration">2.1.5. Configuration</h4>
<div class="paragraph">
<p>The number of objects is hard-coded as 10; it cannot currently be configured.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_bookmarked-pages">2.2. Bookmarked pages</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_bookmarked-pages.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_bookmarked-pages.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_bookmarked-pages.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_bookmarked-pages.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_bookmarked-pages.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The Wicket viewer supports the bookmarking of both domain objects and query-only (<a href="../rgant/rgant.html#_rgant-Action_semantics">@Action(semantics=…)</a>) actions.</p>
</div>
<div class="paragraph">
<p>Domain objects, if bookmarkable, can be nested.</p>
</div>
<div class="paragraph">
<p>Bookmarking is automatic; whenever a bookmarkable object/action is visited, then a bookmark is created. To avoid the number of bookmarks from indefinitely growing, bookmarks that have not been followed after a whle are automatically removed (an MRU/LRU algorithm). The number of bookmarks to preserve can be configured.</p>
</div>
<div class="sect3">
<h4 id="_screenshots_2">2.2.1. Screenshots</h4>
<div class="paragraph">
<p>The following screenshot, taken from <a href="https://github.com/isisaddons/isis-app-todoapp">Isisaddons example todoapp</a> (not ASF) shows how the bookmarks are listed in a sliding panel.</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/bookmarked-pages/panel.png"><img src="images/bookmarked-pages/panel.png" alt="panel" width="800px"></a>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Note that these screenshots show an earlier version of the <a href="../ugvw/ugvw.html">Wicket viewer</a> UI (specifically, pre 1.8.0).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>Note how the list contains both domain objects and an action ("not yet complete").</p>
</div>
<div class="paragraph">
<p>Bookmarks can also form a hierarchy. The following screenshot, also taken from the <a href="https://github.com/estatio/estatio">Estatio</a> application, shows a variety of different bookmarked objects with a nested structure:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/bookmarked-pages/panel-estatio.png"><img src="images/bookmarked-pages/panel-estatio.png" alt="panel estatio" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>Some - like <code>Property</code>, <code>Lease</code> and <code>Party</code> - are root nodes. However, <code>LeaseItem</code> is bookmarkable as a child of <code>Lease</code>, and <code>LeaseTerm</code> is bookmarkable only as a child of <code>LeaseItem</code>. This parent/child relationship is reflected in the layout.</p>
</div>
</div>
<div class="sect3">
<h4 id="_domain_code_2">2.2.2. Domain Code</h4>
<div class="paragraph">
<p>To indicate a class is bookmarkable, use the <a href="../rgant/rgant.html#_rgant-DomainObjectLayout">@DomainObjectLayout</a> annotation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainObjectLayout</span>(
bookmarking=BookmarkPolicy.AS_ROOT
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">Lease</span> { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>To indicate a class is bookmarkable but only as a child of some parent bookmark, specify the bookmark policy:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainObjectLayout</span>(
bookmarking=BookmarkPolicy.AS_CHILD
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">LeaseItem</span> { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>To indicate that a safe (query only) action is bookmarkable, use the <a href="../rgant/rgant.html#_rgant-ActionLayout">@ActionLayout</a> annotation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ToDoItem</span> ... {
<span class="annotation">@Action</span>(
semantics=SemanticsOf.SAFE
)
<span class="annotation">@ActionLayout</span>(
bookmarking=BookmarkPolicy.AS_ROOT
)
<span class="directive">public</span> <span class="predefined-type">List</span><ToDoItem> notYetComplete() { ... }
...
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>The BookmarkPolicy.AS_CHILD does not have a meaning for actions; if the <code>bookmarking</code> attribute is set to any other value, it will be ignored.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_user_experience_2">2.2.3. User Experience</h4>
<div class="paragraph">
<p>The sliding panel appears whenever the mouse pointer hovers over the thin blue tab (to the left of the top header region).</p>
</div>
<div class="paragraph">
<p>Alternatively, <code>alt+[</code> will toggle open/close the panel; it can also be closed using <code>Esc</code> key.</p>
</div>
<div class="sect4">
<h5 id="_related_functionality_2">Related functionality</h5>
<div class="paragraph">
<p>The <a href="../ugvw/ugvw.html#_ugvw_features_recent-pages">Recent Pages</a> also lists recently visited pages, selected from a drop-down.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_configuration_2">2.2.4. Configuration</h4>
<div class="paragraph">
<p>By default, the bookmarked pages panel will show a maximum of 15 'root' pages. This can be overridden using a property (in <code>isis.properties</code>), for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.bookmarkedPages.maxSize=20</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_sidebar-vs-modal-dialogs">2.3. Sidebar vs Modal Dialogs</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_sidebar-vs-modal-dialogs.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_sidebar-vs-modal-dialogs.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_sidebar-vs-modal-dialogs.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_sidebar-vs-modal-dialogs.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_sidebar-vs-modal-dialogs.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The Wicket viewer supports two different styles of dialog prompts for actions that have parameters:</p>
</div>
<div class="ulist">
<ul>
<li> <p>the first is a (movable) modal dialog.</p>
<div class="paragraph">
<p>This was the only style available for 1.16.x and earlier versions.</p>
</div> </li>
<li> <p>the second is as sidebar</p>
<div class="paragraph">
<p>This is available (and the default) for 1.17+.</p>
</div> </li>
</ul>
</div>
<div class="paragraph">
<p>The benefit of the sidebar dialog mode compared to the modal dialog is that it doesn’t obscure the rest of the information shown on the page; it also doesn’t interrupt the end-user’s context so much (they are more likely to remember why they invoked the action). For these reasons the sidebar mode is now the default.</p>
</div>
<div class="paragraph">
<p>For example, here’s what invoking an action (to create a new object) looks like using the original modal dialog:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/dialog-mode/modal.png"><img src="images/dialog-mode/modal.png" alt="modal" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>And here’s what it looks like with the sidebar dialog:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/dialog-mode/sidebar.png"><img src="images/dialog-mode/sidebar.png" alt="sidebar" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>However, the original modal dialog can still be be used if end-users prefer that style, by setting the <code>isis.viewer.wicket.dialog</code> <a href="../ugvw/ugvw.html#_ugvw_configuration-properties_presentation">configuration property</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_hints-and-copy-url">2.4. Hints and copy URL</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_hints-and-copy-url.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_hints-and-copy-url.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_hints-and-copy-url.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_hints-and-copy-url.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_hints-and-copy-url.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>While the user can often copy the URL of a domain object directly from the browser’s address bar, the Wicket viewer also allows the URL of domain objects to be easily copied from a dialog.</p>
</div>
<div class="paragraph">
<p>More interestingly, this URL can also contain hints capturing any sorting or page numbering, or hiding/viewing of collections. End-users can therefore share these URLs as a form of deep linking into a particular view on a domain object.</p>
</div>
<div class="paragraph">
<p>The copy URL and hinting is automatic.</p>
</div>
<div class="sect3">
<h4 id="_screenshots_3">2.4.1. Screenshots</h4>
<div class="paragraph">
<p>The following screenshots are taken from the [Estatio](<a href="https://github.com/estatio/estatio" class="bare">https://github.com/estatio/estatio</a>) application.</p>
</div>
<div class="sect4">
<h5 id="_copy_url">Copy URL</h5>
<div class="paragraph">
<p>This screenshot shows the copy URL button (top right):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/copy-link/010-copy-link-button.png"><img src="images/copy-link/010-copy-link-button.png" alt="010 copy link button" width="800px"></a>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Note that these screenshots show an earlier version of the <a href="../ugvw/ugvw.html">Wicket viewer</a> UI (specifically, pre 1.8.0).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>Clicking on this button brings up a dialog with the URL preselected:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/copy-link/020-copy-link-dialog.png"><img src="images/copy-link/020-copy-link-dialog.png" alt="020 copy link dialog" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>The URL in this case is something like:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>http://localhost:8080/wicket/entity/org.estatio.dom.lease.Lease:0</pre>
</div>
</div>
<div class="paragraph">
<p>The user can copy the link (eg <code>ctrl+C</code>) into the clipboard, then hit <code>OK</code> or <code>Esc</code> to dismiss the dialog.</p>
</div>
</div>
<div class="sect4">
<h5 id="_hints">Hints</h5>
<div class="paragraph">
<p>Using the viewer the user can hide/show collection tables, can sort the tables by header columns:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/copy-link/030-hints.png"><img src="images/copy-link/030-hints.png" alt="030 hints" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>Also, if the collection spans multiple pages, then the individual page can be selected.</p>
</div>
<div class="paragraph">
<p>Once the view has been customised, the URL shown in the copy URL dialog is in an extended form:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/copy-link/040-copy-link-with-hints.png"><img src="images/copy-link/040-copy-link-with-hints.png" alt="040 copy link with hints" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>The URL in this case is something like:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>http://localhost:8080/wicket/entity/org.estatio.dom.lease.Lease:0?hint-1:collectionContents-view=3&hint-1:collectionContents:collectionContents-3:table-DESCENDING=value&hint-1:collectionContents:collectionContents-3:table-pageNumber=0&hint-2:collectionContents-view=0&hint-2:collectionContents:collectionContents-2:table-pageNumber=0&hint-3:collectionContents-view=2&hint-3:collectionContents:collectionContents-2:table-pageNumber=0&hint-4:collectionContents-view=3&hint-4:collectionContents:collectionContents-3:table-ASCENDING=exerciseDate&hint-4:collectionContents:collectionContents-3:table-pageNumber=0&hint-5:collectionContents-view=0&hint-5:collectionContents:collectionContents-3:table-pageNumber=0</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_copy_url_from_title">Copy URL from title</h5>
<div class="paragraph">
<p>When the user invokes an action on the object, the URL (necessarily) changes to indicate that the action was invoked. This URL is specific to the user’s session and cannot be shared with others.</p>
</div>
<div class="paragraph">
<p>A quick way for the user to grab a shareable URL is simply by clicking on the object’s title:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/copy-link/050-title-url.png"><img src="images/copy-link/050-title-url.png" alt="050 title url" width="800px"></a>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_user_experience_3">2.4.2. User Experience</h4>
<div class="paragraph">
<p>The copy URL dialog is typically obtained by clicking on the icon.</p>
</div>
<div class="paragraph">
<p>Alternatively, <code>alt+]</code> will also open the dialog. It can be closed with either <code>OK</code> or the <code>Esc</code> key.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_titles-in-tables">2.5. Titles in Tables</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_titles-in-tables.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_titles-in-tables.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_titles-in-tables.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_titles-in-tables.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_titles-in-tables.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Object titles can often be quite long if the intention is to uniquely identify the object. While this is appropriate for the object view, it can be cumbersome within tables.</p>
</div>
<div class="paragraph">
<p>If an object’s title is specified with from <code>@Title</code> annotation then the Wicket viewer will (for parented collections) automatically "contextualize" a title by excluding the part of the title corresponding to a reference to the owning (parent) object.</p>
</div>
<div class="paragraph">
<p>In other words, suppose we have:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/how-tos/ui-hints/object-titles-and-icons/cust-order-product.png"><img src="images/how-tos/ui-hints/object-titles-and-icons/cust-order-product.png" alt="cust order product" width="579px"></a>
</div>
</div>
<div class="paragraph">
<p>so that <code>Customer</code> has a collection of `Order`s:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Customer</span> {
<span class="directive">public</span> <span class="predefined-type">Set</span><Order> getOrders() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>and <code>Product</code> also has a collection of `Order`s (please forgive the suspect domain modelling in this example (!)):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Product</span> {
<span class="directive">public</span> <span class="predefined-type">Set</span><Order> getOrders() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>and where the <code>Order</code> class references both <code>Customer</code> and <code>Product</code>.</p>
</div>
<div class="paragraph">
<p>The `Order’s might involve each of these:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Order</span> {
<span class="annotation">@Title</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> Customer getCustomer() { ... }
<span class="annotation">@Title</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> Product getProduct() { ... }
<span class="annotation">@Title</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">3</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">String</span> getOtherInfo() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this case, if we view a <code>Customer</code> with its collection of <code>Order</code>s, then in that parented collection’s table the customer’s property will be automatically excluded from the title of the <code>Order</code> (but it would show the product). Conversely, if a <code>Product</code> is viewed then its collection of <code>Order</code>s would suppress product (but would show the customer).</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>This feature is a close cousin of the <code>@PropertyLayout(hidden=Where.REFERENCES_PARENT)</code> annotation, which will cause the property itself to be hidden as a column in the table. An Isis idiom is therefore:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Order</span> {
<span class="annotation">@Title</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="annotation">@PropertyLayout</span>(hidden=Where.REFERENCES_PARENT)
<span class="directive">public</span> Customer getCustomer() { ... }
...
}</code></pre>
</div>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>The above annotations mean that titles usually "just work", altering according to the context in which they are viewed.</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>It is also possible to configure the Wicket viewer to <a href="../ugvw/ugvw.html#_ugvw_configuration-properties_presentation">abbreviate titles or suppress them</a> completely.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_blob-attachments">2.6. File upload/download</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_blob-attachments.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_blob-attachments.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_blob-attachments.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_blob-attachments.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_blob-attachments.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The Apache Isis application library provides the <a href="../rgcms/rgcms.html#_rgcms_classes_value-types_Blob">Blob</a> value type (binary large objects) and also the <a href="../rgcms/rgcms.html#_rgcms_classes_value-types_Clob">Clob</a> value type (character large object), each of which also includes metadata about the data (specifically the filename and mime type).</p>
</div>
<div class="paragraph">
<p>A class can define a property using either of these types, for example:</p>
</div>
<div class="sect3">
<h4 id="_screenshots_4">2.6.1. Screenshots</h4>
<div class="paragraph">
<p>The following screenshots are taken from the Isis addons example <a href="https://github.com/isisaddons/isis-app-todoapp">todoapp</a> (not ASF):</p>
</div>
<div class="sect4">
<h5 id="_view_mode_empty">View mode, empty</h5>
<div class="paragraph">
<p><code>Blob</code> field rendered as attachment (with no data):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/010-attachment-field.png"><img src="images/blob-attachments/010-attachment-field-940.png" alt="010 attachment field 940" width="800px"></a>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Note that these screenshots show an earlier version of the <a href="../ugvw/ugvw.html">Wicket viewer</a> UI (specifically, pre 1.8.0).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_edit_mode">Edit mode</h5>
<div class="paragraph">
<p>Hit edit; 'choose file' button appears:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/020-edit-choose-file.png"><img src="images/blob-attachments/020-edit-choose-file-940.png" alt="020 edit choose file 940" width="800px"></a>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_choose_file">Choose file</h5>
<div class="paragraph">
<p>Choose file using the regular browser window:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/030-choose-file-using-browser.png"><img src="images/blob-attachments/030-choose-file-using-browser-520.png" alt="030 choose file using browser 520" width="520px"></a>
</div>
</div>
<div class="paragraph">
<p>Chosen file is indicated:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/040-edit-chosen-file-indicated.png"><img src="images/blob-attachments/040-edit-chosen-file-indicated-940.png" alt="040 edit chosen file indicated 940" width="800px"></a>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_image_rendered">Image rendered</h5>
<div class="paragraph">
<p>Back in view mode (ie once hit OK) if the <code>Blob</code> is an image, then it is shown:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/050-ok-if-image-then-rendered.png"><img src="images/blob-attachments/050-ok-if-image-then-rendered-940.png" alt="050 ok if image then rendered 940" width="800px"></a>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_download">Download</h5>
<div class="paragraph">
<p><code>Blob</code> can be downloaded:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/060-download.png"><img src="images/blob-attachments/060-download-940.png" alt="060 download 940" width="800px"></a>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_clear">Clear</h5>
<div class="paragraph">
<p>Back in edit mode, can choose a different file or clear (assuming property is not mandatory):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/blob-attachments/070-edit-clear.png"><img src="images/blob-attachments/070-edit-clear-940.png" alt="070 edit clear 940" width="800px"></a>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_domain_code_3">2.6.2. Domain Code</h4>
<div class="paragraph">
<p>To define a <code>Blob</code>, use:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> <span class="predefined-type">Blob</span> attachment;
<span class="annotation">@javax</span>.jdo.annotations.Persistent(defaultFetchGroup=<span class="string"><span class="delimiter">"</span><span class="content">false</span><span class="delimiter">"</span></span>)
<span class="annotation">@javax</span>.jdo.annotations.Persistent(defaultFetchGroup=<span class="string"><span class="delimiter">"</span><span class="content">false</span><span class="delimiter">"</span></span>, columns = {
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">attachment_name</span><span class="delimiter">"</span></span>),
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">attachment_mimetype</span><span class="delimiter">"</span></span>),
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">attachment_bytes</span><span class="delimiter">"</span></span>, jdbcType = <span class="string"><span class="delimiter">"</span><span class="content">BLOB</span><span class="delimiter">"</span></span>, sqlType = <span class="string"><span class="delimiter">"</span><span class="content">BLOB</span><span class="delimiter">"</span></span>)
})
<span class="annotation">@Property</span>(
domainEvent = AttachmentDomainEvent.class,
optionality = Optionality.OPTIONAL
)
<span class="directive">public</span> <span class="predefined-type">Blob</span> getAttachment() { <span class="keyword">return</span> attachment; }
<span class="directive">public</span> <span class="type">void</span> setAttachment(<span class="directive">final</span> <span class="predefined-type">Blob</span> attachment) { <span class="local-variable">this</span>.attachment = attachment; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>To define a <code>Clob</code>, use:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> <span class="predefined-type">Clob</span> doc;
<span class="annotation">@javax</span>.jdo.annotations.Persistent(defaultFetchGroup=<span class="string"><span class="delimiter">"</span><span class="content">false</span><span class="delimiter">"</span></span>, columns = {
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">doc_name</span><span class="delimiter">"</span></span>),
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">doc_mimetype</span><span class="delimiter">"</span></span>),
<span class="annotation">@javax</span>.jdo.annotations.Column(name = <span class="string"><span class="delimiter">"</span><span class="content">doc_chars</span><span class="delimiter">"</span></span>, jdbcType = <span class="string"><span class="delimiter">"</span><span class="content">CLOB</span><span class="delimiter">"</span></span>, sqlType = <span class="string"><span class="delimiter">"</span><span class="content">CLOB</span><span class="delimiter">"</span></span>)
})
<span class="annotation">@Property</span>(
optionality = Optionality.OPTIONAL
)
<span class="directive">public</span> <span class="predefined-type">Clob</span> getDoc() { <span class="keyword">return</span> doc; }
<span class="directive">public</span> <span class="type">void</span> setDoc(<span class="directive">final</span> <span class="predefined-type">Clob</span> doc) { <span class="local-variable">this</span>.doc = doc; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>Blob</code> and <code>Clob</code> types can also be used as parameters to actions.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_features_user-registration">2.7. User Registration</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_user-registration.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_user-registration.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_user-registration.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_user-registration.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_features_user-registration.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The Wicket viewer provides the ability for users to sign-up by providing a valid email address:</p>
</div>
<div class="ulist">
<ul>
<li> <p>from the login page the user can instead follow a link to take them to a sign-up page, where they enter their email address.</p> </li>
<li> <p>a verification email is sent using this service; the email includes a link back to the running application.</p> </li>
<li> <p>the user then completes the registration process by choosing a user name and password.</p> </li>
<li> <p>the Wicket viewer then creates an account for them and logs them in.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>In a similar way, if the user has forgotten their password then they can request a reset link to be sent to their email, again by providing their email address.</p>
</div>
<div class="paragraph">
<p>To support this the framework requires three services to be registered and configured:</p>
</div>
<div class="ulist">
<ul>
<li> <p>the <a href="../rgsvc/rgsvc.html#_rgsvc_persistence-layer-spi_UserRegistrationService">user registration service</a>, which provides an API to create the user account</p> </li>
<li> <p>the <a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_EmailNotificationService">email notification service</a>, which provides an API for to send the verification emails</p> </li>
<li> <p>the <a href="../rgsvc/rgsvc.html#_rgsvc_integration-api_EmailService">email service</a>, that is used by the email notification service to actually send the email.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The Apache Isis core framework provides a default implementation of both the email notification service and the email service. If your application uses the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a>'s security module then an implementation is provided by that module; just add to the classpath. Otherwise you will need to provide your own implementation.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>There is <em>no</em> default implementation of the user registration service in the core framework.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_screenshots_5">2.7.1. Screenshots</h4>
<div class="paragraph">
<p>The user is presented with a login page:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/login-page-default.png"><img src="images/user-registration/login-page-default.png" alt="login page default" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>Navigate to the sign up page. Complete the page, and verify:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/sign-up-page.png"><img src="images/user-registration/sign-up-page.png" alt="sign up page" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>Back to the login page:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/sign-up-login-page-after-sign-up.png"><img src="images/user-registration/sign-up-login-page-after-sign-up.png" alt="sign up login page after sign up" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>Email arrives, with link:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/sign-up-email-with-verification-link.png"><img src="images/user-registration/sign-up-email-with-verification-link.png" alt="sign up email with verification link" width="500px"></a>
</div>
</div>
<div class="paragraph">
<p>Follow the link, complete the page:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/sign-up-registration-page.png"><img src="images/user-registration/sign-up-registration-page.png" alt="sign up registration page" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>Automatically logged in:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/user-registration/sign-up-after-registration.png"><img src="images/user-registration/sign-up-after-registration.png" alt="sign up after registration" width="800px"></a>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_configuration_3">2.7.2. Configuration</h4>
<div class="paragraph">
<p>There are two prerequisites:</p>
</div>
<div class="ulist">
<ul>
<li> <p>register an implementation of the <a href="../rgsvc/rgsvc.html#_rgsvc_persistence-layer-spi_UserRegistrationService">user registration service</a> (eg by using the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a>'s security module)</p> </li>
<li> <p>configure the <a href="../rgsvc/rgsvc.html#_rgsvc_integration-api_EmailService">email service</a></p> </li>
</ul>
</div>
<div class="paragraph">
<p>The latter is required if you are using the default email notification service and email service. If you are using your own alternative implementation of the email notification service then it may be omitted (and configure your own alternative implementation as required).</p>
</div>
<div class="paragraph">
<p>It is also possible to configure the Wicket viewer to suppress the sign-up page link and/or the password reset page, see <a href="../ugvw/ugvw.html#_ugvw_configuration-properties_sign-in">here</a> for further details.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ugvw_layout">3. Layout</h2>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sectionbody">
<div class="paragraph">
<p>In implementing the <a href="http://en.wikipedia.org/wiki/Naked_objects">naked objects pattern</a>, 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.</p>
</div>
<div class="paragraph">
<p>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 <a href="#_ugvw_menubars-layout">separate chapter</a>.</p>
</div>
<div class="sect2">
<h3 id="_ugvw_layout_annotation-based">3.1. Annotation-based Layout</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_annotation-based.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_annotation-based.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_annotation-based.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_annotation-based.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_annotation-based.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Metadata providing UI hints can be specified either using annotations, or using a <a href="../ugvw/ugvw.html#_ugvw_layout_file-based"><code>layout.xml</code></a> file.</p>
</div>
<div class="paragraph">
<p>In most cases you will probably want to use the file-based approach: changes to file layouts are picked up dynamically, and using a file also allows tabs and tab groups to be specified: this is not supported using annotations.</p>
</div>
<div class="paragraph">
<p>Nevertheless, annotations are still supported and are sometimes useful for very simple objects or just when prototyping. This section explains how.</p>
</div>
<div class="sect3">
<h4 id="_code_memberorder_code">3.1.1. <code>@MemberOrder</code></h4>
<div class="paragraph">
<p>The <a href="../rgant/rgant.html#_rgant-MemberOrder"><code>@MemberOrder</code></a> annotation is used to specify the relative order of domain class properties, collections and actions.</p>
</div>
<div class="paragraph">
<p>The annotation defines two attributes, <a href="../rgant/rgant.html#_rgant-MemberOrder_name"><code>name()</code></a> and <a href="../rgant/rgant.html#_rgant-MemberOrder_sequence"><code>sequence()</code></a>. Their usage depends on the member type:</p>
</div>
<div class="ulist">
<ul>
<li> <p>for properties, the <code>name()</code> is used to group properties together into a member group (also called a property group or a fieldset. The <code>sequence()</code> then orders properties within these groups. If no <code>name()</code> is specified then the property is placed in a fallback "General" group, called "General".<br></p>
<div class="paragraph">
<p>The name of these member groups/fieldsets are then referenced by <a href="../rgant/rgant.html#_rgant-MemberGroupLayout"><code>@MemberGroupLayout</code></a>.</p>
</div> </li>
<li> <p>for collections, the <code>name()</code> attribute is (currently) unused. The <code>sequence()</code> orders collections relative to one another</p> </li>
<li> <p>for actions, the <code>name()</code> attribute associates an action with either a property or with a collection.<br></p>
<div class="ulist">
<ul>
<li> <p>If the <code>name()</code> attribute matches a property name, then the action’s button is rendered close to the property, according to <a href="../rgant/rgant.html#_rgant-ActionLayout_position"><code>@ActionLayout#position()</code></a> attribute.<br></p> </li>
<li> <p>On the other hand if the `name() attribute matches a collection name, then the action’s button is rendered on the collection’s header.</p> </li>
<li> <p>If there is no <code>name()</code> value, then the action is considered to pertain to the object as a whole, and its button is rendered close to the object’s icon and title.</p> </li>
</ul>
</div> </li>
</ul>
</div>
<div class="paragraph">
<p>Within any of these, the <code>sequence()</code> then determines the relative ordering of the action with respect to other actions that have been similarly associated with properties/collections or left as "free-standing".</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ToDoItem</span> {
<span class="annotation">@MemberOrder</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">String</span> getDescription() { ... }
<span class="annotation">@MemberOrder</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">String</span> getCategory() { ... }
<span class="annotation">@MemberOrder</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">3</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="type">boolean</span> isComplete() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">Detail</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> LocalDate getDueBy() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">Detail</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">BigDecimal</span> getCost() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">Detail</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">4</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">String</span> getNotes() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">Misc</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">99</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">Long</span> getVersionSequence() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This defines three property (or member) groups, "General", "Detail" and "Misc"; "General" is the default if no <code>name</code> attribute is specified. Properties in the same member group are rendered together, as a fieldset.</p>
</div>
<div class="paragraph">
<p>In addition, actions can optionally be associated (rendered close to) either properties or actions. This is done by overloading the <code>@MemberOrder</code>'s <a href="../rgant/rgant.html#_rgant-MemberOrder_name"><code>name()</code></a> attribute, holding the value of the property or collection.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ToDoItem</span> {
<span class="annotation">@MemberOrder</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">3</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="type">boolean</span> isComplete() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">complete</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> ToDoItem completed() { ...}
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">complete</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> ToDoItem notYetCompleted() { ...}
<span class="annotation">@MemberOrder</span>(sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">SortedSet</span><ToDoItem> getDependencies() { ... }
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">dependencies</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> ToDoItem add(ToDoItem t) { ...}
<span class="annotation">@MemberOrder</span>(name=<span class="string"><span class="delimiter">"</span><span class="content">dependencies</span><span class="delimiter">"</span></span>, sequence=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> ToDoItem remove(ToDoItem t) { ...}
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>will associate the <code>completed()</code> and <code>notYetCompleted()</code> actions with the <code>complete</code> property, and will associate the <code>add()</code> and <code>remove()</code> actions with the <code>dependencies</code> collection.</p>
</div>
<div class="paragraph">
<p>The value of <a href="../rgant/rgant.html#_rgant-MemberOrder_sequence"><code>sequence()</code></a> is a string. The simplest convention (as shown in the example above) is to use numbers — 1, 2, 3 — though it is a better idea to leave gaps in the numbers — 10, 20, 30 perhaps — such that a new member may be added without having to edit existing numbers.</p>
</div>
<div class="paragraph">
<p>Even better is to adopt the 'dewey-decimal' notation — 1, 1.1, 1.2, 2, 3, 5.1.1, 5.2.2, 5.2, 5.3 — which allows for an indefinite amount of future insertion. It also allows subclasses to insert their class members as required.</p>
</div>
</div>
<div class="sect3">
<h4 id="_code_membergrouplayout_code">3.1.2. <code>@MemberGroupLayout</code></h4>
<div class="paragraph">
<p>The <a href="../rgant/rgant.html#_rgant-MemberGroupLayout"><code>@MemberGroupLayout</code></a> annotation specifies the relative positioning of property groups/fieldsets as being either in a left column, a middle column or in a right column. The annotation also specifies the relative width of the columns.</p>
</div>
<div class="paragraph">
<p>The property groups/fieldsets in this case are those that are inferred from the <code>@MemberOrder#name()</code> attribute.</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>It is also possible to combine <code>@MemberOrder</code> with a <a href="../ugvw/ugvw.html#_ugvw_layout_xml">file-based layout</a>. The layout file defines only the regions of a grid structure (fieldsets/columns etc), but does <em>not</em> specify the properties/collections/actions within those grid regions. The <code>@MemberOrder</code> annotation in effect "binds" the properties or collections to those regions of the grid.</p>
</div>
<div class="paragraph">
<p>When file-based layouts are used this way, the <a href="../rgant/rgant.html#_rgant-MemberGroupLayout"><code>@MemberGroupLayout</code></a> annotation is essentially ignored, but the metadata from the <a href="../rgant/rgant.html#_rgant-MemberOrder"><code>@MemberOrder</code></a> annotation (and the other layout annotations, <a href="../rgant/rgant.html#_rgant-ActionLayout"><code>@ActionLayout</code></a>, <a href="../rgant/rgant.html#_rgant-PropertyLayout"><code>@PropertyLayout</code></a> and <a href="../rgant/rgant.html#_rgant-CollectionLayout"><code>@CollectionLayout</code></a>) are all still honoured.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@MemberGroupLayout</span>(
columnSpans={<span class="integer">3</span>,<span class="integer">3</span>,<span class="integer">0</span>,<span class="integer">6</span>},
left={<span class="string"><span class="delimiter">"</span><span class="content">General</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">Misc</span><span class="delimiter">"</span></span>},
middle=<span class="string"><span class="delimiter">"</span><span class="content">Detail</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">ToDoItem</span> {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Four values are given in the <code>columnSpans</code> attribute. The first three are the relative widths of the three columns of property groups. The fourth, meanwhile, indicates the width of a final column that holds all the collections of the object.</p>
</div>
<div class="paragraph">
<p>The values of these spans are taken as proportions of 12 virtual columns across the page (this taken from the <a href="http://getbootstrap.com/2.3.2/">Bootstrap</a> library).</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="ulist">
<ul>
<li> <p><code>{3,3,0,6}</code> indicates:</p>
<div class="ulist">
<ul>
<li> <p>a left column of properties taking up 25% of the width</p> </li>
<li> <p>a middle column of properties taking up 25% of the width</p> </li>
<li> <p>a right column of collections taking up 50% of the width</p> </li>
</ul>
</div> </li>
<li> <p><code>{2,6,0,4}</code> indicates:</p>
<div class="ulist">
<ul>
<li> <p>a left column of properties taking up ~16% of the width</p> </li>
<li> <p>a middle column of properties taking up 50% of the width</p> </li>
<li> <p>a right column of collections taking up ~33% of the width</p> </li>
</ul>
</div> </li>
<li> <p><code>{2,3,3,4}</code> indicates:</p>
<div class="ulist">
<ul>
<li> <p>a left column of properties taking up ~16% of the width</p> </li>
<li> <p>a middle column of properties taking up 25% of the width</p> </li>
<li> <p>a right column of properties taking up 25% of the width</p> </li>
<li> <p>a far right column of collections taking up ~33% of the width</p> </li>
</ul>
</div> </li>
</ul>
</div>
<div class="paragraph">
<p>If the sum of all the columns exceeds 12, then the collections are placed underneath the properties, taking up the full span. For example:</p>
</div>
<div class="ulist">
<ul>
<li> <p>{4,4,4,12} indicates:</p>
<div class="ulist">
<ul>
<li> <p>a left column of properties taking up ~33% of the width</p> </li>
<li> <p>a middle column of properties taking up ~33% of the width</p> </li>
<li> <p>a right column of properties taking up ~33% of the width</p> </li>
<li> <p>the collections underneath the property columns, taking up the full width</p> </li>
</ul>
</div> </li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_example_layouts">3.1.3. Example Layouts</h4>
<div class="paragraph">
<p>Below are sketches for the layout of the <a href="https://github.com/apache/isis/blob/f38fdb92941172eabb12e0943509f239e6d5925f/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java">ToDoItem</a> class of the Isis addons example <a href="https://github.com/isisaddons/isis-app-todoapp/">todoapp</a> (not ASF):</p>
</div>
<div class="paragraph">
<p>The first divides the properties into two equal sized columns (6-6-0) and puts the collections underneath (12):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/reference-layout/6-6-0-12.png"><img src="images/reference-layout/6-6-0-12.png" alt="6 6 0 12" width="720px"></a>
</div>
</div>
<div class="paragraph">
<p>The next divides the collections into three equal sized columns (4-4-4) and again puts the collections underneath (12):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/reference-layout/4-4-4-12.png"><img src="images/reference-layout/4-4-4-12.png" alt="4 4 4 12" width="720px"></a>
</div>
</div>
<div class="paragraph">
<p>The last puts the properties into a single column (4-0) and places the collections into the other larger column (8-0):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/reference-layout/4-0-8-0.png"><img src="images/reference-layout/4-0-8-0.png" alt="4 0 8 0" width="720px"></a>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_other_annotations">3.1.4. Other Annotations</h4>
<div class="paragraph">
<p>All the layout annotations (eg <code>@Regex</code> and <code>@Named</code>) have been deprecated, instead replaced by the various <code>XxxLayout</code> annotations:</p>
</div>
<div class="ulist">
<ul>
<li> <p>for domain services: <a href="../rgant/rgant.html#_rgant-DomainServiceLayout"><code>@DomainServiceLayout</code></a></p> </li>
<li> <p>for domain objects: <a href="../rgant/rgant.html#_rgant-DomainObjectLayout"><code>@DomainObjectLayout</code></a> and <a href="../rgant/rgant.html#_rgant-ViewModelLayout"><code>@ViewModelLayout</code></a></p> </li>
<li> <p>for actions: <a href="../rgant/rgant.html#_rgant-ActionLayout, "><code>@ActionLayout</code></a> and <a href="../rgant/rgant.html#_rgant-ParameterLayout"><code>@ParameterLayout</code></a></p> </li>
<li> <p>for properties: <a href="../rgant/rgant.html#_rgant-PropertyLayout"><code>@PropertyLayout</code></a></p> </li>
<li> <p>for collections: <a href="../rgant/rgant.html#_rgant-CollectionLayout"><code>@CollectionLayout</code></a></p> </li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_layout_file-based">3.2. File-based Layouts</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_file-based.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Metadata providing UI hints can be specified either <a href="../ugvw/ugvw.html#_ugvw_layout_annotation-based">using annotations</a>, or using an <code>Xxx.layout.xml</code> file (where <code>Xxx</code> is the entity or view model object to be rendered).</p>
</div>
<div class="paragraph">
<p>File-based layouts offer a number of benefits:</p>
</div>
<div class="ulist">
<ul>
<li> <p>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</p> </li>
<li> <p>Many developers also find it easier to rationalize about layout when all the hints are collated together in a single place (rather than scattered across the class members as annotations).</p> </li>
<li> <p>UI hints can be provided for <a href="../ugfun/ugfun.html#_ugfun_how-tos_contributed-members">contributed associations and actions</a> that are synthesised at runtime.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>It is also possible to download an initial <code>.layout.xml</code> - capturing any existing layout metadata - using the <a href="../rgsvc/rgsvc.html#_rgsvc_metadata-api_LayoutService"><code>LayoutService</code></a> (exposed on the prototyping menu) or using a <a href="../rgcms/rgcms.html#_rgcms_classes_mixins_Object">mixin action</a> contributed to every domain object.</p>
</div>
<div class="paragraph">
<p>There are some downsides, though:</p>
</div>
<div class="ulist">
<ul>
<li> <p>file-based layouts are not typesafe: a typo will result in the metadata not being picked up for the element.</p> </li>
<li> <p>they suffer from syntactic fragility: an invalid XML document will result in no metadata for the entire class.</p> </li>
<li> <p>there is no notion of inheritance, so a <code>.layout.xml</code> is required for all concrete classes and also for any abstract classes (if used as a collection type). In contrast, the dewey-decimal format <code>@MemberOrder</code> annotation allows the metadata of the subclass its superclasses to fit together relatively seamlessly.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The <code>Xxx.layout.xml</code> file is just the serialized form of a <a href="../rgcms/rgcms.html#_rgcms_classes_layout"><code>Grid</code></a> 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.</p>
</div>
<div class="sect3">
<h4 id="_search_algorithm_library_support">3.2.1. Search Algorithm (Library Support)</h4>
<div class="paragraph">
<p>For a given domain object <code>Xxx</code> the framework initially searches for a file (on the classpath) called <code>Xxx.layout.xml</code>.</p>
</div>
<div class="paragraph">
<p>If this can’t be found, then the framework will search for a file named <code>Xxx.layout.fallback.xml</code>. If present, this will be used instead.</p>
</div>
<div class="paragraph">
<p>This therefore allows libraries that provide a domain entities/view models (for example, the (non-ASF) <a href="http://platform.incode.org">Incode Platform</a> modules) to define the UI of these objects using a layout file, while still allowing the consuming application to override that layout if it so requires.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>It is also possible to describe layouts using a <code>.layout.json</code> file. However, <code>.layout.json</code> support is deprecated; the <code>.layout.xml</code> file also enables much more sophisticated layouts than those afforded by <code>.layout.json</code>.</p>
</div>
<div class="paragraph">
<p>If you have an application with older <code>.layout.json</code> files, then it is possible to download initial <code>.layout.xml</code> files using the <a href="../rgsvc/rgsvc.html#_rgsvc_metadata-api_LayoutService"><code>LayoutService</code></a> (exposed as an action on the prototyping menu).</p>
</div>
<div class="paragraph">
<p>The <code>.layout.json</code> file will be ignored once a <code>.layout.xml</code> file is present.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_grids_vs_components">3.2.2. Grids vs Components</h4>
<div class="paragraph">
<p>The layout file distinguishes between two types of element:</p>
</div>
<div class="ulist">
<ul>
<li> <p>those that define a grid structure, of: rows, columns, tab groups and tabs.<br></p>
<div class="paragraph">
<p>The rows and columns are closely modelled on <a href="http://getbootstrap.com">Bootstrap 3</a> (used in the implementation of the <a href="../ugvw/ugvw.html">Wicket viewer</a>).</p>
</div> </li>
<li> <p>those that defines common components, of: fieldsets (previously called member groups or property groups), properties, collections, actions and also the title/icon of the domain object itself.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>More information about these classes can be found in <a href="../rgcms/rgcms.html#_rgcms_classes_layout">the reference guide</a>. More information on Bootstrap 3’s grid system can be found <a href="http://getbootstrap.com/css/#grid">here</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_screencast">3.2.3. Screencast</h4>
<div class="paragraph">
<p>This <a href="https://www.youtube.com/watch?v=MxewC5Pve5k">screencast</a> describes the feature.</p>
</div>
</div>
<div class="sect3">
<h4 id="_examples">3.2.4. Examples</h4>
<div class="paragraph">
<p>Probably the easiest way to understand dynamic XML layouts is by example. For this we’ll use the <code>ToDoItem</code> from the (non-ASF) <a href="http://github.com/isisaddons/isis-app-todoapp">Isis addons' todoapp</a>:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/layout-dynamic-xml/ToDoItem.png"><img src="images/layout-dynamic-xml/ToDoItem.png" alt="ToDoItem" width="940px"></a>
</div>
</div>
<div class="sect4">
<h5 id="_namespaces">Namespaces</h5>
<div class="paragraph">
<p>First things first; every <code>.layout.xml</code> file must properly declare the XSD namespaces and schemas. There are two: one for the grid classes, and one for the common component classes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor"><?xml version="1.0" encoding="UTF-8" standalone="yes"?></span>
<span class="tag"><bs3:grid</span>
<span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/component</span> <span class="content">http://isis.apache.org/applib/layout/component/component.xsd</span> <span class="content">http://isis.apache.org/applib/layout/grid/bootstrap3</span> <span class="content">http://isis.apache.org/applib/layout/grid/bootstrap3/bootstrap3.xsd</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:bs3</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/grid/bootstrap3</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:c</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/component</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"></bs3:grid></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Most IDEs will automatically download the XSD schemas from the specified schema locations, thereby providing "intellisense" help as you edit the file.</p>
</div>
</div>
<div class="sect4">
<h5 id="_rows_full_width_cols_and_tabs">Rows, full-width cols, and tabs</h5>
<div class="paragraph">
<p>The example layout consists of three rows: a row for the object/icon, a row containing a properties, and a row containing collections. In all three cases the row contains a single column spanning the full width of the page. For the property and collection rows, the column contains a tab group.</p>
</div>
<div class="paragraph">
<p>This corresponds to the following XML:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedActions</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:domainObject</span> <span class="attribute-name">bookmarking</span>=<span class="string"><span class="delimiter">"</span><span class="content">AS_ROOT</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span>
<span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:tabGroup></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Properties</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></bs3:tab></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Other</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></bs3:tab></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Metadata</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></bs3:tab></span>
<span class="tag"></bs3:tabGroup></span>
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span>
<span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:tabGroup</span> <span class="attribute-name">unreferencedCollections</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Similar to</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></bs3:tab></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Dependencies</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></bs3:tab></span>
<span class="tag"></bs3:tabGroup></span>
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You will notice that one of the <code>col</code>umns has an <code>unreferencedActions</code> attribute, while one of the <code>tabGroup</code>s has a similar <code>unreferencedCollections</code> attribute. This topic is discussed in more detail <a href="../ugfun/ugfun.html#__ugvw_layout_file-based_unreferenced">below</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="_fieldsets">Fieldsets</h5>
<div class="paragraph">
<p>The first tab containing properties is divided into two columns, each of which holds a single fieldset of multiple properties. Those properties in turn can have associated actions.</p>
</div>
<div class="paragraph">
<p>This corresponds to the following XML:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Properties</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">6</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:fieldSet</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">General</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">general</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedProperties</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">duplicate</span><span class="delimiter">"</span></span> <span class="attribute-name">position</span>=<span class="string"><span class="delimiter">"</span><span class="content">PANEL_DROPDOWN</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">delete</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:property</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">description</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:property</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">category</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:property</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">subcategory</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">updateCategory</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">analyseCategory</span><span class="delimiter">"</span></span> <span class="attribute-name">position</span>=<span class="string"><span class="delimiter">"</span><span class="content">RIGHT</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></c:property></span>
<span class="tag"><c:property</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">complete</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">completed</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClassFa</span>=<span class="string"><span class="delimiter">"</span><span class="content">fa-thumbs-up</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">notYetCompleted</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClassFa</span>=<span class="string"><span class="delimiter">"</span><span class="content">fa-thumbs-down</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></c:property></span>
<span class="tag"></c:fieldSet></span>
<span class="tag"></bs3:col></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">6</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span>
<span class="tag"></bs3:tab></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The tab defines two columns, each span of 6 (meaning half the width of the page).</p>
</div>
<div class="paragraph">
<p>In the first column there is a single fieldset. Notice how actions - such as <code>duplicate</code> and <code>delete</code> - can be associated with this fieldset directly, meaning that they should be rendered on the fieldset’s top panel.</p>
</div>
<div class="paragraph">
<p>Thereafter the fieldset lists the properties in order. Actions can be associated with properties too; here they are rendered underneath or to the right of the field.</p>
</div>
<div class="paragraph">
<p>Note also the <code>unreferencedProperties</code> attribute for the fieldset; this topic is discussed in more detail <a href="../ugfun/ugfun.html#__ugvw_layout_file-based_unreferenced">below</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>The <code><fieldset></code>'s "name" attribute is optional. If omitted, then the title panel is suppressed, freeing more real estate.</p>
</div>
<div class="paragraph">
<p>Do be aware though that if there are any actions that have been placed on the fieldset’s panel, then these <em>will <strong>not</strong> be displayed</em>.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_collections">Collections</h5>
<div class="paragraph">
<p>In the final row the collections are placed in tabs, simply one collection per tab. This corresponds to the following XML:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Similar to</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:collection</span> <span class="attribute-name">defaultView</span>=<span class="string"><span class="delimiter">"</span><span class="content">table</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">similarTo</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span>
<span class="tag"></bs3:tab></span>
<span class="tag"><bs3:tab</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">Dependencies</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><bs3:row></span>
<span class="tag"><bs3:col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:collection</span> <span class="attribute-name">defaultView</span>=<span class="string"><span class="delimiter">"</span><span class="content">table</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">dependencies</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">add</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"><c:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">remove</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></c:collection></span>
<span class="tag"></bs3:col></span>
<span class="tag"></bs3:row></span>
<span class="tag"></bs3:tab></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>As with properties, actions can be associated with collections; this indicates that they should be rendered in the collection’s header.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="__ugvw_layout_file-based_unreferenced">3.2.5. Unreferenced Members</h4>
<div class="paragraph">
<p>As noted in the preceding discussion, several of the grid’s regions have either an <code>unreferencedActions</code>, <code>unreferencedCollections</code> or <code>unreferencedProperties</code> attribute.</p>
</div>
<div class="paragraph">
<p>The rules are:</p>
</div>
<div class="ulist">
<ul>
<li> <p><code>unreferencedActions</code> attribute can be specified either on a column or on a fieldset. <br></p>
<div class="paragraph">
<p>It would normally be typical to use the column holding the <code><domainObject/></code> icon/title, that is as shown in the example. The unreferenced actions then appear as top-level actions for the domain object.</p>
</div> </li>
<li> <p><code>unreferencedCollections</code> attribute can be specified either on a column or on a tabgroup.<br></p>
<div class="paragraph">
<p>If specified on a column, then that column will contain each of the unreferenced collections, stacked one on top of the other. If specified on a tab group, then a separate tab will be created for each collection, with that tab containing only that single collection.</p>
</div> </li>
<li> <p><code>unreferencedProperties</code> attribute can be specified only on a fieldset.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The purpose of these attributes is to indicate where in the layout any unreferenced members should be rendered. Every grid <em>must</em> nominate one region for each of these three member types, the reason being that to ensure that the layout can be used even if it is incomplete with respect to the object members inferred from the Java source code. This might be because the developer forgot to update the layout, or it might be because of a new mixin (property, collection or action) contributed to many objects.</p>
</div>
<div class="paragraph">
<p>The framework ensures that in any given grid exactly one region is specified for each of the three <code>unreferenced…</code> attributes. If the grid fails this validation, then a warning message will be displayed, and the invalid XML logged. The layout XML will then be ignored.</p>
</div>
</div>
<div class="sect3">
<h4 id="_more_advanced_features">3.2.6. More advanced features</h4>
<div class="paragraph">
<p>This section decribes a number of more features useful in more complex layouts.</p>
</div>
<div class="sect4">
<h5 id="_multiple_references_to_a_feature">Multiple references to a feature</h5>
<div class="paragraph">
<p>One feature worth being aware of is that it is possible to render a single feature more than once.</p>
</div>
<div class="paragraph">
<p>For example, the dashboard home page for the (non-ASF) <a href="http://github.com/isisaddons/isis-app-todoapp">Isis addons' todoapp</a> shows the "not yet complete" collection of todo items twice, once as a table and also as a calendar:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/layout-dynamic-xml/ToDoAppDashboard.png"><img src="images/layout-dynamic-xml/ToDoAppDashboard.png" alt="ToDoAppDashboard" width="940px"></a>
</div>
</div>
<div class="paragraph">
<p>This is accomplished using the following (slightly abbreviated) layout:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><grid</span> <span class="attribute-name">...</span><span class="tag">></span>
<span class="tag"><row></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedActions</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"></col></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedCollections</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClass</span>=<span class="string"><span class="delimiter">"</span><span class="content">custom-padding-top-20</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><ns2:collection</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">notYetComplete</span><span class="delimiter">"</span></span> <span class="attribute-name">defaultView</span>=<span class="string"><span class="delimiter">"</span><span class="content">calendar</span><span class="delimiter">"</span></span><span class="tag">/></span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag"></col></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClass</span>=<span class="string"><span class="delimiter">"</span><span class="content">custom-padding-top-20</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><ns2:collection</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">notYetComplete</span><span class="delimiter">"</span></span> <span class="attribute-name">defaultView</span>=<span class="string"><span class="delimiter">"</span><span class="content">table</span><span class="delimiter">"</span></span> <span class="attribute-name">paged</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span><span class="tag">/></span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag"><ns2:collection</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">complete</span><span class="delimiter">"</span></span> <span class="attribute-name">defaultView</span>=<span class="string"><span class="delimiter">"</span><span class="content">table</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></col></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">0</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><ns2:fieldSet</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">General</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">general</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedProperties</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></col></span>
<span class="tag"></row></span>
<span class="tag"></grid></span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>render the collection in "calendar" view</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>also render the collection in "table" view</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>In the middle column the <code>notYetComplete</code> collection is rendered in "calendar" view, while in the right-most column it is rendered in "table" view.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
</div>
<div class="sect4">
<h5 id="_custom_css">Custom CSS</h5>
<div class="paragraph">
<p>The ToDoApp’s dashboard (above) also shows how custom CSS styles can be associated with specific regions of the layout:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><grid</span> <span class="attribute-name">...</span><span class="tag">></span>
<span class="tag"><row></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedActions</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><ns2:domainObject</span><span class="tag">/></span>
<span class="tag"><row></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">12</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClass</span>=<span class="string"><span class="delimiter">"</span><span class="content">custom-width-100</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag"><ns2:action</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">exportToWordDoc</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></col></span>
<span class="tag"></row></span>
...
<span class="tag"></col></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span> <span class="attribute-name">unreferencedCollections</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClass</span>=<span class="string"><span class="delimiter">"</span><span class="content">custom-padding-top-20</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="2"></i><b>(2)</b>
...
<span class="tag"></col></span>
<span class="tag"><col</span> <span class="attribute-name">span</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span> <span class="attribute-name">cssClass</span>=<span class="string"><span class="delimiter">"</span><span class="content">custom-padding-top-20</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="3"></i><b>(3)</b>
...
<span class="tag"></col></span>
<span class="tag"></row></span>
<span class="tag"></grid></span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Render the column with the <code>custom-width-100</code> CSS class.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Render the column with the <code>custom-padding-top-20</code> CSS class.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Ditto</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>For example the <code>custom-width-100</code> style is used to "stretch" the button for the <code>exportToWordDoc</code> action in the left-most column. This is accomplished with the following CSS in <code>application.css</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.custom-width-100</span> <span class="tag">ul</span>,
<span class="class">.custom-width-100</span> <span class="tag">ul</span> <span class="tag">li</span>,
<span class="class">.custom-width-100</span> <span class="tag">ul</span> <span class="tag">li</span> <span class="tag">a</span><span class="class">.btn</span> {
<span class="key">width</span>: <span class="float">100%</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Similarly, the middle and right columns are rendered using the <code>custom-padding-top-20</code> CSS class. This shifts them down from the top of the page slightly, using the following CSS:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.custom-padding-top-20</span> {
<span class="key">padding-top</span>: <span class="float">20px</span>;
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_migrating_from_earlier_versions">3.2.7. Migrating from earlier versions</h4>
<div class="paragraph">
<p>As noted earlier on, it is possible to download layout XML files using the <a href="../rgsvc/rgsvc.html#_rgsvc_metadata-api_LayoutService"><code>LayoutService</code></a> (exposed on the prototyping menu); this will download a ZIP file of layout XML files for all domain entities and view models. Alternatively the layout XML for a single domain object can be downloaded using the <a href="../rgcms/rgcms.html#_rgcms_classes_mixins_Object">mixin action</a> (contributed to every domain object).</p>
</div>
<div class="paragraph">
<p>There are four "styles":</p>
</div>
<div class="ulist">
<ul>
<li> <p>current</p> </li>
<li> <p>complete</p> </li>
<li> <p>normalized</p> </li>
<li> <p>minimal</p> </li>
</ul>
</div>
<div class="paragraph">
<p>Ignoring the "current" style (which merely downloads the currently cached layout), the other three styles allow the developer to choose how much metadata is to be specified in the XML, and how much (if any) will be obtained from annotations in the metamodel. The table below summarises the choices:</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 1. Table caption
</caption>
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-bottom">Style</th>
<th class="tableblock halign-center valign-bottom"><a href="../rgant/rgant.html#_rgant-MemberGroupLayout"><code>@MemberGroupLayout</code></a></th>
<th class="tableblock halign-center valign-bottom"><a href="../rgant/rgant.html#_rgant-MemberOrder"><code>@MemberOrder</code></a></th>
<th class="tableblock halign-center valign-bottom"><a href="../rgant/rgant.html#_rgant-ActionLayout"><code>@ActionLayout</code></a>, <a href="../rgant/rgant.html#_rgant-PropertyLayout"><code>@PropertyLayout</code></a>, <a href="../rgant/rgant.html#_rgant-CollectionLayout"><code>@CollectionLayout</code></a></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-bottom"><p class="tableblock"><code>COMPLETE</code></p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-bottom"><p class="tableblock"><code>NORMALIZED</code></p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">not in the XML</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-bottom"><p class="tableblock"><code>MINIMAL</code></p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">serialized as XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">not in the XML</p></td>
<td class="tableblock halign-center valign-bottom"><p class="tableblock">not in the XML</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>As a developer, you therefore have a choice as to how you provide the metadata required for customised layouts:</p>
</div>
<div class="ulist">
<ul>
<li> <p>if you want all layout metadata to be read from the <code>.layout.xml</code> file, then download the "complete" version, and copy the file alongside the domain class. You can then remove all <code>@MemberGroupLayout</code>, <code>@MemberOrder</code>, <code>@ActionLayout</code>, <code>@PropertyLayout</code> and <code>@CollectionLayout</code> annotations from the source code of the domain class.</p> </li>
<li> <p>if you want to use layout XML file to describe the grid (columns, tabs etc) and specify which object members are associated with those regions of the grid, then download the "normalized" version. You can then remove the <code>@MemberGroupLayout</code> and <code>@MemberOrder</code> annotations from the source code of the domain class, but retain the <code>@ActionLayout</code>, <code>@PropertyLayout</code> and <code>@CollectionLayout</code> annotations.</p> </li>
<li> <p>if you want to use layout XML file ONLY to describe the grid, then download the "minimal" version. The grid regions will be empty in this version, and the framework will use the <code>@MemberOrder</code> annotation to bind object members to those regions. The only annotation that can be safely removed from the source code with this style is the <code>@MemberGroupLayout</code> annotation.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>Download either for a single domain object, or download all domain objects (entities and view models).</p>
</div>
</div>
<div class="sect3">
<h4 id="_domain_services">3.2.8. Domain Services</h4>
<div class="paragraph">
<p>For more information about layouts, see:</p>
</div>
<div class="ulist">
<ul>
<li> <p><a href="../rgsvc/rgsvc.html#_rgsvc_metadata-api_LayoutService"><code>LayoutService</code></a> (whose functionality is exposed on the prototyping menu as an action) and lso the a <a href="../rgcms/rgcms.html#_rgcms_classes_mixins_Object">mixin action</a></p> </li>
<li> <p><a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_GridService"><code>GridService</code></a> and its supporting services, <a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_GridLoaderService"><code>GridLoaderService</code></a> and <a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_GridSystemService"><code>GridSystemService</code></a></p> </li>
<li> <p><a href="../rgcms/rgcms.html#_rgcms_classes_layout">grid layout classes</a>, defined in the Apache Isis applib</p> </li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_required_updates_to_the_dom_project_s_pom_xml">3.2.9. Required updates to the dom project’s pom.xml</h4>
<div class="paragraph">
<p>Any <code>.layout.xml</code> files must be compiled and available in the classpath. Ensure the following is defined in the dom project’s <code>pom.xml</code>:</p>
</div>
<div class="listingblock xml">
<div class="content">
<pre class="CodeRay highlight"><code><resources>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
</resource>
<resource>
<filtering>false</filtering>
<directory>src/main/java</directory>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources></code></pre>
</div>
</div>
<div class="paragraph">
<p>If using an Apache Isis <a href="../ugfun/ugfun.html#_ugfun_getting-started_helloworld-archetype">HelloWorld</a> <a href="../ugfun/ugfun.html#_ugfun_getting-started_simpleapp-archetype">SimpleApp</a> archetypes, then the POM is already correctly configured.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_layout_table-columns">3.3. Table Columns</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_table-columns.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_table-columns.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_table-columns.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_table-columns.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_layout_table-columns.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The optional <a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_TableColumnOrderService"><code>TableColumnOrderService</code></a> SPI service can be used to reorder columns in a table, either for a parented collection (owned by parent domain object) or a standalone collection (returned from an action invocation).</p>
</div>
<div class="paragraph">
<p>For example, suppose there is a <code>Customer</code> and an <code>Order</code>:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/layouts/customer-order.png" alt="customer order" width="108" height="248">
</div>
</div>
<div class="paragraph">
<p>The order of these properties of <code>Order</code>, when rendered in the context of its owning <code>Customer</code>, can be controlled using this implementation of <code>TableColumnOrderService</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainService</span>(
nature = NatureOfService.DOMAIN,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">100</span><span class="delimiter">"</span></span> <i class="conum" data-value="1"></i><b>(1)</b>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">TableColumnOrderServiceForCustomerOrders</span>
<span class="directive">implements</span> TableColumnOrderService {
<span class="directive">public</span> <span class="predefined-type">List</span><<span class="predefined-type">String</span>> orderParented(
<span class="directive">final</span> <span class="predefined-type">Object</span> parent,
<span class="directive">final</span> <span class="predefined-type">String</span> collectionId,
<span class="directive">final</span> <span class="predefined-type">Class</span><?> collectionType,
<span class="directive">final</span> <span class="predefined-type">List</span><<span class="predefined-type">String</span>> propertyIds) {
<span class="keyword">return</span> parent <span class="keyword">instanceof</span> Customer && <span class="string"><span class="delimiter">"</span><span class="content">orders</span><span class="delimiter">"</span></span>.equals(collectionId)
? <span class="predefined-type">Arrays</span>.asList(<span class="string"><span class="delimiter">"</span><span class="content">num</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">placedOn</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">state</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">shippedOn</span><span class="delimiter">"</span></span>)
: <span class="predefined-constant">null</span>;
}
<span class="directive">public</span> <span class="predefined-type">List</span><<span class="predefined-type">String</span>> orderStandalone(
<span class="directive">final</span> <span class="predefined-type">Class</span><?> collectionType,
<span class="directive">final</span> <span class="predefined-type">List</span><<span class="predefined-type">String</span>> propertyIds) {
<span class="keyword">return</span> <span class="predefined-constant">null</span>;
}
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>specifies the order in which the <code>TableColumnOrderService</code> implementations are called.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ugvw_menubars-layout">4. Menu Bars Layout</h2>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sectionbody">
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>For example, the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a> modules provides services whose actions appear into two top-level menus:</p>
</div>
<div class="ulist">
<ul>
<li> <p>its <code>ApplicationUsers</code>, <code>ApplicationRoles</code>, <code>ApplicationPermission</code>, <code>ApplicationFeatureViewModels</code> and <code>ApplicationTenancies</code> domain services are all grouped together in a single "Security" top-level menu, on the SECONDARY menu bar</p> </li>
<li> <p>its <code>MeService</code> domain service, which provides the <code>me()</code> action, is placed on the TERTIARY menu bar.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The menus themselves can be placed either on a primary, secondary or tertiary menu bar, as shown in this screenshot (taken from <a href="http://github.com/estatio/estatio">Estatio</a>, an open source estate management application built using Apache Isis):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/application-menu/layout-menus.png"><img src="images/application-menu/layout-menus.png" alt="layout menus" width="800px"></a>
</div>
</div>
<div class="paragraph">
<p>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:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/application-menu/dividers.png"><img src="images/application-menu/dividers.png" alt="dividers" width="400px"></a>
</div>
</div>
<div class="paragraph">
<p>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:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/application-menu/tertiary.png"><img src="images/application-menu/tertiary.png" alt="tertiary" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>The Apache Isis framework provides two mechanisms to control the arrangement of domain service actions across menubars and menus, either using annotations or using a file-based layout.</p>
</div>
<div class="sect2">
<h3 id="_ugvw_menubars-layout_annotation-based">4.1. Annotation-based Menu Bars</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_annotation-based.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The annotations-based approach for arranging the placement of menu items is achieved through the <a href="../rgant/rgant.html#_rgant-MemberOrder"><code>@MemberOrder</code></a> and <a href="../rgant/rgant.html#_rgant-DomainServiceLayout"><code>@DomainServiceLayout</code></a> annotations.</p>
</div>
<div class="sect3">
<h4 id="_domainservicelayout">4.1.1. @DomainServiceLayout</h4>
<div class="paragraph">
<p>In the example from Estatio shown above the top-level menu combines the actions from the <code>Properties</code>, <code>Units</code> and <code>FixedAssetRegistrations</code> services. The <code>Properties</code> service is annotated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainServiceLayout</span>(
named=<span class="string"><span class="delimiter">"</span><span class="content">Fixed Assets</span><span class="delimiter">"</span></span>,
menuBar = DomainServiceLayout.MenuBar.PRIMARY,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">10.1</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">Properties</span> ... { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>while the <code>Units</code> service is annotated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainServiceLayout</span>(
named=<span class="string"><span class="delimiter">"</span><span class="content">Fixed Assets</span><span class="delimiter">"</span></span>,
menuBar = DomainServiceLayout.MenuBar.PRIMARY,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">10.2</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">Units</span> ... { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>and similarly <code>FixedAssetRegistrations</code> is annotated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainServiceLayout</span>(
named=<span class="string"><span class="delimiter">"</span><span class="content">Fixed Assets</span><span class="delimiter">"</span></span>,
menuBar = DomainServiceLayout.MenuBar.PRIMARY,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">10.3</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">FixedAssetRegistrations</span> ... { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that in all three cases the value of the <code>named</code> attribute and the <code>menuBar</code> attribute is the same: "Fixed Assets" and PRIMARY. This means that all will appear on a "Fixed Assets" menu in the primary menu bar.</p>
</div>
<div class="paragraph">
<p>Meanwhile the value of <code>menuOrder</code> attribute is significant for two reasons:</p>
</div>
<div class="ulist">
<ul>
<li> <p>for these three services on the same ("Fixed Assets") top-level menu, it determines the relative order of their sections (<code>Properties</code> first, then <code>Units</code>, then <code>FixedAssetRegistrations</code>)</p> </li>
<li> <p>it determines the placement of the top-level menu itself ("Fixed Assets") with respect to other top-level menus on the menu bar.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>To illustrate this latter point, the next top-level menu on the menu bar, "Parties", is placed after "Fixed Assets" because the <code>menuOrder</code> of the first of its domain services, namely the <code>Parties</code> service, is higher than that for "Fixed Assets":</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainServiceLayout</span>(
named=<span class="string"><span class="delimiter">"</span><span class="content">Parties</span><span class="delimiter">"</span></span>,
menuBar = DomainServiceLayout.MenuBar.PRIMARY,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">20.1</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">Parties</span> ... { ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that only the <code>menuOrder</code> of the <em>first</em> domain service is significant in placing the menus along the menu bar; thereafter the purpose of the <code>menuOrder</code> is to order the menu services sections on the menu itself.</p>
</div>
</div>
<div class="sect3">
<h4 id="_ordering_menu_actions">4.1.2. Ordering menu actions</h4>
<div class="paragraph">
<p>For a given service, the actions within a section on a menu is determined by the <code>@MemberOrder</code> annotation. Thus, for the <code>Units</code> domain service, its actions are annotated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Units</span> <span class="directive">extends</span> EstatioDomainService<Unit> {
<span class="annotation">@MemberOrder</span>(sequence = <span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> Unit newUnit( ... ) { ... }
<span class="annotation">@MemberOrder</span>(sequence = <span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">List</span><Unit> findUnits( ... ) { ... }
<span class="annotation">@ActionLayout</span>( prototype = <span class="predefined-constant">true</span> )
<span class="annotation">@MemberOrder</span>(sequence = <span class="string"><span class="delimiter">"</span><span class="content">99</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">List</span><Unit> allUnits() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>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.</p>
</div>
</div>
<div class="sect3">
<h4 id="_tertiary_menu">4.1.3. Tertiary Menu</h4>
<div class="paragraph">
<p>Domain services' actions can be associated with the tertiary menu using the same <code>@DomainServiceLayout</code> annotation, but be aware that the <code>@DomainServiceLayout#name()</code> attribute will be ignored (there is only one effective menu).</p>
</div>
<div class="paragraph">
<p>For example, the <code>updateEpochDate(…)</code> and <code>listAllSettings(…)</code> actions come from the following service:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainServiceLayout</span>(
menuBar = DomainServiceLayout.MenuBar.TERTIARY,
menuOrder = <span class="string"><span class="delimiter">"</span><span class="content">10.1</span><span class="delimiter">"</span></span>
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">EstatioAdministrationService</span> ... {
<span class="annotation">@MemberOrder</span>(sequence = <span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="type">void</span> updateEpochDate( ... ) { ... }
<span class="annotation">@MemberOrder</span>(sequence = <span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> <span class="predefined-type">List</span><ApplicationSetting> listAllSettings() { ... }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>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 <em>not</em> place dividers between actions from different services on the tertiary menu.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_menubars-layout_file-based">4.2. File-based Menu Bars</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_menubars-layout_file-based.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The domain service actions can be arranged across menu items using the <code>menubars.layout.xml</code> file. Not only is this easier to work with, it also can be reloaded dynamically (if in prototype mode), substantially reducing the edit compile run cycle.</p>
</div>
<div class="paragraph">
<p>As for <a href="#_ugvw_layout_file-based">file-based object layouts</a>, this offers a number of benefits:</p>
</div>
<div class="ulist">
<ul>
<li> <p>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</p> </li>
<li> <p>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).</p> </li>
</ul>
</div>
<div class="paragraph">
<p>There are some disadvantages to using file-based layouts:</p>
</div>
<div class="ulist">
<ul>
<li> <p>file-based layouts are not typesafe: a typo will result in the metadata not being picked up for the element.</p> </li>
<li> <p>they also suffer from syntactic fragility: an invalid XML document will result in no metadata for the entire class.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The <code>menubars.layout.xml</code> file is just the serialized form of a <a href="../rgcms/rgcms.html#_rgcms_classes_layout"><code>MenuBars</code></a> 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.</p>
</div>
<div class="sect3">
<h4 id="_obtaining_an_initial_layout">4.2.1. Obtaining an initial layout</h4>
<div class="paragraph">
<p>An initial <code>menubars.layout.xml</code> - capturing any existing metadata either implicit or explicitly specified through annotations can be downloaded from the <a href="../rgsvc/rgsvc.html#_rgsvc_metadata-api_MenuBarsService"><code>MenuBarsService</code></a> (exposed on the prototyping menu):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images//menubars/010-download.png"><img src="images//menubars/010-download.png" alt="010 download" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>This action allows either the "Default" or the "Fallback" layout to be downloaded.</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images//menubars/020-download.png"><img src="images//menubars/020-download.png" alt="020 download" width="400px"></a>
</div>
</div>
<div class="paragraph">
<p>The "Default" layout is that currently in use, while the "Fallback" layout is that provided only from the annotations. Initially these are identical.</p>
</div>
<div class="paragraph">
<p>For example, here’s a fragment of that provided by the simpleapp archetype:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor"><?xml version="1.0" encoding="UTF-8" standalone="yes"?></span>
<span class="tag"><mb3:menuBars</span>
<span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">"</span><span class="content">...</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:cpt</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/component</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:lnk</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/links</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:mb3</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://isis.apache.org/applib/layout/menubars/bootstrap3</span><span class="delimiter">"</span></span>
<span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><mb3:primary></span>
<span class="tag"><mb3:menu></span>
<span class="tag"><mb3:named></span>Simple Objects<span class="tag"></mb3:named></span>
<span class="tag"><mb3:section></span>
<span class="tag"><mb3:serviceAction</span> <span class="attribute-name">objectType</span>=<span class="string"><span class="delimiter">"</span><span class="content">simple.SimpleObjectMenu</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">listAll</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><cpt:named></span>List All<span class="tag"></cpt:named></span>
<span class="tag"></mb3:serviceAction></span>
<span class="tag"><mb3:serviceAction</span> <span class="attribute-name">objectType</span>=<span class="string"><span class="delimiter">"</span><span class="content">simple.SimpleObjectMenu</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">findByName</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><cpt:named></span>Find By Name<span class="tag"></cpt:named></span>
<span class="tag"></mb3:serviceAction></span>
<span class="tag"><mb3:serviceAction</span> <span class="attribute-name">objectType</span>=<span class="string"><span class="delimiter">"</span><span class="content">simple.SimpleObjectMenu</span><span class="delimiter">"</span></span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">create</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><cpt:named></span>Create<span class="tag"></cpt:named></span>
<span class="tag"></mb3:serviceAction></span>
<span class="tag"></mb3:section></span>
<span class="tag"></mb3:menu></span>
<span class="tag"><mb3:menu</span> <span class="attribute-name">unreferencedActions</span>=<span class="string"><span class="delimiter">"</span><span class="content">true</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><mb3:named></span>Other<span class="tag"></mb3:named></span>
<span class="tag"></mb3:menu></span>
<span class="tag"></mb3:primary></span>
<span class="tag"><mb3:secondary></span>
<span class="tag"><mb3:menu></span>
<span class="tag"><mb3:named></span>Prototyping<span class="tag"></mb3:named></span>
...
<span class="tag"></mb3:secondary></span>
<span class="tag"><mb3:tertiary></span>
<span class="tag"><mb3:menu></span>
...
<span class="tag"></mb3:menu></span>
<span class="tag"></mb3:tertiary></span>
<span class="tag"></mb3:menuBars></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note the "Other" menu, with <code>unreferencedActions</code> attribute set to <code>true</code>. For a layout file to be valid there must be exactly one <code><menu></code> with this attribute set. Any domain service actions that are not explicitly listed will be placed under this menu.</p>
</div>
</div>
<div class="sect3">
<h4 id="_adjusting_the_layout">4.2.2. Adjusting the layout</h4>
<div class="paragraph">
<p>The downloaded <code>menubars.layout.xml</code> file can be adjusted as necessary, creating new menus and menu sections. Once done, it can be saved in the same package as the <code>AppManifest</code> used to bootstrap the application. Subsequently, the file is then parsed and used when the application is started.</p>
</div>
<div class="paragraph">
<p>If running in prototype mode, the file will be dynamically reloaded from the classpath.</p>
</div>
<div class="paragraph">
<p>Once the application has bootstrapped with a layout file, downloading the "Default" layout (from the prototyping menu) in essence just returns this file.</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>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.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ugvw_configuration-properties">5. Configuration Properties</h2>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sectionbody">
<div class="paragraph">
<p>Wicket configuration properties alter the way in which Apache Isis' Wicket viewer renders domain objects.</p>
</div>
<div class="sect2">
<h3 id="_loading_configuration_properties">5.1. Loading Configuration Properties</h3>
<div class="paragraph">
<p>Configuration properties are typically stored in <code>WEB-INF/isis.properties</code> or in <code>WEB-INF/viewer_wicket.properties</code>.</p>
</div>
<div class="paragraph">
<p>To tell Apache Isis that the Wicket viewer is in use (and should therefore search for the <code>viewer_wicket.properties</code> file), add the following to <code>WEB-INF/web.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><context-param></span>
<span class="tag"><param-name></span>isis.viewers<span class="tag"></param-name></span>
<span class="tag"><param-value></span>wicket<span class="tag"></param-value></span>
<span class="tag"></context-param></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively, because most of these configuration properties tend not to change between environment (development and production), another practice is to load them programmatically from the <code>AppManifest</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyAppAppManifest</span> <span class="directive">extends</span> AppManifestAbstract2 {
<span class="directive">public</span> <span class="directive">static</span> <span class="directive">final</span> Builder BUILDER = Builder
.forModule(<span class="keyword">new</span> MyApplicationModule())
...
.withConfigurationPropertiesFile(
MyAppManifest.class, <span class="string"><span class="delimiter">"</span><span class="content">isis-non-changing.properties</span><span class="delimiter">"</span></span>) ;
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <code>isis-non-changing.properties</code> is on the classpath in the same package as <code>MyAppAppManifest</code>.</p>
</div>
<div class="paragraph">
<p>Whichever approach is used, the configuration properties from all config files are merged together.</p>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_application">5.2. Application Identity</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_application.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_application.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_application.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_application.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_application.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Configuration properties that identify the application, in the sign-in page, welcome and about pages.</p>
</div>
<div class="paragraph">
<p>These also include top-level overrides for CSS and Javascript.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 2. Application Identity
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.about</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Apache Isis ™</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Label used on the about page.</p>
</div>
<div class="paragraph">
<p>If not specified, then <code>application.name</code> is used instead.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.</code><br> <code>brandLogoHeader</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Image URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Either the location of the image file (relative to <code>src/main/webapp</code>), or an absolute URL. This is rendered on the header panel.</p>
</div>
<div class="paragraph">
<p>An image with a size of 160x40 works well.</p>
</div>
<div class="paragraph">
<p>If not specified, the <code>application.name</code> is used instead.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.</code><br> <code>brandLogoSignin</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Image URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Either the location of the image file (relative to <code>src/main/webapp</code>), or an absolute URL. This is rendered on the sign-in page.</p>
</div>
<div class="paragraph">
<p>An image with a size of 400x40 works well.</p>
</div>
<div class="paragraph">
<p>If not specified, the <code>application.name</code> is used instead.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.css</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>scripts/application.css</code></p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>File to read any custom CSS, relative to <code>src/main/webapp</code> directory.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.js</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>scripts/application.js</code></p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>File to read any custom Javascript, relative to <code>src/main/webapp</code> directory.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.name</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Apache Isis ™</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Identifies the application on the sign-in page (unless a <code>brandLogoSignin</code> image is configured) and on top-left in the header (unless a <code>brandLogoHeader</code> image is configured).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>application.version</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">(none)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>The version of the application, eg <code>1.0</code>, <code>1.1</code>, or something more complex such as <code>20181115.2011.EST-1862.8d8e1c16</code>.</p>
</div>
<div class="paragraph">
<p>If present, then this will be shown in the footer on every page as well as on the about page.</p>
</div>
<div class="paragraph">
<p>See below for further discussion on this topic.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>welcome.file</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>welcome.html</code></p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Location of the HTML file (relative to <code>src/main/webapp</code>) whose contents should be displayed on the application’s home page.</p>
</div>
<div class="paragraph">
<p>Note though that if a <a href="../../guides/rgant/rgant.html#_rgant-HomePage">@HomePage</a> action exists, then that will take precedence.</p>
</div>
<div class="paragraph">
<p>If no welcome file exists, then the value of <code>welcome.text</code> is shown as a fallback.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>welcome.text</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Text to be displayed on the application’s home page, used as a fallback if <code>welcome.file</code> is not specified.</p>
</div>
<div class="paragraph">
<p>Note though that if a <a href="../../guides/rgant/rgant.html#_rgant-HomePage">@HomePage</a> action exists, then that will take precedence.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
<div class="sect3">
<h4 id="_application_versioning">5.2.1. Application versioning</h4>
<div class="paragraph">
<p>If the <code>isis.viewer.wicket.application.version</code> configuration property is present, then this will be shown in the footer on every page as well as on the about page.</p>
</div>
<div class="paragraph">
<p>However, maintaining this configuration property manually is likely to be error prone. An alternative approach is to configure your build system to generate a version identifier automatically.</p>
</div>
<div class="paragraph">
<p>For example, the version <code>20181115.2011.EST-1862.8d8e1c16</code> consists of four parts:</p>
</div>
<div class="ulist">
<ul>
<li> <p>the date of the build</p> </li>
<li> <p>the time of the build (to the nearest minute)</p> </li>
<li> <p>the branch</p> </li>
<li> <p>the git shaId</p> </li>
</ul>
</div>
<div class="paragraph">
<p>This can be computed using a simple script, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="bash">DATE=$(date +%Y%m%d.%H%M)
BRANCH=$(echo $GIT_BRANCH | sed 's|^rel/||g' | sed 's|[.]|_|g' | awk -F/ '{ print $NF }')
GIT_SHORT_COMMIT=$(echo $GIT_COMMIT | cut -c1-8)
REVISION=$DATE.$BRANCH.$GIT_SHORT_COMMIT</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <code>$GIT_BRANCH</code> and <code>$GIT_COMMIT</code> are provided by the CI server/build environment.</p>
</div>
<div class="paragraph">
<p>This environment variable can be passed into the (Maven) build using a system property, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="bash">mvn -Drevision=$REVISION clean install</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we provide a file <code>application-version.properties</code> is in the same package as the app manifest file, but in the <code>src/main/resources</code> directory:</p>
</div>
<div class="listingblock">
<div class="title">
application-version.properties
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.application.version=${revision}</code></pre>
</div>
</div>
<div class="paragraph">
<p>then Maven will automatically interpolate the actual revision when this file is copied over to the build (ie <code>target/classes</code>) directory.</p>
</div>
<div class="paragraph">
<p>Finally, this file can be loaded in the app manifest using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyAppManifest</span> <span class="directive">extends</span> AppManifestAbstract2 {
<span class="directive">public</span> <span class="directive">static</span> <span class="directive">final</span> AppManifestAbstract2.Builder BUILDER =
AppManifestAbstract2.Builder.forModule(<span class="keyword">new</span> MyApplicationModule())
.withConfigurationPropertiesFile(
MyAppManifest.class, <span class="string"><span class="delimiter">"</span><span class="content">application-version.properties</span><span class="delimiter">"</span></span>);
<span class="directive">public</span> MyAppManifest() {
<span class="local-variable">super</span>(BUILDER);
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_sign-in">5.3. Sign-in, Sign-up and Remember Me</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Configuration properties that influence the behaviour and appearance of the sign-in page.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 3. Sign-in, Sign-up and Remember Me
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>rememberMe.cookieKey</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ascii chars<br> (<code><em>isisWicketRememberMe</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Cookie key holding the (encrypted) 'rememberMe' user/password. There is generally no need to change this.</p>
</div>
<div class="paragraph">
<p>Valid values as per <a href="http://stackoverflow.com/a/1969339/56880">this StackOverflow answer</a>.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>rememberMe.encryptionKey</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">any string<br> (in prod, a random UUID each time)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Encryption key is used to encrypt the rememberMe user/password.</p>
</div>
<div class="paragraph">
<p>Apache Isis leverages <a href="http://wicket.apache.org">Apache Wicket</a>'s rememberMe support which holds remembered user/passwords in an encrypted cookie.</p>
</div>
<div class="paragraph">
<p>If a hard-coded and publicly known value were to be used (as was the case prior to <code>1.13.0</code>), then it would be possible for rememberMe user/password to be intercepted and decrypted, possibly compromising access. This configuration property therefore allows a private key to be specified, baked into the application.</p>
</div>
<div class="paragraph">
<p>If no value is set then, in production, a random UUID will be used as the encryption key. The net effect of this fallback behaviour is that 'rememberMe' will work, but only until the webapp is restarted (after which the end-user will have to log in again. In prototype mode, though, a fixed key will still be used; this saves the developer having to login each time.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>rememberMe.suppress</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to suppress "remember me" checkbox on the login page.</p>
</div>
<div class="paragraph">
<p>Further discussion <a href="#_ugvw_configuration-properties_sign-in_remember-me">below</a>.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>suppressPasswordReset</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>If user registration is enabled, whether to suppress the "password reset" link on the login page.</p>
</div>
<div class="paragraph">
<p>Further discussion <a href="#_ugvw_configuration-properties_sign-in_password-reset">below</a>.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>suppressRememberMe</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to suppress "remember me" checkbox on the login page.</p>
</div>
<div class="paragraph">
<p>Further discussion <a href="#_ugvw_configuration-properties_sign-in_remember-me">below</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>(Deprecated in <code>1.13.0</code>, replaced by <code>rememberMe.suppress</code>).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>suppressSignUp</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to suppress "sign-up" link.</p>
</div>
<div class="paragraph">
<p>Note though that user registration services must also be configured.</p>
</div>
<div class="paragraph">
<p>Further discussion <a href="#_ugvw_configuration-properties_sign-in_sign-up">below</a>.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
<div class="sect3">
<h4 id="_ugvw_configuration-properties_sign-in_remember-me">5.3.1. Remember Me</h4>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_remember-me.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_remember-me.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_remember-me.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_remember-me.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_remember-me.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>The 'remember me' checkbox on the login page can be suppressed, if required, by setting a configuration flag:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.rememberMe.suppress=true</code></pre>
</div>
</div>
<div class="paragraph">
<p>With 'remember me' not suppressed (the default):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-remember-me/login-page-default.png"><img src="images/suppress-remember-me/login-page-default.png" alt="login page default" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>and with the checkbox suppressed:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-remember-me/login-page-suppress-remember-me.png"><img src="images/suppress-remember-me/login-page-suppress-remember-me.png" alt="login page suppress remember me" width="300px"></a>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_ugvw_configuration-properties_sign-in_sign-up">5.3.2. Sign-up</h4>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_sign-up.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_sign-up.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_sign-up.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_sign-up.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_sign-up.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>If user registration has been configured, then the Wicket viewer allows the user to sign-up a new account and to reset their password from the login page.</p>
</div>
<div class="paragraph">
<p>The 'sign up' link can be suppressed, if required, by setting a configuration flag.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.suppressSignUp=true</code></pre>
</div>
</div>
<div class="paragraph">
<p>With 'sign up' not suppressed (the default):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-sign-up/login-page-default.png"><img src="images/suppress-sign-up/login-page-default.png" alt="login page default" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>and with the link suppressed:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-sign-up/login-page-suppress-sign-up.png"><img src="images/suppress-sign-up/login-page-suppress-sign-up.png" alt="login page suppress sign up" width="300px"></a>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_ugvw_configuration-properties_sign-in_password-reset">5.3.3. Password Reset</h4>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_password-reset.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_password-reset.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_password-reset.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_password-reset.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_sign-in_password-reset.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>If user registration has been configured, then the Wicket viewer allows the user to sign-up a new account and to reset their password from the login page.</p>
</div>
<div class="paragraph">
<p>The 'password reset' link can be suppressed, if required, by setting a configuration flag:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.suppressPasswordReset=true</code></pre>
</div>
</div>
<div class="paragraph">
<p>With 'password reset' not suppressed (the default):</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-password-reset/login-page-default.png"><img src="images/suppress-password-reset/login-page-default.png" alt="login page default" width="300px"></a>
</div>
</div>
<div class="paragraph">
<p>and with the link suppressed:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/suppress-password-reset/login-page-suppress-password-reset.png"><img src="images/suppress-password-reset/login-page-suppress-password-reset.png" alt="login page suppress password reset" width="300px"></a>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_header-and-footer">5.4. Header and Footer</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_header-and-footer.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_header-and-footer.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_header-and-footer.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_header-and-footer.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_header-and-footer.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>Configuration properties that influence the appearance of the header and footer panels.</p>
</div>
<div class="paragraph">
<p>See also the <a href="#_ugvw_configuration-properties_bookmarks-and-breadcrumbs">bookmarks and breadcrumbs</a> and <a href="#_ugvw_configuration-properties_themes
">themes</a> configuration properties, because these also control UI elements that appear on the header/footer panels.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 4. Header and Footer
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.1.image</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">File path</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>File path to a logo image for the first credited organisation, relative to <code>src/main/webapp</code> directory.</p>
</div>
<div class="paragraph">
<p>For example:<br> <code>/images/apache-isis/logo-48x48.png</code>.</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.1.name</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Name of the first credited organisation.</p>
</div>
<div class="paragraph">
<p>For example: "Apache Isis"</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.1.url</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>URL to the website of the first credited organisation.</p>
</div>
<div class="paragraph">
<p>For example:<br> <code><a href="http://isis.apache.org" class="bare">http://isis.apache.org</a></code>.</p>
</div>
<div class="paragraph">
<p>Optional.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.2.image</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">File path</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>File path to a logo image for the second credited organisation, relative to <code>src/main/webapp</code> directory.</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.2.name</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Name of the second credited organisation.</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.2.url</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>URL to the website of the second credited organisation.</p>
</div>
<div class="paragraph">
<p>Optional.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.3.image</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">File path</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>File path to a logo image for the third credited organisation, relative to <code>src/main/webapp</code> directory.</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.3.name</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Name of the third credited organisation.</p>
</div>
<div class="paragraph">
<p>Either/both of <code>name</code> and <code>image</code> must be defined for the credit to be rendered in the footer.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.+</code> <code>credit.3.url</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>URL to the website of the third credited organisation.</p>
</div>
<div class="paragraph">
<p>Optional.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_presentation">5.5. Presentation</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_presentation.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_presentation.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_presentation.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_presentation.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_presentation.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties that effect the overall presentation and appearance of the viewer.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Some of the properties below use the prefix <code>isis.viewers.</code> (rather than the usual <code>isis.viewer.wicket.</code>).</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 5. Presentation
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (default value)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewers.</code><br> <code>collectionLayout.</code><br> <code>defaultView</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hidden</code>, <code>table</code><br> (<code>hidden</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Default for the default view for all (parented) collections if not explicitly specified using <a href="../rgant/rgant.html#_rgant-CollectionLayout_defaultView"><code>@CollectionLayout#defaultView()</code></a></p>
</div>
<div class="paragraph">
<p>By default the framework renders (parented) collections as "hidden", ie collapsed. These can be overridden on a case-by-case basis using the <a href="../rgant/rgant.html#_rgant-CollectionLayout_defaultView"><code>@CollectionLayout#defaultView()</code></a> or the corresponding <code><collectionLayout defaultView="…"></code> element in the <code>Xxx.layout.xml</code> layout file.</p>
</div>
<div class="paragraph">
<p>If the majority of collections should be displayed as "table" form, then it is more convenient to specify the default view globally.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewers.</code><br> <code>paged.parented</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">positive integer (12)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Default page size for parented collections (as owned by an object, eg <code>Customer#getOrders()</code>)</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewers.</code><br> <code>paged.standalone</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">positive integer (25)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Default page size for standalone collections (as returned from an action invocation)</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewers.</code><br> <code>propertyLayout.</code><br> <code>labelPosition</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>TOP</code>, <code>LEFT</code><br> (<code>LEFT</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Default for label position for all properties if not explicitly specified using <a href="../rgant/rgant.html#_rgant-PropertyLayout_labelPosition"><code>@PropertyLayout#labelPosition()</code></a></p>
</div>
<div class="paragraph">
<p>If you want a consistent look-n-feel throughout the app, eg all property labels to the top, then it’d be rather frustrating to have to annotate every property.</p>
</div>
<div class="paragraph">
<p>If these are not present then Apache Isis will render according to internal defaults. At the time of writing, this means labels are to the left for all datatypes except multiline strings.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>maxTitleLength</code><br> <code>InParentedTables</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ve integer<br> (<code><em>12</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>See further discussion (immediately below).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>maxTitleLength</code><br> <code>InStandaloneTables</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ve integer,<br> (<code><em>12</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>See further discussion (immediately below).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>maxTitleLengthInTables</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ve integer,<br> (<code><em>12</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>See further discussion (immediately below).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>promptStyle</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>dialog</code>,<code>inline</code>,<br> <code>inline_as_if_edit</code><br> (<code>inline</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>whether the prompt for editing a domain object property or invoking an action (associated with a property) is shown inline within the property’s form, or instead shown in a modal dialog box. For actions, <code>inline_as_if_edit</code> will suppress the action’s button, and instead let the action be invoked as if editing the property. The net effect is that being able to "edit" complex properties with multiple parts (eg a date) using a multi-argument editor (this editor, in fact, being the action’s argument panel).</p>
</div>
<div class="paragraph">
<p>The property can be overridden on a property-by-property basis using <a href="../rgant/rgant.html#_rgant-PropertyLayout_promptStyle"><code>@Property#promptStyle()</code></a>) or <a href="../rgant/rgant.html#_rgant-ActionLayout_promptStyle"><code>@Action#promptStyle()</code></a>).</p>
</div>
<div class="paragraph">
<p>Note that <code>inline_as_if_edit</code> does not make sense for a configuration property default, and will instead be interpreted as <code>inline</code>.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>dialogMode</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sidebar</code>,<code>modal</code><br> (<code><em>sidebar</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether action prompts with a style of <code>DIALOG</code> - as in, <code>@ActionLayout(promptStyle="DIALOG")</code> - should be rendered using a sidebar or alternatively in a modal dialog box.</p>
</div>
<div class="paragraph">
<p>See the discussion on the <a href="../ugvw/ugvw.html#_ugvw_features_sidebar-vs-modal-dialogs">sidebar vs modal dialogs</a> feature for further details.</p>
</div>
<div class="paragraph">
<p>p</p>
</div>
</div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Objects whose title is overly long can be cumbersome in titles. The Wicket viewer has a <a href="../ugvw/ugvw.html#_ugvw_features_titles-in-tables">mechanism to automatically shorten</a> the titles of objects specified using <code>@Title</code>. As an alternative/in addition, the viewer can also be configured to simply truncate titles longer than a certain length.</p>
</div>
<div class="paragraph">
<p>The properties themselves are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.maxTitleLengthInStandaloneTables=20
isis.viewer.wicket.maxTitleLengthInParentedTables=8</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you wish to use the same value in both cases, you can also specify just:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.maxTitleLengthInTables=15</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is used as a fallback if the more specific properties are not provided.</p>
</div>
<div class="paragraph">
<p>If no properties are provided, then the Wicket viewer defaults to abbreviating titles to a length of <code>12</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_bookmarks-and-breadcrumbs">5.6. Bookmarks and Breadcrumbs</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_bookmarks-and-breadcrumbs.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_bookmarks-and-breadcrumbs.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_bookmarks-and-breadcrumbs.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_bookmarks-and-breadcrumbs.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_bookmarks-and-breadcrumbs.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties enable or disable the mechanisms for locating previously accessed objects.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 6. Bookmarks and Breadcrumbs
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>bookmarkedPages.maxSize</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ve int<br> (<code><em>15</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>number of pages to bookmark</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>bookmarkedPages.showChooser</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ve int<br> (<code><em>15</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>whether to show the bookmark panel (top-left in the Wicket viewer)</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>breadcrumbs.showChooser</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to show chooser for Breadcrumbs (bottom-left footer in the Wicket viewer)</p>
</div>
</div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_themes">5.7. Themes</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_themes.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_themes.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_themes.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_themes.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_themes.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties control the switching of themes.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 7. Themes
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (default value)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>themes.enabled</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">comma separated list …</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>... of bootswatch themes. Only applies if <code>themes.showChooser</code>==<code>true</code>.</p>
</div>
<div class="paragraph">
<p>See further discussion below.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>themes.initial</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">theme name</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Which theme to show initially.</p>
</div>
<div class="paragraph">
<p>See further discussion below.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>themes.showChooser</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to show chooser for Bootstrap themes.</p>
</div>
<div class="paragraph">
<p>See further discussion below.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The Wicket viewer uses <a href="http://getbootstrap.com/">Bootstrap</a> styles and components (courtesy of the <a href="https://github.com/l0rdn1kk0n/wicket-bootstrap">Wicket Bootstrap</a> integration).</p>
</div>
<div class="paragraph">
<p>By default the viewer uses the "Flatly" theme from <a href="http://bootswatch.com">bootswatch.com</a>. This can be overridden using the following configuration property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.themes.initial=Darky</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>Set this configuration property to different values for different environments (dev, test, prod) so you can know at a glance which environment you are connected to.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>The end-user can also be given the choice of changing the theme:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.themes.showChooser=true</code></pre>
</div>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/theme-chooser/example-1.png"><img src="images/theme-chooser/example-1.png" alt="example 1" width="720px"></a>
</div>
<div class="title">
Figure 1. Example 1
</div>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/theme-chooser/example-2.png"><img src="images/theme-chooser/example-2.png" alt="example 2" width="720px"></a>
</div>
<div class="title">
Figure 2. Example 2:
</div>
</div>
<div class="paragraph">
<p>It is also possible to restrict the themes shown to some subset of those in bootswatch. This is done using a further property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.viewer.wicket.themes.enabled=bootstrap-theme,Cosmo,Flatly,Darkly,Sandstone,United</code></pre>
</div>
</div>
<div class="paragraph">
<p>where the value is the list of themes (from <a href="http://bootswatch.com">bootswatch.com</a>) to be made available.</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td>
<td class="content">
<div class="paragraph">
<p>You can also develop and install a custom themes (eg to fit your company’s look-n-feel/interface guidelines); see the <a href="../ugvw/ugvw.html#_ugvw_extending_custom-bootstrap-theme">Extending</a> chapter for further details.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_date-formatting">5.8. Date Formatting & Date Picker</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_date-formatting.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_date-formatting.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_date-formatting.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_date-formatting.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_date-formatting.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties influence the way in which date/times are rendered and can be selected using the date/time pickers.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 8. Date Formatting & Date Picker
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>datePattern</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">date format<br> (<code>dd-MM-yyyy</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>The <code>SimpleDateFormat</code> used to render dates. For the date picker (which uses <code>moment.js</code> library), this is converted dynamically into the corresponding <code>moment.js</code> format.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>dateTimePattern</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">date/time format<br> (<code>dd-MM-yyyy HH:mm</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>The <code>SimpleDateFormat</code> used to render date/times. For the date picker (which uses <code>moment.js</code> library), this is converted dynamically into the corresponding <code>moment.js</code> format.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>datePicker.maxDate</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ISO format date<br> (<code>2100-01-01T00:00:00.000Z</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Specifies a maximum date after which dates may not be specified.</p>
</div>
<div class="paragraph">
<p>See <a href="http://eonasdan.github.io/bootstrap-datetimepicker/Options/#maxdate">datetimepicker reference docs</a> for further details. The string must be in ISO date format (see <a href="https://github.com/moment/moment/issues/1407">here</a> for further details).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>datePicker.minDate</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ISO format date<br> (<code>1900-01-01T00:00:00.000Z</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Specifies a minimum date before which dates may not be specified.</p>
</div>
<div class="paragraph">
<p>See <a href="http://eonasdan.github.io/bootstrap-datetimepicker/Options/#mindate">datetimepicker reference docs</a> for further details. The string must be in ISO date format (see <a href="https://github.com/moment/moment/issues/1407">here</a> for further details).</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>timestampPattern</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">date/time format<br> (<code>yyyy-MM-dd HH:mm:ss.SSS</code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>The <code>SimpleDateFormat</code> used to render timestamps.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_debugging">5.9. Debugging</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_debugging.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_debugging.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_debugging.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_debugging.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_debugging.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties can assist with debugging the behaviour of the Wicket viewer itself.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 9. Debugging
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>ajaxDebugMode</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>whether the Wicket debug mode should be enabled.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>developmentUtilities.enable</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>when running in production mode, whether to show enable the Wicket development utilities anyway. From a UI perspective, this will cause the DebugBar to be shown (top-right).</p>
</div>
<div class="paragraph">
<p>If running in prototyping mode, the development utilities (debug bar) is always enabled. This feature is primarily just to help track any memory leakage issues that might be suspected when running in production.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>liveReloadUrl</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">URL</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Specifies the URL if <a href="../dg/dg.html#__dg_ide_intellij_advanced_gradle-liveReload">live reload</a> is set up, eg:<br></p>
</div>
<div class="paragraph">
<p><code><a href="http://localhost:35729/livereload.js?snipver=1" class="bare">http://localhost:35729/livereload.js?snipver=1</a></code></p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>stripWicketTags</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to force Wicket tags to be stripped in prototype/development mode.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>In 1.7.0 and earlier, the behaviour is different; the Apache Isis Wicket viewer will preserve wicket tags when running in Apache Isis' prototype/development mode, but will still strip wicket tags in Apache Isis' server/deployment mode.</p>
</div>
<div class="paragraph">
<p>We changed the behaviour in 1.8.0 because we found that Internet Explorer can be sensitive to the presence of Wicket tags.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>wicketSourcePlugin</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether the WicketSource plugin should be enabled; by default it is not enabled.</p>
</div>
<div class="admonitionblock warning">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-warning" title="Warning"></i> </td>
<td class="content">
<div class="paragraph">
<p>Enabling this setting can significantly slow down rendering performance of the Wicket viewer.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_ugvw_configuration-properties_feature-toggles">5.10. Feature Toggles</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_feature-toggles.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_feature-toggles.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_feature-toggles.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_feature-toggles.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_configuration-properties_feature-toggles.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>These configuration properties are used to enable/disable features that are either on the way to becoming the default behaviour (but can temporarily be disabled) or conversely for features that are to be removed (but can temporarily be left as enabled).</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 10. Feature Toggles
</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 16.6666%;">
<col style="width: 50.0001%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property</th>
<th class="tableblock halign-left valign-top">Value<br> (<em>default value</em>)</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>disableDependent</code><br> <code>ChoiceAutoSelection</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>For dependent choices, whether to automatically select the first dependent (eg subcategory) when the parameter on which it depends (category) changes.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>disableModalDialogs</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>No longer supported.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>preventDoubleClick</code><br> <code>ForFormSubmit</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to disable a form submit button after it has been clicked, to prevent users causing an error if they do a double click.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>preventDoubleClick</code><br> <code>ForNoArgAction</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to disable a no-arg action button after it has been clicked, to prevent users causing an error if they do a double click.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>redirectEvenIfSameObject</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>By default, an action invocation that returns the same object will result in the page being updated. The same is true for property edits.</p>
</div>
<div class="paragraph">
<p>If this setting is enabled, then the viewer will always render to a new page.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa icon-note" title="Note"></i> </td>
<td class="content">
<div class="paragraph">
<p>Note that the default behaviour is new in <code>1.15.0</code>, providing a better end-user experience. Setting this option retains the behaviour of the viewer pre-<code>1.15.0</code>.</p>
</div> </td>
</tr>
</tbody>
</table>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>regularCase</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>false</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Ignored for 1.8.0+; in earlier versions forced regular case rather than title case in the UI</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>replaceDisabledTag</code>-<br> <code>WithReadonlyTag</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to replace 'disabled' tag with 'readonly' (for <a href="https://www.w3.org/TR/2014/REC-html5-20141028/forms.html#the-readonly-attribute">w3 spec</a>-compliant browsers such as for Firefox and Chrome 54+) which prevent copy from 'disabled' fields.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>useIndicatorForFormSubmit</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to show an indicator for a form submit button that it has been clicked.</p>
</div>
</div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p><code>isis.viewer.wicket.</code><br> <code>useIndicatorForNoArgAction</code></p>
</div>
</div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code>,<code>false</code><br> (<code><em>true</em></code>)</p></td>
<td class="tableblock halign-left valign-top">
<div>
<div class="paragraph">
<p>Whether to show an indicator for a no-arg action button that it has been clicked.</p>
</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ugvw_customisation">6. Customisation</h2>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="sectionbody">
<div class="sect2">
<h3 id="_ugvw_customisation_top-level-index-page">6.1. Top-level Index Page</h3>
<div class="btn-group" style="float: right; font-size: small; padding: 6px; margin-top: -55px; ">
<button type="button" class="btn btn-xs btn-default" onclick="window.location.href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation_top-level-index-page.adoc""><i class="fa fa-pencil-square-o"></i> Edit</button>
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/isis/edit/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation_top-level-index-page.adoc" target="_blank"><i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> Edit</a></li>
<li><a href="https://github.com/apache/isis/commits/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation_top-level-index-page.adoc" target="_blank"><i class="fa fa-clock-o fa-fw" aria-hidden="true"></i> History</a></li>
<li><a href="https://github.com/apache/isis/raw/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation_top-level-index-page.adoc" target="_blank"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i> Raw</a></li>
<li><a href="https://github.com/apache/isis/blame/master/adocs/documentation/src/main/asciidoc/guides/ugvw/_ugvw_customisation_top-level-index-page.adoc" target="_blank"><i class="fa fa-hand-o-right fa-fw" aria-hidden="true"></i> Blame</a></li>
</ul>
</div>
<div class="paragraph">
<p>If the user visits the root of the webapp (eg <a href="http://localhost:8080" class="bare">http://localhost:8080</a>), then a top-level index page can specified. This is a static file that typically has hyperlinks to the available resources available (eg the Wicket viewer at <code>/wicket/</code>, the Swagger UI is bound to <code>/swagger-ui</code>, the Restful at <code>/restful/</code>).</p>
</div>
<div class="paragraph">
<p>The archetypes provide an example in the <code>about/index.html</code> file (relative to <code>src/main/webapp</code>). This is configured using the <code>web.xml</code>:</p>
</div>
<div class="listingblock">
<div class="title">
web.xml
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><welcome-file-list></span>
<span class="tag"><welcome-file></span>about/index.html<span class="tag"></welcome-file></span>
<span class="tag"></welcome-file-list></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If instead you want to redirect users directly to the Wicket viewer, then this file should contain simply:</p>
</div>
<div class="listingblock">
<div class="title">
about/index.html
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="html"><span class="tag"><html></span>
<span class="tag"><head></span>
<span class="tag"><META</span> <span class="attribute-name">HTTP-EQUIV</span>=<span class="string"><span class="delimiter">"</span><span class="content">Refresh</span><span class="delimiter">"</span></span> <span class="attribute-name">CONTENT</span>=<span class="string"><span class="delimiter">"</span><span class="content">0; URL=wicket/</span><span class="delimiter">"</span></span><span class="tag">/></span>
<span class="tag"></head></span>
<span class="tag"></html></span></code></pre>
</div>
</div>
<div class="exampleblock">
<div class="content">
<div id="_ugvw_customisation_brand-logo" class="paragraph">
<p>= Brand logo :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>By default the Wicket viewer will display the application name top-left in the header menu. This can be changed to display a png logo instead.</p>
</div>
<div class="paragraph">
<p>== Screenshots</p>
</div>
<div class="paragraph">
<p>The screenshot below shows the Isis addons example <a href="https://github.com/isisaddons/isis-app-todoapp/">todoapp</a> (not ASF) with a 'brand logo' image in its header:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/brand-logo/brand-logo.png"><img src="images/brand-logo/brand-logo.png" alt="brand logo" width="750px"></a>
</div>
</div>
<div class="paragraph">
<p>A custom brand logo (typically larger) can also be specified for the signin page:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/brand-logo/brand-logo-signin.png"><img src="images/brand-logo/brand-logo-signin.png" alt="brand logo signin" width="750px"></a>
</div>
</div>
<div class="paragraph">
<p>To configure, simply specify the appropriate configuration properties:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">isis.wicket.viewer.application.brandLogoSignin=/images/todoapp-logo-signin.png
isis.wicket.viewer.application.brandLogoHeader=/images/todoapp-logo-header.png</code></pre>
</div>
</div>
<div class="paragraph">
<p>These are resolved relative to <code>src/main/webapp</code>, or an absolute URL can be specified.</p>
</div>
<div class="ulist">
<ul>
<li> <p>for the signin image, a size of 400x100 works well.</p> </li>
<li> <p>for the header image, a size of 160x40 works well.</p> </li>
</ul>
</div>
<div class="paragraph">
<p>You may also wish to tweak the <a href="../rgcfg/rgcfg.html#_rgcfg_application-specific_application-css"><code>application.css</code></a>. For example, a logo with height 40px works well with the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.navbar-brand</span> <span class="tag">img</span> {
<span class="key">margin-top</span>: <span class="float">-5px</span>;
<span class="key">margin-left</span>: <span class="float">5px</span>;
}</code></pre>
</div>
</div>
<div id="_ugvw_customisation_welcome-page" class="paragraph">
<p>= Welcome page :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>It’s possible to customize the application name, welcome message (as displayed on the home page if not home page service is configured) and the about message can all be customized. This is done by specifying the appropriate configuration properties:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">isis.viewer.wicket.application.name=My Wonderful App
isis.viewer.wicket.welcome.file=welcome.html
isis.viewer.wicket.application.about=My Wonderful App v1.0</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>the <code>welcome.html</code> file is resolved relative to <code>src/main/webapp</code>.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="paragraph">
<p>Do not confuse the welcome page file with the <a href="#_ugvw_customisation_top-level-index-page">top-level index page</a>; they are different things!</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>The <code>application.name</code> is used both on the sign-in page and also top-left on the header. It’s also possible to replace this text with images:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">isis.viewer.wicket.application.brandLogoSignin=/images/logo-512.png
isis.viewer.wicket.application.brandLogoHeader=/images/logo-80x32.png</code></pre>
</div>
</div>
<div class="paragraph">
<p>These images are resolved relative to <code>src/main/webapp</code>.</p>
</div>
<div id="_ugvw_customisation_about-page" class="paragraph">
<p>= About page :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>Isis' Wicket viewer has an About page that, by default, will provide a dump of the JARs that make up the webapp. This page will also show the manifest attributes of the WAR archive itself, if there are any. One of these attributes may also be used as the application version number.</p>
</div>
<div class="paragraph">
<p>== Screenshot</p>
</div>
<div class="paragraph">
<p>Here’s what the About page looks like with this configuration added:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/about-page/about-page.png"><img src="images/about-page/about-page.png" alt="about page" width="800px"></a>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Note that this screenshot shows an earlier version of the <a href="../ugvw/ugvw.html">Wicket viewer</a> UI (specifically, pre 1.8.0).</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>Note that the <code>Build-Time</code> attribute has been used as the version number. The Wicket viewer is hard-coded to search for specific attributes and use as the application version. In order, it searches for:</p>
</div>
<div class="ulist">
<ul>
<li> <p><code>Implementation-Version</code></p> </li>
<li> <p><code>Build-Time</code></p> </li>
</ul>
</div>
<div class="paragraph">
<p>If none of these are found, then no version is displayed.</p>
</div>
<div class="paragraph">
<p>== Configuration</p>
</div>
<div class="paragraph">
<p>=== Adding attributes to the WAR’s manifest</p>
</div>
<div class="paragraph">
<p>Add the following to the webapp’s <code>pom.xml</code> (under <code><build>/<plugins></code>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><plugin></span>
<span class="tag"><groupId></span>org.codehaus.mojo<span class="tag"></groupId></span>
<span class="tag"><artifactId></span>build-helper-maven-plugin<span class="tag"></artifactId></span>
<span class="tag"><version></span>1.5<span class="tag"></version></span>
<span class="tag"><executions></span>
<span class="tag"><execution></span>
<span class="tag"><phase></span>validate<span class="tag"></phase></span>
<span class="tag"><goals></span>
<span class="tag"><goal></span>maven-version<span class="tag"></goal></span>
<span class="tag"></goals></span>
<span class="tag"></execution></span>
<span class="tag"></executions></span>
<span class="tag"></plugin></span>
<span class="tag"><plugin></span>
<span class="tag"><artifactId></span>maven-war-plugin<span class="tag"></artifactId></span>
<span class="tag"><configuration></span>
<span class="tag"><archive></span>
<span class="tag"><manifest></span>
<span class="tag"><addDefaultImplementationEntries></span>true<span class="tag"></addDefaultImplementationEntries></span>
<span class="tag"></manifest></span>
<span class="tag"><manifestEntries></span>
<span class="tag"><Build-Time></span>${maven.build.timestamp}<span class="tag"></Build-Time></span>
<span class="tag"><Build-Number></span>${buildNumber}<span class="tag"></Build-Number></span>
<span class="tag"><Build-Host></span>${agent.name}<span class="tag"></Build-Host></span>
<span class="tag"><Build-User></span>${user.name}<span class="tag"></Build-User></span>
<span class="tag"><Build-Maven></span>Maven ${maven.version}<span class="tag"></Build-Maven></span>
<span class="tag"><Build-Java></span>${java.version}<span class="tag"></Build-Java></span>
<span class="tag"><Build-OS></span>${os.name}<span class="tag"></Build-OS></span>
<span class="tag"><Build-Label></span>${project.version}<span class="tag"></Build-Label></span>
<span class="tag"></manifestEntries></span>
<span class="tag"></archive></span>
<span class="tag"></configuration></span>
<span class="tag"><executions></span>
<span class="tag"><execution></span>
<span class="tag"><phase></span>package<span class="tag"></phase></span>
<span class="tag"><goals></span>
<span class="tag"><goal></span>war<span class="tag"></goal></span>
<span class="tag"></goals></span>
<span class="tag"><configuration></span>
<span class="tag"><classifier></span>${env}<span class="tag"></classifier></span>
<span class="tag"></configuration></span>
<span class="tag"></execution></span>
<span class="tag"></executions></span>
<span class="tag"></plugin></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If you then build the webapp from the Maven command line (<code>mvn clean package</code>), then the WAR should contain a <code>META-INF/MANIFEST.MF</code> with those various attribute entries. This will be picked up automatically and used in the about page.</p>
</div>
<div id="_ugvw_customisation_tweaking-css-classes" class="paragraph">
<p>= Tweaking CSS classes :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The HTML generated by the Wicket viewer include plenty of CSS classes so that you can easily target the required elements as required. For example, you could use CSS to suppress the entity’s icon alongside its title. This would be done using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.entityIconAndTitlePanel</span> <span class="tag">a</span> <span class="tag">img</span> {
<span class="key">display</span>: <span class="value">none</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>These customizations should generally be added to <a href="../rgcfg/rgcfg.html#_rgcfg_application-specific_application-css"><code>application.css</code></a>; this file is included by default in every webpage served up by the Wicket viewer.</p>
</div>
<div class="paragraph">
<p>== Individual members</p>
</div>
<div class="paragraph">
<p>For example, the <code>ToDoItem</code> object of the Isis addons example <a href="https://github.com/isisaddons/isis-app-todoapp/">todoapp</a> (not ASF) has a <code>notes</code> property. The HTML for this will be something like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="html"><span class="tag"><div></span>
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">property ToDoItem-notes</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">multiLineStringPanel scalarNameAndValueComponentType</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><label</span> <span class="attribute-name">for</span>=<span class="string"><span class="delimiter">"</span><span class="content">id83</span><span class="delimiter">"</span></span> <span class="attribute-name">title</span>=<span class="string"><span class="delimiter">"</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><span</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">scalarName</span><span class="delimiter">"</span></span><span class="tag">></span>Notes<span class="tag"></span></span>
<span class="tag"><span</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">scalarValue</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><textarea</span>
<span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">middleColumn:memberGroup:1:properties:4:property:scalarIfRegular:scalarValue</span><span class="delimiter">"</span></span>
<span class="attribute-name">disabled</span>=<span class="string"><span class="delimiter">"</span><span class="content">disabled</span><span class="delimiter">"</span></span>
<span class="attribute-name">id</span>=<span class="string"><span class="delimiter">"</span><span class="content">id83</span><span class="delimiter">"</span></span> <span class="attribute-name">rows</span>=<span class="string"><span class="delimiter">"</span><span class="content">5</span><span class="delimiter">"</span></span> <span class="attribute-name">maxlength</span>=<span class="string"><span class="delimiter">"</span><span class="content">400</span><span class="delimiter">"</span></span> <span class="attribute-name">size</span>=<span class="string"><span class="delimiter">"</span><span class="content">125</span><span class="delimiter">"</span></span>
<span class="attribute-name">title</span>=<span class="string"><span class="delimiter">"</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"></textarea></span>
<span class="tag"><span></span>
<span class="tag"></label></span>
<span class="tag"></div></span>
<span class="tag"></div></span>
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <a href="../rgcfg/rgcfg.html#_rgcfg_application-specific_application-css"><code>application.css</code></a> file is the place to add application-specific styles. By way of an example, if (for some reason) we wanted to completely hide the notes value, we could do so using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="tag">div</span><span class="class">.ToDoItem-notes</span> <span class="tag">span</span><span class="class">.scalarValue</span> {
<span class="key">display</span>: <span class="value">none</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can use a similar approach for collections and actions.</p>
</div>
<div class="paragraph">
<p>== Custom CSS styles</p>
</div>
<div class="paragraph">
<p>The above technique works well if you know the class member to target, but you might instead want to apply a custom style to a set of members. For this, you can use the <code>@PropertyLayout(cssClass=…)</code>.</p>
</div>
<div class="paragraph">
<p>For example, in the <code>ToDoItem</code> class the following annotation (indicating that this is a key, important, property) :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@PropertyLayout</span>(cssClass=<span class="string"><span class="delimiter">"</span><span class="content">x-myapp-highlight</span><span class="delimiter">"</span></span>)
<span class="directive">public</span> LocalDate getDueBy() {
<span class="keyword">return</span> dueBy;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>would generate the HTML:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="html"><span class="tag"><div></span>
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">property ToDoItem-dueBy x-myapp-highlight</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"></div></span>
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This can then be targeted, for example using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="tag">div</span><span class="class">.x-myapp-highlight</span> <span class="tag">span</span><span class="class">.scalarName</span> {
<span class="key">color</span>: <span class="value">red</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note also that instead of using <code>@PropertyLayout(cssClass=…)</code> annotation, you can also specify the CSS style using a <a href="../ugvw/ugvw.html#_ugvw_layout_file-based">layout file</a>.</p>
</div>
<div id="__ugvw_customisation_tweaking-css-classes_columns-in-tables" class="paragraph">
<p>== Table columns</p>
</div>
<div class="paragraph">
<p>Sometimes you may want to apply styling to specific columns of tables. For example, you might want to adjust width so that for certain properties have more (or less) room than they otherwise would; or you might want to hide the column completely. This also applies to the initial icon/title column.</p>
</div>
<div class="paragraph">
<p>There is also the issue of scoping:</p>
</div>
<div class="ulist">
<ul>
<li> <p>You may wish the style to apply globally: that is, dependent on the type of entity being rendered in the table, irrespective of the page on which it is shown.</p> </li>
<li> <p>Alternativel, you may wish to target the CSS for a table as rendered either as a parented collection (owned by some other entity) or rendered as a standarlone collection (the result of invoking an action).</p> </li>
</ul>
</div>
<div class="paragraph">
<p>In each of these cases the Wicket viewer adds CSS classes either to containing <code>div</code>s or to the <code><th></code> and <code><td></code> elements of the table itself so that it can custom styles can be appropriately targetted.</p>
</div>
<div id="__ugvw_customisation_tweaking-css-classes_columns-in-tables_globally" class="paragraph">
<p>=== Applying styles globally</p>
</div>
<div class="paragraph">
<p>Every rendered collection containing a domain class will be wrapped in a <code><div></code> that lists that domain class (in CSS safe form). For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">entityCollection com-mycompany-myapp-Customer</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"><table></span>
<span class="tag"><tr></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">firstName</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">lastName</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
...
<span class="tag"></tr></span>
<span class="tag"><tr></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">firstName</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">lastName</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
...
<span class="tag"></tr></span>
...
<span class="tag"></table></span>
...
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Using this, the <code>lastName</code> property could be targeted using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.com-mycompany-myapp-Customer</span> <span class="tag">th</span><span class="class">.lastName</span> {
<span class="key">width</span>: <span class="float">30%</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>=== Parented collections</p>
</div>
<div class="paragraph">
<p>Parented collections will be wrapped in <code><div></code>s that identify both the entity type and also the collection Id. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">entityPage com-mycompany-myapp-Customer</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="1"></i><b>(1)</b>
...
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">orders</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag"><table></span>
<span class="tag"><tr></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">productRef</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">quantity</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
...
<span class="tag"></tr></span>
<span class="tag"><tr></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">productRef</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">quantity</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
...
<span class="tag"></tr></span>
...
<span class="tag"></table></span>
...
<span class="tag"></div></span>
...
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>the parent class identifier</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>the collection identifier. This element’s class also has the entity type within the collection (as <a href="../ugvw/ugvw.html#__ugvw_customisation_tweaking-css-classes_columns-in-tables_globally">discussed above</a>).</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>Using this, the <code>productRef</code> property could be targeted using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.com-mycompany-myapp-Customer</span> <span class="tag">orders</span> <span class="tag">td</span><span class="class">.productRef</span> {
<span class="key">font-style</span>: <span class="value">italic</span>;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>=== Standalone collections</p>
</div>
<div class="paragraph">
<p>Standalone collections will be wrapped in a <code><div></code> that identifies the action invoked. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">standaloneCollectionPage</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">com-mycompany-myapp-Customer_mostRecentOrders ...</span><span class="delimiter">"</span></span><span class="tag">></span> <i class="conum" data-value="1"></i><b>(1)</b>
...
<span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">orders</span><span class="delimiter">"</span></span><span class="tag">></span>
<span class="tag"><table></span>
<span class="tag"><tr></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">productRef</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
<span class="tag"><th</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">quantity</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></th></span>
...
<span class="tag"></tr></span>
<span class="tag"><tr></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">title-column</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">productRef</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
<span class="tag"><td</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">quantity</span><span class="delimiter">"</span></span><span class="tag">></span>...<span class="tag"></td></span>
...
<span class="tag"></tr></span>
...
<span class="tag"></table></span>
...
<span class="tag"></div></span>
...
<span class="tag"></div></span>
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>action identifier. This element’s class also identifies the entity type within the collection (as <a href="../ugvw/ugvw.html#__ugvw_customisation_tweaking-css-classes_columns-in-tables_globally">discussed above</a>).</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>Using this, the <code>quantity</code> property could be targeted using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.com-mycompany-myapp-Customer_mostRecentOrders</span> <span class="tag">td</span><span class="class">.quantity</span> {
<span class="key">font-weight</span>: <span class="value">bold</span>;
}</code></pre>
</div>
</div>
<div id="_ugvw_customisation_cheap-n-cheerful-theme" class="paragraph">
<p>= Cheap-n-cheerful theme :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The application name (as defined by <code>isis.viewer.wicket.application.name</code> configuration property) is also used (in sanitized form) as the CSS class in a <code><div></code> that wraps all the rendered content of every page.</p>
</div>
<div class="paragraph">
<p>For example, if the application name is "ToDo App", then the <code><div></code> generated is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="html"><span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">"</span><span class="content">todo-app</span><span class="delimiter">"</span></span><span class="tag">></span>
...
<span class="tag"></div></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You can therefore use this CSS class as a way of building your own "theme" for the various elements of the wicket viewer pages.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>Alternatively you could "do it properly" and create your <a href="../ugvw/ugvw.html#_ugvw_extending_custom-bootstrap-theme">own Bootstrap theme</a>, as described in the <a href="../ugbtb/ugbtb.html">Extending</a> chapter.</p>
</div>
<div class="exampleblock">
<div class="content">
<div id="_ugvw_customisation_using-different-css-file" class="paragraph">
<p>= Using a different CSS file :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>If for some reason you wanted to name the CSS file differently (eg <code>stylesheets/myapp.css</code>), then just specify the appropriate configuration property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">isis.viewer.wicket.application.css=stylesheets/myapp.css</code></pre>
</div>
</div>
<div class="paragraph">
<p>This file is resolved relative to <code>src/main/webapp</code>.</p>
</div>
<div id="_ugvw_customisation_custom-javascript" class="paragraph">
<p>= Custom Javascript :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The Wicket viewer ships with embedded JQuery, so this can be leveraged, for example to perform arbitrary transformations of the rendered page on page load.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>Just because something is possible, it doesn’t necessarily mean we encourage it. Please be aware that there is no formal API for any custom javascript that you might implement to target; future versions of Apache Isis might break your code.</p>
</div>
<div class="paragraph">
<p>If possible, consider using the <code>ComponentFactory</code> API described in the <a href="../ugvw/ugvw.html#_ugvw_extending">Extending</a> chapter.</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>To register your Javascript code, then just specify the appropriate configuration property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">isis.viewer.wicket.application.js=stylesheets/myapp.js</code></pre>
</div>
</div>
<div class="paragraph">
<p>This file is resolved relative to <code>src/main/webapp</code>.</p>
</div>
<div class="paragraph">
<p>Currently only one such <code>.js</code> file can be registered.</p>
</div>
<div id="_ugvw_customisation_auto-refresh" class="paragraph">
<p>= Auto-refresh page :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>This requirement from the users mailing list:</p>
</div>
<div class="paragraph">
<p></p>
<div class="extended-quote-first">
<p>Suppose you want to build a monitoring application, eg for an electricity grid. Data is updated in the background (eg via the Restful Objects REST API). What is needed is the ability to show an entity that includes a map, and have it auto-refresh every 5 seconds or so. </p>
</div>
<p></p>
</div>
<div class="paragraph">
<p>Here’s one (somewhat crude, but workable) way to accomplish this.</p>
</div>
<div class="ulist">
<ul>
<li> <p>First, update the domain object to return custom CSS:<br></p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyDomainObject</span> {
...
public <span class="predefined-type">String</span> cssClass() {<span class="keyword">return</span> <span class="string"><span class="delimiter">"</span><span class="content">my-special-auto-updating-entity</span><span class="delimiter">"</span></span>; }
...
}</code></pre>
</div>
</div> </li>
<li> <p>Then, use javascript in <code>scripts/application.js</code> (under <code>src/main/webapp/</code>) to reload:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="javascript"><span class="predefined">$</span>(<span class="keyword">function</span>() {
<span class="keyword">if</span> (<span class="predefined">$</span>(<span class="string"><span class="delimiter">"</span><span class="content">.my-special-auto-updating-entity</span><span class="delimiter">"</span></span>).length) {
setTimeout(<span class="keyword">function</span>() {document.location.reload();}, <span class="integer">5000</span>); <span class="comment">// 1000 is 5 sec</span>
}
});</code></pre>
</div>
</div> </li>
</ul>
</div>
<div id="_ugvw_customisation_request-parameters" class="paragraph">
<p>= Embedded View :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The Wicket viewer provides some support such that an Apache Isis application can be embedded within a host webapp, for example within an iframe.</p>
</div>
<div class="paragraph">
<p>Currently this support consists simply of being able to suppress the header and/or footer.</p>
</div>
<div class="paragraph">
<p>== Screenshots</p>
</div>
<div class="paragraph">
<p>For example, the regular view is:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/embedded-view/regular.png"><img src="images/embedded-view/regular.png" alt="regular" width="720px"></a>
</div>
</div>
<div class="paragraph">
<p>With the header and footer both suppressed only the main content is shown:</p>
</div>
<div class="imageblock">
<div class="content">
<a class="image" href="images/embedded-view/no-header-no-footer.png"><img src="images/embedded-view/no-header-no-footer.png" alt="no header no footer" width="720px"></a>
</div>
</div>
<div class="paragraph">
<p>It is also possible to suppress just the header, or just the footer.</p>
</div>
<div class="paragraph">
<p>== Request parameters</p>
</div>
<div class="paragraph">
<p>To suppress the header, add the following as a request parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.no.header</code></pre>
</div>
</div>
<div class="paragraph">
<p>and to suppress the header, add the following as a request parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">isis.no.footer</code></pre>
</div>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">http://localhost:8080/wicket/entity/TODO:0?isis.no.header&isis.no.footer</code></pre>
</div>
</div>
<div id="_ugvw_extending" class="paragraph">
<p>= Extending the Viewer :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The Wicket viewer allows you to customize the GUI in several (progressively more sophisticated) ways:</p>
</div>
<div class="ulist">
<ul>
<li> <p>by <a href="../ugvw/ugvw.html#_ugvw_customisation_tweaking-css-classes">tweaking the UI using CSS</a></p> </li>
<li> <p>by <a href="../ugvw/ugvw.html#_ugvw_customisation_custom-javascript">tweaking the UI using Javascript</a></p> </li>
<li> <p>by writing a <a href="../ugvw/ugvw.html#_ugvw_extending_custom-bootstrap-theme">custom bootstrap theme</a></p> </li>
<li> <p>by <a href="../ugvw/ugvw.html#_ugvw_extending_replacing-page-elements">replacing elements of the page</a> using the <code>ComponentFactory</code> interface</p> </li>
<li> <p>by implementing <a href="../ugvw/ugvw.html#_ugvw_extending_custom-pages">replacement page implementations</a> for the standard page types</p> </li>
</ul>
</div>
<div class="paragraph">
<p>The first two of these options are discussed in the <a href="../ugvw/ugvw.html">Wicket viewer</a> chapter. This chapter describes the remaining "heavier-weight/more powerful" options.</p>
</div>
<div class="paragraph">
<p>The chapter wraps up with a technique for prototyping, allowing user/passwords to be specified as query arguments.</p>
</div>
<div id="_ugvw_extending_custom-bootstrap-theme" class="paragraph">
<p>= Custom Bootstrap theme :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The Apache Isis Wicket viewer uses <a href="http://getbootstrap.com/">Bootstrap</a> styles and components (courtesy of the <a href="https://github.com/l0rdn1kk0n/wicket-bootstrap">Wicket Bootstrap</a> integration).</p>
</div>
<div class="paragraph">
<p>By default the viewer uses the default bootstrap theme. It is possible to configure the Wicket viewer to allow the user to <a href="../ugvw/ugvw.html#_ugvw_configuration-properties_themes">select other themes</a> provided by <a href="http://bootswatch.com">bootswatch.com</a>, and if required one of these can be <a href="../ugvw/ugvw.html#_ugvw_customisation_default-theme">set as the default</a>.</p>
</div>
<div class="paragraph">
<p>However, you may instead want to write your own custom theme, for example to fit your company’s look-n-feel/interface guidelines. This is done by implementing <a href="https://github.com/l0rdn1kk0n/wicket-bootstrap">Wicket Bootstrap</a>'s <code>de.agilecoders.wicket.core.settings.ITheme</code> class. This defines:</p>
</div>
<div class="ulist">
<ul>
<li> <p>the name of the theme</p> </li>
<li> <p>the resources it needs (the CSS and optional JS and/or fonts), and</p> </li>
<li> <p>optional urls to load them from a Content Delivery Network (CDN).</p> </li>
</ul>
</div>
<div class="paragraph">
<p>To make use of the custom <code>ITheme</code> the application should register it by subclassing <code>IsisWicketApplication</code> (also register this in <code>web.xml</code>) and add the following snippet:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">void</span> init() {
...
IBootstrapSettings settings = <span class="keyword">new</span> BootstrapSettings();
ThemeProvider themeProvider = <span class="keyword">new</span> SingleThemeProvider(<span class="keyword">new</span> MyTheme());
settings.setThemeProvider(themeProvider);
Bootstrap.install(getClass(), settings);
}</code></pre>
</div>
</div>
<div id="_ugvw_extending_replacing-page-elements" class="paragraph">
<p>= Replacing page elements :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>Replacing elements of the page is the most powerful general-purpose way to customize the look-n-feel of the viewer. Examples in the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a> include the gmap3, fullcalendar2, excel, pdfjs and wickedcharts components.</p>
</div>
<div class="paragraph">
<p>The pages generated by Apache Isis' Wicket viewer are built up of numerous elements, from fine-grained widgets for property/parameter fields, to much larger components that take responsibility for rendering an entire entity, or a collection of entities. Under the covers these are all implementations of the the Apache Wicket <code>Component</code> API. The larger components delegate to the smaller, of course.</p>
</div>
<div class="paragraph">
<p>== How the viewer selects components</p>
</div>
<div class="paragraph">
<p>Components are created using Apache Isis' <code>ComponentFactory</code> interface, which are registered in turn through the <code>ComponentFactoryRegistrar</code> interface. Every component is categorizes by type (the <code>ComponentType</code> enum), and Apache Isis uses this to determine which <code>ComponentFactory</code> to use. For example, the <code>ComponentType.BOOKMARKED_PAGES</code> is used to locate the <code>ComponentFactory</code> that will build the bookmarked pages panel.</p>
</div>
<div class="paragraph">
<p>Each factory is also handed a model (an implementation of <code>org.apache.wicket.IModel</code>) appropriate to its <code>ComponentType</code>; this holds the data to be rendered. For example, <code>ComponentType.BOOKMARKED_PAGES</code> is given a <code>BookmarkedPagesModel</code>, while <code>ComponentType.SCALAR_NAME_AND_VALUE</code> factories are provided a model of type of type <code>ScalarModel</code> .</p>
</div>
<div class="paragraph">
<p>In some cases there are several factories for a given <code>ComponentType</code>; this is most notably the case for <code>ComponentType.SCALAR_NAME_AND_VALUE</code>. After doing a first pass selection of candidate factories by <code>ComponentType</code>, each factory is then asked if it <code>appliesTo(Model)</code>. This is an opportunity for the factory to check the model itself to see if the data within it is of the appropriate type.</p>
</div>
<div class="paragraph">
<p>Thus, the <code>BooleanPanelFactory</code> checks that the <code>ScalarModel</code> holds a boolean, while the <code>JodaLocalDatePanelFactory</code> checks to see if it holds <code>org.joda.time.LocalDate</code>.</p>
</div>
<div class="paragraph">
<p>There will typically be only one <code>ComponentFactory</code> capable of rendering a particular <code>ComponentType</code>/<code>ScalarModel</code> combination; at any rate, the framework stops as soon as one is found.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>There is one refinement to the above algorithm where multiple component factories might be used to render an object; this is discussed in <a href="../ugvw/ugvw.html#__ugvw_extending_replacing-page-elements_collections">Additional Views of Collections</a>, below.</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>== How to replace a component</p>
</div>
<div class="paragraph">
<p>This design (the <a href="http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern">chain of responsibility</a> design pattern) makes it quite straightforward to change the rendering of any element of the page. For example, you might switch out Apache Isis' sliding bookmark panel and replace it with one that presents the bookmarks in some different fashion.</p>
</div>
<div class="paragraph">
<p>First, you need to write a <code>ComponentFactory</code> and corresponding <code>Component</code>. The recommended approach is to start with the source of the <code>Component</code> you want to switch out. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyBookmarkedPagesPanelFactory</span> <span class="directive">extends</span> ComponentFactoryAbstract {
<span class="directive">public</span> MyBookmarkedPagesPanelFactory() {
<span class="local-variable">super</span>(ComponentType.BOOKMARKED_PAGES);
}
<span class="annotation">@Override</span>
<span class="directive">public</span> ApplicationAdvice appliesTo(<span class="directive">final</span> IModel<?> model) {
<span class="keyword">return</span> appliesIf(model <span class="keyword">instanceof</span> BookmarkedPagesModel);
}
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="predefined-type">Component</span> createComponent(<span class="directive">final</span> <span class="predefined-type">String</span> id, <span class="directive">final</span> IModel<?> model) {
<span class="directive">final</span> BookmarkedPagesModel bookmarkedPagesModel = (BookmarkedPagesModel) model;
<span class="keyword">return</span> <span class="keyword">new</span> MyBookmarkedPagesPanel(id, bookmarkedPagesModel);
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyBookmarkedPagesPanel</span>
<span class="directive">extends</span> PanelAbstract<BookmarkedPagesModel> {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here <code>PanelAbstract</code> ultimately inherits from <code>org.apache.wicket.Component</code>. Your new <code>Component</code> uses the information in the provided model (eg <code>BookmarkedPagesModel</code>) to know what to render.</p>
</div>
<div class="paragraph">
<p>Next, you will require a custom implementation of the <code>ComponentFactoryRegistrar</code> that registers your custom <code>ComponentFactory</code> as a replacement:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Singleton</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">MyComponentFactoryRegistrar</span> <span class="directive">extends</span> ComponentFactoryRegistrarDefault {
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="type">void</span> addComponentFactories(ComponentFactoryList componentFactories) {
<span class="local-variable">super</span>.addComponentFactories(componentFactories);
componentFactories.add(<span class="keyword">new</span> MyBookmarkedPagesPanelFactory());
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will result in the new component being used instead of (that is, discovered prior to) Isis' default implementation.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>Previously we suggested using "replace" rather than "add"; however this has unclear semantics for some component types; see <a href="https://issues.apache.org/jira/browse/ISIS-996">ISIS-996</a>.</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="paragraph">
<p>Finally, you’ll need to subclass <code>IsisWicketApplication</code> (register in <code>web.xml</code>)and then adjust the Guice bindings returned in the Guice <code>Module</code> returned by <code>newIsisWicketModule()</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyAppApplication</span> <span class="directive">extends</span> IsisWicketApplication {
<span class="annotation">@Override</span>
<span class="directive">protected</span> Module newIsisWicketModule() {
<span class="directive">final</span> Module isisDefaults = <span class="local-variable">super</span>.newIsisWicketModule();
<span class="directive">final</span> Module myAppOverrides = <span class="keyword">new</span> AbstractModule() {
<span class="annotation">@Override</span>
<span class="directive">protected</span> <span class="type">void</span> configure() {
...
bind(ComponentFactoryRegistrar.class)
.to(MyComponentFactoryRegistrar.class);
...
}
};
<span class="keyword">return</span> Modules.override(isisDefaults).with(myAppOverrides);
}
}</code></pre>
</div>
</div>
<div id="__ugvw_extending_replacing-page-elements_collections" class="paragraph">
<p>== Additional Views of Collections</p>
</div>
<div class="paragraph">
<p>As explained above, in most cases Apache Isis' Wicket viewer will search for the first <code>ComponentFactory</code> that can render an element, and use it. In the case of (either standalone or parented) collections, though, Apache Isis will show all available views.</p>
</div>
<div class="paragraph">
<p>For example, out-of-the-box Apache Isis provides a table view, a summary view (totals/sums/averages of any data), and a collapsed view (for <code>@Render(LAZILY)</code> collections). These are selected by clicking on the toolbar by each collection.</p>
</div>
<div class="paragraph">
<p>Additional views though could render the objects in the collection as a variety of ways. Indeed, some third-party implementations in the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a> already exist, including:</p>
</div>
<div class="ulist">
<ul>
<li> <p>excel component - collection as a downloadable excel spreadsheet</p> </li>
<li> <p>gmap3 component - render any objects with a location on a map</p> </li>
<li> <p>pdf.js component - render Blob containined PDF as a scrollable image</p> </li>
<li> <p>wicked charts component - barchart of any data</p> </li>
<li> <p>full calendar - render any objects with date properties on a calendar</p> </li>
</ul>
</div>
<div class="paragraph">
<p>Registering these custom views is just a matter of adding the appropriate Maven module to the classpath. Apache Isis uses the JDK <code>ServiceLoader</code> API to automatically discover and register the <code>ComponentFactory</code> of each such component.</p>
</div>
<div class="paragraph">
<p>If you want to write your own alternative component and auto-register, then include a file <code>META-INF/services/org.apache.isis.viewer.wicket.ui.ComponentFactory</code> whose contents is the fully-qualified class name of the custom <code>ComponentFactory</code> that you have written.</p>
</div>
<div class="paragraph">
<p>Wicket itself has lots of components available at its <a href="http://wicketstuff.org">wicketstuff.org</a> companion website; you might find some of these useful for your own customizations.</p>
</div>
<div class="paragraph">
<p>== Custom object view (eg dashboard)</p>
</div>
<div class="paragraph">
<p>One further use case in particular is worth highlighting; the rendering of an entire entity. Normally entities this is done using <code>EntityCombinedPanelFactory</code>, this being the first <code>ComponentFactory</code> for the <code>ComponentType.ENTITY</code> that is registered in Apache Isis default <code>ComponentFactoryRegistrarDefault</code>.</p>
</div>
<div class="paragraph">
<p>You could, though, register your own <code>ComponentFactory</code> for entities that is targeted at a particular class of entity - some sort of object representing a dashboard, for example. It can use the <code>EntityModel</code> provided to it to determine the class of the entity, checking if it is of the appropriate type. Your custom factory should also be registered before the <code>EntityCombinedPanelFactory</code> so that it is checked prior to the default <code>EntityCombinedPanelFactory</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Singleton</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">MyComponentFactoryRegistrar</span> <span class="directive">extends</span> ComponentFactoryRegistrarDefault {
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="type">void</span> addComponentFactories(ComponentFactoryList componentFactories) {
componentFactories.add(<span class="keyword">new</span> DashboardEntityFactory());
...
super.addComponentFactories(componentFactories);
...
}
}</code></pre>
</div>
</div>
<div id="_ugvw_extending_custom-pages" class="paragraph">
<p>= Custom pages :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>In the vast majority of cases customization should be sufficient by <a href="../ugvw/ugvw.html#_ugvw_extending_replacing-page-elements">replacing elements of a page</a>. However, it is also possible to define an entirely new page for a given page type.</p>
</div>
<div class="paragraph">
<p>Isis defines eight page types (see the <code>org.apache.isis.viewer.wicket.model.models.PageType</code> enum):</p>
</div>
<table class="tableblock frame-all grid-all spread">
<caption class="title">
Table 11. PageType enum
</caption>
<colgroup>
<col style="width: 20%;">
<col style="width: 80%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Page type</th>
<th class="tableblock halign-left valign-top">Renders</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">SIGN_IN</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The initial sign-in (aka login) page</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">SIGN_UP</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The sign-up page (if <a href="../rgsvc/rgsvc.html#_rgsvc_persistence-layer-spi_UserRegistrationService">user registration</a> is enabled).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">SIGN_UP_VERIFY</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The sign-up verification page (if <a href="../rgsvc/rgsvc.html#_rgsvc_persistence-layer-spi_UserRegistrationService">user registration</a> is enabled; as accessed by link from verification email)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PASSWORD_RESET</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The password reset page (if enabled).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">HOME</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The home page, displaying either the welcome message or dashboard</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ABOUT</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The about page, accessible from link top-right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ENTITY</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Renders a single entity or view model</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">STANDALONE_COLLECTION</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Page rendered after invoking an action that returns a collection of entites</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">VALUE</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">After invoking an action that returns a value type (though not URLs or Blob/Clobs, as these are handled appropriately automatically).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">VOID_RETURN</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">After invoking an action that is <code>void</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ACTION_PROMPT</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">(No longer used).</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The <code>PageClassList</code> interface declares which class (subclass of <code>org.apache.wicket.Page</code> is used to render for each of these types. For example, Apache Isis' <code>WicketSignInPage</code> renders the signin page.</p>
</div>
<div class="paragraph">
<p>To specify a different page class, create a custom subclass of <code>PageClassList</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Singleton</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">MyPageClassList</span> <span class="directive">extends</span> PageClassListDefault {
<span class="directive">protected</span> <span class="predefined-type">Class</span><? <span class="directive">extends</span> Page> getSignInPageClass() {
<span class="keyword">return</span> MySignInPage.class;
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You then need to register your custom <code>PageClassList</code>. This is done by subclassing <code>IsisWicketApplication</code> (register the subclass in <code>web.xml</code>) and adjusting the Guice bindings of the guice <code>Module</code> returned by the <code>newIsisWicketModule()</code> method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyAppApplication</span> <span class="directive">extends</span> IsisWicketApplication {
<span class="annotation">@Override</span>
<span class="directive">protected</span> Module newIsisWicketModule() {
<span class="directive">final</span> Module isisDefaults = <span class="local-variable">super</span>.newIsisWicketModule();
<span class="directive">final</span> Module myAppOverrides = <span class="keyword">new</span> AbstractModule() {
<span class="annotation">@Override</span>
<span class="directive">protected</span> <span class="type">void</span> configure() {
...
bind(PageClassList.class).to(MyPageClassList.class);
...
}
};
<span class="keyword">return</span> Modules.override(isisDefaults).with(myAppOverrides);
}
}</code></pre>
</div>
</div>
<div id="_ugvw_extending_login-via-query-args-prototyping" class="paragraph">
<p>= Login via Query Args (for Prototyping) :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>This section describes a (slightly hacky) way of allowing logins using query args, eg <a href="http://localhost:8080/?user=sven&pass=pass">http://localhost:8080/?user=sven&pass=pass</a>. This might be useful while prototyping or demonstrating a scenario involving multiple different interacting users.</p>
</div>
<div class="paragraph">
<p>First, you’ll need to subclass <code>IsisWicketApplication</code> (and register in <code>web.xml</code>). Then, override <code>newSession()</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="ini">private final static boolean DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS = false;
@Override
public Session newSession(final Request request, final Response response) {
if(!DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS) {
return super.newSession(request, response);
}
// else demo mode
final AuthenticatedWebSessionForIsis s = (AuthenticatedWebSessionForIsis) super.newSession(request, response);
IRequestParameters requestParameters = request.getRequestParameters();
final org.apache.wicket.util.string.StringValue user = requestParameters.getParameterValue("user");
final org.apache.wicket.util.string.StringValue password = requestParameters.getParameterValue("pass");
s.signIn(user.toString(), password.toString());
return s;
}
@Override
public WebRequest newWebRequest(HttpServletRequest servletRequest, String filterPath) {
if(!DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS) {
return super.newWebRequest(servletRequest, filterPath);
}
// else demo mode
try {
String uname = servletRequest.getParameter("user");
if (uname != null) {
servletRequest.getSession().invalidate();
}
} catch (Exception e) {
}
WebRequest request = super.newWebRequest(servletRequest, filterPath);
return request;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Rather than using the static <code>DEMO_MODE_USING_CREDENTIALS_AS_QUERYARGS</code>, you might also explore using the feature toggle library provided by the (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a>'s togglz module.</p>
</div>
<div id="_ugvw_hints-and-tips" class="paragraph">
<p>= Hints and Tips :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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.</p>
</div>
<div class="paragraph">
<p>This chapter provides some solutions for problems we’ve encountered ourselves or have been raised on the Apache Isis mailing lists.</p>
</div>
<div class="paragraph">
<p>See also hints-n-tips chapters in the:</p>
</div>
<div class="ulist">
<ul>
<li> <p>the <a href="../dg/dg.html#_dg_hints-and-tips">Developers'</a> guide</p> </li>
<li> <p>the <a href="../ugvw/ugvw.html#_ugvw_hints-and-tips">Wicket viewer</a> guide (this chapter)</p> </li>
<li> <p>the <a href="../ugvro/ugvro.html#_ugvro_hints-and-tips">Restful Objects viewer</a> guide</p> </li>
<li> <p>the <a href="../ugodn/ugodn.html#_ugodn_hints-and-tips">Datanucleus ObjectStore</a> guide</p> </li>
<li> <p>the <a href="../ugsec/ugsec.html#_ugsec_hints-and-tips">Security</a> guide</p> </li>
<li> <p>the <a href="../ugbtb/ugbtb.html#_ugbtb_hints-and-tips">Beyond the Basics</a> guide.</p> </li>
</ul>
</div>
<div id="_ugvw_hints-and-tips_per-user-themes" class="paragraph">
<p>= Per-user Themes :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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.</p>
</div>
<div class="paragraph">
<p>From <a href="http://isis.markmail.org/thread/kb4442niwwbnghey">this thread</a> on the Apache Isis users mailing list:</p>
</div>
<div class="ulist">
<ul>
<li> <p><em>Is it possible to have each of our resellers (using our Apache Isis application) use there own theme/branding with their own logo and colors? Would this also be possible for the login page, possibly depending on the used host name?</em></p> </li>
</ul>
</div>
<div class="paragraph">
<p>Yes, you can do this, by installing a custom implementation of the Wicket Bootstrap’s <code>ActiveThemeProvider</code>.</p>
</div>
<div class="paragraph">
<p>The <a href="http://github.com/isisaddons/isis-app-todoapp">Isis addons' todoapp</a> (non-ASF) actually <a href="https://github.com/isisaddons/isis-app-todoapp/tree/61b8114a8e01dbb3c380b31cf09eaed456407570">does this</a>, storing the info via the (non-ASF) <a href="http://platform.incode.org/modules/dom/settings/dom-settings.html">Incode Platform’s settings module</a> :</p>
</div>
<div class="listingblock">
<div class="title">
IActiveThemeProvider implementation
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">UserSettingsThemeProvider</span> <span class="directive">implements</span> ActiveThemeProvider {
...
<span class="annotation">@Override</span>
<span class="directive">public</span> ITheme getActiveTheme() {
<span class="keyword">if</span>(IsisContext.getSpecificationLoader().isInitialized()) {
<span class="directive">final</span> <span class="predefined-type">String</span> themeName = IsisContext.doInSession(<span class="keyword">new</span> <span class="predefined-type">Callable</span><<span class="predefined-type">String</span>>() {
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="predefined-type">String</span> call() <span class="directive">throws</span> <span class="exception">Exception</span> {
<span class="directive">final</span> UserSettingsService userSettingsService =
lookupService(UserSettingsService.class);
<span class="directive">final</span> UserSetting activeTheme = userSettingsService.find(
IsisContext.getAuthenticationSession().getUserName(),
ACTIVE_THEME);
<span class="keyword">return</span> activeTheme != <span class="predefined-constant">null</span> ? activeTheme.valueAsString() : <span class="predefined-constant">null</span>;
}
});
<span class="keyword">return</span> themeFor(themeName);
}
<span class="keyword">return</span> <span class="keyword">new</span> SessionThemeProvider().getActiveTheme();
}
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="type">void</span> setActiveTheme(<span class="directive">final</span> <span class="predefined-type">String</span> themeName) {
IsisContext.doInSession(<span class="keyword">new</span> <span class="predefined-type">Runnable</span>() {
<span class="annotation">@Override</span>
<span class="directive">public</span> <span class="type">void</span> run() {
<span class="directive">final</span> <span class="predefined-type">String</span> currentUsrName =
IsisContext.getAuthenticationSession().getUserName();
<span class="directive">final</span> UserSettingsServiceRW userSettingsService =
lookupService(UserSettingsServiceRW.class);
<span class="directive">final</span> UserSettingJdo activeTheme =
(UserSettingJdo) userSettingsService.find(
currentUsrName, ACTIVE_THEME);
<span class="keyword">if</span>(activeTheme != <span class="predefined-constant">null</span>) {
activeTheme.updateAsString(themeName);
} <span class="keyword">else</span> {
userSettingsService.newString(
currentUsrName, ACTIVE_THEME, <span class="string"><span class="delimiter">"</span><span class="content">Active Bootstrap theme for user</span><span class="delimiter">"</span></span>, themeName);
}
}
});
}
<span class="directive">private</span> ITheme themeFor(<span class="directive">final</span> <span class="predefined-type">String</span> themeName) {
<span class="directive">final</span> ThemeProvider themeProvider = settings.getThemeProvider();
<span class="keyword">if</span>(themeName != <span class="predefined-constant">null</span>) {
<span class="keyword">for</span> (<span class="directive">final</span> ITheme theme : themeProvider.available()) {
<span class="keyword">if</span> (themeName.equals(theme.name()))
<span class="keyword">return</span> theme;
}
}
<span class="keyword">return</span> themeProvider.defaultTheme();
}
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="title">
Using the ActiveThemeProvider
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Override</span>
<span class="directive">protected</span> <span class="type">void</span> init() {
<span class="local-variable">super</span>.init();
<span class="directive">final</span> IBootstrapSettings settings = Bootstrap.getSettings();
settings.setThemeProvider(<span class="keyword">new</span> BootswatchThemeProvider(BootswatchTheme.Flatly));
settings.setActiveThemeProvider(<span class="keyword">new</span> UserSettingsThemeProvider(settings));
}</code></pre>
</div>
</div>
<div id="_ugvw_hints-and-tips_i18n-label-in-wicket-viewer" class="paragraph">
<p>= How i18n the Wicket viewer? :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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.</p>
</div>
<div class="paragraph">
<p>From <a href="http://isis.markmail.org/thread/ctppmtcbsf4iskzi">this thread</a> on the Apache Isis users mailing list:</p>
</div>
<div class="ulist">
<ul>
<li> <p><em>I am trying to internationalize the label descriptions of form actions, eg those in <code>ActionParametersFormPanel</code>. Referencing those via their message id inside a .po file didn’t work either. Can this be done?</em></p> </li>
</ul>
</div>
<div class="paragraph">
<p>Yes, it <em>is</em> possible to internationalize both the Wicket viewer’s labels as well as the regular translations of the domain object metadata using the <code>.po</code> translation files as supported by the <a href="../rgsvc/rgsvc.html#_rgsvc_presentation-layer-spi_TranslationService"><code>TranslationService</code></a>.</p>
</div>
<div class="paragraph">
<p>Full details of the <code>msgId</code>s that must be added to the <code>translations.po</code> file can be found in <a href="../ugbtb/ugbtb.html#__ugbtb_i18n_wicket-viewer">i18n</a> section of the <a href="../ugbtb/ugbtb.html">beyond the basics</a> guide.</p>
</div>
<div id="_ugvw_hints-and-tips_highlight-current-row" class="paragraph">
<p>= Highlight Current Row :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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.</p>
</div>
<div class="paragraph">
<p>Demo App: Highlighting Current As a by-the-by, the demo app has one further "trick up its sleeve". If you run the app you’ll notice that the currently selected <code>DemoObject</code> is highlighted in the left-hand table of the <code>HomePageViewModel</code>.</p>
</div>
<div class="paragraph">
<p>This is accomplished by having the view model collaborate with a subscribing domain service that configures a CSS class.</p>
</div>
<div class="paragraph">
<p>We start by ensuring that the <code>DemoObject</code> emits an event for its CSS class:</p>
</div>
<div class="listingblock">
<div class="title">
DemoObject.java
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DomainObjectLayout</span>(
...
cssClassUiEvent = DemoObject.CssClassUiEvent.class
)
<span class="directive">public</span> <span class="type">class</span> <span class="class">DemoObject</span> ... {
<span class="directive">public</span> <span class="directive">static</span> <span class="type">class</span> <span class="class">CssClassUiEvent</span>
<span class="directive">extends</span> org.apache.isis.applib.services.eventbus.CssClassUiEvent<DemoObject> {}
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Next, we define the domain service to act as the subscriber:</p>
</div>
<div class="listingblock">
<div class="title">
HomePageViewModel.java
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">HomePageViewModel</span> ... {
<span class="annotation">@DomainService</span>(nature = NatureOfService.DOMAIN)
<span class="directive">public</span> <span class="directive">static</span> <span class="type">class</span> <span class="class">CssHighlighter</span> <span class="directive">extends</span> AbstractSubscriber {
<span class="annotation">@org</span>.axonframework.eventhandling.annotation.EventHandler <span class="comment">// if using axon</span>
<span class="annotation">@com</span>.google.common.eventbus.Subscribe <span class="comment">// if using guava</span>
<span class="directive">public</span> <span class="type">void</span> on(DemoObject.CssClassUiEvent ev) {
<span class="keyword">if</span>(getContext() == <span class="predefined-constant">null</span>) { <span class="keyword">return</span>; }
<span class="keyword">if</span>(ev.getSource() == getContext().getSelected()) { <i class="conum" data-value="1"></i><b>(1)</b>
ev.setCssClass(<span class="string"><span class="delimiter">"</span><span class="content">selected</span><span class="delimiter">"</span></span>);
}
}
<span class="directive">private</span> HomePageViewModel getContext() { <i class="conum" data-value="2"></i><b>(2)</b>
<span class="keyword">return</span> (HomePageViewModel) scratchpad.get(<span class="string"><span class="delimiter">"</span><span class="content">context</span><span class="delimiter">"</span></span>);
}
<span class="type">void</span> setContext(<span class="directive">final</span> HomePageViewModel homePageViewModel) {
scratchpad.put(<span class="string"><span class="delimiter">"</span><span class="content">context</span><span class="delimiter">"</span></span>, homePageViewModel);
}
<span class="annotation">@Inject</span>
Scratchpad scratchpad; <i class="conum" data-value="3"></i><b>(3)</b>
}
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>If the domain object is the currently selected then set the CSS class</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Provide methods to set and get the current <code>HomePageViewModel</code> (acting as the context)</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Store the context using the <code>Scratchpad</code> domain service (request-scoped so thread-safe).</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>The <code>HomePageViewModel</code> is responsible for setting itself as the context for the domain service:</p>
</div>
<div class="listingblock">
<div class="title">
HomePageViewModel.java
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">HomePageViewModel</span> ... {
...
public TranslatableString title() {
cssHighlighter.setContext(<span class="local-variable">this</span>); <i class="conum" data-value="1"></i><b>(1)</b>
...
}
...
<span class="annotation">@javax</span>.inject.Inject
CssHighlighter cssHighlighter;
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tbody>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>set the context on the domain service</td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
<p>Finally we just need some CSS, in the <code>application.css</code> file:</p>
</div>
<div class="listingblock">
<div class="title">
application.css
</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="css"><span class="class">.selected</span> {
<span class="key">font-style</span>: <span class="value">italic</span>; <span class="key">font-weight</span>: <span class="value">bolder</span>;
}</code></pre>
</div>
</div>
<div id="_ugvw_hints-and-tips_svg-support" class="paragraph">
<p>= SVG Support :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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.</p>
</div>
<div class="paragraph">
<p>(As per <a href="https://issues.apache.org/jira/browse/ISIS-1604">ISIS-1604</a>), SVG images can be used:</p>
</div>
<div class="ulist">
<ul>
<li> <p>as Logo in the upper left corner (Wicket Menubar)</p> </li>
<li> <p>on the Login Page (<code>login.html</code>)</p> </li>
<li> <p>as favicon (<code>image/svg+xml</code>, cf. <a href="https://issues.apache.org/jira/browse/ISIS-1115">ISIS-1115</a>)</p> </li>
</ul>
</div>
<div class="paragraph">
<p>However, SVGs are not, by default, displayed on the welcome page. SVGs can be attached as <code>Blob</code>s, but they are displayed as bitmaps (by means of the Batik rasterizer) and do not scale. The rasterizer (of course) can not deal with animations (cf. attachment).</p>
</div>
<div class="paragraph">
<p>To fix this, you can add the following dependencies:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependency></span>
<span class="tag"><groupId></span>com.twelvemonkeys.imageio<span class="tag"></groupId></span>
<span class="tag"><artifactId></span>imageio-batik<span class="tag"></artifactId></span> <span class="comment"><!-- svg --></span>
<span class="tag"><version></span>3.3.2<span class="tag"></version></span>
<span class="tag"></dependency></span>
<span class="tag"><dependency></span>
<span class="tag"><groupId></span>com.twelvemonkeys.imageio<span class="tag"></groupId></span>
<span class="tag"><artifactId></span>imageio-batik<span class="tag"></artifactId></span> <span class="comment"><!-- svg --></span>
<span class="tag"><version></span>3.3.2<span class="tag"></version></span>
<span class="tag"><type></span>test-jar<span class="tag"></type></span>
<span class="tag"><scope></span>test<span class="tag"></scope></span>
<span class="tag"></dependency></span>
<span class="tag"><dependency></span>
<span class="tag"><groupId></span>org.apache.xmlgraphics<span class="tag"></groupId></span>
<span class="tag"><artifactId></span>batik-transcoder<span class="tag"></artifactId></span>
<span class="tag"><version></span>1.8<span class="tag"></version></span>
<span class="tag"></dependency></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>However, <strong>please note</strong> that these dependencies have high CVE values, and so may constitute a security risk.</p>
</div>
<div class="paragraph">
<p>Further discussion on <a href="https://lists.apache.org/thread.html/68f16dd0306a8101c1cde06e5e6309b8d1b81b388a1f59e123cfc2f3@%3Cusers.isis.apache.org%3E">this mailing list thread</a>.</p>
</div>
<div id="_ugvw_incode-platform" class="paragraph">
<p>= Appendix: Incode Platform (not ASF) :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. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . 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. :_basedir: ../../ :_imagesdir: images/</p>
</div>
<div class="paragraph">
<p>The (non-ASF) <a href="http://platform.incode.org" target="_blank" rel="noopener">Incode Platform</a> provides a number of extensions to the Wicket viewer (leveraging the APIs described in <a href="../ugvw/ugvw.html#_ugvw_extending">Extending the Wicket viewer</a> section, later. While you are free to fork and adapt any of them to your needs, they are also intended for use "out-of-the-box".</p>
</div>
<div class="paragraph">
<p>At the time of writing the addons available are:</p>
</div>
<div class="ulist">
<ul>
<li> <p>Excel Wicket component - to export a collection of domain objects as an Excel spreadsheet</p>
<div class="ulist">
<ul>
<li> <p>see also the related Excel library module which can be used to read/import a spreadsheet as an collection of view models or entities</p> </li>
</ul>
</div> </li>
<li> <p>ullcalendar2 Wicket component - to view a collection of domain objects (with a date) on a full-page calendar</p> </li>
<li> <p>Gmap3 Wicket component - to view a collection of domain objects with a location on a google map</p> </li>
<li> <p>pdf.js Wicket component - to view a <code>Blob</code> containing a PDF as an image</p> </li>
<li> <p>Summernote Wicket component - to edit a string property using an RTF editor</p>
<div class="ulist">
<ul>
<li> <p>(not yet compatible with <code>1.15.0</code>)</p> </li>
</ul>
</div> </li>
<li> <p>Wickedcharts Wicket component - low-level integration with Highcharts charting library</p> </li>
</ul>
</div>
<div class="paragraph">
<p>Check the <a href="http://platform.incode.org" target="_blank" rel="noopener">website</a> for the most up-to-date list.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>Note that the Incode Platform, while maintained by Apache Isis committers, are not part of the ASF.</p>
</div>
<div class="exampleblock">
<div class="content">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="hidden-xs hidden-sm hidden-md col-lg-3">
<nav id="toc" data-spy="affix" data-toggle="toc"></nav>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<div class="row">
<p class="text-center small text-muted"> Copyright © 2010~2018 The Apache Software Foundation, licensed under the Apache License, v2.0. <br> Apache, the Apache feather logo, Apache Isis, and the Apache Isis project logo are all trademarks of The Apache Software Foundation. </p>
</div>
</div>
</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="../../js/bootstrap/3.3.7/bootstrap.min.js"></script>
<script src="../../js/bootstrap-toc/0.4.1/bootstrap-toc.min.js"></script>
<script src="../../js/slick/1.5.0/slick.min.js"></script>
<script src="../../js/elasticlunr/elasticlunr.min.js"></script>
<script src="../../js/sticky-header/sticky-header.js"></script>
<script src="../../js/search-panel/search-panel.js"></script>
<script src="../../js/header-link/header-link.js"></script>
<script src="../../js/toc-scroll/toc-scroll.js"></script>
</body>
</html>