You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/12/20 16:42:18 UTC

[1/4] git commit: ISIS-639: increase buffer size in Jetty webserver for longer URLs.

Updated Branches:
  refs/heads/master 192b6b229 -> bb2d31e1d


ISIS-639: increase buffer size in Jetty webserver for longer URLs.


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

Branch: refs/heads/master
Commit: 64a4e37cc214632ac9ab189fa24834b6e7d15de5
Parents: 192b6b2
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 20 15:11:41 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 20 15:11:41 2013 +0000

----------------------------------------------------------------------
 .../org/apache/isis/core/webserver/WebServerBootstrapper.java    | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/64a4e37c/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServerBootstrapper.java
----------------------------------------------------------------------
diff --git a/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServerBootstrapper.java b/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServerBootstrapper.java
index cf887f3..0d85e62 100644
--- a/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServerBootstrapper.java
+++ b/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServerBootstrapper.java
@@ -34,6 +34,7 @@ import com.google.inject.Injector;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.mortbay.jetty.Connector;
 import org.mortbay.jetty.Server;
 import org.mortbay.jetty.webapp.WebAppContext;
 
@@ -78,6 +79,9 @@ final class WebServerBootstrapper implements IsisBootstrapper {
         // TODO get and use the address
 
         jettyServer = new Server(port);
+        Connector[] connectors = jettyServer.getConnectors();
+        Connector connector = connectors[0];
+        connector.setHeaderBufferSize(8192);
         final WebAppContext context = new WebAppContext(SRC_MAIN_WEBAPP, webappContextPath);
 
         copyConfigurationPrimersIntoServletContext(context);


[2/4] git commit: ISIS-640: extending ViewModelSupport API

Posted by da...@apache.org.
ISIS-640: extending ViewModelSupport API


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

Branch: refs/heads/master
Commit: 9eae01f59eec16e74cee1ba32b9a09434315db78
Parents: 64a4e37
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 20 15:12:05 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 20 15:12:05 2013 +0000

----------------------------------------------------------------------
 .../viewmodelsupport/ViewModelSupport.java      |  4 ++++
 .../ViewModelSupportDefault.java                | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/9eae01f5/core/applib/src/main/java/org/apache/isis/applib/services/viewmodelsupport/ViewModelSupport.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/viewmodelsupport/ViewModelSupport.java b/core/applib/src/main/java/org/apache/isis/applib/services/viewmodelsupport/ViewModelSupport.java
index d53a8be..2c46e93 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/viewmodelsupport/ViewModelSupport.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/viewmodelsupport/ViewModelSupport.java
@@ -16,6 +16,8 @@
  */
 package org.apache.isis.applib.services.viewmodelsupport;
 
+import java.util.Set;
+
 import org.apache.isis.applib.annotation.Programmatic;
 
 public interface ViewModelSupport {
@@ -30,6 +32,8 @@ public interface ViewModelSupport {
 
         @Programmatic
         public String asString();
+
+        public Set<String> keySet();
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/9eae01f5/core/runtime/src/main/java/org/apache/isis/core/runtime/services/viewmodelsupport/ViewModelSupportDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/viewmodelsupport/ViewModelSupportDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/viewmodelsupport/ViewModelSupportDefault.java
index 722ed84..646cccd 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/viewmodelsupport/ViewModelSupportDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/viewmodelsupport/ViewModelSupportDefault.java
@@ -17,7 +17,13 @@
 package org.apache.isis.core.runtime.services.viewmodelsupport;
 
 import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Set;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import com.google.common.io.BaseEncoding;
 
 import org.dom4j.Document;
@@ -59,6 +65,20 @@ public class ViewModelSupportDefault implements ViewModelSupport {
             final String xmlStr = Dom4jUtil.asString(doc);
             return BaseEncoding.base64Url().encode(xmlStr.getBytes(Charset.forName("UTF-8")));
         }
+
+        private static final Function<Element, String> ELEMENT_NAME = new Function<Element, String>(){
+            @Override
+            public String apply(final Element input) {
+                return input.getName();
+            }
+        };
+
+        @Override
+        public Set<String> keySet() {
+            Element element = doc.getRootElement();
+            List<Element> elements = element.elements();
+            return Sets.newLinkedHashSet(Iterables.transform(elements, ELEMENT_NAME));
+        }
     }
     
     @Override


[3/4] ISIS-638: ui hints and clipboard behaviour

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/containers/UiHintPathSignificantWebMarkupContainer.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/containers/UiHintPathSignificantWebMarkupContainer.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/containers/UiHintPathSignificantWebMarkupContainer.java
new file mode 100644
index 0000000..d43033f
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/containers/UiHintPathSignificantWebMarkupContainer.java
@@ -0,0 +1,34 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.widgets.containers;
+
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
+
+public class UiHintPathSignificantWebMarkupContainer extends WebMarkupContainer implements UiHintPathSignificant {
+    private static final long serialVersionUID = 1L;
+
+    public UiHintPathSignificantWebMarkupContainer(String id, IModel<?> model) {
+        super(id, model);
+    }
+
+    public UiHintPathSignificantWebMarkupContainer(String id) {
+        super(id);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/formcomponent/FormComponentPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/formcomponent/FormComponentPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/formcomponent/FormComponentPanelAbstract.java
index bfe71c1..785f473 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/formcomponent/FormComponentPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/formcomponent/FormComponentPanelAbstract.java
@@ -34,6 +34,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.Persistor;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.isis.PersistenceSessionProvider;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
@@ -109,6 +110,27 @@ public abstract class FormComponentPanelAbstract<T> extends FormComponentPanel<T
         Components.permanentlyHide(container, ids);
     }
 
+    
+    // ///////////////////////////////////////////////////////////////////
+    // Hint support
+    // ///////////////////////////////////////////////////////////////////
+
+    public UiHintContainer getHintContainer() {
+        return hintContainerOf(this);
+    }
+
+    private UiHintContainer hintContainerOf(Component component) {
+        if(component == null) {
+            return null;
+        }
+        IModel<?> model = component.getDefaultModel();
+        if(model instanceof UiHintContainer) {
+            return (UiHintContainer) model;
+        }
+        // otherwise, go up the UI component hierarchy
+        return hintContainerOf(getParent()); 
+    }
+
     // ///////////////////////////////////////////////////////////////////
     // Convenience
     // ///////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboard.swf
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboard.swf b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboard.swf
new file mode 100644
index 0000000..13bf8e3
Binary files /dev/null and b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboard.swf differ

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardLink.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardLink.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardLink.java
new file mode 100644
index 0000000..962458d
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardLink.java
@@ -0,0 +1,112 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.widgets.zclip;
+
+import com.google.common.io.Resources;
+
+import org.apache.wicket.SharedResources;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.core.util.resource.UrlResourceStream;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.resource.ResourceStreamResource;
+import org.apache.wicket.request.resource.SharedResourceReference;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+public final class ZeroClipboardLink extends AjaxLink<ObjectAdapter> {
+
+    /**
+     * @see #addSharedResourceTo(SharedResources)
+     */
+    private static final String SHARED_RESOURCE_NAME = ZeroClipboardLink.class.getName();
+    /**
+     * Relative to this class.
+     */
+    private static final String FILE_NAME_SWF = "ZeroClipboard.swf";
+
+    private final String linkJQuerySelector;
+    
+    private final CharSequence zeroClipboardSwfUrl;
+    private final String baseUrl;
+    private static final long serialVersionUID = 1L;
+
+    public static void addSharedResourceTo(SharedResources sharedResources) {
+        sharedResources.add(ZeroClipboardLink.SHARED_RESOURCE_NAME, ZeroClipboardLink.newSwfFileResource());
+    }
+
+    private static ResourceStreamResource newSwfFileResource() {
+        return new ResourceStreamResource(
+                new UrlResourceStream(
+                        Resources.getResource(ZeroClipboardLink.class, FILE_NAME_SWF)));
+    }
+
+    // //////////////////////////////////////
+
+    public ZeroClipboardLink(String id, AbstractLink linkComponent) {
+        this(id, "#"+linkComponent.getMarkupId());
+    }
+
+    public ZeroClipboardLink(String id, String linkJQuerySelector) {
+        super(id);
+        this.linkJQuerySelector = linkJQuerySelector;
+        this.zeroClipboardSwfUrl = getRequestCycle().getUrlRenderer().renderFullUrl(Url.parse(urlFor(new SharedResourceReference(SHARED_RESOURCE_NAME), null)));
+        this.baseUrl = getRequestCycle().getUrlRenderer().renderFullUrl(Url.parse("."));
+    }
+    
+    @Override
+    public void onClick(AjaxRequestTarget target) {
+        // (nothing to do)
+    }
+
+    @Override
+    public void renderHead(IHeaderResponse response) {
+        super.renderHead(response);
+
+        final StringBuilder buf = new StringBuilder();
+        //buf.append("var url = " + quote(baseUrl) + "+" + jQueryLinkSelector() + ".attr(\"href\");");
+        
+        buf.append(jQuerySelectorOf("#"+getMarkupId()) + ".zclip({");
+        buf.append("    path:'" + zeroClipboardSwfUrl + "'");
+        //buf.append("   ,copy: url");
+        buf.append("   ,copy: function(){ return " + quote(baseUrl) + "+" + jQueryLinkSelector() + ".attr(\"href\"); }");
+        buf.append("});");
+        buf.append(jQuerySelectorOf("#"+getMarkupId()) + ".zclip('show')");
+
+        String js=buf.toString();
+        
+        response.render(OnDomReadyHeaderItem.forScript(js));
+    }
+
+    private String jQueryLinkSelector() {
+        return jQuerySelectorOf(linkJQuerySelector);
+    }
+
+    private static String jQuerySelectorOf(String selector) {
+        return "$('" + selector + "')";
+    }
+
+    private static String quote(final String baseUrl) {
+        return "\"" + baseUrl +"\"";
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/jquery.zclip.js
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/jquery.zclip.js b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/jquery.zclip.js
new file mode 100644
index 0000000..c21c6b0
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/jquery.zclip.js
@@ -0,0 +1,507 @@
+/*
+ * zClip :: jQuery ZeroClipboard v1.1.3
+ * http://steamdev.com/zclip
+ *
+ * Copyright 2011, SteamDev
+ * Released under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: Wed Jun 01, 2011
+ */
+
+
+(function (jQuery) {
+
+    jQuery.fn.zclip = function (params) {
+
+        if (typeof params == "object" && !params.length) {
+
+            var settings = jQuery.extend({
+
+                path: 'ZeroClipboard.swf',
+                copy: null,
+                beforeCopy: null,
+                afterCopy: null,
+                clickAfter: true,
+                setHandCursor: true,
+                setCSSEffects: true
+
+            }, params);
+			
+
+            return this.each(function () {
+
+                var o = jQuery(this);
+
+                if (o.is(':visible') && (typeof settings.copy == 'string' || jQuery.isFunction(settings.copy))) {
+
+                    ZeroClipboard.setMoviePath(settings.path);
+                    var clip = new ZeroClipboard.Client();
+                    
+                    if(jQuery.isFunction(settings.copy)){
+                    	o.bind('zClip_copy',settings.copy);
+                    }
+                    if(jQuery.isFunction(settings.beforeCopy)){
+                    	o.bind('zClip_beforeCopy',settings.beforeCopy);
+                    }
+                    if(jQuery.isFunction(settings.afterCopy)){
+                    	o.bind('zClip_afterCopy',settings.afterCopy);
+                    }                    
+
+                    clip.setHandCursor(settings.setHandCursor);
+                    clip.setCSSEffects(settings.setCSSEffects);
+                    clip.addEventListener('mouseOver', function (client) {
+                        o.trigger('mouseenter');
+                    });
+                    clip.addEventListener('mouseOut', function (client) {
+                        o.trigger('mouseleave');
+                    });
+                    clip.addEventListener('mouseDown', function (client) {
+
+                        o.trigger('mousedown');
+                        
+			if(!jQuery.isFunction(settings.copy)){
+			   clip.setText(settings.copy);
+			} else {
+			   clip.setText(o.triggerHandler('zClip_copy'));
+			}                        
+                        
+                        if (jQuery.isFunction(settings.beforeCopy)) {
+                            o.trigger('zClip_beforeCopy');                            
+                        }
+
+                    });
+
+                    clip.addEventListener('complete', function (client, text) {
+
+                        if (jQuery.isFunction(settings.afterCopy)) {
+                            
+                            o.trigger('zClip_afterCopy');
+
+                        } else {
+                            if (text.length > 500) {
+                                text = text.substr(0, 500) + "...\n\n(" + (text.length - 500) + " characters not shown)";
+                            }
+							
+			    o.removeClass('hover');
+                            alert("Copied text to clipboard:\n\n " + text);
+                        }
+
+                        if (settings.clickAfter) {
+                            o.trigger('click');
+                        }
+
+                    });
+
+					
+                    clip.glue(o[0], o.parent()[0]);
+					
+		    jQuery(window).bind('load resize',function(){clip.reposition();});
+					
+
+                }
+
+            });
+
+        } else if (typeof params == "string") {
+
+            return this.each(function () {
+
+                var o = jQuery(this);
+
+                params = params.toLowerCase();
+                var zclipId = o.data('zclipId');
+                var clipElm = jQuery('#' + zclipId + '.zclip');
+                var clientId = clipElm.attr('id').replace(/^.*_/g, '') || null; 
+
+                if (params == "remove") {
+
+                    clipElm.remove();
+                    o.removeClass('active hover');
+                    o.unbind('zClip_copy');
+                    o.unbind('zClip_beforeCopy');
+                    o.unbind('zClip_afterCopy');
+                    ZeroClipboard.unregister(clientId);
+
+                } else if (params == "hide") {
+
+                    clipElm.hide();
+                    o.removeClass('active hover');
+
+                } else if (params == "show") {
+
+                    clipElm.show();
+
+                }
+
+            });
+
+        }
+
+    }	
+	
+	
+
+})(jQuery);
+
+
+
+
+
+
+
+// ZeroClipboard
+// Simple Set Clipboard System
+// Author: Joseph Huckaby
+var ZeroClipboard = {
+
+    version: "1.0.7",
+    clients: {},
+    // registered upload clients on page, indexed by id
+    moviePath: 'ZeroClipboard.swf',
+    // URL to movie
+    nextId: 1,
+    // ID of next movie
+    jQuery: function (thingy) {
+        // simple DOM lookup utility function
+        if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
+        if (!thingy.addClass) {
+            // extend element with a few useful methods
+            thingy.hide = function () {
+                this.style.display = 'none';
+            };
+            thingy.show = function () {
+                this.style.display = '';
+            };
+            thingy.addClass = function (name) {
+                this.removeClass(name);
+                this.className += ' ' + name;
+            };
+            thingy.removeClass = function (name) {
+                var classes = this.className.split(/\s+/);
+                var idx = -1;
+                for (var k = 0; k < classes.length; k++) {
+                    if (classes[k] == name) {
+                        idx = k;
+                        k = classes.length;
+                    }
+                }
+                if (idx > -1) {
+                    classes.splice(idx, 1);
+                    this.className = classes.join(' ');
+                }
+                return this;
+            };
+            thingy.hasClass = function (name) {
+                return !!this.className.match(new RegExp("\\s*" + name + "\\s*"));
+            };
+        }
+        return thingy;
+    },
+
+    setMoviePath: function (path) {
+        // set path to ZeroClipboard.swf
+        this.moviePath = path;
+    },
+
+    dispatch: function (id, eventName, args) {
+        // receive event from flash movie, send to client		
+        var client = this.clients[id];
+        if (client) {
+            client.receiveEvent(eventName, args);
+        }
+    },
+
+    register: function (id, client) {
+        // register new client to receive events
+        this.clients[id] = client;
+    },
+    
+    unregister: function (id) {
+    	if (typeof(id) === 'number' && this.clients.hasOwnProperty(id)) {
+    		delete this.clients[id];
+    	}
+    },
+
+    getDOMObjectPosition: function (obj, stopObj) {
+        // get absolute coordinates for dom element
+        var info = {
+            left: 0,
+            top: 0,
+            width: obj.width ? obj.width : obj.offsetWidth,
+            height: obj.height ? obj.height : obj.offsetHeight
+        };
+
+        if (obj && (obj != stopObj)) {
+			info.left += obj.offsetLeft;
+            info.top += obj.offsetTop;
+        }
+
+        return info;
+    },
+
+    Client: function (elem) {
+        // constructor for new simple upload client
+        this.handlers = {};
+
+        // unique ID
+        this.id = ZeroClipboard.nextId++;
+        this.movieId = 'ZeroClipboardMovie_' + this.id;
+
+        // register client with singleton to receive flash events
+        ZeroClipboard.register(this.id, this);
+
+        // create movie
+        if (elem) this.glue(elem);
+    }
+};
+
+ZeroClipboard.Client.prototype = {
+
+    id: 0,
+    // unique ID for us
+    ready: false,
+    // whether movie is ready to receive events or not
+    movie: null,
+    // reference to movie object
+    clipText: '',
+    // text to copy to clipboard
+    handCursorEnabled: true,
+    // whether to show hand cursor, or default pointer cursor
+    cssEffects: true,
+    // enable CSS mouse effects on dom container
+    handlers: null,
+    // user event handlers
+    glue: function (elem, appendElem, stylesToAdd) {
+        // glue to DOM element
+        // elem can be ID or actual DOM element object
+        this.domElement = ZeroClipboard.jQuery(elem);
+
+        // float just above object, or zIndex 99 if dom element isn't set
+        var zIndex = 99;
+        if (this.domElement.style.zIndex) {
+            zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
+        }
+
+        if (typeof(appendElem) == 'string') {
+            appendElem = ZeroClipboard.jQuery(appendElem);
+        } else if (typeof(appendElem) == 'undefined') {
+            appendElem = document.getElementsByTagName('body')[0];
+        }
+
+        // find X/Y position of domElement
+        var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
+
+        // create floating DIV above element
+        this.div = document.createElement('div');
+        this.div.className = "zclip";
+        this.div.id = "zclip-" + this.movieId;
+        jQuery(this.domElement).data('zclipId', 'zclip-' + this.movieId);
+        var style = this.div.style;
+        style.position = 'absolute';
+        style.left = '' + box.left + 'px';
+        style.top = '' + box.top + 'px';
+        style.width = '' + box.width + 'px';
+        style.height = '' + box.height + 'px';
+        style.zIndex = zIndex;
+
+        if (typeof(stylesToAdd) == 'object') {
+            for (addedStyle in stylesToAdd) {
+                style[addedStyle] = stylesToAdd[addedStyle];
+            }
+        }
+
+        // style.backgroundColor = '#f00'; // debug
+        appendElem.appendChild(this.div);
+
+        this.div.innerHTML = this.getHTML(box.width, box.height);
+    },
+
+    getHTML: function (width, height) {
+        // return HTML for movie
+        var html = '';
+        var flashvars = 'id=' + this.id + '&width=' + width + '&height=' + height;
+
+        if (navigator.userAgent.match(/MSIE/)) {
+            // IE gets an OBJECT tag
+            var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
+            html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="' + protocol + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="' + width + '" height="' + height + '" id="' + this.movieId + '" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + ZeroClipboard.moviePath + '" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="' + flashvars + '"/><param name="wmode" value="transparent"/></object>';
+        } else {
+            // all other browsers get an EMBED tag
+            html += '<embed id="' + this.movieId + '" src="' + ZeroClipboard.moviePath + '" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="' + width + '" height="' + height + '" name="' + this.movieId + '" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="' + flashvars + '" wmode="transparent" />';
+        }
+        return html;
+    },
+
+    hide: function () {
+        // temporarily hide floater offscreen
+        if (this.div) {
+            this.div.style.left = '-2000px';
+        }
+    },
+
+    show: function () {
+        // show ourselves after a call to hide()
+        this.reposition();
+    },
+
+    destroy: function () {
+        // destroy control and floater
+        if (this.domElement && this.div) {
+            this.hide();
+            this.div.innerHTML = '';
+
+            var body = document.getElementsByTagName('body')[0];
+            try {
+                body.removeChild(this.div);
+            } catch (e) {;
+            }
+
+            this.domElement = null;
+            this.div = null;
+        }
+    },
+
+    reposition: function (elem) {
+        // reposition our floating div, optionally to new container
+        // warning: container CANNOT change size, only position
+        if (elem) {
+            this.domElement = ZeroClipboard.jQuery(elem);
+            if (!this.domElement) this.hide();
+        }
+
+        if (this.domElement && this.div) {
+            var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
+            var style = this.div.style;
+            style.left = '' + box.left + 'px';
+            style.top = '' + box.top + 'px';
+        }
+    },
+
+    setText: function (newText) {
+        // set text to be copied to clipboard
+        this.clipText = newText;
+        if (this.ready) {
+            this.movie.setText(newText);
+        }
+    },
+
+    addEventListener: function (eventName, func) {
+        // add user event listener for event
+        // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
+        eventName = eventName.toString().toLowerCase().replace(/^on/, '');
+        if (!this.handlers[eventName]) {
+            this.handlers[eventName] = [];
+        }
+        this.handlers[eventName].push(func);
+    },
+
+    setHandCursor: function (enabled) {
+        // enable hand cursor (true), or default arrow cursor (false)
+        this.handCursorEnabled = enabled;
+        if (this.ready) {
+            this.movie.setHandCursor(enabled);
+        }
+    },
+
+    setCSSEffects: function (enabled) {
+        // enable or disable CSS effects on DOM container
+        this.cssEffects = !! enabled;
+    },
+
+    receiveEvent: function (eventName, args) {
+        // receive event from flash
+        eventName = eventName.toString().toLowerCase().replace(/^on/, '');
+
+        // special behavior for certain events
+        switch (eventName) {
+        case 'load':
+            // movie claims it is ready, but in IE this isn't always the case...
+            // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
+            this.movie = document.getElementById(this.movieId);
+            if (!this.movie) {
+                var self = this;
+                setTimeout(function () {
+                    self.receiveEvent('load', null);
+                }, 1);
+                return;
+            }
+
+            // firefox on pc needs a "kick" in order to set these in certain cases
+            if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
+                var self = this;
+                setTimeout(function () {
+                    self.receiveEvent('load', null);
+                }, 100);
+                this.ready = true;
+                return;
+            }
+
+            this.ready = true;
+            try {
+                this.movie.setText(this.clipText);
+            } catch (e) {}
+            try {
+                this.movie.setHandCursor(this.handCursorEnabled);
+            } catch (e) {}
+            break;
+
+        case 'mouseover':
+            if (this.domElement && this.cssEffects) {
+                this.domElement.addClass('hover');
+                if (this.recoverActive) {
+                    this.domElement.addClass('active');
+                }
+
+
+            }
+
+
+            break;
+
+        case 'mouseout':
+            if (this.domElement && this.cssEffects) {
+                this.recoverActive = false;
+                if (this.domElement.hasClass('active')) {
+                    this.domElement.removeClass('active');
+                    this.recoverActive = true;
+                }
+                this.domElement.removeClass('hover');
+
+            }
+            break;
+
+        case 'mousedown':
+            if (this.domElement && this.cssEffects) {
+                this.domElement.addClass('active');
+            }
+            break;
+
+        case 'mouseup':
+            if (this.domElement && this.cssEffects) {
+                this.domElement.removeClass('active');
+                this.recoverActive = false;
+            }
+            break;
+        } // switch eventName
+        if (this.handlers[eventName]) {
+            for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
+                var func = this.handlers[eventName][idx];
+
+                if (typeof(func) == 'function') {
+                    // actual function reference
+                    func(this, args);
+                } else if ((typeof(func) == 'object') && (func.length == 2)) {
+                    // PHP style object + method, i.e. [myObject, 'myMethod']
+                    func[0][func[1]](this, args);
+                } else if (typeof(func) == 'string') {
+                    // name of function
+                    window[func](this, args);
+                }
+            } // foreach event handler defined
+        } // user defined handler for event
+    }
+
+};	
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
index ae7e283..204a5ac 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
@@ -103,6 +103,7 @@ colors
 }
 .headerContainer {
 	background: url("images/bg_header_brown.png") left top repeat;
+	height: 100px;
 }
 
 .headerContainer .links>span:first-child {
@@ -122,12 +123,44 @@ colors
 }
 
 #secondaryMenu {
-	width: 25%;
+    width: 25%;
+}
+
+#tertiaryMenu {
+    width: 8%;
+}
+#tertiaryMenu .imgLinks {
+	line-height: 30px;
+	font-size: 3em;
+	margin-right:20px;
+}
+
+#tertiaryMenu .imgLinks a {
+    background-image: url("copy-26.png"); 
+    background-position: right;
+    background-repeat: no-repeat;
+    cursor: pointer;
+}
+
+#tertiaryMenu  a.copyLink:hover,
+#tertiaryMenu  a.copyLink.hover {
+    cursor: pointer;
+}
+
+#tertiaryMenu  a.copyLink:active,
+#tertiaryMenu  a.copyLink.active {
+    cursor: pointer;
+}
+
+
+#secondaryMenu,
+#tertiaryMenu {
 	display: inline-block;
 	float: right;
 	text-align: right;
     margin-right: 5px;
 }
+
 #header h1 {
 	margin: 10px 10px 10px 0px;
 	font-size: xx-large;
@@ -222,6 +255,8 @@ colors
     padding-left: 10px;
     height:40px;
     margin-left: 10px;
+    width: 73%;
+    float: left;
 }
 
 #applicationActions .menuh {
@@ -230,112 +265,112 @@ colors
 	z-index:501;
 }
 
-	#applicationActions .menuh ul.cssMenuItems {
-		line-height:30px;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh a:link, 
-	#applicationActions .cssMenuPanel .menuh a:visited, 
-	#applicationActions .cssMenuPanel .menuh a:active, 
-	#applicationActions .cssMenuPanel .menuh p {
-		background-color: transparent;
-    	color: #FFFFFF;
-    	text-decoration: none;
-    	text-transform:uppercase;
-    	font-size:0.9em;
-    	font-weight:bold;
-	}
-	
-    #applicationActions .cssMenuPanel .menuh a.prototype span {
-	    color: #CCCC00;
-	    font-style: italic;
-	}
-	
-	
-	#applicationActions .cssMenuPanel .menuh li a:link, 
-	#applicationActions .cssMenuPanel .menuh li a:visited, 
-	#applicationActions .cssMenuPanel .menuh li a:active, 
-	#applicationActions .cssMenuPanel .menuh li p {
-		border-radius:4px 4px 0px 0px;
-    	-moz-border-radius:4px 4px 0px 0px;
-    	-webkit-border-radius:4px 4px 0px 0px;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh li li a:link, 
-	#applicationActions .cssMenuPanel .menuh li li a:visited, 
-	#applicationActions .cssMenuPanel .menuh li li a:active, 
-	#applicationActions .cssMenuPanel .menuh li li p {
-		border-radius:0px;
-    	-moz-border-radius:0px;
-    	-webkit-border-radius:0px;
-		background-color: #20B5C2;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh li li:last-child a:link, 
-	#applicationActions .cssMenuPanel .menuh li li:last-child a:visited, 
-	#applicationActions .cssMenuPanel .menuh li li:last-child a:active, 
-	#applicationActions .cssMenuPanel .menuh li li:last-child p {
-		border-radius:0px 0px 4px 4px;
-		-webkit-border-radius:0px 0px 4px 4px;
-		-moz-border-radius:0px 0px 4px 4px;
-		background-color: #20B5C2;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh li li:first-child a:link, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child a:visited, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child a:active, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child p {
-		border-radius:0px 4px 0px 0px;
-		-webkit-border-radius:0px 4px 0px 0px;
-		-moz-border-radius:0px 4px 0px 0px;
-		background-color: #20B5C2;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:link, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:visited, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:active, 
-	#applicationActions .cssMenuPanel .menuh li li:first-child:last-child p {
-		border-radius:0px 4px 4px 4px;
-		-webkit-border-radius:0px 4px 4px 4px;
-		-moz-border-radius:0px 4px 4px 4px;
-		background-color: #20B5C2;
-	}
-	
-	
-	#applicationActions .menuh a, 
-	#applicationActions .menuh p {
-	    border: 0px solid #00477F;
-	    padding: 0px 1em 0px 1em;
-	    background-image:none !important;
-	}
+#applicationActions .menuh ul.cssMenuItems {
+	line-height:30px;
+}
+
+#applicationActions .cssMenuPanel .menuh a:link, 
+#applicationActions .cssMenuPanel .menuh a:visited, 
+#applicationActions .cssMenuPanel .menuh a:active, 
+#applicationActions .cssMenuPanel .menuh p {
+	background-color: transparent;
+   	color: #FFFFFF;
+   	text-decoration: none;
+   	text-transform:uppercase;
+   	font-size:0.9em;
+   	font-weight:bold;
+}
+
+   #applicationActions .cssMenuPanel .menuh a.prototype span {
+    color: #CCCC00;
+    font-style: italic;
+}
+
+
+#applicationActions .cssMenuPanel .menuh li a:link, 
+#applicationActions .cssMenuPanel .menuh li a:visited, 
+#applicationActions .cssMenuPanel .menuh li a:active, 
+#applicationActions .cssMenuPanel .menuh li p {
+	border-radius:4px 4px 0px 0px;
+   	-moz-border-radius:4px 4px 0px 0px;
+   	-webkit-border-radius:4px 4px 0px 0px;
+}
+
+#applicationActions .cssMenuPanel .menuh li li a:link, 
+#applicationActions .cssMenuPanel .menuh li li a:visited, 
+#applicationActions .cssMenuPanel .menuh li li a:active, 
+#applicationActions .cssMenuPanel .menuh li li p {
+	border-radius:0px;
+   	-moz-border-radius:0px;
+   	-webkit-border-radius:0px;
+	background-color: #20B5C2;
+}
+
+#applicationActions .cssMenuPanel .menuh li li:last-child a:link, 
+#applicationActions .cssMenuPanel .menuh li li:last-child a:visited, 
+#applicationActions .cssMenuPanel .menuh li li:last-child a:active, 
+#applicationActions .cssMenuPanel .menuh li li:last-child p {
+	border-radius:0px 0px 4px 4px;
+	-webkit-border-radius:0px 0px 4px 4px;
+	-moz-border-radius:0px 0px 4px 4px;
+	background-color: #20B5C2;
+}
+
+#applicationActions .cssMenuPanel .menuh li li:first-child a:link, 
+#applicationActions .cssMenuPanel .menuh li li:first-child a:visited, 
+#applicationActions .cssMenuPanel .menuh li li:first-child a:active, 
+#applicationActions .cssMenuPanel .menuh li li:first-child p {
+	border-radius:0px 4px 0px 0px;
+	-webkit-border-radius:0px 4px 0px 0px;
+	-moz-border-radius:0px 4px 0px 0px;
+	background-color: #20B5C2;
+}
+
+#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:link, 
+#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:visited, 
+#applicationActions .cssMenuPanel .menuh li li:first-child:last-child a:active, 
+#applicationActions .cssMenuPanel .menuh li li:first-child:last-child p {
+	border-radius:0px 4px 4px 4px;
+	-webkit-border-radius:0px 4px 4px 4px;
+	-moz-border-radius:0px 4px 4px 4px;
+	background-color: #20B5C2;
+}
 
-	#applicationActions .cssMenuPanel .menuh li:hover a, 
-	#applicationActions .cssMenuPanel .menuh li:hover p {
-		color: #FFFFFF;
-		background-color: #20B5C2;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh a:hover, 
-	#applicationActions .cssMenuPanel .menuh p:hover {
-		color: #FFFFFF;
-		background-color: #20B5C2;
-	}
-	
-	#applicationActions .cssMenuPanel .menuh li li a:hover, 
-	#applicationActions .cssMenuPanel .menuh li li p:hover {
-		color: #FFFFFF;
-		background-color: #40C0CB !important;
-	}
-	
-	#applicationActions ul.cssSubMenuItemsPanel {
-		min-width:220px;
-	}
-	
-    #applicationActions ul.cssSubMenuItemsPanel li.cssSubMenuItem p.disabled {
-        color: lightgray;
-        /*background-color: #F0EFEA;*/
-        
-    } 
+
+#applicationActions .menuh a, 
+#applicationActions .menuh p {
+    border: 0px solid #00477F;
+    padding: 0px 1em 0px 1em;
+    background-image:none !important;
+}
+
+#applicationActions .cssMenuPanel .menuh li:hover a, 
+#applicationActions .cssMenuPanel .menuh li:hover p {
+	color: #FFFFFF;
+	background-color: #20B5C2;
+}
+
+#applicationActions .cssMenuPanel .menuh a:hover, 
+#applicationActions .cssMenuPanel .menuh p:hover {
+	color: #FFFFFF;
+	background-color: #20B5C2;
+}
+
+#applicationActions .cssMenuPanel .menuh li li a:hover, 
+#applicationActions .cssMenuPanel .menuh li li p:hover {
+	color: #FFFFFF;
+	background-color: #40C0CB !important;
+}
+
+#applicationActions ul.cssSubMenuItemsPanel {
+	min-width:220px;
+}
+
+   #applicationActions ul.cssSubMenuItemsPanel li.cssSubMenuItem p.disabled {
+       color: lightgray;
+       /*background-color: #F0EFEA;*/
+       
+   } 
 
 
 /**************** ELEMENTS **************/
@@ -917,3 +952,17 @@ div.wicket-mask-dark {
 }
 
 
+
+/*
+.copyLink {
+	font-family: arial, helvetica, sans-serif;
+	
+	background-color: transparent;
+	color: #FFFFFF;
+	text-decoration: none;
+	text-transform: uppercase;
+	font-size: 0.9em;
+	font-weight: bold;
+	float:right;
+}
+*/
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
index dd6d977..5056d66 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html
@@ -53,9 +53,16 @@
 
 			<div class="clear"/>
 
-			<div wicket:id="applicationActions" id="applicationActions"></div>
-			
-			</div>
+			<div wicket:id="applicationActions" id="applicationActions"/>
+            <div id="tertiaryMenu">
+                <div class="imgLinks">
+                    <a wicket:id="copyLink" href="#">
+                        <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+                    </a>
+                </div>
+            </div>
+
+		</div>
 
 			<div id="body">
 				<wicket:child/>

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
index 3d7f4b0..578aa50 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
@@ -28,24 +28,23 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
 import org.apache.wicket.Application;
-import org.apache.wicket.Component;
 import org.apache.wicket.RestartResponseAtInterceptPageException;
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.markup.head.CssReferenceHeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.head.OnLoadHeaderItem;
 import org.apache.wicket.markup.head.PriorityHeaderItem;
-import org.apache.wicket.markup.head.filter.FilteredHeaderItem;
 import org.apache.wicket.markup.head.filter.HeaderResponseContainer;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.ExternalLink;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.IRequestParameters;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
 import org.slf4j.Logger;
@@ -55,12 +54,13 @@ import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.MessageBroker;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.viewer.wicket.model.mementos.PageParameterNames;
-import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsBroadcastEvent;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
 import org.apache.isis.viewer.wicket.model.models.ApplicationActionsModel;
@@ -71,6 +71,7 @@ import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.components.actionprompt.ActionPromptModalWindow;
+import org.apache.isis.viewer.wicket.ui.components.widgets.zclip.ZeroClipboardLink;
 import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlUtil;
 import org.apache.isis.viewer.wicket.ui.pages.about.AboutPage;
@@ -99,12 +100,19 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
     public static final String ID_MENU_LINK = "menuLink";
     public static final String ID_LOGOUT_LINK = "logoutLink";
     public static final String ID_ABOUT_LINK = "aboutLink";
+    private static final String ID_COPY_LINK = "copyLink";
+
 
     private static final JavaScriptResourceReference JQUERY_JGROWL_JS = new JavaScriptResourceReference(PageAbstract.class, "jquery.jgrowl.js");
     /**
      * @see https://github.com/brandonaaron/livequery
      */
     private static final JavaScriptResourceReference JQUERY_LIVEQUERY_JS = new JavaScriptResourceReference(PageAbstract.class, "jquery.livequery.js");
+    /**
+     * @see https://github.com/patricklodder/jquery-zclip
+     * @see http://steamdev.com/zclip/
+     */
+    private static final JavaScriptResourceReference JQUERY_ZCLIP_JS = new JavaScriptResourceReference(ZeroClipboardLink.class, "jquery.zclip.js");
     private static final JavaScriptResourceReference JQUERY_ISIS_WICKET_VIEWER_JS = new JavaScriptResourceReference(PageAbstract.class, "jquery.isis.wicket.viewer.js");
     
     //private static final JavaScriptResourceReference BOOTSTRAP_JS = new JavaScriptResourceReference(PageAbstract.class, "bootstrap/js/bootstrap.min.js");
@@ -153,6 +161,7 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
             addUserName();
             addLogoutLink();
             addAboutLink();
+            addCopyLink();
             
             add(new Label(ID_PAGE_TITLE, title != null? title: applicationName));
             
@@ -199,6 +208,7 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference())));
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_JGROWL_JS));
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_LIVEQUERY_JS));
+        response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_ZCLIP_JS));
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_ISIS_WICKET_VIEWER_JS));
         
         final String feedbackMsg = JGrowlUtil.asJGrowlCalls(getMessageBroker());
@@ -251,6 +261,11 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         });
     }
 
+    private void addCopyLink() {
+        AjaxLink<ObjectAdapter> zClipCopyLink = new ZeroClipboardLink(ID_COPY_LINK, ".entityHeaderPanel a.entityUrlSource");
+        addOrReplace(zClipCopyLink);
+    }
+    
 
     /**
      * As provided in the {@link #PageAbstract(ComponentType) constructor}.
@@ -340,6 +355,23 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
 
     
     // ///////////////////////////////////////////////////////////////////
+    // UI Hint
+    // ///////////////////////////////////////////////////////////////////
+
+    /**
+     * Propogate any received events down to all child components.
+     */
+    public void onEvent(org.apache.wicket.event.IEvent<?> event) {
+        Object payload = event.getPayload();
+        if(payload instanceof UiHintsSetEvent) {
+            UiHintsSetEvent setEv = (UiHintsSetEvent)payload;
+            UiHintsBroadcastEvent broadcastEv = new UiHintsBroadcastEvent(setEv.getTarget());
+            send(this, Broadcast.BREADTH, broadcastEv);
+        }
+    }
+    
+
+    // ///////////////////////////////////////////////////////////////////
     // Convenience
     // ///////////////////////////////////////////////////////////////////
 
@@ -372,4 +404,6 @@ public abstract class PageAbstract extends WebPage implements ActionPromptProvid
         return IsisContext.getMessageBroker();
     }
 
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png
new file mode 100644
index 0000000..e9473c8
Binary files /dev/null and b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
index d34b217..b942a31 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
@@ -37,6 +37,7 @@ import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -87,7 +88,12 @@ public class EntityPage extends PageAbstract {
     private EntityPage(PageParameters pageParameters, EntityModel entityModel, String titleString) {
         super(pageParameters, ApplicationActions.INCLUDE, titleString, ComponentType.ENTITY);
         this.model = entityModel;
-        addChildComponents(model);
+        //try {
+        //    UiHintContainer.CURRENT.set(entityModel);
+            addChildComponents(model);
+        //} finally {
+        //    UiHintContainer.CURRENT.set(null);
+        //}
         
         final ObjectAndAction objectAndAction =lookupHomePageAction();
         final ActionModel actionModel = ActionModel.create(objectAndAction.objectAdapter, objectAndAction.action);

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
index cd7e2b9..8604da7 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.isis.wicket.viewer.js
@@ -68,6 +68,16 @@ $(document).ready(function() {
             }); 
         }); 
     
+    
+    
+//    $('a#zclip-copy').zclip({
+//        path:'/wicket/wicket/resource/org.apache.isis.viewer.wicket.ui.pages.PageAbstract/ZeroClipboard.swf',
+//        copy:$('a#zclip-source').attr("href")
+//    });
+//
+//    $('a#zclip-copy').zclip('show');
+
+    
 });
 
 /**

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelAbstract.java
index 32cfdee..adc0443 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelAbstract.java
@@ -38,6 +38,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.Persistor;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.isis.PersistenceSessionProvider;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
@@ -79,6 +80,7 @@ public abstract class PanelAbstract<T extends IModel<?>> extends Panel implement
         this.componentType = ComponentType.lookup(id);
     }
 
+
     /**
      * Will be null if created using {@link #PanelAbstract(String, IModel)}.
      */
@@ -138,6 +140,14 @@ public abstract class PanelAbstract<T extends IModel<?>> extends Panel implement
         PanelUtil.renderHead(response, this.getClass());
     }
 
+    
+    // ///////////////////////////////////////////////////////////////////
+    // Hint support
+    // ///////////////////////////////////////////////////////////////////
+
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(this);
+    }
 
 
     // ///////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/selector/links/LinksSelectorPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/selector/links/LinksSelectorPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/selector/links/LinksSelectorPanelAbstract.java
index 36c1148..f8003b5 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/selector/links/LinksSelectorPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/selector/links/LinksSelectorPanelAbstract.java
@@ -32,6 +32,7 @@ import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
@@ -42,6 +43,9 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 
 import org.apache.isis.core.commons.lang.StringExtensions;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.links.LinksProvider;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
@@ -53,7 +57,7 @@ import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
 import org.apache.isis.viewer.wicket.ui.util.Components;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
-public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends PanelAbstract<T> {
+public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends PanelAbstract<T> implements UiHintPathSignificant {
 
     private static final long serialVersionUID = 1L;
 
@@ -70,6 +74,7 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
     private static final String ID_VIEW_TITLE = "viewTitle";
 
     private final ComponentType componentType;
+    private final String underlyingIdPrefix;
     
     private ComponentFactory selectedComponentFactory;
     protected Component selectedComponent;
@@ -81,13 +86,21 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
      */
     protected WebMarkupContainer additionalLinks;
 
+
     public LinksSelectorPanelAbstract(final String id, final String underlyingIdPrefix, final T model, final ComponentFactory factory) {
         super(id, model);
-
-        componentType = factory.getComponentType();
-
-        addAdditionalLinks(model);
-        addUnderlyingViews(underlyingIdPrefix, model, factory);
+        this.underlyingIdPrefix = underlyingIdPrefix;
+        this.componentType = factory.getComponentType();
+    }
+    
+    /**
+     * Build UI only after added to parent.
+     */
+    public void onInitialize() {
+        super.onInitialize();
+        ComponentFactory componentFactory = getComponentFactoryRegistry().findComponentFactoryElseFailFast(getComponentType(), getModel());
+        addAdditionalLinks(getModel());
+        addUnderlyingViews(underlyingIdPrefix, getModel(), componentFactory);
     }
 
     protected void addAdditionalLinks(final T model) {
@@ -111,11 +124,11 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
         additionalLinks = new AdditionalLinksPanel(ID_ADDITIONAL_LINKS, links);
         markupContainer.addOrReplace(additionalLinks);
     }
-
+    
     private void addUnderlyingViews(final String underlyingIdPrefix, final T model, final ComponentFactory factory) {
         final List<ComponentFactory> componentFactories = findOtherComponentFactories(model, factory);
 
-        final int selected = determineInitialFactory(componentFactories, model);
+        final int selected = determineView(componentFactories, model);
 
         final LinksSelectorPanelAbstract<T> selectorPanel = LinksSelectorPanelAbstract.this;
         
@@ -170,6 +183,12 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
                         private static final long serialVersionUID = 1L;
                         @Override
                         public void onClick(AjaxRequestTarget target) {
+                            LinksSelectorPanelAbstract<T> linksSelectorPanel = LinksSelectorPanelAbstract.this;
+                            UiHintContainer hintContainer = linksSelectorPanel.getUiHintContainer();
+                            if(hintContainer != null) {
+                                hintContainer.setHint(LinksSelectorPanelAbstract.this, "view", ""+underlyingViewNum);
+                                send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(target));
+                            }
                             
                             final T dummyModel = dummyOf(model);
                             for(int i=0; i<MAX_NUM_UNDERLYING_VIEWS; i++) {
@@ -181,6 +200,7 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
                                 applyCssVisibility(component, isSelected);
                                 component.setDefaultModel(isSelected? model: dummyModel);
                             }
+                            
                             selectorPanel.selectedComponentFactory = componentFactory;
                             selectorPanel.selectedComponent = underlyingViews[underlyingViewNum];
                             selectorPanel.onSelect(target);
@@ -216,6 +236,8 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
         }
     }
 
+
+
     /**
      * Overrideable hook.
      */
@@ -237,6 +259,23 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
         component.add(modifier);
     }
 
+    protected int determineView(final List<ComponentFactory> componentFactories, final IModel<?> model) {
+        UiHintContainer hintContainer = getUiHintContainer();
+        if(hintContainer != null) {
+            String hintValue = hintContainer.getHint(this, "view");
+            if(hintValue != null) {
+                return Integer.parseInt(hintValue);
+            }
+        }
+
+        int initialFactory = determineInitialFactory(componentFactories, model);
+        if(hintContainer != null) {
+            hintContainer.setHint(this, "view", ""+initialFactory);
+        }
+        return initialFactory;
+    }
+
+
     protected abstract int determineInitialFactory(final List<ComponentFactory> componentFactories, final IModel<?> model);
 
     private List<ComponentFactory> findOtherComponentFactories(final T model, final ComponentFactory ignoreFactory) {
@@ -254,10 +293,12 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
         return otherFactories;
     }
 
+    
     @Override
     public void renderHead(final IHeaderResponse response) {
         super.renderHead(response);
         PanelUtil.renderHead(response, LinksSelectorPanelAbstract.class);
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Links.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Links.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Links.java
index d8eeed5..5225c70 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Links.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Links.java
@@ -19,12 +19,15 @@
 package org.apache.isis.viewer.wicket.ui.util;
 
 import org.apache.wicket.Page;
+import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.form.SubmitLink;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
+import org.apache.isis.viewer.wicket.model.mementos.PageParameterNames;
+
 public final class Links {
 
     public static <T extends Page> AbstractLink newSubmitLink(final String linkId, final PageParameters pageParameters, final Class<T> pageClass) {
@@ -52,7 +55,30 @@ public final class Links {
 
     public static <T extends Page> AbstractLink newBookmarkablePageLink(
             final String linkId, final PageParameters pageParameters, final Class<T> pageClass) {
+
         return new BookmarkablePageLink<T>(linkId, pageClass, pageParameters);
     }
 
+    public static <T extends Page> AbstractLink newBookmarkablePageLinkWithHints(
+            final String linkId, final PageParameters pageParameters, final Class<T> pageClass) {
+
+        final String hints = PageParameterNames.HINTS.getStringFrom(pageParameters);
+        if(hints != null) {
+            PageParameterNames.HINTS.removeFrom(pageParameters);
+            return new BookmarkablePageLink<T>(linkId, pageClass, pageParameters) {
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                protected CharSequence appendAnchor(ComponentTag tag, CharSequence url) {
+                    if(url != null) {
+                        url = url + "#" + hints;
+                    }
+                    return url;
+                }
+            };
+        } else {
+            return newBookmarkablePageLink(linkId, pageParameters, pageClass);
+        }
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index d1477f7..eb881ab 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -77,11 +77,15 @@
 * Twitter Bootstrap, licensed under ASL v2 [2]
 * JGrowl (JQuery plugin), licensed under MIT license [3]
 * LiveQuery (JQuery plugin), licensed under MIT license [4]
+* ZClip (JQuery plugin), licensed under MIT license [5]
+* ZeroClipboard library, licensed under MIT license [6]
 
 [1] http://jquery.org/license/
 [2] http://getbootstrap.com/2.3.2/
 [3] https://github.com/stanlemon/jGrowl/blob/master/jquery.jgrowl.js
-[4] https://github.com/brandonaaron/livequery#license</license.additional-notes>        
+[4] https://github.com/brandonaaron/livequery#license
+[5] http://www.steamdev.com/zclip/
+[6] https://github.com/zeroclipboard/ZeroClipboard</license.additional-notes>        
     </properties>
 
     <scm>

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 73863e1..a81430c 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -228,7 +228,7 @@ public class ToDoItems {
         
         container.persist(toDoItem);
         container.flush();
-        container.informUser("new todo item created!");
+
         return toDoItem;
     }
     

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
index 8015da3..1c07e08 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
@@ -111,6 +111,10 @@
         <filter-name>ResourceCachingFilter</filter-name>
         <url-pattern>*.html</url-pattern>
     </filter-mapping>
+    <filter-mapping>
+        <filter-name>ResourceCachingFilter</filter-name>
+        <url-pattern>*.swf</url-pattern>
+    </filter-mapping>
     
     <servlet>
         <servlet-name>Resource</servlet-name>
@@ -140,6 +144,10 @@
         <servlet-name>Resource</servlet-name>
         <url-pattern>*.html</url-pattern>
     </servlet-mapping>
+    <servlet-mapping>
+        <servlet-name>Resource</servlet-name>
+        <url-pattern>*.swf</url-pattern>
+    </servlet-mapping>
     
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml b/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
index 6edf0c8..c718385 100644
--- a/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
+++ b/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/web.xml
@@ -111,6 +111,10 @@
         <filter-name>ResourceCachingFilter</filter-name>
         <url-pattern>*.html</url-pattern>
     </filter-mapping>
+    <filter-mapping>
+        <filter-name>ResourceCachingFilter</filter-name>
+        <url-pattern>*.swf</url-pattern>
+    </filter-mapping>
     
     <servlet>
         <servlet-name>Resource</servlet-name>
@@ -140,6 +144,10 @@
         <servlet-name>Resource</servlet-name>
         <url-pattern>*.html</url-pattern>
     </servlet-mapping>
+    <servlet-mapping>
+        <servlet-name>Resource</servlet-name>
+        <url-pattern>*.swf</url-pattern>
+    </servlet-mapping>
     
 
 


[4/4] git commit: ISIS-638: ui hints and clipboard behaviour

Posted by da...@apache.org.
ISIS-638: ui hints and clipboard behaviour

Now captures view selection/page number/sorting for tables

New stuff:
* UiHintContainer (implemented by EntityModel)
* overrides of the various AjaxPaging widgets to send UiSetHint to owning page
* broadcast of UiHintEvents to all children
* subscription of hint events by EntityIconAndTitlePanel
* ZipClipboardLink, copy href from EntityIconAndTitlePanel

Also updated the archetypes web.xmls


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

Branch: refs/heads/master
Commit: bb2d31e1d15cfba5fb7a220b916cc52696e42ecb
Parents: 9eae01f
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 20 15:17:04 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 20 15:17:04 2013 +0000

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java    |  20 +-
 .../ComponentFactoryRegistryDefault.java        |   2 +
 .../wicket/model/hints/UiHintContainer.java     |  42 ++
 .../model/hints/UiHintPathSignificant.java      |  21 +
 .../model/hints/UiHintsBroadcastEvent.java      |  17 +
 .../wicket/model/hints/UiHintsSetEvent.java     |  17 +
 .../model/mementos/PageParameterNames.java      |  12 +
 .../viewer/wicket/model/models/EntityModel.java | 153 +++++-
 .../wicket/ui/components/about/AboutPanel.java  |   1 +
 .../components/collection/CollectionPanel.java  |  13 +-
 .../CollectionContentsAsAjaxTablePanel.java     |  75 ++-
 .../ajaxtable/IsisAjaxFallbackDataTable.java    |  25 +-
 .../IsisAjaxFallbackHeadersToolbar.java         |  49 +-
 .../IsisAjaxFallbackOrderByBorder.java          |  79 +++
 .../ajaxtable/IsisAjaxHeadersToolbar.java       |  14 +-
 .../ajaxtable/IsisAjaxNavigationToolbar.java    |  37 ++
 .../ajaxtable/IsisAjaxPagingNavigation.java     |  43 ++
 .../IsisAjaxPagingNavigationIncrementLink.java  |  51 ++
 .../ajaxtable/IsisAjaxPagingNavigationLink.java |  52 ++
 .../ajaxtable/IsisAjaxPagingNavigator.java      |  52 ++
 .../CollectionContentsLinksSelectorPanel.java   |   7 +-
 .../collections/EntityCollectionsPanel.java     |   3 +-
 .../icontitle/EntityIconAndTitlePanel.css       |  17 +
 .../icontitle/EntityIconAndTitlePanel.html      |   2 +-
 .../icontitle/EntityIconAndTitlePanel.java      |  66 ++-
 .../entity/properties/EntityPropertiesForm.java |  10 +-
 .../links/EntityLinksSelectorPanel.java         |   7 +
 .../scalars/ScalarPanelTextFieldAbstract.java   |   1 -
 ...UiHintPathSignificantWebMarkupContainer.java |  34 ++
 .../FormComponentPanelAbstract.java             |  22 +
 .../components/widgets/zclip/ZeroClipboard.swf  | Bin 0 -> 1071 bytes
 .../widgets/zclip/ZeroClipboardLink.java        | 112 ++++
 .../ui/components/widgets/zclip/jquery.zclip.js | 507 +++++++++++++++++++
 .../viewer/wicket/ui/pages/PageAbstract.css     | 261 ++++++----
 .../viewer/wicket/ui/pages/PageAbstract.html    |  13 +-
 .../viewer/wicket/ui/pages/PageAbstract.java    |  46 +-
 .../isis/viewer/wicket/ui/pages/copy-26.png     | Bin 0 -> 476 bytes
 .../wicket/ui/pages/entity/EntityPage.java      |   8 +-
 .../ui/pages/jquery.isis.wicket.viewer.js       |  10 +
 .../viewer/wicket/ui/panels/PanelAbstract.java  |  10 +
 .../links/LinksSelectorPanelAbstract.java       |  57 ++-
 .../isis/viewer/wicket/ui/util/Links.java       |  26 +
 core/pom.xml                                    |   6 +-
 .../dom/src/main/java/dom/todo/ToDoItems.java   |   2 +-
 .../webapp/src/main/webapp/WEB-INF/web.xml      |   8 +
 .../webapp/src/main/webapp/WEB-INF/web.xml      |   8 +
 46 files changed, 1801 insertions(+), 217 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index d164be3..b767159 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.viewer.wicket.viewer;
 
+import java.net.URL;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -42,6 +43,7 @@ import org.apache.wicket.ConverterLocator;
 import org.apache.wicket.IConverterLocator;
 import org.apache.wicket.Page;
 import org.apache.wicket.RuntimeConfigurationType;
+import org.apache.wicket.SharedResources;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.core.request.mapper.MountedMapper;
@@ -52,8 +54,10 @@ import org.apache.wicket.markup.html.IHeaderResponseDecorator;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.Response;
+import org.apache.wicket.request.resource.ByteArrayResource;
 import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.settings.IRequestCycleSettings.RenderStrategy;
+import org.apache.wicket.util.resource.IResourceStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -88,11 +92,14 @@ import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistrar;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAndTitlePanel;
 import org.apache.isis.viewer.wicket.ui.components.entity.properties.EntityPropertiesForm;
 import org.apache.isis.viewer.wicket.ui.components.scalars.string.MultiLineStringPanel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItemPanel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssSubMenuItemsPanel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.zclip.ZeroClipboardLink;
 import org.apache.isis.viewer.wicket.ui.pages.BookmarkedPagesModelProvider;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassList;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
@@ -259,7 +266,11 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
 
             // prettier URLs
             mountPage("/entity/${objectOid}", PageType.ENTITY);
-            mountPage("/action/${objectOid}/${actionOwningSpec}/${actionId}/${actionType}/#{actionArgs}", PageType.ACTION_PROMPT);
+            mountPage("/action/${objectOid}/${actionOwningSpec}/${actionId}/${actionType}/~{actionArgs}", PageType.ACTION_PROMPT);
+            
+            SharedResources sharedResources = getSharedResources();
+            ZeroClipboardLink.addSharedResourceTo(sharedResources);
+            
             
         } catch(RuntimeException ex) {
             List<MetaModelInvalidException> mmies = Lists.newArrayList(
@@ -309,7 +320,12 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
 
     private void mountPage(final String mountPath, final PageType pageType) {
         final Class<? extends Page> pageClass = this.pageClassRegistry.getPageClass(pageType);
-        mount(new MountedMapper(mountPath, pageClass));
+        mount(new MountedMapper(mountPath, pageClass){
+            @Override
+            protected String getOptionalPlaceholder(String s) {
+                return getPlaceholder(s, '~');
+            }
+        });
     }
 
     private void buildCssBundle() {

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistryDefault.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistryDefault.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistryDefault.java
index e1d6058..41d89cf 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistryDefault.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistryDefault.java
@@ -36,6 +36,7 @@ import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.model.IModel;
 
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory.ApplicationAdvice;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
@@ -100,6 +101,7 @@ public class ComponentFactoryRegistryDefault implements ComponentFactoryRegistry
     // Public API
     // ///////////////////////////////////////////////////////
 
+    
     @Override
     public Component addOrReplaceComponent(final MarkupContainer markupContainer, final ComponentType componentType, final IModel<?> model) {
         final Component component = createComponent(componentType, model);

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintContainer.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintContainer.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintContainer.java
new file mode 100644
index 0000000..4041891
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintContainer.java
@@ -0,0 +1,42 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.model.hints;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+
+public interface UiHintContainer {
+
+    String getHint(Component component, String key);
+    
+    void setHint(Component component, String key, String value);
+
+    public static class Util {
+        private Util(){}
+        public static UiHintContainer hintContainerOf(Component component) {
+
+            if(component == null) {
+                return null;
+            }
+            IModel<?> model = component.getDefaultModel();
+            if(model instanceof UiHintContainer) {
+                return (UiHintContainer) model;
+            }
+            return hintContainerOf(component.getParent());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintPathSignificant.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintPathSignificant.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintPathSignificant.java
new file mode 100644
index 0000000..775ce99
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintPathSignificant.java
@@ -0,0 +1,21 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.model.hints;
+
+public interface UiHintPathSignificant {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsBroadcastEvent.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsBroadcastEvent.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsBroadcastEvent.java
new file mode 100644
index 0000000..0aa05f3
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsBroadcastEvent.java
@@ -0,0 +1,17 @@
+package org.apache.isis.viewer.wicket.model.hints;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+public class UiHintsBroadcastEvent
+{
+    private final AjaxRequestTarget target;
+    
+    public UiHintsBroadcastEvent(AjaxRequestTarget target) {
+        this.target = target;
+    }
+
+    public AjaxRequestTarget getTarget() {
+        return target;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsSetEvent.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsSetEvent.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsSetEvent.java
new file mode 100644
index 0000000..fe51798
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/hints/UiHintsSetEvent.java
@@ -0,0 +1,17 @@
+package org.apache.isis.viewer.wicket.model.hints;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+public class UiHintsSetEvent
+{
+    private final AjaxRequestTarget target;
+    
+    public UiHintsSetEvent(AjaxRequestTarget target) {
+        this.target = target;
+    }
+
+    public AjaxRequestTarget getTarget() {
+        return target;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PageParameterNames.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PageParameterNames.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PageParameterNames.java
index 14ce811..f9c52af 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PageParameterNames.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/PageParameterNames.java
@@ -41,6 +41,11 @@ public enum PageParameterNames {
     OBJECT_OID,
     
     /**
+     * Hints for the rendering of an entity.
+     */
+    HINTS,
+    
+    /**
      * Owning type of an action.
      * 
      * <p>
@@ -125,6 +130,13 @@ public enum PageParameterNames {
         addStringTo(pageParameters, someEnum.name());
     }
 
+    /**
+     * @param pageParameters
+     */
+    public void removeFrom(PageParameters pageParameters) {
+        pageParameters.remove(this.toString());
+    }
+
 
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
index 8060c35..b503db2 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
@@ -21,13 +21,20 @@ package org.apache.isis.viewer.wicket.model.models;
 
 import java.io.Serializable;
 import java.util.Map;
+import java.util.Set;
 
+import com.google.common.base.Joiner;
 import com.google.common.collect.Maps;
 
+import org.apache.wicket.Component;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.util.string.PrependingStringBuffer;
+import org.apache.wicket.util.string.StringValue;
+import org.apache.wicket.util.string.Strings;
 
 import org.apache.isis.applib.annotation.BookmarkPolicy;
+import org.apache.isis.applib.services.viewmodelsupport.ViewModelSupport.Memento;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
@@ -41,7 +48,10 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.ObjectSpecifications.MemberGroupLayoutHint;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.runtime.services.viewmodelsupport.ViewModelSupportDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.mementos.PageParameterNames;
 import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
@@ -53,7 +63,7 @@ import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
  * So that the model is {@link Serializable}, the {@link ObjectAdapter} is
  * stored as a {@link ObjectAdapterMemento}.
  */
-public class EntityModel extends BookmarkableModel<ObjectAdapter> {
+public class EntityModel extends BookmarkableModel<ObjectAdapter> implements UiHintContainer {
 
     private static final long serialVersionUID = 1L;
     
@@ -79,8 +89,7 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
         } else {
             // don't do anything; instead the page should be redirected back to
             // an EntityPage so that the underlying EntityModel that contains
-            // the
-            // memento for the transient ObjectAdapter can be accessed.
+            // the memento for the transient ObjectAdapter can be accessed.
         }
         return pageParameters;
     }
@@ -139,6 +148,8 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
      */
     private ConcurrencyException concurrencyException;
 
+    private final HintPageParameterSerializer hintPageParameterSerializer = new HintPageParameterSerializerDirect();
+
     // //////////////////////////////////////////////////////////
     // constructors
     // //////////////////////////////////////////////////////////
@@ -149,8 +160,8 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
 
     public EntityModel(final PageParameters pageParameters) {
         this(ObjectAdapterMemento.createPersistent(rootOidFrom(pageParameters)));
+        hintPageParameterSerializer.pageParametersToHints(pageParameters, this.hints);
     }
-
     public EntityModel(final ObjectAdapter adapter) {
         this(ObjectAdapterMemento.createOrNull(adapter));
         setObject(adapter);
@@ -158,7 +169,7 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
 
     public EntityModel(final ObjectAdapterMemento adapterMemento) {
         this.adapterMemento = adapterMemento;
-        pendingModel = new PendingModel(this);
+        this.pendingModel = new PendingModel(this);
     }
 
     private static String oidStr(final PageParameters pageParameters) {
@@ -174,10 +185,85 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
     // BookmarkableModel
     //////////////////////////////////////////////////
 
+    
     @Override
     public PageParameters getPageParameters() {
-        return createPageParameters(getObject());
+        PageParameters pageParameters = createPageParameters(getObject());
+        hintPageParameterSerializer.hintsToPageParameters(hints, pageParameters);
+        return pageParameters;
+    }
+
+
+    static interface HintPageParameterSerializer {
+        public void hintsToPageParameters(Map<String,String> hints, PageParameters pageParameters);
+        public void pageParametersToHints(final PageParameters pageParameters, Map<String,String> hints);
+    }
+    
+    static class HintPageParameterSerializerDirect implements HintPageParameterSerializer, Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public void hintsToPageParameters(Map<String,String> hints, PageParameters pageParameters) {
+            Set<String> hintKeys = hints.keySet();
+            for (String key : hintKeys) {
+                String value = hints.get(key);
+                pageParameters.add("hint-" + key, value);
+            }
+        }
+
+        @Override
+        public void pageParametersToHints(final PageParameters pageParameters, Map<String,String> hints) {
+            Set<String> namedKeys = pageParameters.getNamedKeys();
+            for (String namedKey : namedKeys) {
+                if(namedKey.startsWith("hint-")) {
+                    String value = pageParameters.get(namedKey).toString(null);
+                    String key = namedKey.substring(5);
+                    hints.put(key, value); // may replace
+                }
+            }
+        }
+    }
+    
+    static class HintPageParameterSerializerUsingViewModelSupport implements HintPageParameterSerializer, Serializable {
+        private static final long serialVersionUID = 1L;
+
+        public void hintsToPageParameters(Map<String,String> hints, PageParameters pageParameters) {
+            if(hints.isEmpty()) {
+                return;
+            }
+            ViewModelSupportDefault vms = new ViewModelSupportDefault();
+            Memento memento = vms.create();
+            Set<String> hintKeys = hints.keySet();
+            for (String key : hintKeys) {
+                String safeKey = key.replace(':', '_');
+                Serializable value = hints.get(key);
+                memento.set(safeKey, value);
+            }
+            String serializedHints = memento.asString();
+            PageParameterNames.HINTS.addStringTo(pageParameters, serializedHints);
+        }
+
+        public void pageParametersToHints(final PageParameters pageParameters, Map<String,String> hints) {
+            String hintsStr = PageParameterNames.HINTS.getStringFrom(pageParameters);
+            if(hintsStr != null) {
+                try {
+                    Memento memento = new ViewModelSupportDefault().parse(hintsStr);
+                    Set<String> keys = memento.keySet();
+                    for (String safeKey : keys) {
+                        String value = memento.get(safeKey, String.class);
+                        String key = safeKey.replace('_', ':');
+                        hints.put(key, value);
+                    }
+                } catch(RuntimeException ex) {
+                    // fail gracefully, ie ignore.
+                    System.err.println(ex);
+                }
+            }
+        }
     }
+    
+
+
 
     @Override
     public String getTitle() {
@@ -386,6 +472,60 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
     }
 
     
+    
+    // //////////////////////////////////////////////////////////
+    // Hint support
+    // //////////////////////////////////////////////////////////
+    
+    private final Map<String, String> hints = Maps.newTreeMap();
+    
+    public String getHint(final Component component, final String key) {
+        if(component == null) {
+            return null;
+        }
+        String hintKey = hintKey(component, key);
+        String value = hints.get(hintKey);
+        System.err.println("GET " + hintKey + "=" + value) ;
+        return value;
+    }
+    
+    @Override
+    public void setHint(Component component, String key, String value) {
+        if(component == null) {
+            return;
+        }
+        String hintKey = hintKey(component, key);
+        System.err.println("PUT " + hintKey + "=" + value) ;
+        hints.put(hintKey, value);
+    }
+
+    
+    private static String hintKey(Component component, String key) {
+        return hintPathFor(component) + "-" + key;
+    }
+
+    private static String hintPathFor(Component component)
+    {
+        return Strings.afterFirstPathComponent(fullHintPathFor(component), Component.PATH_SEPARATOR);
+    }
+
+    private static String fullHintPathFor(Component component)
+    {
+        final PrependingStringBuffer buffer = new PrependingStringBuffer(32);
+        for (Component c = component; c != null; c = c.getParent())
+        {
+            if(c instanceof UiHintPathSignificant) {
+                if (buffer.length() > 0)
+                {
+                    buffer.prepend(Component.PATH_SEPARATOR);
+                }
+                buffer.prepend(c.getId());
+            }
+        }
+        return buffer.toString();
+    }
+
+    
     // //////////////////////////////////////////////////////////
     // concurrency exceptions
     // //////////////////////////////////////////////////////////
@@ -565,4 +705,5 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> {
 
 
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
index 04ae1c8..9d3ac09 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
@@ -61,4 +61,5 @@ public class AboutPanel extends PanelAbstract<AboutModel> {
         add(new JarManifestPanel(ID_MANIFEST_ATTRIBUTES, jarManifestModel));
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
index fc0e893..c65cbed 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -23,7 +23,6 @@ import java.util.List;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
@@ -37,7 +36,6 @@ import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.actionprompt.ActionPromptModalWindow;
 import org.apache.isis.viewer.wicket.ui.components.additionallinks.EntityActionUtil;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
-import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 
 /**
@@ -46,13 +44,14 @@ import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
  */
 public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implements ActionPromptProvider {
 
+
     private static final long serialVersionUID = 1L;
 
     private static final String ID_COLLECTION = "collection";
     private static final String ID_FEEDBACK = "feedback";
     private static final String ID_ACTION_PROMPT_MODAL_WINDOW = "actionPromptModalWindow";
 
-    private final Component collectionContents;
+    private Component collectionContents;
 
     private String collectionName;
     private Label label;
@@ -77,7 +76,15 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
         
         List<LinkAndLabel> entityActions = EntityActionUtil.entityActions(entityModel, otma, this);
         collectionModel.addEntityActions(entityActions);
+    }
+    
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
+        buildGui();
+    }
 
+    private void buildGui() {
         final WebMarkupContainer markupContainer = new WebMarkupContainer(ID_COLLECTION);
         collectionContents = getComponentFactoryRegistry().addOrReplaceComponent(markupContainer, ComponentType.COLLECTION_CONTENTS, getModel());
 

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index ce34577..03e3a96 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -29,7 +29,6 @@ import com.google.inject.Inject;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
@@ -51,6 +50,8 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
 import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
@@ -61,8 +62,8 @@ import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterPropertyColumn;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterTitleColumn;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuBuilder;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuBuilder;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 
@@ -70,9 +71,7 @@ import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
  * {@link PanelAbstract Panel} that represents a {@link EntityCollectionModel
  * collection of entity}s rendered using {@link AjaxFallbackDefaultDataTable}.
  */
-public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityCollectionModel> implements CollectionCountProvider, ActionPromptProvider {
-
-    private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
+public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityCollectionModel> implements CollectionCountProvider, ActionPromptProvider, UiHintPathSignificant {
 
     private static final long serialVersionUID = 1L;
 
@@ -80,11 +79,17 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
     private static final String ID_ENTITY_ACTIONS = "entityActions";
     private static final String ID_ACTION_PROMPT_MODAL_WINDOW = "actionPromptModalWindow";
 
+    private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
+    
     private DataTable<ObjectAdapter,String> dataTable;
 
     public CollectionContentsAsAjaxTablePanel(final String id, final EntityCollectionModel model) {
         super(id, model);
+    }
 
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
         buildGui();
     }
 
@@ -101,13 +106,32 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
 
         final SortableDataProvider<ObjectAdapter,String> dataProvider = new CollectionContentsSortableDataProvider(model);
         dataTable = new IsisAjaxFallbackDataTable<ObjectAdapter,String>(ID_TABLE, columns, dataProvider, model.getPageSize());
-
+        
         addActionPromptModalWindow();
         buildEntityActionsGui(bulkActions, this);
 
         addOrReplace(dataTable);
+        configureHintsFor(dataTable);
     }
-    
+
+    private void configureHintsFor(DataTable<ObjectAdapter, String> dataTable) {
+        UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        }
+        final String pageNumber = uiHintContainer.getHint(dataTable, "pageNumber");
+        if(pageNumber != null) {
+            try {
+                long parseLong = Long.parseLong(pageNumber);
+                dataTable.setCurrentPage(parseLong);
+            } catch(Exception ex) {
+                // ignore.
+            }
+        }
+        final long currentPage = dataTable.getCurrentPage();
+        uiHintContainer.setHint(dataTable, "pageNumber", ""+currentPage);
+    }
+
     private void addToggleboxColumnIfRequired(final List<IColumn<ObjectAdapter,String>> columns, List<ObjectAction> bulkActions) {
         final EntityCollectionModel entityCollectionModel = getModel();
         if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
@@ -193,23 +217,6 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
     }
 
     
-    public boolean isExploring() {
-        return IsisContext.getDeploymentType().isExploring();
-    }
-    public boolean isPrototyping() {
-        return IsisContext.getDeploymentType().isPrototyping();
-    }
-
-    /**
-     * Protected so can be overridden in testing if required.
-     */
-    protected boolean isDebugMode() {
-        // TODO: need to figure out how to switch into debug mode;
-        // probably call a Debug toggle page, and stuff into
-        // Session.getMetaData()
-        return true;
-    }
-
 
     private void addTitleColumn(final List<IColumn<ObjectAdapter,String>> columns, ObjectAdapterMemento parentAdapterMementoIfAny, int maxTitleParented, int maxTitleStandalone) {
         int maxTitleLength = getModel().isParented()? maxTitleParented: maxTitleStandalone;
@@ -290,6 +297,26 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
 
 
     // //////////////////////////////////////
+    
+    public boolean isExploring() {
+        return IsisContext.getDeploymentType().isExploring();
+    }
+    public boolean isPrototyping() {
+        return IsisContext.getDeploymentType().isPrototyping();
+    }
+
+    /**
+     * Protected so can be overridden in testing if required.
+     */
+    protected boolean isDebugMode() {
+        // TODO: need to figure out how to switch into debug mode;
+        // probably call a Debug toggle page, and stuff into
+        // Session.getMetaData()
+        return true;
+    }
+
+
+    // //////////////////////////////////////
 
     @Inject
     private WicketViewerSettings settings;

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
index ceab997..ef9b869 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackDataTable.java
@@ -35,24 +35,35 @@ import org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.util.lang.Generics;
 
-public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S>
-{
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
+
+public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S> implements UiHintPathSignificant {
     private static final long serialVersionUID = 1L;
+    private final ISortableDataProvider<T, S> dataProvider;
 
     public IsisAjaxFallbackDataTable(final String id, final List<? extends IColumn<T, S>> columns,
         final ISortableDataProvider<T, S> dataProvider, final int rowsPerPage)
     {
         super(id, columns, dataProvider, rowsPerPage);
+        this.dataProvider = dataProvider;
         setOutputMarkupId(true);
         setVersioned(false);
-        addTopToolbar(new IsisAjaxFallbackHeadersToolbar<S>(this, dataProvider));
-        addBottomToolbar(new AjaxNavigationToolbar(this));
-        addBottomToolbar(new NoRecordsToolbar(this));
-        //setItemReuseStrategy(new ReuseIfModelsEqualStrategy());
         setItemReuseStrategy(new PreserveModelReuseStrategy());
     }
 
     @Override
+    protected void onInitialize() {
+        super.onInitialize();
+        buildGui();
+    }
+    
+    private void buildGui() {
+        addTopToolbar(new IsisAjaxFallbackHeadersToolbar<S>(this, this.dataProvider));
+        addBottomToolbar(new IsisAjaxNavigationToolbar(this));
+        addBottomToolbar(new NoRecordsToolbar(this));
+    }
+    
+    @Override
     protected Item<T> newRowItem(final String id, final int index, final IModel<T> model)
     {
         return new OddEvenItem<T>(id, index, model);
@@ -122,4 +133,6 @@ public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S>
         }
 
     }
+
+    
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
index daabcd5..7d4464b 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackHeadersToolbar.java
@@ -16,14 +16,17 @@
  */
 package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
 
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.attributes.IAjaxCallListener;
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.sort.AjaxFallbackOrderByBorder;
+import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackHeadersToolbar;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
+
 
 /**
  * Adapted from Wicket's own {@link AjaxFallbackHeadersToolbar}.
@@ -31,34 +34,42 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
 public class IsisAjaxFallbackHeadersToolbar<S> extends IsisAjaxHeadersToolbar<S>
 {
     private static final long serialVersionUID = 1L;
+    private final ISortStateLocator<S> stateLocator;
 
     public IsisAjaxFallbackHeadersToolbar(final DataTable<?, S> table, final ISortStateLocator<S> stateLocator)
     {
         super(table, stateLocator);
         table.setOutputMarkupId(true);
+        this.stateLocator = stateLocator;
+    }
+    
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer != null) {
+            for (SortOrder sortOrder : SortOrder.values()) {
+                String property = uiHintContainer.getHint(getTable(), sortOrder.name());
+                if(property != null) {
+                    // bit hacky... how know this is safe?
+                    S propertyS = (S) property;
+                    stateLocator.getSortState().setPropertySortOrder(propertyS, sortOrder);
+                }
+            }
+        }
+    }
+    
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(getTable());
     }
 
+
+
     @Override
     protected WebMarkupContainer newSortableHeader(final String borderId, final S property,
         final ISortStateLocator<S> locator)
     {
-        return new AjaxFallbackOrderByBorder<S>(borderId, property, locator, getAjaxCallListener())
-        {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void onAjaxClick(final AjaxRequestTarget target)
-            {
-                target.add(getTable());
-            }
-
-            @Override
-            protected void onSortChanged()
-            {
-                super.onSortChanged();
-                getTable().setCurrentPage(0);
-            }
-        };
+        return new IsisAjaxFallbackOrderByBorder<S>(borderId, getTable(), property, locator, getAjaxCallListener());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackOrderByBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackOrderByBorder.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackOrderByBorder.java
new file mode 100644
index 0000000..0f9f476
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxFallbackOrderByBorder.java
@@ -0,0 +1,79 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.IAjaxCallListener;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.sort.AjaxFallbackOrderByBorder;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
+
+public class IsisAjaxFallbackOrderByBorder<T> extends AjaxFallbackOrderByBorder<T> {
+
+    private static final long serialVersionUID = 1L;
+    
+    private final T sortProperty;
+    private final DataTable<?, ?> dataTable;
+
+    private final ISortStateLocator<T> stateLocator;
+    
+    public IsisAjaxFallbackOrderByBorder(String id, DataTable<?, ?> dataTable, T sortProperty, ISortStateLocator<T> stateLocator, IAjaxCallListener ajaxCallListener) {
+        super(id, sortProperty, stateLocator, ajaxCallListener);
+        this.dataTable = dataTable;
+        this.stateLocator = stateLocator;
+        this.sortProperty = sortProperty;
+    }
+
+    @Override
+    protected void onAjaxClick(final AjaxRequestTarget target)
+    {
+        target.add(dataTable);
+
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer != null) {
+            String hintKey = sortOrderName();
+            uiHintContainer.setHint(dataTable, hintKey, sortProperty.toString());
+            send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(target));
+        }
+    }
+
+    private String sortOrderName() {
+        final ISortState<T> state = stateLocator.getSortState();
+        final SortOrder order = state.getPropertySortOrder(sortProperty);
+        return order.name();
+    }
+
+    @Override
+    protected void onSortChanged()
+    {
+        super.onSortChanged();
+        dataTable.setCurrentPage(0);
+        
+    }
+    
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(dataTable);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxHeadersToolbar.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxHeadersToolbar.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxHeadersToolbar.java
index 05c9aa6..de6821c 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxHeadersToolbar.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxHeadersToolbar.java
@@ -131,20 +131,10 @@ public class IsisAjaxHeadersToolbar<S> extends AbstractToolbar
 
                 item.add(header);
                 item.setRenderBodyOnly(true);
+                Component label = new Label("label");
                 
-                Component label;
-                //Component checkBox;
-                //if(column instanceof ObjectAdapterToggleboxColumn) {
-                    label = new Label("label");
-                //    checkBox = column.getHeader("checkbox");
-                //    label.setVisible(false);
-                //} else {
-                    label = column.getHeader("label");
-                //    checkBox = new CheckBox("checkbox");
-                //    checkBox.setVisible(false);
-                // }
+                label = column.getHeader("label");
                 header.add(label);
-                //header.add(checkBox);
             }
         };
         add(headers);

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxNavigationToolbar.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxNavigationToolbar.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxNavigationToolbar.java
new file mode 100644
index 0000000..ddf893c
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxNavigationToolbar.java
@@ -0,0 +1,37 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxNavigationToolbar;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
+
+
+public class IsisAjaxNavigationToolbar extends AjaxNavigationToolbar {
+
+    private static final long serialVersionUID = 1L;
+
+    public IsisAjaxNavigationToolbar(DataTable<?, ?> table) {
+        super(table);
+    }
+
+    @Override
+    protected PagingNavigator newPagingNavigator(String navigatorId, DataTable<?, ?> table) {
+        return new IsisAjaxPagingNavigator(navigatorId, table);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigation.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigation.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigation.java
new file mode 100644
index 0000000..8ce5919
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigation.java
@@ -0,0 +1,43 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigation;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.navigation.paging.IPageable;
+import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
+
+
+public class IsisAjaxPagingNavigation extends AjaxPagingNavigation {
+
+    private static final long serialVersionUID = 1L;
+
+    public IsisAjaxPagingNavigation(String id, IPageable pageable, IPagingLabelProvider labelProvider) {
+        super(id, pageable, labelProvider);
+    }
+
+    public IsisAjaxPagingNavigation(String id, IPageable pageable) {
+        super(id, pageable);
+    }
+    
+    @Override
+    protected Link<?> newPagingNavigationLink(String id, IPageable pageable, long pageIndex) {
+        return new IsisAjaxPagingNavigationLink(id, pageable, pageIndex);
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationIncrementLink.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationIncrementLink.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationIncrementLink.java
new file mode 100644
index 0000000..019dfd4
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationIncrementLink.java
@@ -0,0 +1,51 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigationIncrementLink;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.markup.html.navigation.paging.IPageable;
+
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
+
+public class IsisAjaxPagingNavigationIncrementLink extends AjaxPagingNavigationIncrementLink {
+
+    private static final long serialVersionUID = 1L;
+    private final Component component;
+
+    public IsisAjaxPagingNavigationIncrementLink(String id, IPageable pageable, int increment) {
+        super(id, pageable, increment);
+        component = pageable instanceof Component ? (Component) pageable : null;
+    }
+
+    @Override
+    public void onClick(AjaxRequestTarget target) {
+        super.onClick(target);
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer != null) {
+            uiHintContainer.setHint(component, "pageNumber", ""+pageable.getCurrentPage());
+            send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(target));
+        }
+    }
+    
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(component);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationLink.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationLink.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationLink.java
new file mode 100644
index 0000000..62776f5
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigationLink.java
@@ -0,0 +1,52 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigationLink;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.markup.html.navigation.paging.IPageable;
+
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
+
+public class IsisAjaxPagingNavigationLink extends AjaxPagingNavigationLink {
+
+    private static final long serialVersionUID = 1L;
+    private final Component component;
+
+    public IsisAjaxPagingNavigationLink(String id, IPageable pageable, long pageNumber) {
+        super(id, pageable, pageNumber);
+        component = pageable instanceof Component ? (Component) pageable : null;
+    }
+
+    @Override
+    public void onClick(AjaxRequestTarget target) {
+        super.onClick(target);
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer != null) {
+            uiHintContainer.setHint(component, "pageNumber", ""+pageable.getCurrentPage());
+            send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(target));
+        }
+    }
+    
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(component);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigator.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigator.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigator.java
new file mode 100644
index 0000000..c20f8d7
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/IsisAjaxPagingNavigator.java
@@ -0,0 +1,52 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+
+import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.navigation.paging.IPageable;
+import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
+import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;
+
+
+public class IsisAjaxPagingNavigator extends AjaxPagingNavigator {
+
+    private static final long serialVersionUID = 1L;
+
+    public IsisAjaxPagingNavigator(String id, IPageable pageable, IPagingLabelProvider labelProvider) {
+        super(id, pageable, labelProvider);
+    }
+
+    public IsisAjaxPagingNavigator(String id, IPageable pageable) {
+        super(id, pageable);
+    }
+
+    @Override
+    protected AbstractLink newPagingNavigationLink(String id, IPageable pageable, int pageNumber) {
+        return new IsisAjaxPagingNavigationLink(id, pageable, pageNumber);
+    }
+
+    @Override
+    protected AbstractLink newPagingNavigationIncrementLink(String id, IPageable pageable, int increment) {
+        return new IsisAjaxPagingNavigationIncrementLink(id, pageable, increment);
+    }
+    
+    @Override
+    protected PagingNavigation newNavigation(String id, IPageable pageable, IPagingLabelProvider labelProvider) {
+        return new IsisAjaxPagingNavigation(id, pageable, labelProvider);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/selector/links/CollectionContentsLinksSelectorPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/selector/links/CollectionContentsLinksSelectorPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/selector/links/CollectionContentsLinksSelectorPanel.java
index 2546b6c..d3b9cb5 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/selector/links/CollectionContentsLinksSelectorPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/selector/links/CollectionContentsLinksSelectorPanel.java
@@ -30,6 +30,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.isis.applib.annotation.Render.Type;
 import org.apache.isis.core.metamodel.facets.members.resolve.RenderFacet;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
@@ -37,7 +38,6 @@ import org.apache.isis.viewer.wicket.ui.components.collection.CollectionCountPro
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanel;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsAsUnresolvedPanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.entity.collections.EntityCollectionsPanel;
 import org.apache.isis.viewer.wicket.ui.selector.links.LinksSelectorPanelAbstract;
 
 /**
@@ -62,6 +62,7 @@ public class CollectionContentsLinksSelectorPanel extends LinksSelectorPanelAbst
         return model.asDummy();
     }
 
+    
     /**
      * return the index of {@link CollectionContentsAsUnresolvedPanelFactory unresolved panel} if present and not eager loading;
      * else the index of {@link CollectionContentsAsAjaxTablePanelFactory ajax table} if present,
@@ -133,6 +134,10 @@ public class CollectionContentsLinksSelectorPanel extends LinksSelectorPanelAbst
      * Yeah, agreed, it's a little bit hacky doing it this way, because it bakes
      * in knowledge that this component is created, somehow, by a parent {@link CollectionPanel}.
      * Perhaps it could be refactored to use a more general purpose observer pattern?
+     * 
+     * <p>
+     * In fact, I've since discovered that Wicket has an event bus, which is used by the 
+     * {@link UiHintContainer hinting mechanism}.  So this ought to be relatively easy to do.
      */
     protected void onSelect(AjaxRequestTarget target) {
         super.onSelect(target);

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
index 8cd73b3..6a162f9 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
@@ -38,6 +38,7 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPathSignificantWebMarkupContainer;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 
@@ -89,7 +90,7 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> {
 
         for (final ObjectAssociation association : associations) {
 
-            final WebMarkupContainer collectionRvContainer = new WebMarkupContainer(collectionRv.newChildId());
+            final WebMarkupContainer collectionRvContainer = new UiHintPathSignificantWebMarkupContainer(collectionRv.newChildId());
             collectionRv.add(collectionRvContainer);
             
             addCollectionToForm(entityModel, association, collectionRvContainer);

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.css
index 9f1612a..aff2cf5 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.css
@@ -17,3 +17,20 @@
  *  under the License.
  */
 
+.entityIconAndTitlePanel a.zclip-copy {
+    background-image: url("../org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAndTitlePanel/copy-26.png"); 
+    background-position: right;
+    background-repeat: no-repeat;
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+.entityIconAndTitlePanel a.zclip-copy:hover,
+.entityIconAndTitlePanel a.zclip-copy.hover {
+	cursor: pointer;
+}
+
+.entityIconAndTitlePanel a.zclip-copy:active,
+.entityIconAndTitlePanel a.zclip-copy.active {
+    /* not required */
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.html
index df8cae4..bb9d9ed 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.html
@@ -21,7 +21,7 @@
 	<body>
 		<wicket:panel>
 		     <span wicket:id="entityLinkWrapper" class="entityIconAndTitlePanel entityIconAndTitleComponentType">
-				<a href="#" wicket:id="entityLink">
+				<a href="#" wicket:id="entityLink" class="entityUrlSource">
 					<img wicket:id="entityImage" class="entityImage"/>
 					<span wicket:id="entityTitle" class="entityTitle">[title]</span>
 				</a>

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
index ec7e2b8..c230924 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
@@ -19,28 +19,48 @@
 
 package org.apache.isis.viewer.wicket.ui.components.entity.icontitle;
 
+import java.net.ResponseCache;
+
+import com.google.common.base.Strings;
 import com.google.inject.Inject;
 
 import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
 import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.head.JavaScriptContentHeaderItem;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.image.Image;
 import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.cycle.RequestCycle;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.request.resource.ResourceReference;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsBroadcastEvent;
+import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
 import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.mementos.PageParameterNames;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ImageResourceCache;
 import org.apache.isis.viewer.wicket.model.models.PageType;
 import org.apache.isis.viewer.wicket.ui.components.entity.EntityActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.zclip.ZeroClipboardLink;
+import org.apache.isis.viewer.wicket.ui.errors.JGrowlUtil;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
 import org.apache.isis.viewer.wicket.ui.util.Links;
 
 /**
@@ -49,7 +69,6 @@ import org.apache.isis.viewer.wicket.ui.util.Links;
  */
 public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
 
-
     private static final long serialVersionUID = 1L;
 
     private static final String ID_ENTITY_LINK_WRAPPER = "entityLinkWrapper";
@@ -57,8 +76,9 @@ public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
     private static final String ID_ENTITY_TITLE = "entityTitle";
     private static final String ID_ENTITY_ICON = "entityImage";
 
-
+    @SuppressWarnings("unused")
     private Label label;
+    @SuppressWarnings("unused")
     private Image image;
 
     public EntityIconAndTitlePanel(final String id, final EntityModel entityModel) {
@@ -80,6 +100,7 @@ public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
 
     private void buildGui() {
         addOrReplaceLinkWrapper();
+        setOutputMarkupId(true);
     }
 
     private void addOrReplaceLinkWrapper() {
@@ -90,23 +111,25 @@ public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
     private WebMarkupContainer addOrReplaceLinkWrapper(final EntityModel entityModel) {
         final ObjectAdapter adapter = entityModel.getObject();
 
-        final PageParameters pageParameters = EntityModel.createPageParameters(adapter);
-        final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ENTITY);
-        
-        final AbstractLink link = newLink(ID_ENTITY_LINK, pageClass, pageParameters);
-        
-        link.addOrReplace(this.label = newLabel(ID_ENTITY_TITLE));
-        link.addOrReplace(this.image = newImage(ID_ENTITY_ICON, adapter));
+        final PageParameters pageParameters = entityModel.getPageParameters();
         
-        link.add(new AttributeModifier("title", adapter.getSpecification().getSingularName()));
+        final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ENTITY);
         
         final WebMarkupContainer entityLinkWrapper = new WebMarkupContainer(ID_ENTITY_LINK_WRAPPER);
+        final AbstractLink link = createIconAndTitle(adapter, pageParameters, pageClass);
         entityLinkWrapper.addOrReplace(link);
+        
         return entityLinkWrapper;
     }
 
-    protected AbstractLink newLink(final String linkId, final Class<? extends Page> pageClass, final PageParameters pageParameters) {
-        return Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
+    private AbstractLink createIconAndTitle(final ObjectAdapter adapter, final PageParameters pageParameters, final Class<? extends Page> pageClass) {
+        final AbstractLink link = Links.newBookmarkablePageLinkWithHints(ID_ENTITY_LINK, pageParameters, pageClass);
+        
+        link.addOrReplace(this.label = newLabel(ID_ENTITY_TITLE));
+        link.addOrReplace(this.image = newImage(ID_ENTITY_ICON, adapter));
+        
+        link.add(new AttributeModifier("title", adapter.getSpecification().getSingularName()));
+        return link;
     }
 
     protected Label newLabel(final String id) {
@@ -137,10 +160,9 @@ public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
     }
 
     protected Image newImage(final String id, final ObjectAdapter adapter) {
-        Image image;
         final ResourceReference imageResource = imageCache.resourceReferenceFor(adapter);
          
-        image = new Image(id, imageResource) {
+        final Image image = new Image(id, imageResource) {
             private static final long serialVersionUID = 1L;
             @Override
             protected boolean shouldAddAntiCacheParameter() {
@@ -166,6 +188,22 @@ public class EntityIconAndTitlePanel extends PanelAbstract<EntityModel> {
 
     
     // ///////////////////////////////////////////////////////////////////
+    // UI Hints
+    // ///////////////////////////////////////////////////////////////////
+    
+    /* (non-Javadoc)
+     * @see org.apache.wicket.Component#onEvent(org.apache.wicket.event.IEvent)
+     */
+    @Override
+    public void onEvent(IEvent<?> event) {
+        if(event.getPayload() instanceof UiHintsBroadcastEvent) {
+            UiHintsBroadcastEvent ev = (UiHintsBroadcastEvent) event.getPayload();
+            buildGui();
+            ev.getTarget().add(this);
+        }
+    }
+    
+    // ///////////////////////////////////////////////////////////////////
     // Convenience
     // ///////////////////////////////////////////////////////////////////
 

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index 54ca1a8..d13dc50 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -23,11 +23,15 @@ import java.util.Map;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.RestartResponseException;
 import org.apache.wicket.Session;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.attributes.IAjaxCallListener;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.core.request.handler.BookmarkablePageRequestHandler;
+import org.apache.wicket.core.request.handler.PageProvider;
+import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.Button;
@@ -37,6 +41,9 @@ import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
 import org.apache.wicket.markup.html.panel.FeedbackPanel;
 import org.apache.wicket.markup.repeater.RepeatingView;
 import org.apache.wicket.model.Model;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.handler.RedirectRequestHandler;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.util.visit.IVisit;
 import org.apache.wicket.util.visit.IVisitor;
 
@@ -65,6 +72,7 @@ import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPathSignificantWebMarkupContainer;
 import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
@@ -217,7 +225,7 @@ public class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
             @SuppressWarnings("unused")
             Component component;
             for (final ObjectAssociation association : associationsInGroup) {
-                final WebMarkupContainer propertyRvContainer = new WebMarkupContainer(propertyRv.newChildId());
+                final WebMarkupContainer propertyRvContainer = new UiHintPathSignificantWebMarkupContainer(propertyRv.newChildId());
                 propertyRv.add(propertyRvContainer);
                 addPropertyToForm(entityModel, association, propertyRvContainer);
             }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
index 36c8d2c..378f277 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/selector/links/EntityLinksSelectorPanel.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.apache.wicket.model.IModel;
 
+import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
@@ -54,4 +55,10 @@ public class EntityLinksSelectorPanel extends LinksSelectorPanelAbstract<EntityM
         return 0;
     }
 
+    @Override
+    public UiHintContainer getUiHintContainer() {
+        // disables hinting by this component
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/bb2d31e1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index 0d7c34e..2021994 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -32,7 +32,6 @@ import org.apache.wicket.model.Model;
 
 import org.apache.isis.core.metamodel.facets.SingleIntValueFacet;
 import org.apache.isis.core.metamodel.facets.maxlen.MaxLengthFacet;
-import org.apache.isis.core.metamodel.facets.multiline.MultiLineFacet;
 import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacet;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;