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/11/30 14:54:21 UTC

[1/2] ISI-486: using ModalWindow

Updated Branches:
  refs/heads/master 7353305d8 -> 81b200fbb


http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 6a2d47a..c9e688f 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
@@ -683,6 +683,58 @@ div.scalarPanel {
 	font-weight: normal;
 }
 
+/******** fix for select2 on ModalWindow ********/
+/* http://osdir.com/ml/users-wicket.apache.org/2013-09/msg00165.html */
+
+.select2-drop,
+.select2-drop {
+	z-index: 30001
+}
+
+.select2-drop-mask,
+.select2-drop-mask {
+    z-index: 30000
+}
+
+
+/******** action prompt modal dialog ********/
+
+.wicket-modal .w_content_container {
+  background-color: #E4E4DB;
+  border-radius:4px;
+  -moz-border-radius:4px;
+  -webkit-border-radius:4px;
+}
+
+.actionPanel .myBlockContainer {
+    margin:20px;
+    width: 600px;
+    min-height: 200px;
+}
+
+.wicket-modal .w_caption {
+	display: none;
+}
+
+div.wicket-modal div.w_content_2 {
+	padding-top: 0em;
+  padding-right: 20px;
+  background-color: #E4E4DB;
+  border-radius:4px;
+  -moz-border-radius:4px;
+  -webkit-border-radius:4px;
+}
+
+div.wicket-modal div.w_content_3 {
+	border: 0px;
+}
+
+div.wicket-modal div.w_content {
+  border-radius:4px;
+  -moz-border-radius:4px;
+  -webkit-border-radius:4px;
+}
+
 /******** FORM STYLES ********/
 
 form input[type=text][disabled] {

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 237cdc0..cf1b290 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
@@ -63,6 +63,8 @@
 				<div class="clear"/>
 			</div>
 
+            <div wicket:id="actionPromptModalWindow"/>
+
 			<div id="footer">
 				<div class="links">
 					powered by: <a href="http://isis.apache.org">Apache Isis</a>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 a07ba40..2d60545 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,7 +28,11 @@ 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.markup.head.CssReferenceHeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
@@ -56,6 +60,8 @@ 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.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.ApplicationActionsModel;
 import org.apache.isis.viewer.wicket.model.models.BookmarkableModel;
 import org.apache.isis.viewer.wicket.model.models.BookmarkedPagesModel;
@@ -72,7 +78,8 @@ import org.apache.isis.viewer.wicket.ui.util.Components;
 /**
  * Convenience adapter for {@link WebPage}s built up using {@link ComponentType}s.
  */
-public abstract class PageAbstract extends WebPage {
+public abstract class PageAbstract extends WebPage implements ActionPromptModalWindowProvider {
+
 
     private static Logger LOG = LoggerFactory.getLogger(PageAbstract.class);
 
@@ -83,6 +90,8 @@ public abstract class PageAbstract extends WebPage {
     private static final String ID_APPLICATION_NAME = "applicationName";
     private static final String ID_USER_NAME = "userName";
     
+    private static final String ID_ACTION_PROMPT_MODAL_WINDOW = "actionPromptModalWindow";
+    
     private static final String ID_PAGE_TITLE = "pageTitle";
     
     public static final String ID_MENU_LINK = "menuLink";
@@ -135,13 +144,14 @@ public abstract class PageAbstract extends WebPage {
     
     public PageAbstract(final PageParameters pageParameters, ApplicationActions applicationActions, final String title, final ComponentType... childComponentIds) {
         try {
-            addApplicationActionsComponent(applicationActions);
+            addApplicationActions(applicationActions);
             this.childComponentIds = Collections.unmodifiableList(Arrays.asList(childComponentIds));
             this.pageParameters = pageParameters;
             addHomePageLinkAndApplicationName();
             addUserName();
             addLogoutLink();
             addAboutLink();
+            
             add(new Label(ID_PAGE_TITLE, title != null? title: applicationName));
             
             // ensure that all collected JavaScript contributions are loaded at the page footer
@@ -257,12 +267,15 @@ public abstract class PageAbstract extends WebPage {
         return pageParameters;
     }
 
-    private void addApplicationActionsComponent(final ApplicationActions applicationActions) {
+    private void addApplicationActions(final ApplicationActions applicationActions) {
         if(applicationActions == ApplicationActions.INCLUDE) {
-        final ApplicationActionsModel model = new ApplicationActionsModel();
+            addActionPromptModalWindow();
+            final ApplicationActionsModel model = new ApplicationActionsModel();
+            model.setActionPromptModalWindowProvider(this);
             addComponent(ComponentType.APPLICATION_ACTIONS, model);
         } else {
             Components.permanentlyHide(this, ComponentType.APPLICATION_ACTIONS);
+            Components.permanentlyHide(this, ID_ACTION_PROMPT_MODAL_WINDOW);
         }
     }
 
@@ -310,6 +323,44 @@ public abstract class PageAbstract extends WebPage {
 
 
     // ///////////////////////////////////////////////////////////////////
+    // ActionPromptModalWindowProvider
+    // ///////////////////////////////////////////////////////////////////
+    
+    private ModalWindow actionPromptModalWindow;
+    public ModalWindow getActionPromptModalWindow() {
+        return PageAbstract.getActionPromptModalWindowIfEnabled(actionPromptModalWindow);
+    }
+
+    private void addActionPromptModalWindow() {
+        this.actionPromptModalWindow = PageAbstract.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW); 
+        addOrReplace(actionPromptModalWindow);
+    }
+
+    // TODO: tidy-up
+    public static ModalWindow newModalWindow(String id) {
+        ModalWindow actionPromptModalWindow = new ModalWindow(id);
+        //actionPromptModalWindow.setResizable(false);
+        actionPromptModalWindow.setAutoSize(true);
+        actionPromptModalWindow.setCssClassName("w_isis");
+        return actionPromptModalWindow;
+    }
+
+    public static ModalWindow getActionPromptModalWindowIfEnabled(ModalWindow modalWindow) {
+        boolean enable = isActionPromptModalDialogEnabled();
+        if(!enable) {
+            // no-op
+            return null;
+        }
+        return modalWindow;
+    }
+
+    public static boolean isActionPromptModalDialogEnabled() {
+        return IsisContext.getConfiguration().getBoolean("isis.viewer.wicket.enableModalDialogs", false);
+    }
+    
+
+    
+    // ///////////////////////////////////////////////////////////////////
     // Convenience
     // ///////////////////////////////////////////////////////////////////
 

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 09a09c5..cbc1980 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
@@ -19,13 +19,26 @@
 
 package org.apache.isis.viewer.wicket.ui.pages.entity;
 
+import java.util.List;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 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.version.ConcurrencyException;
+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.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
@@ -40,6 +53,7 @@ public class EntityPage extends PageAbstract {
     
     private final EntityModel model;
 
+
     /**
      * Called reflectively, in support of 
      * {@link BookmarkablePageLink bookmarkable} links.
@@ -49,12 +63,7 @@ public class EntityPage extends PageAbstract {
     }
     
     private EntityPage(final PageParameters pageParameters, final EntityModel entityModel) {
-        super(pageParameters, ApplicationActions.INCLUDE, entityModel.getObject().titleString(null), ComponentType.ENTITY);
-        this.model = entityModel;
-        addChildComponents(model);
-        
-        bookmarkPage(model);
-        addBookmarkedPages();
+        this(pageParameters, entityModel, entityModel.getObject().titleString(null));
     }
 
     public EntityPage(final ObjectAdapter adapter) {
@@ -66,15 +75,49 @@ public class EntityPage extends PageAbstract {
      * (eg from an action invocation) is show.
      */
     public EntityPage(ObjectAdapter adapter, ConcurrencyException exIfAny) {
-        super(new PageParameters(), ApplicationActions.INCLUDE, adapter.titleString(null), ComponentType.ENTITY);
-        this.model = new EntityModel(adapter);
+        this(new PageParameters(), newEntityModel(adapter, exIfAny));
+    }
+
+    private static EntityModel newEntityModel(ObjectAdapter adapter, ConcurrencyException exIfAny) {
+        EntityModel model = new EntityModel(adapter);
         model.setException(exIfAny);
+        return model;
+    }
+
+    private EntityPage(PageParameters pageParameters, EntityModel entityModel, String titleString) {
+        super(pageParameters, ApplicationActions.INCLUDE, titleString, ComponentType.ENTITY);
+        this.model = entityModel;
         addChildComponents(model);
         
+        final ObjectAndAction objectAndAction =lookupHomePageAction();
+        final ActionModel actionModel = ActionModel.create(objectAndAction.objectAdapter, objectAndAction.action);
+        
         bookmarkPage(model);
         addBookmarkedPages();
     }
 
+    private static class ObjectAndAction {
+        ObjectAndAction(final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
+            this.objectAdapter = serviceAdapter;
+            action = objectAction;
+        }
+        ObjectAdapter objectAdapter;
+        ObjectAction action;
+    }
+    
+    private ObjectAndAction lookupHomePageAction() {
+        List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
+        for (ObjectAdapter serviceAdapter : serviceAdapters) {
+            final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
+            List<ObjectAction> objectActions = serviceSpec.getObjectActions(Contributed.EXCLUDED);
+            for (ObjectAction objectAction : objectActions) {
+                if(objectAction.containsFacet(HomePageFacet.class)) {
+                    return new ObjectAndAction(serviceAdapter, objectAction);
+                }
+            }
+        }
+        return null;
+    }
 
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
index 6db4ee9..19067d7 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
@@ -21,7 +21,11 @@ package org.apache.isis.viewer.wicket.ui.pages.home;
 
 import java.util.List;
 
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
@@ -45,7 +49,7 @@ public class HomePage extends PageAbstract {
 
     public HomePage() {
         super(new PageParameters(), ApplicationActions.INCLUDE, null);
-
+        
         addChildComponents(null);
         buildGui();
 
@@ -53,10 +57,10 @@ public class HomePage extends PageAbstract {
     }
 
     private void buildGui() {
-        final HomePageTuple homePageTuple = lookupHomePageAction();
-        if(homePageTuple != null) {
+        final ObjectAndAction objectAndAction = lookupHomePageAction();
+        if(objectAndAction != null) {
             Components.permanentlyHide(this, ComponentType.WELCOME); 
-            final IModel<?> actionModel = ActionModel.create(homePageTuple.serviceAdapter, homePageTuple.action);
+            final IModel<?> actionModel = ActionModel.create(objectAndAction.objectAdapter, objectAndAction.action);
             getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ACTION_PROMPT, actionModel);
         } else {
             Components.permanentlyHide(this, ComponentType.ACTION_PROMPT);
@@ -64,23 +68,23 @@ public class HomePage extends PageAbstract {
         }
     }
 
-    private static class HomePageTuple {
-        HomePageTuple(ObjectAdapter serviceAdapter, ObjectAction objectAction) {
-            this.serviceAdapter = serviceAdapter;
+    private static class ObjectAndAction {
+        ObjectAndAction(final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
+            this.objectAdapter = serviceAdapter;
             action = objectAction;
         }
-        ObjectAdapter serviceAdapter;
+        ObjectAdapter objectAdapter;
         ObjectAction action;
     }
     
-    private HomePageTuple lookupHomePageAction() {
+    private ObjectAndAction lookupHomePageAction() {
         List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
         for (ObjectAdapter serviceAdapter : serviceAdapters) {
             final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
             List<ObjectAction> objectActions = serviceSpec.getObjectActions(Contributed.EXCLUDED);
             for (ObjectAction objectAction : objectActions) {
                 if(objectAction.containsFacet(HomePageFacet.class)) {
-                    return new HomePageTuple(serviceAdapter, objectAction);
+                    return new ObjectAndAction(serviceAdapter, objectAction);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 ff00aee..d8eeed5 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
@@ -50,7 +50,8 @@ public final class Links {
       };
     }
 
-    public static <T extends Page> AbstractLink newBookmarkablePageLink(final String linkId, final PageParameters pageParameters, final Class<T> pageClass) {
+    public static <T extends Page> AbstractLink newBookmarkablePageLink(
+            final String linkId, final PageParameters pageParameters, final Class<T> pageClass) {
         return new BookmarkablePageLink<T>(linkId, pageClass, pageParameters);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/fixtures/SystemFixtures.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/fixtures/SystemFixtures.java b/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/fixtures/SystemFixtures.java
index 33fb106..fa78dc8 100644
--- a/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/fixtures/SystemFixtures.java
+++ b/component/viewer/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/fixtures/SystemFixtures.java
@@ -25,7 +25,8 @@ import org.jmock.Mockery;
 
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 
 public final class SystemFixtures {
 
@@ -35,10 +36,16 @@ public final class SystemFixtures {
         this.context = context;
     }
 
-    public <T> void newLink(final CssMenuLinkFactory mockLinkBuilder, final String linkId, final ObjectAdapterMemento adapterMemento, final ObjectAction noAction, final Link<T> returns) {
+    public <T> void newLink(
+            final ActionLinkFactory mockLinkBuilder, 
+            final String linkId, 
+            final ObjectAdapterMemento adapterMemento,
+            final ObjectAction noAction, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider,
+            final Link<T> returns) {
         context.checking(new Expectations() {
             {
-                allowing(mockLinkBuilder).newLink(adapterMemento, noAction, linkId);
+                allowing(mockLinkBuilder).newLink(adapterMemento, noAction, linkId, actionPromptModalWindowProvider);
                 will(returnValue(returns));
             }
         });

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 2e172bd..bf5b43c 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -521,18 +521,11 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
     // (a) has different semantics and (b) is in any case automatically ignored
     // by the framework
     public ToDoItem duplicate(
-            @Named("Description") 
-            String description,
-            @Named("Category")
-            ToDoItem.Category category, 
-            @Named("Subcategory")
-            ToDoItem.Subcategory subcategory, 
-            @Named("Due by") 
-            @Optional
-            LocalDate dueBy,
-            @Named("Cost") 
-            @Optional
-            BigDecimal cost) {
+            final @RegEx(validation = "\\w[@&:\\-\\,\\.\\+ \\w]*") @Named("Description") String description, 
+            final @Named("Category") Category category,
+            final @Named("Subcategory") Subcategory subcategory,
+            final @Optional @Named("Due by") LocalDate dueBy,
+            final @Optional @Named("Cost") BigDecimal cost) {
         return toDoItems.newToDo(description, category, subcategory, dueBy, cost);
     }
     public String default0Duplicate() {
@@ -547,6 +540,16 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
     public LocalDate default3Duplicate() {
         return getDueBy();
     }
+    public List<Subcategory> choices2Duplicate(
+            final String description, final Category category) {
+        return toDoItems.choices2NewToDo(description, category);
+    }
+    public String validateDuplicate(
+            final String description, 
+            final Category category, final Subcategory subcategory, 
+            final LocalDate dueBy, final BigDecimal cost) {
+        return toDoItems.validateNewToDo(description, category, subcategory, dueBy, cost);
+    }
 
     // //////////////////////////////////////
     // Delete (action)


[2/2] git commit: ISI-486: using ModalWindow

Posted by da...@apache.org.
ISI-486: using ModalWindow

... not yet complete, so disabled unless switched on using
'isis.viewer.wicket.enableModalDialogs' flag.

In addition, added missing bus logic to example ToDoItem.


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

Branch: refs/heads/master
Commit: 81b200fbb71f609c8b27b88648dcdd2d5eee90e2
Parents: 7353305
Author: Dan Haywood <da...@apache.org>
Authored: Sat Nov 30 13:54:06 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Sat Nov 30 13:54:06 2013 +0000

----------------------------------------------------------------------
 component/viewer/wicket/model/pom.xml           |   4 +
 .../wicket/model/models/ActionExecutor.java     |   4 +-
 .../viewer/wicket/model/models/ActionModel.java |   4 +-
 .../models/ActionPromptModalWindowProvider.java |  38 +++++
 .../model/models/ApplicationActionsModel.java   |   9 ++
 .../ui/components/actions/ActionPanel.html      |  14 +-
 .../ui/components/actions/ActionPanel.java      |  33 +++--
 .../actions/ActionParametersFormPanel.html      |   3 +-
 .../actions/ActionParametersFormPanel.java      |  27 +++-
 .../additionallinks/EntityActionUtil.java       |  14 +-
 .../cssmenu/AppActionsCssMenuFactory.java       |  18 ++-
 .../cssmenu/AppActionsCssMenuLinkFactory.java   |  45 ++----
 .../components/collection/CollectionPanel.html  |   1 +
 .../components/collection/CollectionPanel.java  |  43 ++++--
 .../ajaxtable/BulkActionsLinkFactory.java       |  12 +-
 .../CollectionContentsAsAjaxTablePanel.html     |   1 +
 .../CollectionContentsAsAjaxTablePanel.java     |  36 ++++-
 .../entity/EntityActionLinkFactory.java         |  82 +++--------
 .../entity/header/EntityHeaderPanel.java        |   5 +-
 .../components/scalars/ScalarPanelAbstract.java |   6 +-
 .../widgets/cssmenu/ActionLinkFactory.java      |  32 +++++
 .../cssmenu/ActionLinkFactoryAbstract.java      | 141 +++++++++++++++++++
 .../widgets/cssmenu/CssMenuBuilder.java         |  50 ++++---
 .../components/widgets/cssmenu/CssMenuItem.java |  17 ++-
 .../widgets/cssmenu/CssMenuLinkFactory.java     |  53 -------
 .../viewer/wicket/ui/pages/PageAbstract.css     |  52 +++++++
 .../viewer/wicket/ui/pages/PageAbstract.html    |   2 +
 .../viewer/wicket/ui/pages/PageAbstract.java    |  59 +++++++-
 .../wicket/ui/pages/entity/EntityPage.java      |  59 ++++++--
 .../viewer/wicket/ui/pages/home/HomePage.java   |  24 ++--
 .../isis/viewer/wicket/ui/util/Links.java       |   3 +-
 .../wicket/ui/fixtures/SystemFixtures.java      |  13 +-
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  27 ++--
 33 files changed, 657 insertions(+), 274 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/model/pom.xml
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/pom.xml b/component/viewer/wicket/model/pom.xml
index a003bb9..bc90ba4 100644
--- a/component/viewer/wicket/model/pom.xml
+++ b/component/viewer/wicket/model/pom.xml
@@ -43,6 +43,10 @@
 			<groupId>org.apache.wicket</groupId>
 			<artifactId>wicket-core</artifactId>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket-extensions</artifactId>
+        </dependency>
 
 		<dependency>
 			<groupId>org.apache.isis.core</groupId>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionExecutor.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionExecutor.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionExecutor.java
index ec73fcd..729055e 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionExecutor.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionExecutor.java
@@ -22,6 +22,8 @@ package org.apache.isis.viewer.wicket.model.models;
 import java.io.Serializable;
 
 import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.form.Form;
 
 /**
  * Decouples the {@link ActionModel}, which needs to delegate the actual
@@ -29,6 +31,6 @@ import org.apache.wicket.MarkupContainer;
  */
 public interface ActionExecutor extends Serializable {
 
-    void executeActionAndProcessResults(MarkupContainer paramForm);
+    void executeActionAndProcessResults(AjaxRequestTarget target, Form<?> feedbackForm);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index 0ba71dd..693e4ea 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -83,11 +83,11 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
      * @param action
      * @return
      */
-    public static IModel<?> create(ObjectAdapter objectAdapter, ObjectAction action) {
+    public static ActionModel create(ObjectAdapter objectAdapter, ObjectAction action) {
         final ObjectAdapterMemento serviceMemento = ObjectAdapterMemento.Functions.fromAdapter().apply(objectAdapter);
         final ActionMemento homePageActionMemento = ObjectAdapterMemento.Functions.fromAction().apply(action);
         final Mode mode = action.getParameterCount() > 0? Mode.PARAMETERS : Mode.RESULTS;
-        return (IModel<?>) new ActionModel(serviceMemento, homePageActionMemento, mode);
+        return new ActionModel(serviceMemento, homePageActionMemento, mode);
     }
 
     public static ActionModel createForPersistent(final PageParameters pageParameters) {

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptModalWindowProvider.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptModalWindowProvider.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptModalWindowProvider.java
new file mode 100644
index 0000000..028c92c
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptModalWindowProvider.java
@@ -0,0 +1,38 @@
+/**
+ *  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.models;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+public interface ActionPromptModalWindowProvider {
+
+    public static class Util{
+
+        public static ActionPromptModalWindowProvider getFrom(Component component) {
+            final Page page = component.getPage();
+            if(page instanceof ActionPromptModalWindowProvider) {
+                final ActionPromptModalWindowProvider provider = (ActionPromptModalWindowProvider) page;
+                return provider;
+            } 
+            // else
+            return null;
+        }}
+
+    public ModalWindow getActionPromptModalWindow();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
index 6eb18fd..4bf2b77 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ApplicationActionsModel.java
@@ -30,10 +30,19 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 public class ApplicationActionsModel extends ModelAbstract<List<ObjectAdapter>> {
 
     private static final long serialVersionUID = 1L;
+    private ActionPromptModalWindowProvider actionPromptModalWindowProvider;
 
     @Override
     protected List<ObjectAdapter> load() {
         return getServiceAdapters();
     }
 
+    public void setActionPromptModalWindowProvider(ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        this.actionPromptModalWindowProvider = actionPromptModalWindowProvider;
+    }
+    
+    public ActionPromptModalWindowProvider getActionPromptModalWindowProvider() {
+        return actionPromptModalWindowProvider;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.html
index d41b7b7..4148de7 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.html
@@ -25,13 +25,15 @@
 	<head></head>
 	<body>
 		<wicket:panel>
-			<div class="actionPanel actionComponentType myBlockContainer">
-				<div class="iconAndTitle panel actionPanelHeaderNew">
-			         <span wicket:id="entityIconAndTitle">[icon and title]</span>
-			         <p wicket:id="actionName" class="actionName">[action name]</p>
+			<div class="actionPanel actionComponentType">
+                <div class="myBlockContainer">
+    				<div class="iconAndTitle panel actionPanelHeaderNew">
+    			         <span wicket:id="entityIconAndTitle">[icon and title]</span>
+    			         <p wicket:id="actionName" class="actionName">[action name]</p>
+                    </div>
+    				<span wicket:id="parameters">
+    				</span>
                 </div>
-				<span wicket:id="parameters">
-				</span>
 			</div>
 		</wicket:panel>
 	</body>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
index a5bce11..05d3135 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
@@ -27,7 +27,9 @@ import com.google.common.collect.Iterables;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.handler.resource.ResourceRequestHandler;
@@ -94,7 +96,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         if (actionModel.hasParameters()) {
             buildGuiForParameters(actionModel);
         } else {
-            executeActionAndProcessResults(null);
+            executeActionAndProcessResults(null, null);
         }
     }
 
@@ -145,7 +147,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
      * @param feedbackForm - for feedback messages.
      */
     @Override
-    public void executeActionAndProcessResults(MarkupContainer feedbackForm) {
+    public void executeActionAndProcessResults(AjaxRequestTarget target, Form<?> feedbackForm) {
 
         permanentlyHide(ComponentType.ENTITY_ICON_AND_TITLE);
 
@@ -156,7 +158,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
                 targetAdapter = getModel().getTargetAdapter();
 
                 // no concurrency exception, so continue...
-                clearArgs = executeActionOnTargetAndProcessResults(targetAdapter, feedbackForm);
+                clearArgs = executeActionOnTargetAndProcessResults(targetAdapter, target, feedbackForm);
 
             } catch (ConcurrencyException ex) {
 
@@ -182,15 +184,16 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
     }
 
     /**
+     * @param target 
      * @return whether to clear args or not (they aren't if there was a validation exception)
      */
-    private boolean executeActionOnTargetAndProcessResults(ObjectAdapter targetAdapter, MarkupContainer feedbackForm) {
+    private boolean executeActionOnTargetAndProcessResults(ObjectAdapter targetAdapter, AjaxRequestTarget target, Form<?> feedbackForm) {
 
         // validate the action parameters (if any)
         final ActionModel actionModel = getActionModel();
         final String invalidReasonIfAny = actionModel.getReasonInvalidIfAny();
         if (invalidReasonIfAny != null) {
-            feedbackForm.error(invalidReasonIfAny);
+            raiseWarning(target, feedbackForm, invalidReasonIfAny);
             return false;
         } 
         // the object store could raise an exception (eg uniqueness constraint)
@@ -210,13 +213,11 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
                 bookmarkPage(actionModel);
             }
 
-            //return true;
-            // change in policy: never clear args (need them, even after successful execution, for bulk actions).
             return false;
 
         } catch (RuntimeException ex) {
 
-            String message = recognizeException(ex, feedbackForm);
+            String message = recognizeException(ex, target, feedbackForm);
             
             if (message != null) {
                 // no need to add to message broker, should already have been added...
@@ -237,7 +238,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         }
     }
 
-    private String recognizeException(RuntimeException ex, Component feedbackComponent) {
+    private String recognizeException(RuntimeException ex, AjaxRequestTarget target, Form<?> feedbackForm) {
         
         // REVIEW: this code is similar to stuff in EntityPropertiesForm, perhaps move up to superclass?
         // REVIEW: similar code also in WebRequestCycleForIsis; combine?
@@ -249,10 +250,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         if(recognizedErrorIfAny != null) {
 
             // recognized
-            if(feedbackComponent != null) {
-                feedbackComponent.error(recognizedErrorIfAny);
-            }
-            getMessageBroker().addWarning(recognizedErrorIfAny);
+            raiseWarning(target, feedbackForm, recognizedErrorIfAny);
 
             getTransactionManager().getTransaction().clearAbortCause();
             
@@ -263,6 +261,15 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         return recognizedErrorIfAny;
     }
 
+    public void raiseWarning(AjaxRequestTarget target, Form<?> feedbackForm, String error) {
+        if(target != null && feedbackForm != null) {
+            target.add(feedbackForm);
+            feedbackForm.error(error);
+        } else {
+            getMessageBroker().addWarning(error);
+        }
+    }
+
     /**
      * Executes the action, handling any {@link ApplicationException}s that
      * might be encountered.

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.html
index 89032c6..a716300 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.html
@@ -29,7 +29,8 @@
 				    	</div>
 	   	      			<span wicket:id="feedback"></span>
 				    	<div class="buttons">
-				    		<input type="submit" wicket:id="okButton" value="OK" class="okButton"/>
+				    		<input type="submit" wicket:id="okButton" value="OK" class="ok"/>
+                            <input type="submit" wicket:id="cancelButton" value="Cancel" class="cancel"/>
                             <div id="veil"> 
                                 <div class="imgHolder">
                                     <wicket:link>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
index 9f13e72..c22f08f 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
@@ -32,6 +32,7 @@ import com.google.common.collect.Lists;
 import org.apache.wicket.Component;
 import org.apache.wicket.RestartResponseAtInterceptPageException;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.Button;
 import org.apache.wicket.markup.html.form.Form;
@@ -57,6 +58,7 @@ import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarModelSubscriber
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.components.scalars.TextFieldValueModel.ScalarModelProvider;
 import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.FormFeedbackPanel;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
@@ -70,6 +72,7 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
     private static final long serialVersionUID = 1L;
 
     private static final String ID_OK_BUTTON = "okButton";
+    private static final String ID_CANCEL_BUTTON = "cancelButton";
     private static final String ID_ACTION_PARAMETERS = "parameters";
 
     private final ActionExecutor actionExecutor;
@@ -107,7 +110,7 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
             FormFeedbackPanel formFeedback = new FormFeedbackPanel(ID_FEEDBACK);
             formFeedback.setEscapeModelStrings(false);
             addOrReplace(formFeedback);
-            addOkButton();
+            addButtons();
         }
 
         private ActionModel getActionModel() {
@@ -151,16 +154,30 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
         }
 
 
-        private void addOkButton() {
-            Button okButton = new Button(ID_OK_BUTTON) {
+        private void addButtons() {
+            AjaxButton okButton = new AjaxButton(ID_OK_BUTTON) {
                 private static final long serialVersionUID = 1L;
 
                 @Override
-                public void onSubmit() {
-                    actionExecutor.executeActionAndProcessResults(ActionParameterForm.this);
+                public void onSubmit(AjaxRequestTarget target, Form<?> form) {
+                    actionExecutor.executeActionAndProcessResults(target, form);
                 };
             };
             add(okButton);
+            Button cancelButton = new Button(ID_CANCEL_BUTTON) {
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                public void onSubmit() {
+                    // no-op works fine for prompt modal dialog, but need to do something else if modal dialog disabled
+                };
+            };
+            add(cancelButton);
+            
+            // TODO: hide cancel button if dialogs disabled, as not yet implemented.
+            if(!PageAbstract.isActionPromptModalDialogEnabled()) {
+                cancelButton.setVisible(false);
+            }
         }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
index 846c258..bd14335 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
@@ -25,7 +25,9 @@ import java.util.List;
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 
+import org.apache.wicket.Page;
 import org.apache.wicket.Session;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.filter.Filter;
@@ -44,9 +46,10 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.entity.EntityActionLinkFactory;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.selector.links.LinksSelectorPanelAbstract;
 
 public final class EntityActionUtil {
@@ -55,7 +58,10 @@ public final class EntityActionUtil {
 
     private final static MemberOrderFacetComparator memberOrderFacetComparator = new MemberOrderFacetComparator(false);
     
-    public static List<LinkAndLabel> entityActions(EntityModel entityModel, ObjectAssociation association) {
+    public static List<LinkAndLabel> entityActions(
+            final EntityModel entityModel, 
+            final ObjectAssociation association, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         final ObjectSpecification adapterSpec = entityModel.getTypeOfSpecification();
         final ObjectAdapter adapter = entityModel.load(ConcurrencyChecking.NO_CHECK);
         final ObjectAdapterMemento adapterMemento = entityModel.getObjectAdapterMemento();
@@ -72,13 +78,13 @@ public final class EntityActionUtil {
                 return memberOrderFacetComparator.compare(m1, m2);
             }});
         
-        final CssMenuLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
+        final ActionLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
     
         return Lists.transform(userActions, new Function<ObjectAction, LinkAndLabel>(){
     
             @Override
             public LinkAndLabel apply(ObjectAction objectAction) {
-                return linkFactory.newLink(adapterMemento, objectAction, LinksSelectorPanelAbstract.ID_ADDITIONAL_LINK);
+                return linkFactory.newLink(adapterMemento, objectAction, LinksSelectorPanelAbstract.ID_ADDITIONAL_LINK, actionPromptModalWindowProvider);
             }});
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
index 016731f..ca875aa 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuFactory.java
@@ -39,13 +39,14 @@ import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.ApplicationActionsModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem.Builder;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel;
 
 /**
@@ -55,9 +56,8 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel;
 public class AppActionsCssMenuFactory extends ComponentFactoryAbstract {
 
     private final static long serialVersionUID = 1L;
-    
-    private final static CssMenuLinkFactory cssMenuLinkFactory = new AppActionsCssMenuLinkFactory();
 
+    
     static class LogicalServiceAction {
         private final String serviceName;
         private final ObjectAdapter serviceAdapter;
@@ -76,6 +76,8 @@ public class AppActionsCssMenuFactory extends ComponentFactoryAbstract {
         }
     }
 
+    private final static ActionLinkFactory cssMenuLinkFactory = new AppActionsCssMenuLinkFactory();
+
     public AppActionsCssMenuFactory() {
         super(ComponentType.APPLICATION_ACTIONS, CssMenuPanel.class);
     }
@@ -110,13 +112,17 @@ public class AppActionsCssMenuFactory extends ComponentFactoryAbstract {
         // prune any service names that have no service actions
         serviceNamesInOrder.retainAll(serviceActionsByName.keySet());
         
-        return buildMenuItems(serviceNamesInOrder, serviceActionsByName);
+        return buildMenuItems(serviceNamesInOrder, serviceActionsByName, appActionsModel.getActionPromptModalWindowProvider());
     }
 
     /**
      * Builds a hierarchy of {@link CssMenuItem}s, following the provided map of {@link LogicalServiceAction}s (keyed by their service Name).
      */
-    private List<CssMenuItem> buildMenuItems(final List<String> serviceNamesInOrder, final Map<String, List<LogicalServiceAction>> serviceActionsByName) {
+    private List<CssMenuItem> buildMenuItems(
+            final List<String> serviceNamesInOrder, 
+            final Map<String, List<LogicalServiceAction>> serviceActionsByName, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        
         final List<CssMenuItem> menuItems = Lists.newArrayList();
         for (String serviceName : serviceNamesInOrder) {
             final CssMenuItem serviceMenuItem = CssMenuItem.newMenuItem(serviceName).build();
@@ -129,7 +135,7 @@ public class AppActionsCssMenuFactory extends ComponentFactoryAbstract {
                 }
                 final ObjectAdapterMemento serviceAdapterMemento = logicalServiceAction.serviceAdapterMemento;
                 final ObjectAction objectAction = logicalServiceAction.objectAction;
-                final Builder subMenuItemBuilder = serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, cssMenuLinkFactory);
+                final Builder subMenuItemBuilder = serviceMenuItem.newSubMenuItem(serviceAdapterMemento, objectAction, cssMenuLinkFactory, actionPromptModalWindowProvider);
                 if (subMenuItemBuilder == null) {
                     // not visible
                     continue;

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
index d73dedb..5298364 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/appactions/cssmenu/AppActionsCssMenuLinkFactory.java
@@ -19,55 +19,32 @@
 
 package org.apache.isis.viewer.wicket.ui.components.appactions.cssmenu;
 
-import org.apache.wicket.Application;
-import org.apache.wicket.Page;
 import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
 
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.model.models.ActionModel;
-import org.apache.isis.viewer.wicket.model.models.PageType;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
-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.util.Links;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactoryAbstract;
 
-class AppActionsCssMenuLinkFactory implements CssMenuLinkFactory {
+class AppActionsCssMenuLinkFactory extends ActionLinkFactoryAbstract {
 
     private static final long serialVersionUID = 1L;
-
+    
     @Override
-    public LinkAndLabel newLink(final ObjectAdapterMemento adapterMemento, final ObjectAction action, final String linkId) {
-        final PageParameters pageParameters = ActionModel.createPageParameters(adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK), action, ConcurrencyChecking.NO_CHECK);
-
-        final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION_PROMPT);
-
-        final AbstractLink link = Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
-        final String actionLabel = ObjectAction.Utils.nameFor(action);
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento adapterMemento, final ObjectAction action, final String linkId, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         
-        // special case handling if this action is returning a URL
-        Util.addTargetBlankIfActionReturnsUrl(link, action);
+        ObjectAdapter objectAdapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
 
-        final boolean blobOrClob = CssMenuItem.returnsBlobOrClob(action);
-        final boolean prototype = CssMenuItem.isExplorationOrPrototype(action);
-        final String actionIdentifier = CssMenuItem.actionIdentifierFor(action);
-        final String cssClass = CssMenuItem.cssClassFor(action);
+        final AbstractLink link = newLink(linkId, objectAdapter, action, actionPromptModalWindowProvider);
 
-        return new LinkAndLabel(link, actionLabel, null, blobOrClob, prototype, actionIdentifier, cssClass);
+        return newLinkAndLabel(action, link, null);
     }
 
-    
-
-    // ////////////////////////////////////////////////////////////
-    // Dependencies
-    // ////////////////////////////////////////////////////////////
 
-    protected PageClassRegistry getPageClassRegistry() {
-        return ((PageClassRegistryAccessor) Application.get()).getPageClassRegistry();
-    }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.html
index a99da16..4e0ec63 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.html
@@ -30,6 +30,7 @@
 	      			<span class="collectionContents" wicket:id="collectionContents"/>
 				</div>
       			<span wicket:id="feedback"></span>
+                <div wicket:id="actionPromptModalWindow"/>
 			</div>
 		</wicket:panel>
 	</body>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 85fa535..671e0c8 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,53 +23,61 @@ 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;
 
-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.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 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;
 
 /**
  * Panel for rendering entity collection; analogous to (any concrete subclass
  * of) {@link ScalarPanelAbstract}.
  */
-public class CollectionPanel extends PanelAbstract<EntityCollectionModel> {
+public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implements ActionPromptModalWindowProvider {
 
     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 String collectionName;
     private Label label;
 
-    private static EntityCollectionModel createEntityCollectionModel(EntityModel entityModel, OneToManyAssociation otma) {
-        EntityCollectionModel collectionModel = EntityCollectionModel.createParented(entityModel, otma);
-        List<LinkAndLabel> entityActions = EntityActionUtil.entityActions(entityModel, otma);
+    public CollectionPanel(final String id, final EntityModel entityModel, OneToManyAssociation otma) {
+        this(id, newEntityCollectionModel(entityModel, otma), entityModel, otma);
+    }
 
-        collectionModel.addEntityActions(entityActions);
+    private static EntityCollectionModel newEntityCollectionModel(final EntityModel entityModel, OneToManyAssociation otma) {
+        EntityCollectionModel collectionModel = EntityCollectionModel.createParented(entityModel, otma);
         return collectionModel;
     }
 
-    public CollectionPanel(final String id, final EntityModel entityModel, OneToManyAssociation otma) {
-        this(id, createEntityCollectionModel(entityModel, otma));
+    CollectionPanel(String id, EntityCollectionModel collectionModel) {
+        this(id, collectionModel, new EntityModel(collectionModel.getParentObjectAdapterMemento()), collectionModel.getCollectionMemento().getCollection());
     }
 
-    CollectionPanel(String id, EntityCollectionModel collectionModel) {
+    CollectionPanel(String id, EntityCollectionModel collectionModel, EntityModel entityModel, OneToManyAssociation otma) {
         super(id, collectionModel);
 
-        final WebMarkupContainer markupContainer = new WebMarkupContainer(ID_COLLECTION);
+        addActionPromptModalWindow();
         
+        List<LinkAndLabel> entityActions = EntityActionUtil.entityActions(entityModel, otma, this);
+        collectionModel.addEntityActions(entityActions);
+
+        final WebMarkupContainer markupContainer = new WebMarkupContainer(ID_COLLECTION);
         collectionContents = getComponentFactoryRegistry().addOrReplaceComponent(markupContainer, ComponentType.COLLECTION_CONTENTS, getModel());
 
         addOrReplace(new ComponentFeedbackPanel(ID_FEEDBACK, collectionContents));
@@ -110,5 +118,20 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> {
         final String labelText = collectionName + (count != null? " (" + count + ")": " (+)");
         return labelText;
     }
+    
+    // ///////////////////////////////////////////////////////////////////
+    // ActionPromptModalWindowProvider
+    // ///////////////////////////////////////////////////////////////////
+    
+    private ModalWindow actionPromptModalWindow;
+    public ModalWindow getActionPromptModalWindow() {
+        return PageAbstract.getActionPromptModalWindowIfEnabled(actionPromptModalWindow);
+    }
+    
+    private void addActionPromptModalWindow() {
+        this.actionPromptModalWindow = PageAbstract.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW); 
+        addOrReplace(actionPromptModalWindow);
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
index cc3e1d4..ffdc949 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
@@ -47,14 +47,15 @@ import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.model.util.MementoFunctions;
 import org.apache.isis.viewer.wicket.model.util.ObjectAdapterFunctions;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 
-final class BulkActionsLinkFactory implements CssMenuLinkFactory {
+final class BulkActionsLinkFactory implements ActionLinkFactory {
     
     private static final long serialVersionUID = 1L;
     private final EntityCollectionModel model;
@@ -68,7 +69,12 @@ final class BulkActionsLinkFactory implements CssMenuLinkFactory {
     }
 
     @Override
-    public LinkAndLabel newLink(final ObjectAdapterMemento serviceAdapterMemento, final ObjectAction objectAction, final String linkId) {
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento serviceAdapterMemento, 
+            final ObjectAction objectAction, 
+            final String linkId, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        
         final ActionMemento actionMemento = new ActionMemento(objectAction);
         final AbstractLink link = new Link<Object>(linkId) {
             

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.html
index 0f6bbf6..403ae94 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.html
@@ -34,6 +34,7 @@
 			    </div>
                 <div class="clear"/>
 				<table class="contents" cellspacing="0" wicket:id="table">[table]</table>
+                <div wicket:id="actionPromptModalWindow"/>
 			</div>
 		</wicket:panel>
 	</body>

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/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 de74f1b..ec22d77 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,6 +29,7 @@ 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;
@@ -52,6 +53,7 @@ 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.isis.WicketViewerSettings;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionCountProvider;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ColumnAbstract;
@@ -59,15 +61,16 @@ import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.
 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.CssMenuLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 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 {
+public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityCollectionModel> implements CollectionCountProvider, ActionPromptModalWindowProvider {
 
     private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
 
@@ -75,6 +78,7 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
 
     private static final String ID_TABLE = "table";
     private static final String ID_ENTITY_ACTIONS = "entityActions";
+    private static final String ID_ACTION_PROMPT_MODAL_WINDOW = "actionPromptModalWindow";
 
     private DataTable<ObjectAdapter,String> dataTable;
 
@@ -98,7 +102,8 @@ 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());
 
-        buildEntityActionsGui(bulkActions);
+        addActionPromptModalWindow();
+        buildEntityActionsGui(bulkActions, this);
 
         addOrReplace(dataTable);
     }
@@ -137,7 +142,9 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         }));
     }
 
-    private void buildEntityActionsGui(List<ObjectAction> bulkActions) {
+    private void buildEntityActionsGui(
+            final List<ObjectAction> bulkActions, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         final EntityCollectionModel model = getModel();
         
         if(bulkActions.isEmpty() || model.isParented()) {
@@ -146,11 +153,11 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         }
         
         if(!bulkActions.isEmpty()) {
-            final CssMenuLinkFactory linkFactory = new BulkActionsLinkFactory(model, dataTable);
+            final ActionLinkFactory linkFactory = new BulkActionsLinkFactory(model, dataTable);
 
             final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(null, getServiceAdapters(), bulkActions, linkFactory);
             // TODO: i18n
-            final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
+            final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions", actionPromptModalWindowProvider);
 
             this.addOrReplace(cssMenuPanel);
         } else {
@@ -266,6 +273,23 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         return model.getCount();
     }
 
+    
+    // ///////////////////////////////////////////////////////////////////
+    // ActionPromptModalWindowProvider
+    // ///////////////////////////////////////////////////////////////////
+    
+    private ModalWindow actionPromptModalWindow;
+    public ModalWindow getActionPromptModalWindow() {
+        return PageAbstract.getActionPromptModalWindowIfEnabled(actionPromptModalWindow);
+    }
+    
+    private void addActionPromptModalWindow() {
+        this.actionPromptModalWindow = PageAbstract.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW); 
+        addOrReplace(actionPromptModalWindow);
+    }
+
+
+    // //////////////////////////////////////
 
     @Inject
     private WicketViewerSettings settings;

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
index c2b67ab..e8c5a0e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
@@ -19,12 +19,10 @@
 
 package org.apache.isis.viewer.wicket.ui.components.entity;
 
-import org.apache.wicket.Application;
 import org.apache.wicket.Page;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
-import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -36,18 +34,14 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.PageType;
-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.widgets.cssmenu.ActionLinkFactoryAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
-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.pages.actionprompt.ActionPromptPage;
 import org.apache.isis.viewer.wicket.ui.util.Links;
 
-public final class EntityActionLinkFactory implements CssMenuLinkFactory {
+public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
 
     private static final long serialVersionUID = 1L;
 
@@ -59,64 +53,34 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
     }
 
     @Override
-    public LinkAndLabel newLink(final ObjectAdapterMemento adapterMemento, final ObjectAction action, final String linkId) {
+    public LinkAndLabel newLink(final ObjectAdapterMemento adapterMemento, final ObjectAction action, final String linkId, final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-
-        final AbstractLink link = createLinkToPersistent(adapterMemento, action, linkId, adapter);
-        final String label = ObjectAction.Utils.nameFor(action);
-
+        
+        final Boolean persistent = adapter.representsPersistent();
+        if (!persistent) {
+            throw new IllegalArgumentException("Object '" + adapter.titleString(null) + "' is not persistent.");
+        }
+        
         // check visibility and whether enabled
         final AuthenticationSession session = getAuthenticationSession();
-
+        
         final Consent visibility = action.isVisible(session, adapter, Where.OBJECT_FORMS);
         if (visibility.isVetoed()) {
             return null;
         }
-
+        
+        final AbstractLink link = newLink(linkId, adapter, action, actionPromptModalWindowProvider);
+        
         final Consent usability = action.isUsable(session, adapter, Where.OBJECT_FORMS);
         final String disabledReasonIfAny = usability.getReason();
         if(disabledReasonIfAny != null) {
             link.setEnabled(false);
         }
 
-        // special case handling if this action is returning a URL
-        Util.addTargetBlankIfActionReturnsUrl(link, action);
-
-        final boolean blobOrClob = CssMenuItem.returnsBlobOrClob(action);
-        final boolean prototype = CssMenuItem.isExplorationOrPrototype(action);
-        final String actionIdentifier = CssMenuItem.actionIdentifierFor(action);
-        final String cssClass = CssMenuItem.cssClassFor(action);
-        return new LinkAndLabel(link, label, disabledReasonIfAny, blobOrClob, prototype, actionIdentifier, cssClass);
-    }
-
-    private AbstractLink createLinkToPersistent(final ObjectAdapterMemento adapterMemento, final ObjectAction action, final String linkId, final ObjectAdapter adapter) {
-        final Boolean persistent = adapter.representsPersistent();
-        if (!persistent) {
-            throw new IllegalArgumentException("Object '" + adapter.titleString(null) + "' is not persistent.");
-        } 
-        return createLinkForPersistent(linkId, adapterMemento, action);
-    }
-
-    /**
-     * Creates a link to the {@link ActionPromptPage} (ie the {@link PageClassRegistry registered page} for 
-     * {@link PageType#ACTION_PROMPT action}s) with the appropriate {@link PageParameters} to either render the action's
-     * parameter form (if it takes arguments) or to invoke the action directly.
-     * 
-     * <p>
-     * If the action's {@link ObjectAction#getSemantics() semantics} are {@link ActionSemantics.Of#SAFE safe}, then
-     * concurrency checking is disabled; otherwise it is enforced.
-     */
-    private AbstractLink createLinkForPersistent(final String linkId, final ObjectAdapterMemento adapterMemento, final ObjectAction action) {
-        final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-
-        // use the action semantics to determine whether invoking this action will require a concurrency check or not
-        // if it's "safe", then we'll just continue without any checking. 
-        final ConcurrencyChecking concurrencyChecking = ConcurrencyChecking.concurrencyCheckingFor(action.getSemantics());
-        final PageParameters pageParameters = ActionModel.createPageParameters(adapter, action, concurrencyChecking);
-        final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION_PROMPT);
-        return Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
+        return newLinkAndLabel(action, link, disabledReasonIfAny);
     }
 
+    
 
     // ///////////////////////////////////////////////////////////////////
     // Dependencies (from IsisContext)
@@ -134,18 +98,4 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
         return IsisContext.getAuthenticationSession();
     }
 
-    // ///////////////////////////////////////////////////////////////////
-    // Convenience
-    // ///////////////////////////////////////////////////////////////////
-
-    protected ComponentFactoryRegistry getComponentFactoryRegistry() {
-        final ComponentFactoryRegistryAccessor cfra = (ComponentFactoryRegistryAccessor) Application.get();
-        return cfra.getComponentFactoryRegistry();
-    }
-
-    protected PageClassRegistry getPageClassRegistry() {
-        final PageClassRegistryAccessor pcra = (PageClassRegistryAccessor) Application.get();
-        return pcra.getPageClassRegistry();
-    }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
index e81796d..55fd23f 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
@@ -27,6 +27,8 @@ import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.filter.Filter;
@@ -43,6 +45,7 @@ import org.apache.isis.core.runtime.system.DeploymentType;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ImageResourceCache;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
@@ -108,7 +111,7 @@ public class EntityHeaderPanel extends PanelAbstract<EntityModel> implements Act
 
             if(!topLevelActions.isEmpty()) {
                 final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(adapterMemento, getServiceAdapters(), topLevelActions, linkFactory);
-                final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
+                final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions", ActionPromptModalWindowProvider.Util.getFrom(this));
 
                 this.addOrReplace(cssMenuPanel);
             } else {

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index 827476f..86d0946 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -38,10 +38,9 @@ import org.apache.wicket.model.Model;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ActionParameterMemento;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel.RenderingHint;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
@@ -242,7 +241,8 @@ public abstract class ScalarPanelAbstract extends PanelAbstract<ScalarModel> imp
         if(scalarModel.getKind() == ScalarModel.Kind.PROPERTY) {
             final ObjectAdapterMemento parentMemento = scalarModel.getParentObjectAdapterMemento();
             final EntityModel parentEntityModel = new EntityModel(parentMemento);
-            entityActions = EntityActionUtil.entityActions(parentEntityModel, scalarModel.getPropertyMemento().getProperty());
+            final ActionPromptModalWindowProvider provider = ActionPromptModalWindowProvider.Util.getFrom(this);
+            entityActions = EntityActionUtil.entityActions(parentEntityModel, scalarModel.getPropertyMemento().getProperty(), provider);
         } else {
             entityActions = null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
new file mode 100644
index 0000000..2fbb784
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactory.java
@@ -0,0 +1,32 @@
+/*
+ *  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.cssmenu;
+
+import java.io.Serializable;
+
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
+
+public interface ActionLinkFactory extends Serializable {
+
+    LinkAndLabel newLink(ObjectAdapterMemento adapter, ObjectAction noAction, String linkId, ActionPromptModalWindowProvider actionPromptModalWindowProvider);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
new file mode 100644
index 0000000..a25e267
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
@@ -0,0 +1,141 @@
+/*
+ *  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.cssmenu;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
+import org.apache.isis.viewer.wicket.model.models.PageType;
+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.pages.PageClassRegistry;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+import org.apache.isis.viewer.wicket.ui.util.Links;
+
+public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public static void addTargetBlankIfActionReturnsUrl(final AbstractLink link, final ObjectAction action) {
+        final ObjectSpecification returnType = action.getReturnType();
+        if(returnType != null && "java.net.URL".equals(returnType.getFullIdentifier())) {
+            link.add(new AttributeAppender("target", Model.of("_blank")));
+            link.add(new CssClassAppender("noVeil"));
+        }
+    }
+    
+    /**
+     * Either creates a link for the action be rendered in a {@link ModalWindow}, or (if none can be
+     * {@link ActionPromptModalWindowProvider#getActionPromptModalWindow() provided}, or creates a link to 
+     * the {@link ActionPromptPage} (ie the {@link PageClassRegistry registered page} for 
+     * {@link PageType#ACTION_PROMPT action}s).
+     * 
+     * <p>
+     * If the action's {@link ObjectAction#getSemantics() semantics} are {@link ActionSemantics.Of#SAFE safe}, then
+     * concurrency checking is disabled; otherwise it is enforced.
+     */
+    protected AbstractLink newLink(
+            final String linkId, 
+            final ObjectAdapter objectAdapter, final ObjectAction action, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        
+        final ModalWindow modalWindow = actionPromptModalWindowProvider.getActionPromptModalWindow();
+        if(modalWindow != null) {
+            final ActionModel actionModel = ActionModel.create(objectAdapter, action);
+            AjaxLink<Object> link = new AjaxLink<Object>(linkId) {
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                public void onClick(AjaxRequestTarget target) {
+
+                    final Component actionPromptPanel = 
+                            getComponentFactoryRegistry().createComponent(
+                                    ComponentType.ACTION_PROMPT, modalWindow.getContentId(), actionModel);
+
+                    modalWindow.setTitle(actionModel.getTitle());
+                    modalWindow.setContent(actionPromptPanel);
+
+                    // http://stackoverflow.com/questions/8013364/how-to-defeat-browser-dialog-popup-when-calling-wicket-setresponsepage-from-mo/8679946#8679946
+                    target.prependJavaScript("Wicket.Window.unloadConfirmation = false;");
+                    modalWindow.show(target);
+                }
+            };
+            link.add(new CssClassAppender("noVeil"));
+            return link;
+            
+        } else {
+            
+            // use the action semantics to determine whether invoking this action will require a concurrency check or not
+            // if it's "safe", then we'll just continue without any checking. 
+            final ConcurrencyChecking concurrencyChecking = ConcurrencyChecking.concurrencyCheckingFor(action.getSemantics());
+            final PageParameters pageParameters = ActionModel.createPageParameters(objectAdapter, action, concurrencyChecking);
+            final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION_PROMPT);
+            AbstractLink link = Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
+            
+            // special case handling if this a no-arg action is returning a URL
+            if(action.getParameterCount()==0) {
+                addTargetBlankIfActionReturnsUrl(link, action);
+            }
+
+            return link;
+        }
+    }
+
+    protected LinkAndLabel newLinkAndLabel(final ObjectAction action, final AbstractLink link, final String disabledReasonIfAny) {
+        final String label = ObjectAction.Utils.nameFor(action);
+        final boolean blobOrClob = CssMenuItem.returnsBlobOrClob(action);
+        final boolean prototype = CssMenuItem.isExplorationOrPrototype(action);
+        final String actionIdentifier = CssMenuItem.actionIdentifierFor(action);
+        final String cssClass = CssMenuItem.cssClassFor(action);
+        
+        return new LinkAndLabel(link, label, disabledReasonIfAny, blobOrClob, prototype, actionIdentifier, cssClass);
+    }
+
+
+    // ////////////////////////////////////////////////////////////
+    // Dependencies
+    // ////////////////////////////////////////////////////////////
+    
+    protected ComponentFactoryRegistry getComponentFactoryRegistry() {
+        return ((ComponentFactoryRegistryAccessor)Application.get()).getComponentFactoryRegistry();
+    }
+    
+    protected PageClassRegistry getPageClassRegistry() {
+        return ((PageClassRegistryAccessor) Application.get()).getPageClassRegistry();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
index fffb2cc..5e87cee 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
 import org.apache.isis.core.progmodel.facets.actions.notcontributed.NotContributedFacet;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem.Builder;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel.Style;
 
@@ -54,35 +55,40 @@ public class CssMenuBuilder {
     
     private final List<ObjectAction> actions;
 
-    private final CssMenuLinkFactory cssMenuLinkFactory;
+    private final ActionLinkFactory cssMenuLinkFactory;
     
-    public CssMenuBuilder(final ObjectAdapterMemento adapterMemento, final List<ObjectAdapter> serviceAdapters, final List<ObjectAction> actions, final CssMenuLinkFactory cssMenuLinkFactory) {
+    public CssMenuBuilder(final ObjectAdapterMemento adapterMemento, final List<ObjectAdapter> serviceAdapters, final List<ObjectAction> actions, final ActionLinkFactory cssMenuLinkFactory) {
         this.adapterMemento = adapterMemento; // may be null
         this.serviceAdapters = serviceAdapters;
         this.actions = actions;
         this.cssMenuLinkFactory = cssMenuLinkFactory;
     }
 
-    public CssMenuBuilder(final List<ObjectAction> actions, final CssMenuLinkFactory cssMenuLinkFactory) {
+    public CssMenuBuilder(final List<ObjectAction> actions, final ActionLinkFactory cssMenuLinkFactory) {
         this(null, null, actions, cssMenuLinkFactory);
     }
 
 
-    public CssMenuPanel buildPanel(final String wicketId, final String rootName) {
+    public CssMenuPanel buildPanel(
+            final String wicketId, final String rootName, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         final CssMenuItem findUsing = CssMenuItem.newMenuItem(rootName).build();
-        addMenuItems(findUsing, actions);
+        addMenuItems(findUsing, actions, actionPromptModalWindowProvider);
         final CssMenuPanel cssMenuPanel = new CssMenuPanel(wicketId, Style.SMALL, Collections.singletonList(findUsing));
         return cssMenuPanel;
     }
 
-    private void addMenuItems(final CssMenuItem parent, final List<ObjectAction> actions) {
-        addMenuItemsForActionsOfType(parent, actions, ActionType.USER);
+    private void addMenuItems(
+            final CssMenuItem parent, 
+            final List<ObjectAction> actions, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        addMenuItemsForActionsOfType(parent, actions, ActionType.USER, actionPromptModalWindowProvider);
         if ( isExploring() || isPrototyping()) {
-            addMenuItemsForActionsOfType(parent, actions, ActionType.EXPLORATION);
-            addMenuItemsForActionsOfType(parent, actions, ActionType.PROTOTYPE);
+            addMenuItemsForActionsOfType(parent, actions, ActionType.EXPLORATION, actionPromptModalWindowProvider);
+            addMenuItemsForActionsOfType(parent, actions, ActionType.PROTOTYPE, actionPromptModalWindowProvider);
         }
         if (isDebugMode()) {
-            addMenuItemsForActionsOfType(parent, actions, ActionType.DEBUG);
+            addMenuItemsForActionsOfType(parent, actions, ActionType.DEBUG, actionPromptModalWindowProvider);
         }
     }
 
@@ -103,18 +109,28 @@ public class CssMenuBuilder {
         return true;
     }
 
-    private void addMenuItemsForActionsOfType(final CssMenuItem parent, final List<ObjectAction> actions, final ActionType type) {
+    private void addMenuItemsForActionsOfType(
+            final CssMenuItem parent, 
+            final List<ObjectAction> actions, 
+            final ActionType type, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         final Collection<ObjectAction> filterActionsOfType = Collections2.filter(actions, Filters.asPredicate(ObjectAction.Filters.ofType(type)));
         for (final ObjectAction action : filterActionsOfType) {
-            addMenuItem(parent, action);
+            addMenuItem(parent, action, actionPromptModalWindowProvider);
         }
     }
 
-    private void addMenuItem(final CssMenuItem parent, final ObjectAction action) {
-        addMenuItemForAction(parent, action);
+    private void addMenuItem(
+            final CssMenuItem parent, 
+            final ObjectAction action, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
+        addMenuItemForAction(parent, action, actionPromptModalWindowProvider);
     }
 
-    private void addMenuItemForAction(final CssMenuItem parent, final ObjectAction action) {
+    private void addMenuItemForAction(
+            final CssMenuItem parent, 
+            final ObjectAction action, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
         
         final NotContributedFacet notContributed = action.getFacet(NotContributedFacet.class);
         if (notContributed != null && notContributed.toActions()) {
@@ -127,13 +143,13 @@ public class CssMenuBuilder {
         final ObjectAdapterMemento targetAdapterMemento = adapterMemento; // determineAdapterFor(action);
         if(targetAdapterMemento != null) {
             // against an entity or a service (if a contributed action)
-            subMenuItemBuilder = parent.newSubMenuItem(targetAdapterMemento, action, cssMenuLinkFactory);
+            subMenuItemBuilder = parent.newSubMenuItem(targetAdapterMemento, action, cssMenuLinkFactory, actionPromptModalWindowProvider);
         } else {
             if (action.containsDoOpFacet(BulkFacet.class)) {
                 // ignore fact have no target action; 
                 // we expect that the link factory is able to handle this
                 // (ie will iterate through all objects from a list and invoke in bulk)
-                subMenuItemBuilder = parent.newSubMenuItem(action, cssMenuLinkFactory);
+                subMenuItemBuilder = parent.newSubMenuItem(action, cssMenuLinkFactory, actionPromptModalWindowProvider);
             }
         }
         

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
index 413abfb..15ac0da 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
@@ -52,6 +52,7 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptModalWindowProvider;
 import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
 import org.apache.isis.viewer.wicket.ui.util.Components;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
@@ -259,11 +260,16 @@ public class CssMenuItem implements Serializable {
     /**
      * Creates a {@link Builder} for a submenu item invoking an action on the provided
      * {@link ObjectAdapterMemento target adapter}.
+     * @param page 
      * 
      * @return the builder, else <tt>null</tt> if the action is not visible for
      *         the current user.
      */
-    public Builder newSubMenuItem(final ObjectAdapterMemento targetAdapterMemento, final ObjectAction objectAction, final CssMenuLinkFactory cssMenuLinkFactory) {
+    public Builder newSubMenuItem(
+            final ObjectAdapterMemento targetAdapterMemento, 
+            final ObjectAction objectAction, 
+            final ActionLinkFactory cssMenuLinkFactory, 
+            final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
 
         // check visibility
         final AuthenticationSession session = getAuthenticationSession();
@@ -274,7 +280,7 @@ public class CssMenuItem implements Serializable {
         }
 
         // build the link
-        final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(targetAdapterMemento, objectAction, PageAbstract.ID_MENU_LINK);
+        final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(targetAdapterMemento, objectAction, PageAbstract.ID_MENU_LINK, actionPromptModalWindowProvider);
         if(linkAndLabel==null) {
             // can only get a null if invisible, so this should not happen given guard above
             return null;
@@ -338,11 +344,12 @@ public class CssMenuItem implements Serializable {
     }
 
     /**
-     * Creates a {@link Builder} for a submenu item where the provided {@link CssMenuLinkFactory} is able to provide the target adapter. 
+     * Creates a {@link Builder} for a submenu item where the provided {@link ActionLinkFactory} is able to provide the target adapter. 
+     * @param page 
      */
-    public Builder newSubMenuItem(final ObjectAction objectAction, final CssMenuLinkFactory cssMenuLinkFactory) {
+    public Builder newSubMenuItem(final ObjectAction objectAction, final ActionLinkFactory cssMenuLinkFactory, final ActionPromptModalWindowProvider actionPromptModalWindowProvider) {
 
-        final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(null, objectAction, PageAbstract.ID_MENU_LINK);
+        final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(null, objectAction, PageAbstract.ID_MENU_LINK, actionPromptModalWindowProvider);
 
         final AbstractLink link = linkAndLabel.getLink();
         final String actionLabel = linkAndLabel.getLabel();

http://git-wip-us.apache.org/repos/asf/isis/blob/81b200fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
deleted file mode 100644
index bf1b09d..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuLinkFactory.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  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.cssmenu;
-
-import java.io.Serializable;
-
-import org.apache.wicket.behavior.AttributeAppender;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.model.Model;
-
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
-import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
-
-/**
- * Abstracts out the creation of the links within the CSS menu.
- */
-public interface CssMenuLinkFactory extends Serializable {
-
-    LinkAndLabel newLink(ObjectAdapterMemento adapter, ObjectAction noAction, String linkId);
-
-    public static class Util {
-        private Util() {}
-        public static void addTargetBlankIfActionReturnsUrl(AbstractLink link, ObjectAction action) {
-            final ObjectSpecification returnType = action.getReturnType();
-            if(returnType != null && "java.net.URL".equals(returnType.getFullIdentifier())) {
-                link.add(new AttributeAppender("target", Model.of("_blank")));
-                link.add(new CssClassAppender("noVeil"));
-            }
-        }
-    }
-
-
-}