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/22 13:19:58 UTC

git commit: ISIS-638: fixing order that hints are applied...

Updated Branches:
  refs/heads/master f031f27b9 -> 2f4941b16


ISIS-638: fixing order that hints are applied...

... and some refactoring to centre responsibility for setting page/sort hints in the dataTable.


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

Branch: refs/heads/master
Commit: 2f4941b16e6e7f94faa4b3c0b5d4e8330d815b31
Parents: f031f27
Author: Dan Haywood <da...@apache.org>
Authored: Sun Dec 22 12:19:45 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Sun Dec 22 12:19:45 2013 +0000

----------------------------------------------------------------------
 .../wicket/model/hints/UiHintContainer.java     |  2 +
 .../viewer/wicket/model/models/EntityModel.java | 18 ++++-
 .../components/collection/CollectionPanel.java  |  7 +-
 .../CollectionContentsAsAjaxTablePanel.java     | 42 ++++------
 .../ajaxtable/IsisAjaxFallbackDataTable.java    | 80 +++++++++++++++++---
 .../IsisAjaxFallbackHeadersToolbar.java         | 47 +++++++-----
 .../IsisAjaxFallbackOrderByBorder.java          | 22 +++---
 .../IsisAjaxPagingNavigationIncrementLink.java  |  9 +--
 .../ajaxtable/IsisAjaxPagingNavigationLink.java | 10 +--
 .../CollectionContentsLinksSelectorPanel.java   | 16 +++-
 .../widgets/zclip/ZeroClipboardPanel.java       | 13 ++--
 .../viewer/wicket/ui/pages/PageAbstract.css     | 14 +---
 .../links/LinksSelectorPanelAbstract.java       | 28 +++++--
 .../viewer/wicket/ui/util/CssClassRemover.java  | 53 +++++++++++++
 14 files changed, 248 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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
index 4041891..7a2df82 100644
--- 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
@@ -25,6 +25,8 @@ public interface UiHintContainer {
     
     void setHint(Component component, String key, String value);
 
+    void clearHint(Component component, String key);
+
     public static class Util {
         private Util(){}
         public static UiHintContainer hintContainerOf(Component component) {

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 a2b53cf..7b07217 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
@@ -499,8 +499,22 @@ public class EntityModel extends BookmarkableModel<ObjectAdapter> implements UiH
             return;
         }
         String hintKey = hintKey(component, key);
-        System.err.println("PUT " + hintKey + "=" + value) ;
-        hints.put(hintKey, value);
+        if(value != null) {
+            System.err.println("PUT " + hintKey + "=" + value) ;
+            hints.put(hintKey, value);
+        } else {
+            clearHint(component, hintKey);
+        }
+    }
+
+    @Override
+    public void clearHint(Component component, String key) {
+        if(component == null) {
+            return;
+        }
+        String hintKey = hintKey(component, key);
+        System.err.println("CLEAR " + hintKey) ;
+        hints.remove(hintKey);
     }
 
     

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 c65cbed..459c17c 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
@@ -99,17 +99,20 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
     	return this.label;
     }
 
+    public void updateLabel(AjaxRequestTarget target) {
+        target.add(label);
+    }
+
     /**
      * Returns true if a collection count is available from the rendered component 
      * (ie an eagerly rendered/expanded view).
      */
-    public boolean onSelect(AjaxRequestTarget target) {
+    public boolean hasCount() {
         if(label == null) {
             return false;
         }
         final Integer count = getCount();
         label.setDefaultModelObject(labelTextFor(count));
-        target.add(label);
         return count != null;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 4792714..d6bfac4 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
@@ -79,16 +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 String UIHINT_PAGE_NUMBER = "pageNumber";
-
     private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
     
-    private DataTable<ObjectAdapter,String> dataTable;
+    private IsisAjaxFallbackDataTable<ObjectAdapter,String> dataTable;
 
     public CollectionContentsAsAjaxTablePanel(final String id, final EntityCollectionModel model) {
         super(id, model);
-        // build eagerly rather than onInitialize...
-        // want to ensure that set sorting hints prior to pageNumber hint
+    }
+    
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
         buildGui();
     }
 
@@ -110,28 +111,7 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         buildEntityActionsGui(bulkActions, this);
 
         addOrReplace(dataTable);
-        configureHintsFor(dataTable);
-    }
-
-    private void configureHintsFor(DataTable<ObjectAdapter, String> dataTable) {
-        UiHintContainer uiHintContainer = getUiHintContainer();
-        if(uiHintContainer == null) {
-            return;
-        }
-        final String pageNumberStr = uiHintContainer.getHint(dataTable, UIHINT_PAGE_NUMBER);
-        if(pageNumberStr != null) {
-            try {
-                long pageNumber = Long.parseLong(pageNumberStr);
-                if(pageNumber >= 0) {
-                    // dataTable is clever enough to deal with too-large numbers
-                    dataTable.setCurrentPage(pageNumber);
-                }
-            } catch(Exception ex) {
-                // ignore.
-            }
-        }
-        final long currentPage = dataTable.getCurrentPage();
-        uiHintContainer.setHint(dataTable, UIHINT_PAGE_NUMBER, ""+currentPage);
+        dataTable.honourHints();
     }
 
     private void addToggleboxColumnIfRequired(final List<IColumn<ObjectAdapter,String>> columns, List<ObjectAction> bulkActions) {
@@ -228,6 +208,11 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
     private void addPropertyColumnsIfRequired(final List<IColumn<ObjectAdapter,String>> columns) {
         final ObjectSpecification typeOfSpec = getModel().getTypeOfSpecification();
 
+        final Where whereContext = 
+                getModel().isParented()
+                    ? Where.PARENTED_TABLES
+                    : Where.STANDALONE_TABLES;
+        
         final ObjectSpecification parentSpecIfAny = 
                 getModel().isParented() 
                     ? getModel().getParentObjectAdapterMemento().getObjectAdapter(ConcurrencyChecking.NO_CHECK).getSpecification() 
@@ -236,8 +221,9 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         @SuppressWarnings("unchecked")
         final Filter<ObjectAssociation> filter = Filters.and(
                 ObjectAssociation.Filters.PROPERTIES, 
-                ObjectAssociation.Filters.staticallyVisible(getModel().isParented()? Where.PARENTED_TABLES: Where.STANDALONE_TABLES),
+                ObjectAssociation.Filters.staticallyVisible(whereContext),
                 associationDoesNotReferenceParent(parentSpecIfAny));
+        
         final List<? extends ObjectAssociation> propertyList = typeOfSpec.getAssociations(Contributed.INCLUDED, filter);
         for (final ObjectAssociation property : propertyList) {
             final ColumnAbstract<ObjectAdapter> nopc = createObjectAdapterPropertyColumn(property);

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 ef9b869..b08d498 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
@@ -22,7 +22,10 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxNavigationToolbar;
+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.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
@@ -35,12 +38,20 @@ import org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.util.lang.Generics;
 
+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;
 
 public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S> implements UiHintPathSignificant {
+    
     private static final long serialVersionUID = 1L;
+    
+    static final String UIHINT_PAGE_NUMBER = "pageNumber";
+
     private final ISortableDataProvider<T, S> dataProvider;
 
+    private IsisAjaxFallbackHeadersToolbar<S> headersToolbar;
+
     public IsisAjaxFallbackDataTable(final String id, final List<? extends IColumn<T, S>> columns,
         final ISortableDataProvider<T, S> dataProvider, final int rowsPerPage)
     {
@@ -58,7 +69,8 @@ public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S> implements
     }
     
     private void buildGui() {
-        addTopToolbar(new IsisAjaxFallbackHeadersToolbar<S>(this, this.dataProvider));
+        headersToolbar = new IsisAjaxFallbackHeadersToolbar<S>(this, this.dataProvider);
+        addTopToolbar(headersToolbar);
         addBottomToolbar(new IsisAjaxNavigationToolbar(this));
         addBottomToolbar(new NoRecordsToolbar(this));
     }
@@ -113,14 +125,8 @@ public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S> implements
                     final IModel<T> model = newModels.next();
                     final Item<T> oldItem = modelToItem.get(model);
 
-                    final IModel<T> model2;
-                    if (oldItem == null) {
-                        model2 = model;
-                    } else {
-                        model2 = oldItem.getModel();
-                    }
-                    return factory.newItem(index++, 
-                            model2);
+                    final IModel<T> model2 = oldItem != null ? oldItem.getModel() : model;
+                    return factory.newItem(index++, model2);
                 }
 
                 @Override
@@ -134,5 +140,61 @@ public class IsisAjaxFallbackDataTable<T, S> extends DataTable<T, S> implements
 
     }
 
+    public void honourHints() {
+        UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        }
+        
+        headersToolbar.honourSortOrderHints();
+        
+        honourPageNumberHint(uiHintContainer);
+    }
+
+    private void honourPageNumberHint(final UiHintContainer uiHintContainer) {
+        final String pageNumberStr = uiHintContainer.getHint(this, UIHINT_PAGE_NUMBER);
+        if(pageNumberStr != null) {
+            try {
+                long pageNumber = Long.parseLong(pageNumberStr);
+                if(pageNumber >= 0) {
+                    // dataTable is clever enough to deal with too-large numbers
+                    this.setCurrentPage(pageNumber);
+                }
+            } catch(Exception ex) {
+                // ignore.
+            }
+        }
+        uiHintContainer.setHint(this, UIHINT_PAGE_NUMBER, ""+getCurrentPage());
+        // don't broadcast (no AjaxRequestTarget, still configuring initial setup)
+    }
+
+    public void setPageNumberHintAndBroadcast(AjaxRequestTarget target) {
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        } 
+        uiHintContainer.setHint(this, IsisAjaxFallbackDataTable.UIHINT_PAGE_NUMBER, ""+getCurrentPage());
+        send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(uiHintContainer, target));
+    }
+
+    public void setSortOrderHintAndBroadcast(SortOrder order, String property, AjaxRequestTarget target) {
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        }
+
+        // first clear all SortOrder hints...
+        for (SortOrder eachSortOrder : SortOrder.values()) {
+            uiHintContainer.clearHint(this, eachSortOrder.name());
+        }
+        // .. then set this one
+        uiHintContainer.setHint(this, order.name(), property);
+        send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(uiHintContainer, target));
+    }
+
+    private UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(this);
+    }
+
     
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 7d4464b..2ffada0 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
@@ -17,7 +17,6 @@
 package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
 
 import org.apache.wicket.ajax.attributes.IAjaxCallListener;
-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;
@@ -25,7 +24,6 @@ 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;
 
 
 /**
@@ -35,10 +33,12 @@ public class IsisAjaxFallbackHeadersToolbar<S> extends IsisAjaxHeadersToolbar<S>
 {
     private static final long serialVersionUID = 1L;
     private final ISortStateLocator<S> stateLocator;
+    private IsisAjaxFallbackDataTable<?, S> table;
 
-    public IsisAjaxFallbackHeadersToolbar(final DataTable<?, S> table, final ISortStateLocator<S> stateLocator)
+    public IsisAjaxFallbackHeadersToolbar(final IsisAjaxFallbackDataTable<?, S> table, final ISortStateLocator<S> stateLocator)
     {
         super(table, stateLocator);
+        this.table = table;
         table.setOutputMarkupId(true);
         this.stateLocator = stateLocator;
     }
@@ -46,30 +46,15 @@ public class IsisAjaxFallbackHeadersToolbar<S> extends IsisAjaxHeadersToolbar<S>
     @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 IsisAjaxFallbackOrderByBorder<S>(borderId, getTable(), property, locator, getAjaxCallListener());
+        return new IsisAjaxFallbackOrderByBorder<S>(borderId, table, property, locator, getAjaxCallListener());
     }
 
     /**
@@ -81,4 +66,26 @@ public class IsisAjaxFallbackHeadersToolbar<S> extends IsisAjaxHeadersToolbar<S>
     {
         return null;
     }
+    
+    // //////////////////////////////////////
+
+    void honourSortOrderHints() {
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        } 
+        for (SortOrder sortOrder : SortOrder.values()) {
+            String property = uiHintContainer.getHint(table, sortOrder.name());
+            if(property != null) {
+                // bit hacky... how know this cast is safe?
+                S propertyS = (S) property;
+                stateLocator.getSortState().setPropertySortOrder(propertyS, sortOrder);
+            }
+        }
+    }
+    
+    public UiHintContainer getUiHintContainer() {
+        return UiHintContainer.Util.hintContainerOf(table);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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
index 8030bf1..6b4c8fb 100644
--- 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
@@ -33,11 +33,11 @@ public class IsisAjaxFallbackOrderByBorder<T> extends AjaxFallbackOrderByBorder<
     private static final long serialVersionUID = 1L;
     
     private final T sortProperty;
-    private final DataTable<?, ?> dataTable;
+    private final IsisAjaxFallbackDataTable<?, ?> dataTable;
 
     private final ISortStateLocator<T> stateLocator;
     
-    public IsisAjaxFallbackOrderByBorder(String id, DataTable<?, ?> dataTable, T sortProperty, ISortStateLocator<T> stateLocator, IAjaxCallListener ajaxCallListener) {
+    public IsisAjaxFallbackOrderByBorder(String id, IsisAjaxFallbackDataTable<?, ?> dataTable, T sortProperty, ISortStateLocator<T> stateLocator, IAjaxCallListener ajaxCallListener) {
         super(id, sortProperty, stateLocator, ajaxCallListener);
         this.dataTable = dataTable;
         this.stateLocator = stateLocator;
@@ -50,25 +50,23 @@ public class IsisAjaxFallbackOrderByBorder<T> extends AjaxFallbackOrderByBorder<
         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(uiHintContainer, target));
+        if(uiHintContainer == null) {
+            return;
         }
-    }
-
-    private String sortOrderName() {
+        
         final ISortState<T> state = stateLocator.getSortState();
         final SortOrder order = state.getPropertySortOrder(sortProperty);
-        return order.name();
+        
+        dataTable.setSortOrderHintAndBroadcast(order, sortProperty.toString(), target);
+        dataTable.setPageNumberHintAndBroadcast(target);
     }
 
     @Override
     protected void onSortChanged()
     {
         super.onSortChanged();
-        dataTable.setCurrentPage(0);
-        
+        // UI hint & event broadcast in onAjaxClick
+        dataTable.setCurrentPage(0); 
     }
     
     public UiHintContainer getUiHintContainer() {

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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
index cf6358b..0a94eff 100644
--- 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
@@ -28,21 +28,20 @@ import org.apache.isis.viewer.wicket.model.hints.UiHintsSetEvent;
 public class IsisAjaxPagingNavigationIncrementLink extends AjaxPagingNavigationIncrementLink {
 
     private static final long serialVersionUID = 1L;
+    
+    private final IsisAjaxFallbackDataTable<?, ?> dataTable;
     private final Component component;
 
     public IsisAjaxPagingNavigationIncrementLink(String id, IPageable pageable, int increment) {
         super(id, pageable, increment);
+        dataTable = (IsisAjaxFallbackDataTable<?, ?>) pageable;
         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(uiHintContainer, target));
-        }
+        dataTable.setPageNumberHintAndBroadcast(target);
     }
     
     public UiHintContainer getUiHintContainer() {

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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
index b2a38ab..c4d7a31 100644
--- 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
@@ -19,30 +19,26 @@ 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 IsisAjaxFallbackDataTable<?, ?> dataTable;
     private final Component component;
 
     public IsisAjaxPagingNavigationLink(String id, IPageable pageable, long pageNumber) {
         super(id, pageable, pageNumber);
+        dataTable = (IsisAjaxFallbackDataTable<?, ?>) pageable;
         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(uiHintContainer, target));
-        }
+        dataTable.setPageNumberHintAndBroadcast(target);
     }
     
     public UiHintContainer getUiHintContainer() {

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 d3b9cb5..297548b 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
@@ -57,6 +57,15 @@ public class CollectionContentsLinksSelectorPanel extends LinksSelectorPanelAbst
         super(id, ComponentType.COLLECTION_CONTENTS.toString(), model, factory);
     }
 
+    /* (non-Javadoc)
+     * @see org.apache.isis.viewer.wicket.ui.selector.links.LinksSelectorPanelAbstract#onInitialize()
+     */
+    @Override
+    public void onInitialize() {
+        super.onInitialize();
+        applyCssVisibility(additionalLinks, selectedComponent instanceof CollectionCountProvider);
+    }
+    
     @Override
     protected EntityCollectionModel dummyOf(EntityCollectionModel model) {
         return model.asDummy();
@@ -145,9 +154,12 @@ public class CollectionContentsLinksSelectorPanel extends LinksSelectorPanelAbst
         while(component != null) {
             if(component instanceof CollectionPanel) {
                 CollectionPanel collectionPanel = (CollectionPanel) component;
-                final boolean expanded = collectionPanel.onSelect(target);
+                boolean hasCount = collectionPanel.hasCount();
+                if(hasCount) {
+                    collectionPanel.updateLabel(target);
+                }
                 if(additionalLinks != null) {
-                    applyCssVisibility(additionalLinks, expanded);
+                    applyCssVisibility(additionalLinks, hasCount);
                 }
                 return;
             }

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardPanel.java
index 07d1950..767d40f 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/zclip/ZeroClipboardPanel.java
@@ -31,6 +31,8 @@ import org.apache.isis.viewer.wicket.model.models.PageType;
 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.CssClassAppender;
+import org.apache.isis.viewer.wicket.ui.util.CssClassRemover;
 import org.apache.isis.viewer.wicket.ui.util.Links;
 
 public class ZeroClipboardPanel extends PanelAbstract<IModel<Void>> {
@@ -83,11 +85,12 @@ public class ZeroClipboardPanel extends PanelAbstract<IModel<Void>> {
     @Override
     public void onEvent(IEvent<?> event) {
         super.onEvent(event);
-        if(event.getPayload() instanceof UiHintsBroadcastEvent) {
-            UiHintsBroadcastEvent ev = (UiHintsBroadcastEvent) event.getPayload();
-            addSubscribingLink(ev.getUiHintContainer());
-            ev.getTarget().add(subscribingLink);
-        }
+        if(!(event.getPayload() instanceof UiHintsBroadcastEvent)) {
+            return;
+        } 
+        final UiHintsBroadcastEvent ev = (UiHintsBroadcastEvent) event.getPayload();
+        addSubscribingLink(ev.getUiHintContainer());
+        ev.getTarget().add(subscribingLink);
     }
     
     // //////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/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 204a5ac..4e53306 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
@@ -953,16 +953,4 @@ 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/2f4941b1/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 cac47e4..82f0e72 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
@@ -52,6 +52,7 @@ import org.apache.isis.viewer.wicket.model.links.LinksProvider;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.additionallinks.AdditionalLinksPanel;
+import org.apache.isis.viewer.wicket.ui.components.collection.CollectionCountProvider;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsAsUnresolvedPanelFactory;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
@@ -131,7 +132,7 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
     private void addUnderlyingViews(final String underlyingIdPrefix, final T model, final ComponentFactory factory) {
         final List<ComponentFactory> componentFactories = findOtherComponentFactories(model, factory);
 
-        final int selected = determineView(componentFactories, model);
+        final int selected = honourViewHintElseDefault(componentFactories, model);
 
         final LinksSelectorPanelAbstract<T> selectorPanel = LinksSelectorPanelAbstract.this;
         
@@ -187,11 +188,7 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
                         @Override
                         public void onClick(AjaxRequestTarget target) {
                             LinksSelectorPanelAbstract<T> linksSelectorPanel = LinksSelectorPanelAbstract.this;
-                            UiHintContainer uiHintContainer = linksSelectorPanel.getUiHintContainer();
-                            if(uiHintContainer != null) {
-                                uiHintContainer.setHint(LinksSelectorPanelAbstract.this, UIHINT_VIEW, ""+underlyingViewNum);
-                                send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(uiHintContainer, target));
-                            }
+                            linksSelectorPanel.setViewHintAndBroadcast(underlyingViewNum, target);
                             
                             final T dummyModel = dummyOf(model);
                             for(int i=0; i<MAX_NUM_UNDERLYING_VIEWS; i++) {
@@ -241,6 +238,15 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
 
 
 
+    protected void setViewHintAndBroadcast(int viewNum, AjaxRequestTarget target) {
+        final UiHintContainer uiHintContainer = getUiHintContainer();
+        if(uiHintContainer == null) {
+            return;
+        }
+        uiHintContainer.setHint(LinksSelectorPanelAbstract.this, UIHINT_VIEW, ""+viewNum);
+        send(getPage(), Broadcast.EXACT, new UiHintsSetEvent(uiHintContainer, target));
+    }
+
     /**
      * Overrideable hook.
      */
@@ -254,6 +260,9 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
     protected abstract T dummyOf(T model);
 
     protected static void applyCssVisibility(final Component component, final boolean visible) {
+        if(component == null) {
+            return;
+        }
         final AttributeModifier modifier =  
                 visible 
                     ? new AttributeModifier("class", String.valueOf(component.getMarkupAttributes().get("class")).replaceFirst(INVISIBLE_CLASS, "")) 
@@ -262,8 +271,9 @@ 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();
+    protected int honourViewHintElseDefault(final List<ComponentFactory> componentFactories, final IModel<?> model) {
+        // honour hints ...
+        final UiHintContainer hintContainer = getUiHintContainer();
         if(hintContainer != null) {
             String viewStr = hintContainer.getHint(this, UIHINT_VIEW);
             if(viewStr != null) {
@@ -278,9 +288,11 @@ public abstract class LinksSelectorPanelAbstract<T extends IModel<?>> extends Pa
             }
         }
 
+        // ... else default
         int initialFactory = determineInitialFactory(componentFactories, model);
         if(hintContainer != null) {
             hintContainer.setHint(this, UIHINT_VIEW, ""+initialFactory);
+            // don't broadcast (no AjaxRequestTarget, still configuring initial setup)
         }
         return initialFactory;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/2f4941b1/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssClassRemover.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssClassRemover.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssClassRemover.java
new file mode 100644
index 0000000..6999555
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssClassRemover.java
@@ -0,0 +1,53 @@
+/*
+ *  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.util;
+
+import java.util.Set;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Sets;
+
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.model.Model;
+
+/**
+ * Implementation of {@link AttributeAppender} that appends the provided CSS
+ * <tt>class</tt> attribute.
+ */
+public class CssClassRemover extends AttributeModifier {
+
+    private static final long serialVersionUID = 1L;
+
+    public CssClassRemover(String cssClass) {
+        super("class", new Model<String>(cssClass));
+    }
+    
+    @Override
+    protected String newValue(String currentValue, String valueToRemove) {
+        if (currentValue == null) return "";
+
+        Set<String> classes = Sets.newHashSet(Splitter.on(" ").split(currentValue));
+        classes.remove(valueToRemove);
+        return Joiner.on(" ").join(classes); 
+    }
+
+}
\ No newline at end of file