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 2012/12/06 18:42:19 UTC

[50/52] [partial] ISIS-188: moving framework/ subdirs up to parent

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Toolkit.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Toolkit.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Toolkit.java
new file mode 100644
index 0000000..f761721
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Toolkit.java
@@ -0,0 +1,95 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Text;
+
+public abstract class Toolkit {
+    public static boolean debug = false;
+    private static Toolkit instance;
+
+    public static int defaultBaseline() {
+        return getInstance().colorsAndFonts.defaultBaseline();
+    }
+
+    public static int defaultFieldHeight() {
+        return getInstance().colorsAndFonts.defaultFieldHeight();
+    }
+
+    public static Color getColor(final int rgbColor) {
+        return getInstance().colorsAndFonts.getColor(rgbColor);
+    }
+
+    public static Color getColor(final String name) {
+        final Color color = getInstance().colorsAndFonts.getColor(name);
+        if (color == null) {
+            throw new IsisException("No such color: " + name);
+        }
+        return color;
+    }
+
+    public static ContentFactory getContentFactory() {
+        return getInstance().contentFactory;
+    }
+
+    protected static Toolkit getInstance() {
+        return instance;
+    }
+
+    public static Text getText(final String name) {
+        final Text text = getInstance().colorsAndFonts.getText(name);
+        if (text == null) {
+            throw new IsisException("No such text style: " + name);
+        }
+        return text;
+    }
+
+    public static Viewer getViewer() {
+        return getInstance().viewer;
+    }
+
+    public static Feedback getFeedbackManager() {
+        return getInstance().feedbackManager;
+    }
+
+    public static GlobalViewFactory getViewFactory() {
+        return getInstance().viewFactory;
+    }
+
+    protected ContentFactory contentFactory;
+    protected ColorsAndFonts colorsAndFonts;
+    protected Viewer viewer;
+    protected Feedback feedbackManager;
+    protected GlobalViewFactory viewFactory;
+
+    protected Toolkit() {
+        if (instance != null) {
+            throw new IllegalStateException("Toolkit already instantiated");
+        }
+        instance = this;
+        init();
+    }
+
+    protected abstract void init();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UndoStack.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UndoStack.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UndoStack.java
new file mode 100644
index 0000000..586f450
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UndoStack.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.dnd.view;
+
+import java.util.Vector;
+
+public class UndoStack {
+
+    private final Vector<Command> commands = new Vector<Command>();
+
+    public void add(final Command command) {
+        commands.addElement(command);
+        command.execute();
+    }
+
+    public void undoLastCommand() {
+        final Command lastCommand = commands.lastElement();
+        lastCommand.undo();
+        commands.removeElement(lastCommand);
+    }
+
+    public String descriptionOfUndo() {
+        final Command lastCommand = commands.lastElement();
+        return lastCommand.getDescription();
+    }
+
+    public boolean isEmpty() {
+        return commands.isEmpty();
+    }
+
+    public String getNameOfUndo() {
+        final Command lastCommand = commands.lastElement();
+        return lastCommand.getName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserAction.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserAction.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserAction.java
new file mode 100644
index 0000000..240492c
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserAction.java
@@ -0,0 +1,57 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.viewer.dnd.drawing.Location;
+
+public interface UserAction {
+
+    /**
+     * Returns the type of action: user, exploration, debug, or a set.
+     */
+    ActionType getType();
+
+    /**
+     * Indicate that this action is disabled
+     */
+    Consent disabled(View view);
+
+    /**
+     * Invoke this action.
+     */
+    void execute(Workspace workspace, View view, Location at);
+
+    /**
+     * Returns the description of the action.
+     */
+    String getDescription(View view);
+
+    /**
+     * Returns the help text for the action.
+     */
+    String getHelp(View view);
+
+    /**
+     * Returns the name of the action as the user will refer to it.
+     */
+    String getName(View view);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserActionSet.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserActionSet.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserActionSet.java
new file mode 100644
index 0000000..a3d7048
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/UserActionSet.java
@@ -0,0 +1,44 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.dnd.drawing.Color;
+
+public interface UserActionSet extends UserAction {
+
+    void add(UserAction userAction);
+
+    void addObjectMenuOptions(ObjectAdapter object);
+
+    void addCreateOptions(ObjectSpecification specification);
+
+    UserActionSet addNewActionSet(String name);
+
+    UserActionSet addNewActionSet(String name, ActionType type);
+
+    UserAction[] getUserActions();
+
+    Color getColor();
+
+    void setColor(Color color);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/View.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/View.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/View.java
new file mode 100644
index 0000000..406405d
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/View.java
@@ -0,0 +1,396 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.runtime.userprofile.OptionsClient;
+import org.apache.isis.viewer.dnd.drawing.Bounds;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Padding;
+import org.apache.isis.viewer.dnd.drawing.Size;
+
+public interface View extends Cloneable, OptionsClient {
+    
+    void addView(View view);
+
+    /**
+     * Determines if the user is able to change the held value.
+     */
+    Consent canChangeValue();
+
+    /**
+     * Determines whether this view accepts keyboard focus. If so focusLost and
+     * focusReceived will be called.
+     */
+    boolean canFocus();
+
+    boolean contains(View view);
+
+    boolean containsFocus();
+
+    /**
+     * Called when the popup menu is being populated for this view. Any content
+     * options that need to appear on the menu should be added to the
+     * <code>menuOptions</code> object.
+     */
+    void contentMenuOptions(UserActionSet menuOptions);
+
+    void debug(DebugBuilder debug);
+
+    void debugStructure(DebugBuilder debug);
+
+    /**
+     * Called when a view is no longer needed and its resources can be disposed
+     * of. Dissociates this view from its parent, and removes itself from the
+     * list of views that need to be updated.
+     * 
+     * @see #removeView(View)
+     */
+    void dispose();
+
+    /**
+     * Called as mouse is dragged within and without this view. This only occurs
+     * when no content or view is being dragged.
+     */
+    void drag(InternalDrag drag);
+
+    void drag(ViewDrag drag);
+
+    void dragCancel(InternalDrag drag);
+
+    View dragFrom(Location location);
+
+    /**
+     * Called as the content being dragged is dragged into this view. This only
+     * occurs when view contents are being dragged, and not when views
+     * themselves are being dragged.
+     */
+    void dragIn(ContentDrag drag);
+
+    /**
+     * Called as the content being dragged is dragged out of this view. This
+     * only occurs when view contents are being dragged, and not when views
+     * themselves are being dragged.
+     */
+    void dragOut(ContentDrag drag);
+
+    DragEvent dragStart(DragStart drag);
+
+    /**
+     * Called as the drag ends within and without this view. This only occurs
+     * when no content or view is being dragged.
+     */
+    void dragTo(InternalDrag drag);
+
+    /**
+     * Called by the frame, or the parent view, when this view must redraw
+     * itself.
+     */
+    void draw(Canvas canvas);
+
+    /**
+     * Called as another view's contents (the source) is dropped on this view's
+     * contents (the target). The source view can be obtained from the ViewDrag
+     * object.
+     */
+    void drop(ContentDrag drag);
+
+    /**
+     * Called as another view (the source) is dropped on this view (the target).
+     * The source view can be obtained from the ViewDrag object.
+     */
+    void drop(ViewDrag drag);
+
+    /**
+     * Indicates that editing has been completed and the entry should be saved.
+     * Will be called by the view manager when other action place within the
+     * parent.
+     * 
+     * @param moveFocus
+     *            flags that focus should be moved from this field after the
+     *            entry has been processed.
+     * @param toNextField
+     *            flags that the focus should be moved to the next field (if
+     *            <code>true</code>) or to the previous field (if
+     *            <code>false</code>). This parameter is ignored if the
+     *            moveFocus parameter is <code>false</code>.
+     */
+    void editComplete(boolean moveFocus, boolean toNextField);
+
+    /**
+     * Called as the mouse crosses the bounds, and ends up inside, of this view.
+     * Is also called as the mouse returns into this view from a contained view.
+     */
+    void entered();
+
+    /**
+     * Called as the mouse crosses the bounds, and ends up outside, of this
+     * view.
+     */
+    void exited();
+
+    /**
+     * Called when the user clicks the mouse buttone within this view.
+     * 
+     * @param click
+     *            the location within the current view where the mouse click
+     *            took place
+     */
+    void firstClick(Click click);
+
+    void focusLost();
+
+    void focusReceived();
+
+    Location getAbsoluteLocation();
+
+    int getBaseline();
+
+    /**
+     * Returns the bounding rectangle that describes where (within it parent),
+     * and how big, this view is.
+     * 
+     * @see #getSize()
+     * @see #getLocation()
+     * @return Bounds
+     */
+    Bounds getBounds();
+
+    /**
+     * get the object that this view represents
+     */
+    Content getContent();
+
+    FocusManager getFocusManager();
+
+    int getId();
+
+    /**
+     * Determines the location relative to this object's containing view
+     * 
+     * @see #getBounds()
+     */
+    Location getLocation();
+
+    Padding getPadding();
+
+    View getParent();
+
+    Size getRequiredSize(Size availableSpace);
+
+    /**
+     * Determines the size of this view.
+     * 
+     * @see #getBounds()
+     */
+    Size getSize();
+
+    ViewSpecification getSpecification();
+
+    ViewState getState();
+
+    View[] getSubviews();
+
+    /**
+     * returns the topmost decorator in the chain, or the view itself if not
+     * decorated.
+     */
+    View getView();
+
+    Viewer getViewManager();
+
+    Axes getViewAxes();
+
+    Feedback getFeedbackManager();
+
+    Workspace getWorkspace();
+
+    boolean hasFocus();
+
+    View identify(Location mouseLocation);
+
+    /**
+     * Flags that the views do not properly represent the content, and hence it
+     * needs rebuilding. Contrast this with invalidateLayout(), which deals with
+     * an a complete view, but one that is not showing properly.
+     * 
+     * @see #invalidateLayout()
+     */
+    void invalidateContent();
+
+    /**
+     * Flags that the views are possibly not displaying the content fully - too
+     * small, wrong place etc - although views exists for all the content.
+     * Contrast this with invalidateContent(), which deals with an incomplete
+     * view.
+     * 
+     * @see #invalidateContent()
+     */
+    void invalidateLayout();
+
+    /**
+     * Called when the user presses any key on the keyboard while this view has
+     * the focus.
+     */
+    void keyPressed(KeyboardAction key);
+
+    /**
+     * Called when the user releases any key on the keyboard while this view has
+     * the focus.
+     */
+    void keyReleased(KeyboardAction action);
+
+    /**
+     * Called when the user presses a non-control key (i.e. data entry keys and
+     * not shift, up-arrow etc). Such a key press will result in a prior call to
+     * <code>keyPressed</code> and a subsequent call to <code>keyReleased</code>
+     * .
+     */
+    void keyTyped(KeyboardAction action);
+
+    void layout();
+
+    /**
+     * Limits the bounds of this view (normally when being moved or dropped) so
+     * it never extends beyond the bounds of a view of the specified size.
+     */
+    void limitBoundsWithin(Size size);
+
+    void markDamaged();
+
+    void markDamaged(Bounds bounds);
+
+    /**
+     * Called as the mouse button is pressed down within this view. Does
+     * nothing; should be overriden when needed. the position relative to the
+     * top-left of this view
+     */
+    void mouseDown(Click click);
+
+    /**
+     * Called as the mouse is moved around within this view. Does nothing;
+     * should be overriden when needed.
+     * 
+     * @param location
+     *            the position relative to the top-left of this view
+     */
+    void mouseMoved(Location location);
+
+    /**
+     * Called as the mouse button is released within this view (assuming that it
+     * was pressed in this view). Does nothing; should be overridden when
+     * needed.
+     */
+    void mouseUp(Click click);
+
+    /**
+     * Called when an action generates a result, allowing this view to decide
+     * what to do with it.
+     */
+    void objectActionResult(ObjectAdapter result, Placement placement);
+
+    /**
+     * Called as the drag of this view's content starts.
+     */
+    View pickupContent(Location location);
+
+    /**
+     * Called as the drag of this view starts.
+     */
+    View pickupView(Location location);
+
+    void print(Canvas canvas);
+
+    /**
+     * Refreshes this view by reaccessing its content and redisplaying it.
+     */
+    void refresh();
+
+    /**
+     * Removes the specifed view from the subviews contained by this view.
+     */
+    void removeView(View view);
+
+    void replaceView(View toReplace, View replacement);
+
+    /**
+     * Called when the user double-clicked this view. This method will have been
+     * preceded by a call to <code>click</code>.
+     */
+    void secondClick(Click click);
+
+    void setBounds(Bounds bounds);
+
+    void setFocusManager(FocusManager focusManager);
+
+    /**
+     * Specifies the location of this view, relative to its enclosing view.
+     */
+    void setLocation(Location point);
+
+    void setParent(View view);
+
+    void setSize(Size size);
+
+    void setView(View view);
+
+    /**
+     * Identifies the subview that contains the specified location within its
+     * bounds. Returns null if no subview exists for that location.
+     */
+    View subviewFor(Location location);
+
+    /**
+     * Called when the user triple-clicks the mouse buttone within this view.
+     * This method will have been preceded by a call to <code>doubleClick</code>
+     * .
+     */
+    void thirdClick(Click click);
+
+    /**
+     * notification that the content of this view has changed
+     */
+    void update(ObjectAdapter object);
+
+    void updateView();
+
+    /**
+     * Determines if the user is invoking an action relating to this view,
+     * rather than to whatever this view represents.
+     * 
+     * @param mouseLocation
+     * @return true if the user is targeting the view itself, false if the user
+     *         is targeting what is being represented
+     */
+    ViewAreaType viewAreaType(Location mouseLocation);
+
+    /**
+     * Called when the popup menu is being populated for this view. Any view
+     * options that need to appear on the menu should be added to the
+     * <code>menuOptions</code> object.
+     */
+    void viewMenuOptions(UserActionSet menuOptions);
+
+    void drag(ContentDrag contentDrag);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAreaType.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAreaType.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAreaType.java
new file mode 100644
index 0000000..4f0e337
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAreaType.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.dnd.view;
+
+public class ViewAreaType {
+    public static final ViewAreaType VIEW = new ViewAreaType("View");
+    public static final ViewAreaType CONTENT = new ViewAreaType("Content");
+    public static final ViewAreaType INTERNAL = new ViewAreaType("Internal");
+    private final String name;
+
+    public ViewAreaType(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAxis.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAxis.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAxis.java
new file mode 100644
index 0000000..9fdfdc0
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewAxis.java
@@ -0,0 +1,23 @@
+/*
+ *  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.dnd.view;
+
+public interface ViewAxis {
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewConstants.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewConstants.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewConstants.java
new file mode 100644
index 0000000..5f3d6dc
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewConstants.java
@@ -0,0 +1,31 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.util.Properties;
+
+public final class ViewConstants {
+
+    /** Horizontal padding (||) between two components */
+    public static final int HPADDING = IsisContext.getConfiguration().getInteger(Properties.PROPERTY_BASE + "hpadding", 3);
+    /** Vertical padding (=) between two components */
+    public static final int VPADDING = IsisContext.getConfiguration().getInteger(Properties.PROPERTY_BASE + "vpadding", 3);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewDrag.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewDrag.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewDrag.java
new file mode 100644
index 0000000..316efde
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewDrag.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.dnd.view;
+
+import org.apache.isis.viewer.dnd.drawing.Location;
+
+/**
+ * Details a drag event that affects a view. The target of a ViewDrag is always
+ * the workspace of the source view.
+ * 
+ * <p>
+ * An overlay view, as returned by the pickup() method on the source view, is
+ * moved by this drag objects so its location follows the pointer by an offset
+ * equivalent to the mouse location within the view.
+ */
+public interface ViewDrag extends Drag {
+
+    View getSourceView();
+
+    Location getLocation();
+
+    Location getViewDropLocation();
+
+    void subtract(int left, int top);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewFactory.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewFactory.java
new file mode 100644
index 0000000..e0557b4
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewFactory.java
@@ -0,0 +1,29 @@
+/*
+ *  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.dnd.view;
+
+public interface ViewFactory {
+    /**
+     * Create a new view to this specification for the specified context, and
+     * using the specified axis if specified (which can be null).
+     */
+
+    View createView(Content content, Axes axes, int sequence);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewRequirement.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewRequirement.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewRequirement.java
new file mode 100644
index 0000000..87fef3f
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewRequirement.java
@@ -0,0 +1,123 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class ViewRequirement {
+    public static final int NONE = 0;
+    public static final int CLOSED = 0x01;
+    // public static final int SUMMARY = 0x02;
+    public static final int OPEN = 0x04;
+
+    public static final int EDITABLE = 0x10;
+
+    public static final int FIXED = 0x100;
+    public static final int EXPANDABLE = 0x200;
+
+    public static final int ROOT = 0x1000;
+    public static final int SUBVIEW = 0x2000;
+
+    public static final int DESIGN = 0x10000;
+
+    private final Content content;
+    private final int status;
+
+    public ViewRequirement(final Content content, int status) {
+        Assert.assertNotNull(content);
+        this.content = content;
+        this.status = status;
+        status = CLOSED;
+    }
+
+    public Content getContent() {
+        return content;
+    }
+
+    public boolean is(final int status) {
+        return (this.status & status) == status;
+    }
+
+    public boolean isClosed() {
+        return is(CLOSED);
+    }
+
+    public boolean isOpen() {
+        return is(OPEN);
+    }
+
+    public boolean isFixed() {
+        return is(FIXED);
+    }
+
+    public boolean isExpandable() {
+        return is(EXPANDABLE);
+    }
+
+    public boolean isSubview() {
+        return is(SUBVIEW);
+    }
+
+    public boolean isEditable() {
+        return is(EDITABLE);
+    }
+
+    @Deprecated
+    public boolean isDesign() {
+        return true;
+    }
+
+    public boolean isObject() {
+        return content.isObject();
+    }
+
+    public boolean isCollection() {
+        return content.isCollection();
+    }
+
+    public boolean isTextParseable() {
+        return content.isTextParseable();
+    }
+
+    public boolean isFor(final Class<?> cls) {
+        return cls.isAssignableFrom(content.getClass());
+    }
+
+    public boolean hasReference() {
+        return content.getAdapter() != null;
+    }
+
+    public boolean isForValueType(final Class<? extends Facet> cls) {
+        final ObjectSpecification specification = content.getSpecification();
+        return specification != null && specification.containsFacet(cls);
+    }
+
+    public ObjectSpecification getSpecification() {
+        return content.getAdapter().getSpecification();
+    }
+
+    public ObjectAdapter getAdapter() {
+        return content.getAdapter();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewSpecification.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewSpecification.java
new file mode 100644
index 0000000..05ec850
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewSpecification.java
@@ -0,0 +1,65 @@
+/*
+ *  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.dnd.view;
+
+/**
+ * Describes a view, and how it is built.
+ */
+public interface ViewSpecification extends ViewFactory {
+
+    String getName();
+
+    /**
+     * Determines if the view created to this specification can display the
+     * specified type. Returns true if it can.
+     */
+    boolean canDisplay(ViewRequirement requirement);
+
+    /**
+     * Indicates whether views to this specification are open - displaying the
+     * attributes of the content object - or are closed - display only the title
+     * of the content object.
+     */
+    boolean isOpen();
+
+    /**
+     * Indicates whether this view can be replaced with another view (for the
+     * same value or reference).
+     * 
+     * @return true if it can be replaced by another view; false if it can't be
+     *         replaces
+     */
+    boolean isReplaceable();
+
+    boolean isSubView();
+
+    /**
+     * Return true if the generated views are to have their sizes adjusted so
+     * they are consistent with surrounding views.
+     */
+    // TODO rename
+    boolean isAligned();
+
+    /**
+     * Indicates if this view can handled being resized. If it can't then the
+     * viewer can put it in a scroll border.
+     */
+    boolean isResizeable();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewState.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewState.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewState.java
new file mode 100644
index 0000000..cc76f88
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/ViewState.java
@@ -0,0 +1,158 @@
+/*
+ *  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.dnd.view;
+
+public class ViewState implements Cloneable {
+    private static final short CAN_DROP = 0x10;
+    private static final short CANT_DROP = 0x08;
+    private static final short CONTENT_IDENTIFIED = 0x04;
+    private static final short ROOT_VIEW_IDENTIFIED = 0x01;
+    private static final short VIEW_IDENTIFIED = 0x02;
+    private static final short INVALID = 0x40;
+    private static final short ACTIVE = 0x20;
+    private static final short OUT_OF_SYNCH = 0x80;
+
+    private short state;
+
+    public void setCanDrop() {
+        state |= CAN_DROP;
+    }
+
+    public void setCantDrop() {
+        state |= CANT_DROP;
+    }
+
+    public void setContentIdentified() {
+        state |= CONTENT_IDENTIFIED;
+    }
+
+    public boolean isObjectIdentified() {
+        return (state & CONTENT_IDENTIFIED) > 0;
+    }
+
+    public void setRootViewIdentified() {
+        state |= ROOT_VIEW_IDENTIFIED;
+    }
+
+    public boolean isRootViewIdentified() {
+        return (state & ROOT_VIEW_IDENTIFIED) > 0;
+    }
+
+    public void setViewIdentified() {
+        state |= VIEW_IDENTIFIED;
+    }
+
+    public boolean isViewIdentified() {
+        return (state & VIEW_IDENTIFIED) > 0;
+    }
+
+    public boolean canDrop() {
+        return (state & CAN_DROP) == CAN_DROP;
+    }
+
+    public boolean cantDrop() {
+        return (state & CANT_DROP) == CANT_DROP;
+    }
+
+    public void clearObjectIdentified() {
+        state &= ~(CONTENT_IDENTIFIED | CAN_DROP | CANT_DROP);
+    }
+
+    public void clearRootViewIdentified() {
+        state &= ~ROOT_VIEW_IDENTIFIED;
+    }
+
+    public void clearViewIdentified() {
+        state &= ~(VIEW_IDENTIFIED | CONTENT_IDENTIFIED | CAN_DROP | CANT_DROP);
+    }
+
+    @Override
+    protected Object clone() throws CloneNotSupportedException {
+        return super.clone();
+    }
+
+    @Override
+    public String toString() {
+        String str = "";
+        if (state == 0) {
+            str = "Normal";
+        } else {
+            str += isObjectIdentified() ? "Object-Identified " : "";
+            str += isViewIdentified() ? "View-identified " : "";
+            str += isRootViewIdentified() ? "Root-view-identified " : "";
+            str += canDrop() ? "Can-drop " : "";
+            str += cantDrop() ? "Cant-drop " : "";
+            str += isActive() ? "Active " : "";
+            str += isInvalid() ? "Invalid " : "";
+            str += isOutOfSynch() ? "Out-of-synch " : "";
+            str += " " + Integer.toBinaryString(state);
+        }
+        return str;
+    }
+
+    public void setActive() {
+        setFlag(ACTIVE);
+    }
+
+    public void setInactive() {
+        resetFlag(ACTIVE);
+    }
+
+    public boolean isActive() {
+        return isFlagSet(ACTIVE);
+    }
+
+    private boolean isFlagSet(final short flag) {
+        return (state & flag) > 0;
+    }
+
+    public void clearInvalid() {
+        resetFlag(INVALID);
+    }
+
+    private void setFlag(final short flag) {
+        state |= flag;
+    }
+
+    public void setInvalid() {
+        setFlag(INVALID);
+    }
+
+    private void resetFlag(final short flag) {
+        state &= ~flag;
+    }
+
+    public boolean isInvalid() {
+        return isFlagSet(INVALID);
+    }
+
+    public boolean isOutOfSynch() {
+        return isFlagSet(OUT_OF_SYNCH);
+    }
+
+    public void setOutOfSynch() {
+        setFlag(OUT_OF_SYNCH);
+    }
+
+    public void clearOutOfSynch() {
+        resetFlag(OUT_OF_SYNCH);
+    }
+
+}

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

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Viewer.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Viewer.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Viewer.java
new file mode 100644
index 0000000..27211ca
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Viewer.java
@@ -0,0 +1,84 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.viewer.dnd.drawing.Background;
+import org.apache.isis.viewer.dnd.drawing.Bounds;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+
+public interface Viewer {
+
+    void markDamaged(final Bounds bounds);
+
+    boolean hasFocus(final View view);
+
+    UndoStack getUndoStack();
+
+    Size getOverlaySize();
+
+    void saveCurrentFieldEntry();
+
+    void setKeyboardFocus(final View view);
+
+    boolean isRunningAsExploration();
+
+    boolean isRunningAsPrototype();
+
+    void clearAction();
+
+    /**
+     * Force a repaint of the damaged area of the viewer.
+     */
+    void scheduleRepaint();
+
+    void addToNotificationList(final View view);
+
+    void removeFromNotificationList(final View view);
+
+    void setBackground(Background background);
+
+    InteractionSpy getSpy();
+
+    void clearOverlayView();
+
+    void clearOverlayView(final View view);
+
+    void setOverlayView(final View view);
+
+    void showDebugFrame(DebuggableWithTitle[] info, Location at);
+
+    void showInOverlay(Content content, Location location);
+
+    // TODO should this be an extension?
+    String selectFilePath(final String title, final String directory);
+
+    void setClipboard(String clip, Class<?> class1);
+
+    Object getClipboard(Class<?> class1);
+
+    /**
+     * Removes views for objects that no longer exist, ie have been deleted.
+     */
+    void disposeUnneededViews();
+
+    void saveOpenObjects();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Workspace.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Workspace.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Workspace.java
new file mode 100644
index 0000000..0270b08
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/Workspace.java
@@ -0,0 +1,44 @@
+/*
+ *  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.dnd.view;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+public interface Workspace extends View {
+
+    View addIconFor(ObjectAdapter adapter, Placement placement);
+
+    View addWindowFor(ObjectAdapter object, Placement placement);
+
+    void addWindow(View window, Placement placement);
+
+    void addDialog(View dialog, Placement placement);
+
+    /**
+     * Lower the specified view so it is below all the other views.
+     */
+    void lower(View view);
+
+    /**
+     * Raise the specified view so it is above all the other views.
+     */
+    void raise(View view);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/AbstractObjectOption.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/AbstractObjectOption.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/AbstractObjectOption.java
new file mode 100644
index 0000000..cf428ab
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/AbstractObjectOption.java
@@ -0,0 +1,88 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Allow;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public abstract class AbstractObjectOption extends UserActionAbstract {
+
+    // REVIEW: confirm this rendering context
+    private final Where where = Where.OBJECT_FORMS;
+
+    protected final ObjectAction action;
+    protected final ObjectAdapter target;
+
+    protected AbstractObjectOption(final ObjectAction action, final ObjectAdapter target, final String name) {
+        super(name);
+        this.action = action;
+        this.target = target;
+    }
+
+    @Override
+    public Consent disabled(final View view) {
+        final ObjectAdapter adapter = view.getContent().getAdapter();
+        if (adapter != null && adapter.isDestroyed()) {
+            // TODO: move logic into Facet
+            return new Veto("Can't do anything with a destroyed object");
+        }
+        final Consent usableForUser = action.isUsable(IsisContext.getAuthenticationSession(), target, where);
+        if (usableForUser.isVetoed()) {
+            return usableForUser;
+        }
+
+        final Consent validParameters = checkValid();
+        if (validParameters != null && validParameters.isVetoed()) {
+            return validParameters;
+        }
+        final String desc = action.getDescription();
+        final String description = getName(view) + (desc.length() == 0 ? "" : ": " + desc);
+        // TODO: replace with a Facet
+        return new Allow(description);
+    }
+
+    protected Consent checkValid() {
+        return null;
+    }
+
+    @Override
+    public String getHelp(final View view) {
+        return action.getHelp();
+    }
+
+    @Override
+    public ActionType getType() {
+        return action.getType();
+    }
+
+    @Override
+    public String toString() {
+        return new ToString(this).append("action", action).toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionContent.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionContent.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionContent.java
new file mode 100644
index 0000000..6dd01b4
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionContent.java
@@ -0,0 +1,41 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.viewer.dnd.view.Content;
+
+public interface ActionContent extends Content {
+    public Consent disabled();
+
+    public ObjectAdapter execute();
+
+    public String getActionName();
+
+    public int getNoParameters();
+
+    public ParameterContent getParameterContent(final int index);
+
+    public ObjectAdapter getParameterObject(final int index);
+
+    @Override
+    public String getDescription();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
new file mode 100644
index 0000000..7a39a93
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
@@ -0,0 +1,168 @@
+/*
+ *  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.dnd.view.action;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ParseableEntryActionParameter;
+
+public class ActionHelper {
+
+    public static ActionHelper createInstance(final ObjectAdapter target, final ObjectAction action) {
+        final int numberParameters = action.getParameterCount();
+        final ObjectAdapter[] parameters = new ObjectAdapter[numberParameters];
+        final List<ObjectActionParameter> parameterSpecs = action.getParameters();
+        ObjectAdapter[] defaultValues;
+        ObjectAdapter[][] options;
+
+        // action choices most be old or new syntax - cannot be mixed
+
+        defaultValues = new ObjectAdapter[parameterSpecs.size()];
+        options = new ObjectAdapter[parameterSpecs.size()][];
+
+        for (int i = 0; i < parameterSpecs.size(); i++) {
+            defaultValues[i] = parameterSpecs.get(i).getDefault(target);
+            options[i] = parameterSpecs.get(i).getChoices(target);
+        }
+
+        if (!hasValues(defaultValues) && !hasValues(options)) {
+            // fall back to old method
+
+            defaultValues = action.getDefaults(target);
+            options = action.getChoices(target);
+        }
+
+        for (int i = 0; i < parameterSpecs.size(); i++) {
+            if (defaultValues[i] != null) {
+                parameters[i] = defaultValues[i];
+            } else {
+                parameters[i] = null; // PersistorUtil.createValueInstance(noap.getSpecification());
+            }
+        }
+
+        /*
+         * int[] maxLength = action.getParameterMaxLengths(); int[]
+         * typicalLength = action.getParameterTypicalLengths(); int[] noLines =
+         * action.getParameterNoLines(); boolean[] canWrap =
+         * action.canParametersWrap();
+         */
+        return new ActionHelper(target, action, parameters, defaultValues, options);
+    }
+
+    private final ObjectAction action;
+    private final ObjectAdapter[] parameters;
+    private final ObjectAdapter target;
+    private final ObjectAdapter[][] options;
+
+    private ActionHelper(final ObjectAdapter target, final ObjectAction action, final ObjectAdapter[] parameters, final ObjectAdapter[] defaultValues, final ObjectAdapter[][] options) {
+        this.target = target;
+        this.action = action;
+        this.parameters = parameters;
+        this.options = options;
+    }
+
+    public ParameterContent[] createParameters() {
+        final ParameterContent[] parameterContents = new ParameterContent[parameters.length];
+        for (int i = 0; i < parameters.length; i++) {
+            final List<ObjectActionParameter> parameters2 = action.getParameters();
+            final ObjectAdapter adapter = parameters[i];
+            final ObjectSpecification specification = parameters2.get(i).getSpecification();
+            if (specification.isParseable()) {
+                final ParseableEntryActionParameter parseableEntryActionParameter = (ParseableEntryActionParameter) parameters2.get(i);
+                parameterContents[i] = new TextParseableParameterImpl(parseableEntryActionParameter, adapter, options[i], i, this);
+            } else {
+                parameterContents[i] = new ObjectParameterImpl((OneToOneActionParameter) parameters2.get(i), adapter, options[i], i, this);
+            }
+        }
+
+        return parameterContents;
+    }
+
+    public Consent disabled() {
+        // REVIEW this is no good as it lumps all the parameters together; I
+        // need to know which parameter is
+        // disabled!
+        return action.isProposedArgumentSetValid(target, parameters);
+    }
+
+    public String getName() {
+        return action.getName();
+    }
+
+    public String getDescription() {
+        return action.getDescription();
+    }
+
+    public String getHelp() {
+        return action.getHelp();
+    }
+
+    public ObjectAdapter getParameter(final int index) {
+        return parameters[index];
+    }
+
+    public ObjectAdapter getTarget() {
+        return action.realTarget(target);
+    }
+
+    public ObjectAdapter invoke() {
+        return action.execute(target, parameters);
+    }
+
+    public void setParameter(final int index, final ObjectAdapter parameter) {
+        this.parameters[index] = parameter;
+    }
+
+    public String title() {
+        return getTarget().titleString();
+    }
+
+    public String getIconName() {
+        return getTarget().getIconName();
+    }
+
+    private static boolean hasValues(final ObjectAdapter[] values) {
+        if (values != null) {
+            for (final ObjectAdapter adapter : values) {
+                if (adapter != null) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean hasValues(final ObjectAdapter[][] values) {
+        if (values != null) {
+            for (final ObjectAdapter[] adapters : values) {
+                if (hasValues(adapters)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/BackgroundWork.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/BackgroundWork.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/BackgroundWork.java
new file mode 100644
index 0000000..9d0a6bb
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/BackgroundWork.java
@@ -0,0 +1,81 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.exceptions.IsisApplicationException;
+import org.apache.isis.viewer.dnd.view.BackgroundTask;
+import org.apache.isis.viewer.dnd.view.View;
+
+public final class BackgroundWork {
+    private static final Logger LOG = Logger.getLogger(BackgroundTask.class);
+
+    private static class BackgroundThread extends Thread {
+        private final View view;
+        private final BackgroundTask task;
+
+        public BackgroundThread(final View view, final BackgroundTask task) {
+            super("nof-background");
+            this.view = view;
+            this.task = task;
+            LOG.debug("creating background thread for task " + task);
+        }
+
+        @Override
+        public void run() {
+            try {
+                view.getState().setActive();
+                view.getFeedbackManager().setBusy(view, task);
+                scheduleRepaint(view);
+
+                LOG.debug("running background thread for task " + task);
+                task.execute();
+
+            } catch (final Throwable e) {
+                if (!(e instanceof IsisApplicationException)) {
+                    final String message = "Error while running background task " + task.getName();
+                    LOG.error(message, e);
+                }
+                view.getFeedbackManager().showException(e);
+
+            } finally {
+                view.getState().setInactive();
+                view.getFeedbackManager().clearBusy(view);
+                scheduleRepaint(view);
+            }
+        }
+
+        private static void scheduleRepaint(final View view) {
+            view.markDamaged();
+            view.getViewManager().scheduleRepaint();
+        }
+
+    }
+
+    public static void runTaskInBackground(final View view, final BackgroundTask task) {
+        final Thread t = new BackgroundThread(view, task);
+        t.start();
+    }
+
+    private BackgroundWork() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/CollectionActionContent.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/CollectionActionContent.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/CollectionActionContent.java
new file mode 100644
index 0000000..bce8242
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/CollectionActionContent.java
@@ -0,0 +1,145 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.collection.AbstractCollectionContent;
+
+public class CollectionActionContent extends AbstractCollectionContent implements ActionContent {
+    private final ActionHelper invocation;
+    private final ParameterContent[] parameters;
+
+    public CollectionActionContent(final ActionHelper invocation) {
+        this.invocation = invocation;
+        parameters = invocation.createParameters();
+    }
+
+    @Override
+    public void debugDetails(final DebugBuilder debug) {
+        debug.appendln("action", getActionName());
+        debug.appendln("target", getAdapter());
+        String parameterSet = "";
+        for (final ParameterContent parameter : parameters) {
+            parameterSet += parameter;
+        }
+        debug.appendln("parameters", parameterSet);
+    }
+
+    @Override
+    public Consent canDrop(final Content sourceContent) {
+        return Veto.DEFAULT;
+    }
+
+    @Override
+    public Consent disabled() {
+        return invocation.disabled();
+    }
+
+    @Override
+    public ObjectAdapter drop(final Content sourceContent) {
+        throw new NotYetImplementedException();
+    }
+
+    @Override
+    public ObjectAdapter[] elements() {
+        throw new NotYetImplementedException();
+    }
+
+    @Override
+    public ObjectAdapter execute() {
+        return invocation.invoke();
+    }
+
+    @Override
+    public String getActionName() {
+        return invocation.getName();
+    }
+
+    @Override
+    public ObjectAdapter getCollection() {
+        return invocation.getTarget();
+    }
+
+    @Override
+    public String getDescription() {
+        return invocation.getDescription();
+    }
+
+    @Override
+    public String getHelp() {
+        return invocation.getHelp();
+    }
+
+    @Override
+    public String getIconName() {
+        return getAdapter().getIconName();
+    }
+
+    @Override
+    public String getId() {
+        return invocation.getName();
+    }
+
+    @Override
+    public ObjectAdapter getAdapter() {
+        return invocation.getTarget();
+    }
+
+    @Override
+    public int getNoParameters() {
+        return parameters.length;
+    }
+
+    @Override
+    public ParameterContent getParameterContent(final int index) {
+        return parameters[index];
+    }
+
+    @Override
+    public ObjectAdapter getParameterObject(final int index) {
+        return invocation.getParameter(index);
+    }
+
+    @Override
+    public ObjectSpecification getSpecification() {
+        return getAdapter().getSpecification();
+    }
+
+    @Override
+    public boolean isTransient() {
+        return true;
+    }
+
+    @Override
+    public String title() {
+        return getAdapter().titleString();
+    }
+
+    @Override
+    public String windowTitle() {
+        return getActionName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/DialoggedObjectOption.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/DialoggedObjectOption.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/DialoggedObjectOption.java
new file mode 100644
index 0000000..756a03c
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/DialoggedObjectOption.java
@@ -0,0 +1,94 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.exceptions.UnknownTypeException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.BackgroundTask;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.Placement;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.Workspace;
+
+/**
+ * Options for an underlying object determined dynamically by looking for
+ * methods starting with action, veto and option for specifying the action,
+ * vetoing the option and giving the option an name respectively.
+ */
+public class DialoggedObjectOption extends AbstractObjectOption {
+
+    // REVIEW: should provide this rendering context, rather than hardcoding.
+    // the net effect currently is that class members annotated with 
+    // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed
+    // be hidden/disabled, but will be visible/enabled (perhaps incorrectly) 
+    // for any other value for Where
+    private final static Where where = Where.ANYWHERE;
+
+    public static DialoggedObjectOption createOption(final ObjectAction action, final ObjectAdapter object) {
+        final int paramCount = action.getParameterCount();
+        Assert.assertTrue("Only for actions taking one or more params", paramCount > 0);
+        if (!action.isVisible(IsisContext.getAuthenticationSession(), object, where).isAllowed() || !action.isVisible(IsisContext.getAuthenticationSession(), object, where).isAllowed()) {
+            return null;
+        }
+
+        final DialoggedObjectOption option = new DialoggedObjectOption(action, object);
+        return option;
+    }
+
+    private DialoggedObjectOption(final ObjectAction action, final ObjectAdapter target) {
+        super(action, target, action.getName() + "...");
+    }
+
+    @Override
+    public void execute(final Workspace workspace, final View view, final Location at) {
+        BackgroundWork.runTaskInBackground(view, new BackgroundTask() {
+            @Override
+            public void execute() {
+                final ActionHelper helper = ActionHelper.createInstance(target, action);
+                Content content;
+                if (target == null && action.getOnType().isService() || target != null && target.getSpecification().isNotCollection()) {
+                    content = new ObjectActionContent(helper);
+                } else if (target.getSpecification().isParentedOrFreeCollection()) {
+                    content = new CollectionActionContent(helper);
+                } else {
+                    throw new UnknownTypeException(target);
+                }
+                final View dialog = Toolkit.getViewFactory().createDialog(content);
+                workspace.addDialog(dialog, new Placement(view));
+            }
+
+            @Override
+            public String getDescription() {
+                return "Preparing action " + getName() + " on  " + view.getContent().getAdapter();
+            }
+
+            @Override
+            public String getName() {
+                return "Preparing action " + action.getName();
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ImmediateObjectOption.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ImmediateObjectOption.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ImmediateObjectOption.java
new file mode 100644
index 0000000..78e449f
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ImmediateObjectOption.java
@@ -0,0 +1,100 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.BackgroundTask;
+import org.apache.isis.viewer.dnd.view.Placement;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.Workspace;
+
+/**
+ * Options for an underlying object determined dynamically by looking for
+ * methods starting with action, veto and option for specifying the action,
+ * vetoing the option and giving the option an name respectively.
+ */
+public class ImmediateObjectOption extends AbstractObjectOption {
+
+    // REVIEW: should provide this rendering context, rather than hardcoding.
+    // the net effect currently is that class members annotated with 
+    // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed
+    // be hidden/disabled, but will be visible/enabled (perhaps incorrectly) 
+    // for any other value for Where
+    private final static Where where = Where.ANYWHERE;
+
+    public static ImmediateObjectOption createOption(final ObjectAction action, final ObjectAdapter object) {
+        Assert.assertTrue("Only suitable for 0 param methods", action.getParameterCount() == 0);
+        if (!action.isVisible(IsisContext.getAuthenticationSession(), object, where).isAllowed()) {
+            return null;
+        }
+        final ImmediateObjectOption option = new ImmediateObjectOption(action, object);
+        return option;
+    }
+
+    public static ImmediateObjectOption createServiceOption(final ObjectAction action, final ObjectAdapter object) {
+        Assert.assertTrue("Only suitable for 1 param methods", action.getParameterCount() == 1);
+        if (!action.isVisible(IsisContext.getAuthenticationSession(), object, where).isAllowed()) {
+            return null;
+        }
+        final ImmediateObjectOption option = new ImmediateObjectOption(action, object);
+
+        return option;
+    }
+
+    private ImmediateObjectOption(final ObjectAction action, final ObjectAdapter target) {
+        super(action, target, action.getName());
+    }
+
+    @Override
+    protected Consent checkValid() {
+        return action.isProposedArgumentSetValid(target, null);
+    }
+
+    // TODO this method is very similar to ActionDialogSpecification.execute()
+    @Override
+    public void execute(final Workspace workspace, final View view, final Location at) {
+        BackgroundWork.runTaskInBackground(view, new BackgroundTask() {
+            @Override
+            public void execute() {
+                ObjectAdapter result;
+                result = action.execute(target, null);
+                view.objectActionResult(result, new Placement(view));
+                view.getViewManager().disposeUnneededViews();
+                view.getFeedbackManager().showMessagesAndWarnings();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Running action " + getName() + " on  " + view.getContent().getAdapter();
+            }
+
+            @Override
+            public String getName() {
+                return "ObjectAction " + action.getName();
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectActionContent.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectActionContent.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectActionContent.java
new file mode 100644
index 0000000..42cd0f8
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectActionContent.java
@@ -0,0 +1,176 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.dnd.view.content.AbstractObjectContent;
+
+/**
+ * Links an action on an object to a view.
+ */
+public class ObjectActionContent extends AbstractObjectContent implements ActionContent {
+    private final ActionHelper actionHelper;
+    private final ParameterContent[] parameters;
+
+    public ObjectActionContent(final ActionHelper invocation) {
+        this.actionHelper = invocation;
+        parameters = invocation.createParameters();
+    }
+
+    @Override
+    public Consent canClear() {
+        return Veto.DEFAULT;
+    }
+
+    @Override
+    public Consent canSet(final ObjectAdapter dragSource) {
+        return Veto.DEFAULT;
+    }
+
+    @Override
+    public void clear() {
+        throw new IsisException("Invalid call");
+    }
+
+    @Override
+    public void debugDetails(final DebugBuilder debug) {
+        debug.appendln("action", getActionName());
+        debug.appendln("target", getAdapter());
+        String parameterSet = "";
+        for (final ParameterContent parameter : parameters) {
+            parameterSet += parameter;
+        }
+        debug.appendln("parameters", parameterSet);
+    }
+
+    @Override
+    public Consent disabled() {
+        return actionHelper.disabled();
+    }
+
+    @Override
+    public ObjectAdapter execute() {
+        return actionHelper.invoke();
+    }
+
+    @Override
+    public String getActionName() {
+        return actionHelper.getName();
+    }
+
+    @Override
+    public String getIconName() {
+        return actionHelper.getIconName();
+    }
+
+    @Override
+    public ObjectAdapter getAdapter() {
+        return actionHelper.getTarget();
+    }
+
+    @Override
+    public int getNoParameters() {
+        return parameters.length;
+    }
+
+    @Override
+    public ObjectAdapter getObject() {
+        return actionHelper.getTarget();
+    }
+
+    @Override
+    public ParameterContent getParameterContent(final int index) {
+        return parameters[index];
+    }
+
+    @Override
+    public ObjectAdapter getParameterObject(final int index) {
+        return actionHelper.getParameter(index);
+    }
+
+    @Override
+    public ObjectSpecification getSpecification() {
+        return getObject().getSpecification();
+    }
+
+    /**
+     * Can't persist actions
+     */
+    @Override
+    public boolean isPersistable() {
+        return false;
+    }
+
+    @Override
+    public boolean isObject() {
+        return true;
+    }
+
+    @Override
+    public boolean isTransient() {
+        return true;
+    }
+
+    @Override
+    public void setObject(final ObjectAdapter object) {
+        throw new IsisException("Invalid call");
+    }
+
+    @Override
+    public String title() {
+        return actionHelper.title();
+    }
+
+    @Override
+    public String windowTitle() {
+        return getActionName();
+    }
+
+    @Override
+    public String getId() {
+        return actionHelper.getName();
+    }
+
+    @Override
+    public String getDescription() {
+        return actionHelper.getDescription();
+    }
+
+    @Override
+    public String getHelp() {
+        return actionHelper.getHelp();
+    }
+
+    @Override
+    public ObjectAdapter[] getOptions() {
+        return null;
+    }
+
+    @Override
+    public boolean isOptionEnabled() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectParameter.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectParameter.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectParameter.java
new file mode 100644
index 0000000..9ebdf00
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/view/action/ObjectParameter.java
@@ -0,0 +1,31 @@
+/*
+ *  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.dnd.view.action;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+
+public interface ObjectParameter extends ParameterContent {
+
+    Consent canSet(final ObjectAdapter dragSource);
+
+    void setObject(final ObjectAdapter object);
+
+}