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/08 15:56:01 UTC
[20/53] [partial] ISIS-188: making structure of component viewers
consistent
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/BlankView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/BlankView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/BlankView.java
new file mode 100644
index 0000000..f54cc12
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/BlankView.java
@@ -0,0 +1,49 @@
+/*
+ * 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.base;
+
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.content.NullContent;
+
+public class BlankView extends AbstractView {
+ private final Size size;
+
+ public BlankView() {
+ this(new NullContent());
+ }
+
+ public BlankView(final Content content) {
+ super(content);
+ size = new Size(100, 50);
+ }
+
+ public BlankView(final Content content, final Size size) {
+ super(content);
+ this.size = size;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ final Size requiredSize = new Size(size);
+ requiredSize.limitSize(availableSpace);
+ return requiredSize;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/DragViewOutline.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/DragViewOutline.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/DragViewOutline.java
new file mode 100644
index 0000000..ea93795
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/DragViewOutline.java
@@ -0,0 +1,54 @@
+/*
+ * 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.base;
+
+import org.apache.isis.viewer.dnd.drawing.Bounds;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+
+public class DragViewOutline extends AbstractView {
+ private final int thickness = 5;
+ private final Size size;
+
+ public DragViewOutline(final View view) {
+ super(view.getContent());
+ size = view.getSize();
+ setLocation(view.getAbsoluteLocation());
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ super.draw(canvas);
+
+ final Bounds r = getBounds();
+
+ for (int i = 0; i < thickness; i++) {
+ canvas.drawRectangle(i, i, r.getWidth() - i * 2 - 1, r.getHeight() - i * 2 - 1, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1));
+ }
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ return new Size(size);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/FieldErrorView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/FieldErrorView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/FieldErrorView.java
new file mode 100644
index 0000000..18840eb
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/FieldErrorView.java
@@ -0,0 +1,117 @@
+/*
+ * 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.base;
+
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewAreaType;
+import org.apache.isis.viewer.dnd.view.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+
+/**
+ * Displays an error message in place of a normal field when a problem occurs,
+ * usually due to a programming error, and the normal field cannot be created. A
+ * example of this is where value field is declared in an ObjectAdapter, but the
+ * programmer forgot to instantiate the value object, causing null to be
+ * returned instead, which is an illegal value.
+ */
+public class FieldErrorView extends AbstractView {
+
+ private final String error;
+
+ public FieldErrorView(final String errorMessage) {
+ super(null);
+ this.error = errorMessage;
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ super.draw(canvas);
+
+ final Size size = getSize();
+ canvas.drawSolidRectangle(0, 0, size.getWidth() - 1, size.getHeight() - 1, Toolkit.getColor(ColorsAndFonts.COLOR_WHITE));
+ canvas.drawRectangle(0, 0, size.getWidth() - 1, size.getHeight() - 1, Toolkit.getColor(ColorsAndFonts.COLOR_BLACK));
+ canvas.drawText(error, 14, 20, Toolkit.getColor(ColorsAndFonts.COLOR_INVALID), Toolkit.getText(ColorsAndFonts.TEXT_NORMAL));
+ }
+
+ @Override
+ public int getBaseline() {
+ return 20;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ return new Size(250, 30);
+ }
+
+ @Override
+ public ViewAreaType viewAreaType(final Location mouseLocation) {
+ return mouseLocation.getX() <= 10 ? ViewAreaType.VIEW : ViewAreaType.CONTENT;
+ }
+
+ public static class Specification implements ViewSpecification {
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return true;
+ }
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ throw new NotYetImplementedException();
+ }
+
+ @Override
+ public String getName() {
+ return "Field Error";
+ }
+
+ @Override
+ public boolean isAligned() {
+ return false;
+ }
+
+ @Override
+ public boolean isSubView() {
+ return false;
+ }
+
+ @Override
+ public boolean isResizeable() {
+ return false;
+ }
+
+ @Override
+ public boolean isReplaceable() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/IconGraphic.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/IconGraphic.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/IconGraphic.java
new file mode 100644
index 0000000..4ff8f39
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/IconGraphic.java
@@ -0,0 +1,115 @@
+/*
+ * 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.base;
+
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.viewer.dnd.drawing.Bounds;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Image;
+import org.apache.isis.viewer.dnd.drawing.ImageFactory;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.drawing.Text;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+
+/*
+ * TODO why does this pass out the baseline, and then expect it back when doing the drawing?
+ */
+public class IconGraphic {
+ private final int baseline;
+ protected final Content content;
+ protected Image icon;
+ protected final int iconHeight;
+ private String lastIconName;
+
+ public IconGraphic(final View view, final int height, final int baseline) {
+ content = view.getContent();
+ iconHeight = height;
+ this.baseline = baseline;
+ }
+
+ public IconGraphic(final View view, final int height) {
+ content = view.getContent();
+ iconHeight = height;
+ baseline = height * 80 / 100;
+ }
+
+ public IconGraphic(final View view, final Text style) {
+ content = view.getContent();
+ iconHeight = style.getTextHeight();
+ this.baseline = style.getAscent();
+ }
+
+ public void draw(final Canvas canvas, final int x, final int baseline) {
+ final int y = baseline - this.baseline + 1;
+ if (Toolkit.debug) {
+ canvas.drawDebugOutline(new Bounds(new Location(x, y), getSize()), getBaseline(), Toolkit.getColor(ColorsAndFonts.COLOR_DEBUG_BOUNDS_DRAW));
+ }
+ final Image icon = icon();
+ if (icon == null) {
+ canvas.drawSolidOval(x + 1, y, iconHeight, iconHeight, Toolkit.getColor(ColorsAndFonts.COLOR_PRIMARY3));
+ } else {
+ canvas.drawImage(icon, x + 1, y);
+ }
+ }
+
+ public int getBaseline() {
+ return baseline;
+ }
+
+ public Size getSize() {
+ final Image icon = icon();
+ final int iconWidth = icon == null ? iconHeight : icon.getWidth();
+ return new Size(iconWidth + 2, iconHeight + 2);
+ }
+
+ protected Image icon() {
+ final String iconName = content.getIconName();
+ /*
+ * If the graphic is based on a name provided by the object then the
+ * icon could be changed at any time, so we won't lazily load it.
+ */
+ if (icon != null && (iconName == null || iconName.equals(lastIconName))) {
+ return icon;
+ }
+ lastIconName = iconName;
+ if (iconName != null) {
+ icon = ImageFactory.getInstance().loadIcon(iconName, iconHeight, null);
+ }
+ if (icon == null) {
+ icon = content.getIconPicture(iconHeight);
+ }
+ if (icon == null) {
+ icon = ImageFactory.getInstance().loadDefaultIcon(iconHeight, null);
+ }
+ return icon;
+ }
+
+ @Override
+ public String toString() {
+ final ToString str = new ToString(this);
+ str.append("baseline", baseline);
+ str.append("icon", icon);
+ return str.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/Layout.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/Layout.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/Layout.java
new file mode 100644
index 0000000..3188f21
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/Layout.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.base;
+
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.View;
+
+public interface Layout {
+ Size getRequiredSize(final View view);
+
+ void layout(final View view, final Size maximumSize);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NonBuildingSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NonBuildingSpecification.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NonBuildingSpecification.java
new file mode 100644
index 0000000..46aaf2a
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NonBuildingSpecification.java
@@ -0,0 +1,77 @@
+/*
+ * 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.base;
+
+import org.apache.isis.core.commons.exceptions.UnexpectedCallException;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+
+public class NonBuildingSpecification implements ViewSpecification {
+ private final String name;
+
+ public NonBuildingSpecification(final View view) {
+ final String name = view.getClass().getName();
+ this.name = name.substring(name.lastIndexOf('.') + 1);
+ }
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ throw new UnexpectedCallException();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean isAligned() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+
+ @Override
+ public boolean isReplaceable() {
+ return false;
+ }
+
+ @Override
+ public boolean isResizeable() {
+ return false;
+ }
+
+ @Override
+ public boolean isSubView() {
+ return false;
+ }
+
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NullView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NullView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NullView.java
new file mode 100644
index 0000000..9fe68a3
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/NullView.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.base;
+
+import org.apache.isis.viewer.dnd.view.content.NullContent;
+
+public class NullView extends AbstractView {
+ public NullView() {
+ super(new NullContent(""));
+ }
+
+ @Override
+ public String toString() {
+ final String name = getClass().getName();
+ return name.substring(name.lastIndexOf('.') + 1) + getId();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ObjectView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ObjectView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ObjectView.java
new file mode 100644
index 0000000..8e83abe
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ObjectView.java
@@ -0,0 +1,143 @@
+/*
+ * 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.base;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.Persistor;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Offset;
+import org.apache.isis.viewer.dnd.interaction.ViewDragImpl;
+import org.apache.isis.viewer.dnd.view.Click;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.ContentDrag;
+import org.apache.isis.viewer.dnd.view.DragEvent;
+import org.apache.isis.viewer.dnd.view.DragStart;
+import org.apache.isis.viewer.dnd.view.Placement;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.UserActionSet;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public abstract class ObjectView extends AbstractView {
+
+ public ObjectView(final Content content, final ViewSpecification specification) {
+ super(content, specification);
+ }
+
+ @Override
+ public void dragIn(final ContentDrag drag) {
+ final Consent consent = getContent().canDrop(drag.getSourceContent());
+ final String description = getContent().getDescription();
+ if (consent.isAllowed()) {
+ getFeedbackManager().setAction(consent.getDescription() + " " + description);
+ getState().setCanDrop();
+ } else {
+ getFeedbackManager().setAction(consent.getReason() + " " + description);
+ getState().setCantDrop();
+ }
+ markDamaged();
+ }
+
+ @Override
+ public void dragOut(final ContentDrag drag) {
+ getState().clearObjectIdentified();
+ markDamaged();
+ }
+
+ @Override
+ public DragEvent dragStart(final DragStart drag) {
+ final View subview = subviewFor(drag.getLocation());
+ if (subview != null) {
+ drag.subtract(subview.getLocation());
+ return subview.dragStart(drag);
+ } else {
+ if (drag.isCtrl()) {
+ final View dragOverlay = new DragViewOutline(getView());
+ return new ViewDragImpl(this, new Offset(drag.getLocation()), dragOverlay);
+ } else {
+ return Toolkit.getViewFactory().createDragContentOutline(this, drag.getLocation());
+ }
+ }
+ }
+
+ /**
+ * Called when a dragged object is dropped onto this view. The default
+ * behaviour implemented here calls the action method on the target, passing
+ * the source object in as the only parameter.
+ */
+ @Override
+ public void drop(final ContentDrag drag) {
+ final ObjectAdapter result = getContent().drop(drag.getSourceContent());
+ if (result != null) {
+ objectActionResult(result, new Placement(this));
+ }
+ getState().clearObjectIdentified();
+ getFeedbackManager().showMessagesAndWarnings();
+
+ markDamaged();
+ }
+
+ @Override
+ public void firstClick(final Click click) {
+ final View subview = subviewFor(click.getLocation());
+ if (subview != null) {
+ click.subtract(subview.getLocation());
+ subview.firstClick(click);
+ } else {
+ if (click.button2()) {
+ final Location location = new Location(click.getLocationWithinViewer());
+ getViewManager().showInOverlay(getContent(), location);
+ }
+ }
+ }
+
+ @Override
+ public void invalidateContent() {
+ super.invalidateLayout();
+ }
+
+ @Override
+ public void secondClick(final Click click) {
+ final View subview = subviewFor(click.getLocation());
+ if (subview != null) {
+ click.subtract(subview.getLocation());
+ subview.secondClick(click);
+ } else {
+ final Location location = getAbsoluteLocation();
+ location.translate(click.getLocation());
+ getWorkspace().addWindowFor(getContent().getAdapter(), new Placement(this));
+ }
+ }
+
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // Dependencies (from context)
+ // ///////////////////////////////////////////////////////////////////////////
+
+ private static Persistor getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/TextView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/TextView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/TextView.java
new file mode 100644
index 0000000..4ec4afc
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/TextView.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.base;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.drawing.Text;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.ViewConstants;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+
+public class TextView extends AbstractView {
+ private final Text style = Toolkit.getText(ColorsAndFonts.TEXT_NORMAL);
+ private final Color color = Toolkit.getColor(ColorsAndFonts.COLOR_BLACK);
+ private final String text;
+
+ public TextView(final Content content, final ViewSpecification specification) {
+ super(content, specification);
+ final ObjectAdapter object = content.getAdapter();
+ text = object == null ? "" : object.titleString();
+ }
+
+ @Override
+ public boolean canFocus() {
+ return false;
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ canvas.drawText(text, ViewConstants.HPADDING, getBaseline(), color, style);
+ }
+
+ @Override
+ public int getBaseline() {
+ return style.getAscent() + ViewConstants.VPADDING;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size maximumSize) {
+ final int width = style.stringWidth(text) + ViewConstants.HPADDING * 2;
+ final int height = style.getTextHeight() + ViewConstants.VPADDING * 2;
+ return new Size(width, height);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/UserViewSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/UserViewSpecification.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/UserViewSpecification.java
new file mode 100644
index 0000000..963106b
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/UserViewSpecification.java
@@ -0,0 +1,96 @@
+/*
+ * 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.base;
+
+import org.apache.isis.core.runtime.userprofile.Options;
+import org.apache.isis.viewer.dnd.util.Properties;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+
+public class UserViewSpecification implements ViewSpecification {
+
+ private final ViewSpecification specification;
+ private final String name;
+
+ public UserViewSpecification(final ViewSpecification specification, final String name) {
+ this.specification = specification;
+ this.name = name;
+ }
+
+ /*
+ * public UserViewSpecification(View view) { specification =
+ * view.getSpecification(); Options copyOptions = new Options();
+ * view.saveOptions(copyOptions); name = specification.getName() + " " + new
+ * Date().getSeconds();
+ *
+ * // view.setSpecification(this); // view.loadOptions(copyOptions); }
+ */
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return specification.canDisplay(requirement);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean isAligned() {
+ return specification.isAligned();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return specification.isOpen();
+ }
+
+ @Override
+ public boolean isReplaceable() {
+ return specification.isReplaceable();
+ }
+
+ @Override
+ public boolean isResizeable() {
+ return specification.isResizeable();
+ }
+
+ @Override
+ public boolean isSubView() {
+ return specification.isSubView();
+ }
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ final View createView = specification.createView(content, axes, sequence);
+
+ final Options viewOptions = Properties.getViewConfigurationOptions(this);
+ createView.loadOptions(viewOptions);
+ return createView;
+ }
+
+ public ViewSpecification getWrappedSpecification() {
+ return specification;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ViewUpdateNotifierImpl.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ViewUpdateNotifierImpl.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ViewUpdateNotifierImpl.java
new file mode 100644
index 0000000..16203b5
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/base/ViewUpdateNotifierImpl.java
@@ -0,0 +1,273 @@
+/*
+ * 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.base;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.log4j.Logger;
+
+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.adapter.mgr.AdapterManager;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.MessageBroker;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.UpdateNotifier;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.ObjectContent;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewUpdateNotifier;
+import org.apache.isis.viewer.dnd.view.collection.RootCollection;
+
+public class ViewUpdateNotifierImpl implements ViewUpdateNotifier {
+
+ private static final Logger LOG = Logger.getLogger(ViewUpdateNotifierImpl.class);
+
+ protected Map<ObjectAdapter, List<View>> viewListByAdapter = Maps.newHashMap();
+
+ @Override
+ public void add(final View view) {
+ final Content content = view.getContent();
+ if (content != null && content.isObject()) {
+ final ObjectAdapter adapter = content.getAdapter();
+
+ if (adapter != null) {
+ List<View> viewsToNotify;
+
+ if (viewListByAdapter.containsKey(adapter)) {
+ viewsToNotify = viewListByAdapter.get(adapter);
+ } else {
+ viewsToNotify = new Vector<View>();
+ viewListByAdapter.put(adapter, viewsToNotify);
+ }
+
+ if (viewsToNotify.contains(view)) {
+ throw new IsisException(view + " already being notified");
+ }
+ viewsToNotify.add(view);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("added " + view + " to observers for " + adapter);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void debugData(final DebugBuilder buf) {
+ for(Map.Entry<ObjectAdapter, List<View>> mapEntry: viewListByAdapter.entrySet()) {
+ final ObjectAdapter objectAdapter = mapEntry.getKey();
+ final List<View> viewsToNotify = mapEntry.getValue();
+
+ buf.append("Views for " + objectAdapter + " \n");
+
+ for(View view: viewsToNotify) {
+ buf.append(" " + view);
+ buf.append("\n");
+ }
+ buf.append("\n");
+ }
+ }
+
+ @Override
+ public String debugTitle() {
+ return "Views for object details (observers)";
+ }
+
+ @Override
+ public void remove(final View view) {
+ final Content content = view.getContent();
+ if (content == null || !content.isObject()) {
+ // nothing to do
+ return;
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("removing " + content + " for " + view);
+ }
+
+ final ObjectAdapter object = ((ObjectContent) content).getObject();
+ if (object != null) {
+ if (!viewListByAdapter.containsKey(object)) {
+ throw new IsisException("Tried to remove a non-existant view " + view + " from observers for " + object);
+ }
+
+ List<View> viewsToNotify = viewListByAdapter.get(object);
+ for(View v: viewsToNotify) {
+ if (view == v.getView()) {
+ viewsToNotify.remove(v);
+ LOG.debug("removed " + view + " from observers for " + object);
+ break;
+ }
+ }
+
+ if (viewsToNotify.size() == 0) {
+ viewListByAdapter.remove(object);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("removed observer list for " + object);
+ }
+
+ // TODO need to do garbage collection instead
+ // ObjectAdapterLoader loader = Isis.getObjectLoader();
+ // loader.unloaded((ObjectAdapter) object);
+ }
+ }
+ }
+
+ public void shutdown() {
+ viewListByAdapter.clear();
+ }
+
+ @Override
+ public void invalidateViewsForChangedObjects() {
+ for (final ObjectAdapter object : getUpdateNotifier().getChangedObjects()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("invalidate views for " + object);
+ }
+ final List<View> viewsVector = viewListByAdapter.get(object);
+ if (viewsVector == null) {
+ continue;
+ }
+ for(View view: viewsVector) {
+ LOG.debug(" - " + view);
+ view.getView().invalidateContent();
+ }
+ }
+ }
+
+ @Override
+ public void removeViewsForDisposedObjects() {
+ for (final ObjectAdapter objectToDispose : getUpdateNotifier().getDisposedObjects()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("dispose views for " + objectToDispose);
+ }
+ final List<View> viewsForObject = viewListByAdapter.get(objectToDispose);
+ if (viewsForObject == null) {
+ continue;
+ }
+ removeViews(viewsForObject);
+ final List<View> remainingViews = viewListByAdapter.get(objectToDispose);
+ if (remainingViews != null && remainingViews.size() > 0) {
+ getMessageBroker().addWarning("There are still views (within other views) for the disposed object " + objectToDispose.titleString() + ". Only objects that are shown as root views can be properly disposed of");
+ } else {
+ getPersistenceSession().removeAdapter(objectToDispose);
+ }
+ }
+ }
+
+ private void removeViews(final List<View> viewsForObject) {
+ //final View[] viewsArray = new View[viewsForObject.size()];
+ //viewsForObject.copyInto(viewsArray);
+
+ final List<View> viewsArray = Lists.newArrayList(viewsForObject); // take a copy
+
+ final View[] viewsOnWorkspace = viewsArray.get(0).getWorkspace().getSubviews();
+
+ for (final View element : viewsArray) {
+ final View view = element.getView();
+ for (final View viewOnWorkspace : viewsOnWorkspace) {
+ if (view == viewOnWorkspace) {
+ LOG.debug(" (root removed) " + view);
+ view.getView().dispose();
+ break;
+ }
+ }
+
+ for (final View element2 : viewsOnWorkspace) {
+ if (element2.getContent() instanceof RootCollection) {
+ final View[] subviewsOfRootView = element2.getSubviews();
+ for (final View element3 : subviewsOfRootView) {
+ if (element3 == view) {
+ LOG.debug(" (element removed) " + view);
+ view.getView().dispose();
+ }
+ }
+ }
+ }
+
+ for (final View element2 : viewsOnWorkspace) {
+ if (element2.contains(view)) {
+ LOG.debug(" (invalidated) " + view);
+ final View parent = view.getParent();
+ parent.invalidateContent();
+ }
+ }
+
+ }
+
+ }
+
+ // ////////////////////////////////////////////////////////////////
+ // Dependencies (from singleton)
+ // ////////////////////////////////////////////////////////////////
+
+ private static PersistenceSession getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+ private static AdapterManager getAdapterManager() {
+ return getPersistenceSession().getAdapterManager();
+ }
+
+ private static MessageBroker getMessageBroker() {
+ return IsisContext.getMessageBroker();
+ }
+
+ private static UpdateNotifier getUpdateNotifier() {
+ return IsisContext.inSession() ? IsisContext.getUpdateNotifier() : new NoOpUpdateNotifier();
+ }
+
+}
+
+class NoOpUpdateNotifier implements UpdateNotifier {
+
+ @Override
+ public void addChangedObject(final ObjectAdapter object) {
+ }
+
+ @Override
+ public void addDisposedObject(final ObjectAdapter adapter) {
+ }
+
+ @Override
+ public void clear() {
+ }
+
+ @Override
+ public void ensureEmpty() {
+ }
+
+ @Override
+ public List<ObjectAdapter> getChangedObjects() {
+ return new ArrayList<ObjectAdapter>();
+ }
+
+ @Override
+ public List<ObjectAdapter> getDisposedObjects() {
+ return new ArrayList<ObjectAdapter>();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BackgroundBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BackgroundBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BackgroundBorder.java
new file mode 100644
index 0000000..2f2dbf0
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BackgroundBorder.java
@@ -0,0 +1,63 @@
+/*
+ * 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.border;
+
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+
+/**
+ * A background border provides a coloured background to a view of a specified
+ * colour.
+ */
+public class BackgroundBorder extends AbstractBorder {
+ private Color background;
+
+ /**
+ * Creates a background border with a default colour of white.
+ */
+ public BackgroundBorder(final View wrappedView) {
+ super(wrappedView);
+ background = Toolkit.getColor(ColorsAndFonts.COLOR_WHITE);
+ }
+
+ public BackgroundBorder(final Color background, final View wrappedView) {
+ super(wrappedView);
+ this.background = background;
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ clearBackground(canvas, background);
+ super.draw(canvas);
+ }
+
+ public void setBackground(final Color color) {
+ this.background = color;
+ }
+
+ @Override
+ public String toString() {
+ return wrappedView.toString() + "/BackgroundBorder";
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BorderDrawing.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BorderDrawing.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BorderDrawing.java
new file mode 100644
index 0000000..d50b2b8
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/BorderDrawing.java
@@ -0,0 +1,48 @@
+/*
+ * 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.border;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewState;
+
+public interface BorderDrawing {
+
+ public abstract void debugDetails(final DebugBuilder debug);
+
+ public abstract void layoutControls(final Size size, View[] controls);
+
+ public abstract void draw(final Canvas canvas, Size s, boolean hasFocus, final ViewState state, View[] controls, String title);
+
+ public abstract void drawTransientMarker(Canvas canvas, Size size);
+
+ public abstract void getRequiredSize(Size size, String title, View[] controls);
+
+ public abstract int getLeft();
+
+ public abstract int getRight();
+
+ public abstract int getTop();
+
+ public abstract int getBottom();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/ButtonBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/ButtonBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/ButtonBorder.java
new file mode 100644
index 0000000..366c0ca
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/ButtonBorder.java
@@ -0,0 +1,199 @@
+/*
+ * 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.border;
+
+import java.awt.event.KeyEvent;
+
+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.Size;
+import org.apache.isis.viewer.dnd.view.ButtonAction;
+import org.apache.isis.viewer.dnd.view.Click;
+import org.apache.isis.viewer.dnd.view.KeyboardAction;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewConstants;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+import org.apache.isis.viewer.dnd.view.control.Button;
+
+public class ButtonBorder extends AbstractBorder {
+ private static final int BUTTON_SPACING = 5;
+ private final View[] buttons;
+ private ButtonAction defaultAction;
+
+ public ButtonBorder(final ButtonAction[] actions, final View view) {
+ super(view);
+
+ buttons = new View[actions.length];
+ for (int i = 0; i < actions.length; i++) {
+ final ButtonAction action = actions[i];
+ buttons[i] = new Button(action, view);
+ if (action.isDefault()) {
+ defaultAction = action;
+ }
+ }
+ // space for: line & button with whitespace
+ bottom = 1 + ViewConstants.VPADDING + buttons[0].getRequiredSize(new Size()).getHeight() + ViewConstants.VPADDING;
+
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ // draw buttons
+ for (final View button : buttons) {
+ final Canvas buttonCanvas = canvas.createSubcanvas(button.getBounds());
+ button.draw(buttonCanvas);
+ final int buttonWidth = button.getSize().getWidth();
+ buttonCanvas.offset(BUTTON_SPACING + buttonWidth, 0);
+ }
+
+ // draw rest
+ super.draw(canvas);
+ }
+
+ @Override
+ public void firstClick(final Click click) {
+ final View button = overButton(click.getLocation());
+ if (button == null) {
+ super.firstClick(click);
+ } else {
+ button.firstClick(click);
+ }
+ }
+
+ public View[] getButtons() {
+ return buttons;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size maximumSize) {
+ final Size size = super.getRequiredSize(maximumSize);
+ size.ensureWidth(totalButtonWidth());
+ size.extendWidth(BUTTON_SPACING * 2);
+ return size;
+ }
+
+ @Override
+ public View identify(final Location location) {
+ for (final View button : buttons) {
+ if (button.getBounds().contains(location)) {
+ return button;
+ }
+ }
+ return super.identify(location);
+ }
+
+ @Override
+ public void keyPressed(final KeyboardAction key) {
+ if (key.getKeyCode() == KeyEvent.VK_ENTER) {
+ if (defaultAction != null && defaultAction.disabled(getView()).isAllowed()) {
+ key.consume();
+ defaultAction.execute(getWorkspace(), getView(), getLocation());
+ }
+ }
+
+ super.keyPressed(key);
+ }
+
+ public void layout(final int width) {
+ int x = width / 2 - totalButtonWidth() / 2;
+ final int y = getSize().getHeight() - ViewConstants.VPADDING - buttons[0].getRequiredSize(new Size()).getHeight();
+
+ for (int i = 0; i < buttons.length; i++) {
+ buttons[i] = buttons[i];
+ buttons[i].setSize(buttons[i].getRequiredSize(new Size()));
+ buttons[i].setLocation(new Location(x, y));
+
+ x += buttons[i].getSize().getWidth();
+ x += BUTTON_SPACING;
+ }
+ }
+
+ @Override
+ public void mouseDown(final Click click) {
+ final View button = overButton(click.getLocation());
+ if (button == null) {
+ super.mouseDown(click);
+ } else {
+ button.mouseDown(click);
+ }
+ }
+
+ @Override
+ public void mouseUp(final Click click) {
+ final View button = overButton(click.getLocation());
+ if (button == null) {
+ super.mouseUp(click);
+ } else {
+ button.mouseUp(click);
+ }
+ }
+
+ /**
+ * Finds the action button under the pointer; returning null if none.
+ */
+ private View overButton(final Location location) {
+ for (final View button : buttons) {
+ if (button.getBounds().contains(location)) {
+ return button;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void secondClick(final Click click) {
+ final View button = overButton(click.getLocation());
+ if (button == null) {
+ super.secondClick(click);
+ }
+ }
+
+ @Override
+ public void setBounds(final Bounds bounds) {
+ super.setBounds(bounds);
+ layout(bounds.getWidth());
+ }
+
+ @Override
+ public void setSize(final Size size) {
+ super.setSize(size);
+ layout(size.getWidth());
+ }
+
+ @Override
+ public void thirdClick(final Click click) {
+ final View button = overButton(click.getLocation());
+ if (button == null) {
+ super.thirdClick(click);
+ }
+ }
+
+ private int totalButtonWidth() {
+ int totalButtonWidth = 0;
+ for (int i = 0; i < buttons.length; i++) {
+ final int buttonWidth = buttons[i].getRequiredSize(new Size()).getWidth();
+ totalButtonWidth += i > 0 ? BUTTON_SPACING : 0;
+ totalButtonWidth += buttonWidth;
+ }
+ return totalButtonWidth;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DisposedObjectBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DisposedObjectBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DisposedObjectBorder.java
new file mode 100644
index 0000000..85741ec
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DisposedObjectBorder.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.border;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.DragEvent;
+import org.apache.isis.viewer.dnd.view.DragStart;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+
+public class DisposedObjectBorder extends AbstractBorder {
+
+ public DisposedObjectBorder(final int size, final View wrappedView) {
+ super(wrappedView);
+ top = size;
+ left = size;
+ bottom = size;
+ right = size;
+ }
+
+ public DisposedObjectBorder(final View wrappedView) {
+ this(2, wrappedView);
+ }
+
+ @Override
+ protected void debugDetails(final DebugBuilder debug) {
+ debug.append("DisposedObjectBorder " + top + " pixels");
+ }
+
+ @Override
+ public DragEvent dragStart(final DragStart drag) {
+ return super.dragStart(drag);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ super.draw(canvas);
+
+ Color color = null;
+ color = Toolkit.getColor(ColorsAndFonts.COLOR_INVALID);
+ final Size s = getSize();
+
+ final int w = s.getWidth();
+ final int xExtent = s.getWidth() - left;
+ for (int i = 0; i < left; i++) {
+ canvas.drawRectangle(i, i, xExtent - 2 * i, s.getHeight() - 2 * i, color);
+ }
+ for (int i = 0; i < 15; i++) {
+ canvas.drawLine(left, top + i, left + i, top, color);
+ canvas.drawLine(w - left - right - 1, s.getHeight() - top - i - 1, w - left - right - i - 1, s.getHeight() - top - 1, color);
+ }
+ }
+
+ @Override
+ public void entered() {
+ wrappedView.entered();
+ getFeedbackManager().setError("Destroyed objects cannot be used");
+ markDamaged();
+ }
+
+ @Override
+ public void exited() {
+ wrappedView.exited();
+ getFeedbackManager().setError("");
+ markDamaged();
+ }
+
+ @Override
+ public String toString() {
+ return wrappedView.toString() + "/DisposedObjectBorder [" + getSpecification() + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DragViewBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DragViewBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DragViewBorder.java
new file mode 100644
index 0000000..d8c033d
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DragViewBorder.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.dnd.view.border;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Offset;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.interaction.ViewDragImpl;
+import org.apache.isis.viewer.dnd.view.DragEvent;
+import org.apache.isis.viewer.dnd.view.DragStart;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+import org.apache.isis.viewer.dnd.view.base.DragViewOutline;
+
+/**
+ * A drag view border provides a line and handle that appears when the mouse
+ * moves over the contained view and allows the view to be dragged.
+ */
+public class DragViewBorder extends AbstractBorder {
+ private final int handleWidth = 14;
+
+ public DragViewBorder(final View wrappedView) {
+ this(1, wrappedView);
+ }
+
+ public DragViewBorder(final int size, final View wrappedView) {
+ super(wrappedView);
+
+ top = size;
+ left = size;
+ bottom = size;
+ right = size + handleWidth;
+ }
+
+ @Override
+ protected void debugDetails(final DebugBuilder debug) {
+ debug.append("SimpleBorder " + top + " pixels\n");
+ debug.append(" handle " + handleWidth + " pixels");
+ }
+
+ @Override
+ public DragEvent dragStart(final DragStart drag) {
+ if (overBorder(drag.getLocation())) {
+ final Location location = drag.getLocation();
+ final DragViewOutline dragOverlay = new DragViewOutline(getView());
+ return new ViewDragImpl(this, new Offset(location.getX(), location.getY()), dragOverlay);
+ } else {
+ return super.dragStart(drag);
+ }
+ }
+
+ @Override
+ public void entered() {
+ getState().setContentIdentified();
+ getState().setViewIdentified();
+ wrappedView.entered();
+ markDamaged();
+ }
+
+ @Override
+ public void exited() {
+ getState().clearObjectIdentified();
+ getState().clearViewIdentified();
+ wrappedView.exited();
+ markDamaged();
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ if (getState().isViewIdentified()) {
+ final Color color = Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2);
+ final Size s = getSize();
+ final int width = s.getWidth();
+ for (int i = 0; i < left; i++) {
+ canvas.drawRectangle(i, i, width - 2 * i - 1, s.getHeight() - 2 * i - 1, color);
+ }
+ final int w2 = width - left - 2;
+ final int w3 = w2 - handleWidth;
+ for (int x = w2; x > w3; x -= 2) {
+ canvas.drawLine(x, top, x, s.getHeight() - top, color);
+ }
+ }
+ super.draw(canvas);
+ }
+
+ @Override
+ public String toString() {
+ return wrappedView.toString() + "/SimpleBorder";
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DroppableLabelBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DroppableLabelBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DroppableLabelBorder.java
new file mode 100644
index 0000000..281f777
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/DroppableLabelBorder.java
@@ -0,0 +1,172 @@
+/*
+ * 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.border;
+
+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.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.ContentDrag;
+import org.apache.isis.viewer.dnd.view.InternalDrag;
+import org.apache.isis.viewer.dnd.view.ObjectContent;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewAreaType;
+import org.apache.isis.viewer.dnd.view.ViewState;
+import org.apache.isis.viewer.dnd.view.action.ParameterContent;
+import org.apache.isis.viewer.dnd.view.axis.LabelAxis;
+import org.apache.isis.viewer.dnd.view.content.FieldContent;
+
+public class DroppableLabelBorder extends LabelBorder {
+
+ public static View createObjectFieldLabelBorder(final LabelAxis axis, final View wrappedView) {
+ final FieldContent fieldContent = (FieldContent) wrappedView.getContent();
+ return new DroppableLabelBorder(fieldContent, axis, wrappedView);
+ }
+
+ public static View createObjectParameterLabelBorder(final LabelAxis axis, final View wrappedView) {
+ final ParameterContent parameterContent = (ParameterContent) wrappedView.getContent();
+ return new DroppableLabelBorder(parameterContent, axis, wrappedView);
+ }
+
+ private final ViewState labelState = new ViewState();
+ private boolean overContent;
+
+ public DroppableLabelBorder(final FieldContent fieldContent, final LabelAxis axis, final View wrappedView) {
+ super(fieldContent, axis, wrappedView);
+ }
+
+ public DroppableLabelBorder(final ParameterContent fieldContent, final LabelAxis axis, final View wrappedView) {
+ super(fieldContent, axis, wrappedView);
+ }
+
+ @Override
+ public ViewAreaType viewAreaType(final Location location) {
+ if (overBorder(location)) {
+ return ViewAreaType.CONTENT; // used to ensure menu options for
+ // contained object are shown
+ } else {
+ return super.viewAreaType(location);
+ }
+ }
+
+ @Override
+ public void dragCancel(final InternalDrag drag) {
+ super.dragCancel(drag);
+ labelState.clearViewIdentified();
+ }
+
+ @Override
+ public void drag(final ContentDrag drag) {
+ final Location targetLocation = drag.getTargetLocation();
+ if (overContent(targetLocation) && overContent == false) {
+ overContent = true;
+ super.dragIn(drag);
+ dragOutOfLabel();
+ } else if (overBorder(targetLocation) && overContent == true) {
+ overContent = false;
+ super.dragOut(drag);
+ dragInToLabel(drag.getSourceContent());
+ }
+
+ super.drag(drag);
+ }
+
+ @Override
+ public void dragIn(final ContentDrag drag) {
+ if (overContent(drag.getTargetLocation())) {
+ super.dragIn(drag);
+ } else {
+ final Content sourceContent = drag.getSourceContent();
+ dragInToLabel(sourceContent);
+ markDamaged();
+ }
+ }
+
+ private void dragInToLabel(final Content sourceContent) {
+ overContent = false;
+ final Consent canDrop = canDrop(sourceContent);
+ if (canDrop.isAllowed()) {
+ labelState.setCanDrop();
+ } else {
+ labelState.setCantDrop();
+ }
+ final String actionText = canDrop.isVetoed() ? canDrop.getReason() : "Set to " + sourceContent.title();
+ getFeedbackManager().setAction(actionText);
+ }
+
+ @Override
+ public void dragOut(final ContentDrag drag) {
+ super.dragOut(drag);
+ dragOutOfLabel();
+ }
+
+ private void dragOutOfLabel() {
+ labelState.clearObjectIdentified();
+ markDamaged();
+ }
+
+ @Override
+ public void drop(final ContentDrag drag) {
+ if (overContent(drag.getTargetLocation())) {
+ super.drop(drag);
+ } else {
+ dragOutOfLabel();
+ final Content sourceContent = drag.getSourceContent();
+ if (canDrop(sourceContent).isAllowed()) {
+ drop(sourceContent);
+ }
+ }
+ }
+
+ protected Consent canDrop(final Content dropContent) {
+ if (dropContent instanceof ObjectContent) {
+ final ObjectAdapter source = ((ObjectContent) dropContent).getObject();
+ final ObjectContent content = (ObjectContent) getContent();
+ return content.canSet(source);
+ } else {
+ return Veto.DEFAULT;
+ }
+ }
+
+ protected void drop(final Content dropContent) {
+ if (dropContent instanceof ObjectContent) {
+ final ObjectAdapter object = ((ObjectContent) dropContent).getObject();
+ ((ObjectContent) getContent()).setObject(object);
+ getParent().invalidateContent();
+ }
+ }
+
+ @Override
+ protected Color textColor() {
+ Color color;
+ if (labelState.canDrop()) {
+ color = Toolkit.getColor(ColorsAndFonts.COLOR_VALID);
+ } else if (labelState.cantDrop()) {
+ color = Toolkit.getColor(ColorsAndFonts.COLOR_INVALID);
+ } else {
+ color = super.textColor();
+ }
+ return color;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/EmptyBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/EmptyBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/EmptyBorder.java
new file mode 100644
index 0000000..4c28283
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/EmptyBorder.java
@@ -0,0 +1,46 @@
+/*
+ * 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.border;
+
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+
+public class EmptyBorder extends AbstractBorder {
+
+ public EmptyBorder(final int width, final View view) {
+ super(view);
+ left = top = right = bottom = width;
+ }
+
+ public EmptyBorder(final int topBottom, final int leftRight, final View view) {
+ super(view);
+ left = right = bottom = leftRight;
+ top = bottom = topBottom;
+ }
+
+ public EmptyBorder(final int left, final int top, final int right, final int bottom, final View view) {
+ super(view);
+ this.left = left;
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/FieldOrderBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/FieldOrderBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/FieldOrderBorder.java
new file mode 100644
index 0000000..3f509dd
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/FieldOrderBorder.java
@@ -0,0 +1,64 @@
+/*
+ * 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.border;
+
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.UserActionSet;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.base.AbstractViewDecorator;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public class FieldOrderBorder extends AbstractViewDecorator {
+
+ private boolean isReversed;
+
+ public FieldOrderBorder(final View wrappedView) {
+ super(wrappedView);
+ }
+
+ @Override
+ public View[] getSubviews() {
+ View[] subviews = super.getSubviews();
+ if (isReversed) {
+ final View[] v = new View[subviews.length];
+ for (int i = 0; i < v.length; i++) {
+ v[i] = subviews[v.length - i - 1];
+ }
+ subviews = v;
+ }
+
+ return subviews;
+ }
+
+ @Override
+ public void viewMenuOptions(final UserActionSet menuOptions) {
+ super.viewMenuOptions(menuOptions);
+
+ menuOptions.add(new UserActionAbstract("Reverse view order") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ isReversed = !isReversed;
+ invalidateLayout();
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/IconBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/IconBorder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/IconBorder.java
new file mode 100644
index 0000000..48f51e6
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/border/IconBorder.java
@@ -0,0 +1,170 @@
+/*
+ * 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.border;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.dnd.drawing.Bounds;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.drawing.Text;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Click;
+import org.apache.isis.viewer.dnd.view.DragEvent;
+import org.apache.isis.viewer.dnd.view.DragStart;
+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.ViewAreaType;
+import org.apache.isis.viewer.dnd.view.ViewConstants;
+import org.apache.isis.viewer.dnd.view.base.AbstractBorder;
+import org.apache.isis.viewer.dnd.view.base.IconGraphic;
+import org.apache.isis.viewer.dnd.view.composite.CompositeViewDecorator;
+import org.apache.isis.viewer.dnd.view.text.ObjectTitleText;
+import org.apache.isis.viewer.dnd.view.text.TitleText;
+
+public class IconBorder extends AbstractBorder {
+
+ public static class Factory implements CompositeViewDecorator {
+ private final Text textStyle;
+
+ public Factory() {
+ this(Toolkit.getText(ColorsAndFonts.TEXT_TITLE));
+ }
+
+ public Factory(final Text textStyle) {
+ this.textStyle = textStyle;
+ }
+
+ @Override
+ public View decorate(final View child, final Axes axes) {
+ return new IconBorder(child, textStyle);
+ }
+ }
+
+ private final int baseline;
+ private final int titlebarHeight;
+ private final IconGraphic icon;
+ private final TitleText text;
+
+ public IconBorder(final View wrappedView, final Text style) {
+ this(wrappedView, null, null, style);
+ }
+
+ public IconBorder(final View wrappedView, final TitleText titleText, final IconGraphic iconGraphic, final Text style) {
+ super(wrappedView);
+
+ icon = iconGraphic == null ? new IconGraphic(this, style) : iconGraphic;
+ text = titleText == null ? new ObjectTitleText(this, style) : titleText;
+ titlebarHeight = ViewConstants.VPADDING + icon.getSize().getHeight() + 1;
+
+ top = titlebarHeight + ViewConstants.VPADDING;
+ left = right = ViewConstants.HPADDING;
+ bottom = ViewConstants.VPADDING;
+
+ baseline = ViewConstants.VPADDING + icon.getBaseline() + 1;
+ }
+
+ @Override
+ public void debugDetails(final DebugBuilder debug) {
+ super.debugDetails(debug);
+ debug.appendln("titlebar", top - titlebarHeight);
+ }
+
+ @Override
+ public DragEvent dragStart(final DragStart drag) {
+ if (overBorder(drag.getLocation())) {
+ return Toolkit.getViewFactory().createDragContentOutline(this, drag.getLocation());
+ } else {
+ return super.dragStart(drag);
+ }
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ int x = left - 2;
+
+ if (Toolkit.debug) {
+ canvas.drawDebugOutline(new Bounds(getSize()), baseline, Toolkit.getColor(ColorsAndFonts.COLOR_DEBUG_BOUNDS_DRAW));
+ }
+
+ // icon & title
+ icon.draw(canvas, x, baseline);
+ x += icon.getSize().getWidth();
+ x += ViewConstants.HPADDING;
+ final int maxWidth = getSize().getWidth() - x - right;
+ text.draw(canvas, x, baseline, maxWidth);
+
+ // components
+ super.draw(canvas);
+ }
+
+ @Override
+ public int getBaseline() {
+ return baseline; // wrappedView.getBaseline() + baseline +
+ // titlebarHeight;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ final Size size = super.getRequiredSize(availableSpace);
+ size.ensureWidth(left + icon.getSize().getWidth() + ViewConstants.HPADDING + text.getSize().getWidth() + right);
+ return size;
+ }
+
+ @Override
+ public void firstClick(final Click click) {
+ final int y = click.getLocation().getY();
+ if (y < top && click.button2()) {
+ final Location location = new Location(click.getLocationWithinViewer());
+ getViewManager().showInOverlay(getContent(), location);
+ } else {
+ super.firstClick(click);
+ }
+ }
+
+ @Override
+ public void secondClick(final Click click) {
+ final int y = click.getLocation().getY();
+ if (y < top) {
+ getWorkspace().addWindowFor(getContent().getAdapter(), new Placement(this));
+ } else {
+ super.secondClick(click);
+ }
+ }
+
+ @Override
+ public ViewAreaType viewAreaType(final Location mouseLocation) {
+ final Bounds title = new Bounds(new Location(), icon.getSize());
+ title.extendWidth(left);
+ title.extendWidth(text.getSize().getWidth());
+ if (title.contains(mouseLocation)) {
+ return ViewAreaType.CONTENT;
+ } else {
+ return super.viewAreaType(mouseLocation);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return wrappedView.toString() + "/IconBorder [" + getSpecification() + "]";
+ }
+}