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:18 UTC
[43/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/configurable/PanelViewSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/PanelViewSpecification.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/PanelViewSpecification.java
new file mode 100644
index 0000000..8ef3d32
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/PanelViewSpecification.java
@@ -0,0 +1,76 @@
+/*
+ * 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.configurable;
+
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.form.InternalFormSpecification;
+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.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+import org.apache.isis.viewer.dnd.view.border.IconBorder;
+
+public class PanelViewSpecification implements ViewSpecification {
+
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return requirement.isObject() && requirement.isOpen() && requirement.isExpandable() && requirement.isDesign();
+ }
+
+ @Override
+ public String getName() {
+ return "Panel (experimental)";
+ }
+
+ @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 View createView(final Content content, final Axes axes, final int sequence) {
+ final PanelView wrappedView = new PanelView(content, this);
+ wrappedView.setInitialViewSpecification(new InternalFormSpecification());
+ final View newView = new IconBorder(wrappedView, Toolkit.getText(ColorsAndFonts.TEXT_TITLE));
+ return newView;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/ViewDesignBorder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/ViewDesignBorder.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/ViewDesignBorder.java
new file mode 100644
index 0000000..52bc891
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/configurable/ViewDesignBorder.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.configurable;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+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.AbstractBorder;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public class ViewDesignBorder extends AbstractBorder {
+ private final NewObjectView viewUnderControl;
+
+ protected ViewDesignBorder(final View view, final NewObjectView view2) {
+ super(view);
+ viewUnderControl = view2;
+ }
+
+ private NewObjectView getNewObjectView() {
+ return viewUnderControl;
+ }
+
+ @Override
+ public void viewMenuOptions(final UserActionSet menuOptions) {
+ super.viewMenuOptions(menuOptions);
+
+ // ObjectAdapter object = getContent().getAdapter();
+ final List<ObjectAssociation> associations = getContent().getSpecification().getAssociations();
+
+ for (final ObjectAssociation objectAssociation : associations) {
+ final ObjectAssociation f = objectAssociation;
+ final UserActionAbstract action = new UserActionAbstract("Add field " + objectAssociation.getName()) {
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final NewObjectField field = new NewObjectField(f);
+ getNewObjectView().addField(field);
+ }
+ };
+ menuOptions.add(action);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogFocusManager.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogFocusManager.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogFocusManager.java
new file mode 100644
index 0000000..19f425a
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogFocusManager.java
@@ -0,0 +1,45 @@
+/*
+ * 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.dialog;
+
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractFocusManager;
+import org.apache.isis.viewer.dnd.view.border.ButtonBorder;
+
+public class ActionDialogFocusManager extends AbstractFocusManager {
+ private final ButtonBorder buttonBorder;
+
+ public ActionDialogFocusManager(final ButtonBorder buttonBorder) {
+ super(buttonBorder.getView());
+ this.buttonBorder = buttonBorder;
+
+ }
+
+ @Override
+ protected View[] getChildViews() {
+ final View[] subviews = container.getSubviews();
+ final View[] buttons = buttonBorder.getButtons();
+
+ final View[] views = new View[subviews.length + buttons.length];
+ System.arraycopy(subviews, 0, views, 0, subviews.length);
+ System.arraycopy(buttons, 0, views, subviews.length, buttons.length);
+ return views;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogSpecification.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogSpecification.java
new file mode 100644
index 0000000..53febd7
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionDialogSpecification.java
@@ -0,0 +1,204 @@
+/*
+ * 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.dialog;
+
+import org.apache.log4j.Logger;
+
+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.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.BackgroundTask;
+import org.apache.isis.viewer.dnd.view.ButtonAction;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.GlobalViewFactory;
+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.ViewFactory;
+import org.apache.isis.viewer.dnd.view.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.action.ActionContent;
+import org.apache.isis.viewer.dnd.view.action.BackgroundWork;
+import org.apache.isis.viewer.dnd.view.action.ObjectParameter;
+import org.apache.isis.viewer.dnd.view.action.ParameterContent;
+import org.apache.isis.viewer.dnd.view.action.TextParseableParameter;
+import org.apache.isis.viewer.dnd.view.base.Layout;
+import org.apache.isis.viewer.dnd.view.border.ButtonBorder;
+import org.apache.isis.viewer.dnd.view.border.IconBorder;
+import org.apache.isis.viewer.dnd.view.composite.CompositeViewDecorator;
+import org.apache.isis.viewer.dnd.view.composite.CompositeViewSpecification;
+import org.apache.isis.viewer.dnd.view.composite.StackLayout;
+import org.apache.isis.viewer.dnd.view.control.AbstractButtonAction;
+import org.apache.isis.viewer.dnd.view.control.CancelAction;
+
+public class ActionDialogSpecification extends CompositeViewSpecification {
+ private static final Logger LOG = Logger.getLogger(ActionDialogSpecification.class);
+
+ private static class DialogFormSubviews implements ViewFactory {
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int fieldNumber) {
+ if (content instanceof TextParseableParameter) {
+ final GlobalViewFactory factory = Toolkit.getViewFactory();
+ return factory.createView(new ViewRequirement(content, ViewRequirement.CLOSED | ViewRequirement.SUBVIEW));
+ } else if (content instanceof ObjectParameter) {
+ final GlobalViewFactory factory = Toolkit.getViewFactory();
+ return factory.createView(new ViewRequirement(content, ViewRequirement.CLOSED | ViewRequirement.SUBVIEW));
+ }
+
+ return null;
+ }
+ }
+
+ private static class ExecuteAction extends AbstractButtonAction {
+ public ExecuteAction() {
+ this("Apply");
+ }
+
+ public ExecuteAction(final String name) {
+ super(name, true);
+ }
+
+ @Override
+ public Consent disabled(final View view) {
+ final View[] subviews = view.getSubviews();
+ final StringBuffer missingFields = new StringBuffer();
+ final StringBuffer invalidFields = new StringBuffer();
+ for (final View field : subviews) {
+ final ParameterContent content = ((ParameterContent) field.getContent());
+ final boolean isEmpty = content.getAdapter() == null;
+ if (content.isRequired() && isEmpty) {
+ final String parameterName = content.getParameterName();
+ if (missingFields.length() > 0) {
+ missingFields.append(", ");
+ }
+ missingFields.append(parameterName);
+
+ } else if (field.getState().isInvalid()) {
+ final String parameterName = content.getParameterName();
+ if (invalidFields.length() > 0) {
+ invalidFields.append(", ");
+ }
+ invalidFields.append(parameterName);
+ }
+ }
+ if (missingFields.length() > 0) {
+ // TODO: move logic into Facet
+ return new Veto(String.format("Fields needed: %s", missingFields));
+ }
+ if (invalidFields.length() > 0) {
+ // TODO: move logic into Facet
+ return new Veto(String.format("Invalid fields: %s", invalidFields));
+ }
+
+ final ActionContent actionContent = ((ActionContent) view.getContent());
+ return actionContent.disabled();
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final BackgroundTask task = new BackgroundTask() {
+ @Override
+ public void execute() {
+ final ActionContent actionContent = ((ActionContent) view.getContent());
+ final ObjectAdapter result = actionContent.execute();
+ LOG.debug("action invoked with result " + result);
+ if (result != null) {
+ view.objectActionResult(result, new Placement(view.getAbsoluteLocation()));
+ }
+ view.getViewManager().disposeUnneededViews();
+ view.getFeedbackManager().showMessagesAndWarnings();
+ }
+
+ @Override
+ public String getName() {
+ return ((ActionContent) view.getContent()).getActionName();
+ }
+
+ @Override
+ public String getDescription() {
+ return "Running action " + getName() + " on " + view.getContent().getAdapter();
+ }
+ };
+ LOG.debug(" ... created task " + task);
+
+ BackgroundWork.runTaskInBackground(view, task);
+ }
+
+ protected void move(final Location at) {
+ at.move(30, 60);
+ }
+ }
+
+ private static class ExecuteAndCloseAction extends ExecuteAction {
+ public ExecuteAndCloseAction() {
+ super("OK");
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ LOG.debug("executing action " + this);
+ view.dispose();
+ LOG.debug(" ... disposed view, now executing");
+ super.execute(workspace, view, at);
+ view.getViewManager().setKeyboardFocus(workspace);
+ // view.getViewManager().clearKeyboardFocus();
+ }
+
+ @Override
+ protected void move(final Location at) {
+ }
+ }
+
+ public ActionDialogSpecification() {
+ builder = new ActionFieldBuilder(new DialogFormSubviews());
+ addSubviewDecorator(new ParametersLabelDecorator());
+ addViewDecorator(new CompositeViewDecorator() {
+ @Override
+ public View decorate(final View view, final Axes axes) {
+ // TODO reintroduce the 'Apply' notion, but under control from
+ // the method declaration
+ final ButtonAction[] actions = new ButtonAction[] { new ExecuteAndCloseAction(), new CancelAction() };
+ final ButtonBorder buttonBorder = new ButtonBorder(actions, new IconBorder(view, Toolkit.getText(ColorsAndFonts.TEXT_TITLE_SMALL)));
+ buttonBorder.setFocusManager(new ActionDialogFocusManager(buttonBorder));
+ return buttonBorder;
+ }
+ });
+ }
+
+ @Override
+ public Layout createLayout(final Content content, final Axes axes) {
+ return new StackLayout();
+ }
+
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return requirement.getContent() instanceof ActionContent;
+ }
+
+ @Override
+ public String getName() {
+ return "Action Dialog";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionFieldBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionFieldBuilder.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionFieldBuilder.java
new file mode 100644
index 0000000..9107dee
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ActionFieldBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * 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.dialog;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+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.ViewFactory;
+import org.apache.isis.viewer.dnd.view.action.ActionContent;
+import org.apache.isis.viewer.dnd.view.action.ObjectParameter;
+import org.apache.isis.viewer.dnd.view.action.ObjectParameterImpl;
+import org.apache.isis.viewer.dnd.view.action.ParameterContent;
+import org.apache.isis.viewer.dnd.view.action.TextParseableParameter;
+import org.apache.isis.viewer.dnd.view.composite.AbstractViewBuilder;
+
+public class ActionFieldBuilder extends AbstractViewBuilder {
+ private static final Logger LOG = Logger.getLogger(ActionFieldBuilder.class);
+ private final ViewFactory subviewDesign;
+
+ public ActionFieldBuilder(final ViewFactory subviewDesign) {
+ this.subviewDesign = subviewDesign;
+ }
+
+ @Override
+ public void build(final View view, final Axes axes) {
+ Assert.assertEquals(view.getView(), view);
+
+ final ActionContent actionContent = ((ActionContent) view.getContent());
+ if (view.getSubviews().length == 0) {
+ initialBuild(view, actionContent);
+ } else {
+ updateBuild(view, actionContent);
+ }
+
+ }
+
+ private View createFieldView(final View view, final ParameterContent parameter, final int sequence) {
+ final View fieldView = subviewDesign.createView(parameter, null, sequence);
+ if (fieldView == null) {
+ throw new IsisException("All parameters must be shown");
+ }
+ return fieldView;
+ }
+
+ private void initialBuild(final View view, final ActionContent actionContent) {
+ LOG.debug("build new view " + view + " for " + actionContent);
+ final int noParameters = actionContent.getNoParameters();
+ View focusOn = null;
+ for (int f = 0; f < noParameters; f++) {
+ final ParameterContent parameter = actionContent.getParameterContent(f);
+ final View fieldView = createFieldView(view, parameter, f);
+ final View decoratedSubview = decorateSubview(view.getViewAxes(), fieldView);
+ view.addView(decoratedSubview);
+
+ // set focus to first value field
+ if (focusOn == null && parameter instanceof TextParseableParameter && fieldView.canFocus()) {
+ focusOn = decoratedSubview;
+ }
+ }
+
+ if (focusOn != null) {
+ view.getViewManager().setKeyboardFocus(focusOn);
+ }
+ }
+
+ private void updateBuild(final View view, final ActionContent actionContent) {
+ LOG.debug("rebuild view " + view + " for " + actionContent);
+ final View[] subviews = view.getSubviews();
+
+ for (int i = 0; i < subviews.length; i++) {
+ final View subview = subviews[i];
+ final Content content = subview.getContent();
+
+ final ObjectAdapter subviewsObject = subview.getContent().getAdapter();
+ final ObjectAdapter invocationsObject = ((ActionContent) view.getContent()).getParameterObject(i);
+
+ if (content instanceof ObjectParameter) {
+ if (subviewsObject != invocationsObject) {
+ final ObjectParameter parameter = new ObjectParameterImpl((ObjectParameterImpl) content, invocationsObject);
+ final View fieldView = createFieldView(view, parameter, i);
+ view.replaceView(subview, decorateSubview(view.getViewAxes(), fieldView));
+ }
+ } else {
+ subview.refresh();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ParametersLabelDecorator.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ParametersLabelDecorator.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ParametersLabelDecorator.java
new file mode 100644
index 0000000..f61b886
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/dialog/ParametersLabelDecorator.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dialog;
+
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.SubviewDecorator;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewAxis;
+import org.apache.isis.viewer.dnd.view.axis.LabelAxis;
+import org.apache.isis.viewer.dnd.view.border.DroppableLabelBorder;
+import org.apache.isis.viewer.dnd.view.border.LabelBorder;
+
+public class ParametersLabelDecorator implements SubviewDecorator {
+
+ @Override
+ public ViewAxis createAxis(final Content content) {
+ return new LabelAxis();
+ }
+
+ @Override
+ public View decorate(final Axes axes, final View view) {
+ final LabelAxis axis = axes.getAxis(LabelAxis.class);
+ if (view.getContent().isObject() && !view.getContent().isTextParseable()) {
+ return DroppableLabelBorder.createObjectParameterLabelBorder(axis, view);
+ } else {
+ return LabelBorder.createValueParameterLabelBorder(axis, view);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Background.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Background.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Background.java
new file mode 100644
index 0000000..5cc9037
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Background.java
@@ -0,0 +1,27 @@
+/*
+ * 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.drawing;
+
+/**
+ * A strategy for rendering the background of the application window.
+ */
+public interface Background {
+ void draw(Canvas canvas, Size size);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Bounds.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Bounds.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Bounds.java
new file mode 100644
index 0000000..2d9f931
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Bounds.java
@@ -0,0 +1,330 @@
+/*
+ * 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.drawing;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Bounds represent a rectangular area on the screen. The top-left corner is
+ * represented by the location (available using getLocation(), and getX() and
+ * getY()). The extent of the bounds is specified by its height and width
+ * (available using getHeight() and getWidth()). The bottom-right point is the
+ * offset from the top-left point by width -1 and hieght - 1 pixels.
+ *
+ * For example a bounds created as follows
+ *
+ * new Bounds(5, 10, 10, 20)
+ *
+ * Would represent a rectangle at location (5, 10), with a width of 10 pixels
+ * and a height of 20. Note, hower that the lower-right corner would be at (14,
+ * 29), as there are 10 pixels between pixel 5 and pixel 14, and 20 between 10
+ * and 29.
+ */
+public class Bounds {
+ Logger LOG = Logger.getLogger("Bounds");
+ int x;
+ int y;
+ int height;
+ int width;
+
+ public Bounds() {
+ x = 0;
+ y = 0;
+ width = 0;
+ height = 0;
+ }
+
+ public Bounds(final Bounds bounds) {
+ this(bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+
+ public Bounds(final int x, final int y, final int width, final int height) {
+ super();
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ public Bounds(final Location location, final Size size) {
+ this(location.x, location.y, size.width, size.height);
+ }
+
+ public Bounds(final Size size) {
+ this(0, 0, size.width, size.height);
+ }
+
+ public boolean contains(final Location location) {
+ final int xp = location.getX();
+ final int yp = location.getY();
+ final int xMax = x + width - 1;
+ final int yMax = y + height - 1;
+
+ return xp >= x && xp <= xMax && yp >= y && yp <= yMax;
+ }
+
+ public void contract(final int width, final int height) {
+ this.width -= width;
+ this.height -= height;
+ }
+
+ public void contract(final Padding padding) {
+ height -= padding.top + padding.bottom;
+ width -= padding.left + padding.right;
+ x += padding.left;
+ y += padding.top;
+ }
+
+ public void contract(final Size size) {
+ this.width -= size.width;
+ this.height -= size.height;
+ }
+
+ public void contractHeight(final int height) {
+ this.height -= height;
+ }
+
+ public void contractWidth(final int width) {
+ this.width -= width;
+ }
+
+ public void ensureHeight(final int height) {
+ this.height = Math.max(this.height, height);
+ }
+
+ public void ensureWidth(final int width) {
+ this.width = Math.max(this.width, width);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Bounds) {
+ final Bounds b = (Bounds) obj;
+
+ return b.x == x && b.y == y && b.width == width && b.height == height;
+ }
+
+ return false;
+ }
+
+ public void extend(final int width, final int height) {
+ this.width += width;
+ this.height += height;
+ }
+
+ public void extend(final Padding padding) {
+ this.width += padding.getLeftRight();
+ this.height += padding.getTopBottom();
+ }
+
+ public void extend(final Size size) {
+ this.width += size.width;
+ this.height += size.height;
+ }
+
+ public void extendHeight(final int height) {
+ this.height += height;
+ }
+
+ public void extendWidth(final int width) {
+ this.width += width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public Location getLocation() {
+ return new Location(x, y);
+ }
+
+ public Size getSize() {
+ return new Size(width, height);
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getX2() {
+ return x + width - 1;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getY2() {
+ return y + height - 1;
+ }
+
+ /**
+ * Determines whether this bounds overlaps the specified bounds. If any area
+ * is shared by the two bounds then this will return true. As the edges of
+ * the bounds are of a finite size the bounds overlap if any of the edges
+ * overlap.
+ */
+ public boolean intersects(final Bounds bounds) {
+ final int tx1 = this.x;
+ final int tx2 = this.x + this.width - 1;
+ final int ox1 = bounds.x;
+ final int ox2 = bounds.x + bounds.width - 1;
+
+ // tx1 < ox1 < tx2 || tx1 < ox2 < tx2
+ final boolean xOverlap = (tx1 <= ox1 && ox1 <= tx2) || (tx1 <= ox2 && ox1 <= tx2) || (ox1 <= tx1 && tx1 <= ox2) || (ox1 <= tx2 && tx1 <= ox2);
+
+ final int ty1 = this.y;
+ final int ty2 = this.y + this.height - 1;
+ final int oy1 = bounds.y;
+ final int oy2 = bounds.y + bounds.height - 1;
+ final boolean yOverlap = (ty1 <= oy1 && oy1 <= ty2) || (ty1 <= oy2 && oy1 <= ty2) || (oy1 <= ty1 && ty1 <= oy2) || (oy1 <= ty2 && ty1 <= oy2);
+ return xOverlap && yOverlap;
+
+ }
+
+ public void limitLocation(final Size bounds) {
+ if (x + width > bounds.width) {
+ x = bounds.width - width;
+ }
+ if (y + height > bounds.height) {
+ y = bounds.height - height;
+ }
+ }
+
+ /**
+ * Limits the specified bounds so that it fits within this bounds.
+ */
+ public boolean limitBounds(final Bounds toLimit) {
+ boolean limited = false;
+ final Location location = toLimit.getLocation();
+ final Size size = toLimit.getSize();
+
+ int viewLeft = location.getX();
+ int viewTop = location.getY();
+ int viewRight = viewLeft + size.getWidth();
+ int viewBottom = viewTop + size.getHeight();
+
+ final Size wd = getSize();
+
+ final int limitLeft = x;
+ final int limitTop = y;
+ final int limitRight = x + width;
+ final int limitBottom = y + height;
+
+ if (viewRight > limitRight) {
+ viewLeft = limitRight - size.getWidth();
+ limited = true;
+ LOG.info("right side oustide limits, moving left to " + viewLeft);
+ }
+
+ if (viewLeft < limitLeft) {
+ viewLeft = limitLeft;
+ limited = true;
+ LOG.info("left side outside limit, moving left to " + viewLeft);
+ }
+
+ if (viewBottom > limitBottom) {
+ viewTop = limitBottom - size.getHeight();
+ limited = true;
+ LOG.info("bottom outside limit, moving top to " + viewTop);
+ }
+
+ if (viewTop < limitTop) {
+ viewTop = limitTop;
+ limited = true;
+ LOG.info("top outside limit, moving top to " + viewTop);
+ }
+
+ toLimit.setX(viewLeft);
+ toLimit.setY(viewTop);
+
+ viewBottom = viewTop + size.getHeight();
+ viewRight = viewLeft + size.getWidth();
+
+ if (viewRight > limitRight) {
+ toLimit.width = wd.width;
+ limited = true;
+ LOG.info("width outside limit, reducing width to " + viewTop);
+ }
+
+ if (viewBottom > limitBottom) {
+ toLimit.height = wd.height;
+ limited = true;
+ LOG.info("height outside limit, reducing height to " + viewTop);
+ }
+
+ if (limited) {
+ LOG.info("limited " + toLimit);
+ }
+ return limited;
+ }
+
+ public void setBounds(final Bounds bounds) {
+ x = bounds.x;
+ y = bounds.y;
+ width = bounds.width;
+ height = bounds.height;
+
+ }
+
+ public void setHeight(final int height) {
+ this.height = height;
+ }
+
+ public void setWidth(final int width) {
+ this.width = width;
+ }
+
+ public void setX(final int x) {
+ this.x = x;
+ }
+
+ public void setY(final int y) {
+ this.y = y;
+ }
+
+ @Override
+ public String toString() {
+ return x + "," + y + " " + width + "x" + height;
+ }
+
+ public void translate(final int x, final int y) {
+ this.x += x;
+ this.y += y;
+ }
+
+ public void union(final Bounds bounds) {
+ final int newX = Math.min(x, bounds.x);
+ final int newY = Math.min(y, bounds.y);
+ width = Math.max(x + width, bounds.x + bounds.width) - newX;
+ height = Math.max(y + height, bounds.y + bounds.height) - newY;
+ x = newX;
+ y = newY;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Canvas.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Canvas.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Canvas.java
new file mode 100644
index 0000000..4271de1
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Canvas.java
@@ -0,0 +1,68 @@
+/*
+ * 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.drawing;
+
+public interface Canvas {
+ Canvas createSubcanvas();
+
+ Canvas createSubcanvas(Bounds bounds);
+
+ Canvas createSubcanvas(int x, int y, int width, int height);
+
+ void draw3DRectangle(int x, int y, int width, int height, Color color, boolean raised);
+
+ void drawDebugOutline(Bounds bounds, int baseline, Color color);
+
+ void drawImage(Image image, int x, int y);
+
+ void drawImage(Image image, int x, int y, int width, int height);
+
+ void drawLine(int x, int y, int x2, int y2, Color color);
+
+ void drawLine(Location start, int xExtent, int yExtent, Color color);
+
+ void drawOval(int x, int y, int width, int height, Color color);
+
+ void drawRectangle(int x, int y, int width, int height, Color color);
+
+ void drawRectangleAround(Bounds bounds, Color color);
+
+ void drawRoundedRectangle(int x, int y, int width, int height, int arcWidth, int arcHeight, Color color);
+
+ void drawShape(Shape shape, Color color);
+
+ void drawShape(Shape shape, int x, int y, Color color);
+
+ void drawSolidOval(int x, int y, int width, int height, Color color);
+
+ void drawSolidRectangle(int x, int y, int width, int height, Color color);
+
+ void drawSolidShape(Shape shape, Color color);
+
+ void drawSolidShape(Shape shape, int x, int y, Color color);
+
+ void drawText(String text, int x, int y, Color color, Text style);
+
+ void drawText(String text, int x, int y, int maxWidth, Color color, Text style);
+
+ void offset(int x, int y);
+
+ boolean overlaps(Bounds bounds);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Color.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Color.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Color.java
new file mode 100644
index 0000000..cadf826
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Color.java
@@ -0,0 +1,30 @@
+/*
+ * 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.drawing;
+
+public interface Color {
+
+ Color brighter();
+
+ Color darker();
+
+ String getName();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ColorsAndFonts.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ColorsAndFonts.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ColorsAndFonts.java
new file mode 100644
index 0000000..5cc4866
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ColorsAndFonts.java
@@ -0,0 +1,101 @@
+/*
+ * 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.drawing;
+
+/**
+ * A look-up for font and color details.
+ *
+ */
+public interface ColorsAndFonts {
+ public final static String COLOR_BLACK = "color.black";
+ public final static String COLOR_WHITE = "color.white";
+ public final static String COLOR_PRIMARY1 = "color.primary1";
+ public final static String COLOR_PRIMARY2 = "color.primary2";
+ public final static String COLOR_PRIMARY3 = "color.primary3";
+ public final static String COLOR_SECONDARY1 = "color.secondary1";
+ public final static String COLOR_SECONDARY2 = "color.secondary2";
+ public final static String COLOR_SECONDARY3 = "color.secondary3";
+
+ // background colors
+ public final static String COLOR_APPLICATION = "color.background.application";
+ public final static String COLOR_WINDOW = "color.background.window";
+ public final static String COLOR_MENU_VALUE = "color.background.menu.value";
+ public final static String COLOR_MENU_CONTENT = "color.background.menu.content";
+ public final static String COLOR_MENU_VIEW = "color.background.menu.view";
+ public final static String COLOR_MENU_WORKSPACE = "color.background.menu.workspace";
+
+ // menu colors
+ public final static String COLOR_MENU = "color.menu.normal";
+ public final static String COLOR_MENU_DISABLED = "color.menu.disabled";
+ public final static String COLOR_MENU_REVERSED = "color.menu.reversed";
+
+ // label colors
+ public final static String COLOR_LABEL = "color.label.normal";
+ public final static String COLOR_LABEL_DISABLED = "color.label.disabled";
+ public final static String COLOR_LABEL_MANDATORY = "color.label.mandatory";
+
+ // state colors
+ public final static String COLOR_IDENTIFIED = "color.identified";
+ public final static String COLOR_VALID = "color.valid";
+ public final static String COLOR_INVALID = "color.invalid";
+ public final static String COLOR_ERROR = "color.error";
+ public final static String COLOR_ACTIVE = "color.active";
+ public final static String COLOR_OUT_OF_SYNC = "color.out-of-sync";
+
+ // text colors
+ public final static String COLOR_TEXT_SAVED = "color.text.saved";
+ public final static String COLOR_TEXT_EDIT = "color.text.edit";
+ public final static String COLOR_TEXT_CURSOR = "color.text.cursor";
+ public final static String COLOR_TEXT_HIGHLIGHT = "color.text.highlight";
+
+ // debug outline colors
+ public final static String COLOR_DEBUG_BASELINE = "color.debug.baseline";
+ public final static String COLOR_DEBUG_BOUNDS_BORDER = "color.debug.bounds.border";
+ public final static String COLOR_DEBUG_BOUNDS_DRAW = "color.debug.bounds.draw";
+ public final static String COLOR_DEBUG_BOUNDS_REPAINT = "color.debug.bounds.repaint";
+ public final static String COLOR_DEBUG_BOUNDS_VIEW = "color.debug.bounds.view";
+
+ // fonts
+ public final static String TEXT_DEFAULT = "text.default";
+ public final static String TEXT_CONTROL = "text.control";
+ public final static String TEXT_TITLE = "text.title";
+ public final static String TEXT_TITLE_SMALL = "text.title.small";
+ public final static String TEXT_DEBUG = "text.debug";
+ public final static String TEXT_STATUS = "text.status";
+ public final static String TEXT_ICON = "text.icon";
+ public final static String TEXT_LABEL = "text.label";
+ public final static String TEXT_LABEL_MANDATORY = "text.label.mandatory";
+ public final static String TEXT_LABEL_DISABLED = "text.label.disabled";
+ public final static String TEXT_MENU = "text.menu";
+ public final static String TEXT_NORMAL = "text.normal";
+
+ int defaultBaseline();
+
+ int defaultFieldHeight();
+
+ Color getColor(int rgbColor);
+
+ Color getColor(String name);
+
+ Text getText(String name);
+
+ void init();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvas.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvas.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvas.java
new file mode 100644
index 0000000..7cc7656
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvas.java
@@ -0,0 +1,187 @@
+/*
+ * 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.drawing;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+
+public class DebugCanvas implements Canvas {
+ private final DebugBuilder buffer;
+ private final int level;
+
+ public DebugCanvas(final DebugBuilder buffer, final Bounds bounds) {
+ this(buffer, 0);
+ }
+
+ private DebugCanvas(final DebugBuilder buffer, final int level) {
+ this.level = level;
+ this.buffer = buffer;
+ }
+
+ @Override
+ public Canvas createSubcanvas() {
+ buffer.blankLine();
+ indent();
+ buffer.appendln("Create subcanvas for same area");
+ return new DebugCanvas(buffer, level + 1);
+ }
+
+ @Override
+ public Canvas createSubcanvas(final Bounds bounds) {
+ return createSubcanvas(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+ }
+
+ @Override
+ public Canvas createSubcanvas(final int x, final int y, final int width, final int height) {
+ buffer.blankLine();
+ indent();
+ buffer.appendln("Create subcanvas for area " + x + "," + y + " " + width + "x" + height);
+ return new DebugCanvas(buffer, level + 1);
+ }
+
+ @Override
+ public void draw3DRectangle(final int x, final int y, final int width, final int height, final Color color, final boolean raised) {
+ indent();
+ buffer.appendln("Rectangle (3D) " + x + "," + y + " " + width + "x" + height);
+ }
+
+ @Override
+ public void drawImage(final Image image, final int x, final int y) {
+ indent();
+ buffer.appendln("Icon " + x + "," + y + " " + image.getWidth() + "x" + image.getHeight());
+ }
+
+ @Override
+ public void drawImage(final Image image, final int x, final int y, final int width, final int height) {
+ indent();
+ buffer.appendln("Icon " + x + "," + y + " " + width + "x" + height);
+ }
+
+ @Override
+ public void drawLine(final int x, final int y, final int x2, final int y2, final Color color) {
+ indent();
+ buffer.appendln("Line from " + x + "," + y + " to " + x2 + "," + y2 + " " + color);
+ }
+
+ @Override
+ public void drawLine(final Location start, final int xExtent, final int yExtent, final Color color) {
+ indent();
+ buffer.appendln("Line from " + start.getX() + "," + start.getY() + " to " + (start.getX() + xExtent) + "," + (start.getY() + yExtent) + " " + color);
+ }
+
+ @Override
+ public void drawOval(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ buffer.appendln("Oval " + x + "," + y + " " + width + "x" + height + " " + color);
+ }
+
+ @Override
+ public void drawRectangle(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ buffer.appendln("Rectangle " + x + "," + y + " " + width + "x" + height + " " + color);
+ }
+
+ @Override
+ public void drawRectangleAround(final Bounds bounds, final Color color) {
+ indent();
+ buffer.appendln("Rectangle 0,0 " + bounds.getWidth() + "x" + bounds.getHeight() + " " + color);
+ }
+
+ @Override
+ public void drawRoundedRectangle(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight, final Color color) {
+ indent();
+ buffer.appendln("Rounded Rectangle " + x + "," + y + " " + (x + width) + "x" + (y + height) + " " + color);
+ }
+
+ @Override
+ public void drawShape(final Shape shape, final Color color) {
+ indent();
+ buffer.appendln("Shape " + shape + " " + color);
+ }
+
+ @Override
+ public void drawShape(final Shape shape, final int x, final int y, final Color color) {
+ indent();
+ buffer.appendln("Shape " + shape + " at " + x + "/" + y + " (left, top)" + " " + color);
+ }
+
+ @Override
+ public void drawSolidOval(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ buffer.appendln("Oval (solid) " + x + "," + y + " " + width + "x" + height + " " + color);
+ }
+
+ @Override
+ public void drawSolidRectangle(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ buffer.appendln("Rectangle (solid) " + x + "," + y + " " + width + "x" + height + " " + color);
+ }
+
+ @Override
+ public void drawSolidShape(final Shape shape, final Color color) {
+ indent();
+ buffer.appendln("Shape (solid) " + shape + " " + color);
+ }
+
+ @Override
+ public void drawSolidShape(final Shape shape, final int x, final int y, final Color color) {
+ indent();
+ buffer.appendln("Shape (solid)" + shape + " at " + x + "/" + y + " (left, top)" + " " + color);
+ }
+
+ @Override
+ public void drawText(final String text, final int x, final int y, final Color color, final Text style) {
+ indent();
+ buffer.appendln("Text " + x + "," + y + " \"" + text + "\" " + style + " " + color);
+ }
+
+ @Override
+ public void drawText(final String text, final int x, final int y, final int maxWidth, final Color color, final Text style) {
+ indent();
+ buffer.appendln("Text " + x + "," + y + " +" + maxWidth + "xh \"" + text + "\" " + style + " " + color);
+ }
+
+ private void indent() {
+ // buffer.append("\n");
+ for (int i = 0; i < level; i++) {
+ buffer.append(" ");
+ }
+ }
+
+ @Override
+ public void offset(final int x, final int y) {
+ indent();
+ buffer.appendln("Offset by " + x + "/" + y + " (left, top)");
+ }
+
+ @Override
+ public boolean overlaps(final Bounds bounds) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Canvas";
+ }
+
+ @Override
+ public void drawDebugOutline(final Bounds bounds, final int baseline, final Color color) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvasAbsolute.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvasAbsolute.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvasAbsolute.java
new file mode 100644
index 0000000..e9fba46
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DebugCanvasAbsolute.java
@@ -0,0 +1,257 @@
+/*
+ * 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.drawing;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.StringTokenizer;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+
+public class DebugCanvasAbsolute implements Canvas {
+ private final DebugBuilder buffer;
+ private final int level;
+ private int offsetX;
+ private int offsetY;
+
+ public DebugCanvasAbsolute(final DebugBuilder buffer, final Bounds bounds) {
+ this(buffer, 0, bounds.getX(), bounds.getY());
+ }
+
+ private DebugCanvasAbsolute(final DebugBuilder buffer, final int level, final int x, final int y) {
+ this.level = level;
+ this.buffer = buffer;
+ offsetX = x;
+ offsetY = y;
+ }
+
+ @Override
+ public Canvas createSubcanvas() {
+ buffer.blankLine();
+ indent();
+ buffer.appendln("Create subcanvas for same area");
+ return new DebugCanvasAbsolute(buffer, level + 1, offsetX, offsetY);
+ }
+
+ @Override
+ public Canvas createSubcanvas(final Bounds bounds) {
+ return createSubcanvas(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+ }
+
+ @Override
+ public Canvas createSubcanvas(final int x, final int y, final int width, final int height) {
+ // buffer.blankLine();
+ indent();
+ final int dx = offsetX + x;
+ final int qx = dx + width - 1;
+ final int dy = offsetY + y;
+ final int qy = dy + height - 1;
+ buffer.appendln("Canvas " + dx + "," + dy + " " + width + "x" + height + " (" + qx + "," + qy + ") " + line());
+ // buffer.appendln(line());
+ return new DebugCanvasAbsolute(buffer, level + 1, dx, dy);
+ }
+
+ @Override
+ public void draw3DRectangle(final int x, final int y, final int width, final int height, final Color color, final boolean raised) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+ buffer.appendln("Rectangle (3D) " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + line());
+ }
+
+ @Override
+ public void drawImage(final Image image, final int x, final int y) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + image.getWidth() - 1;
+ final int qy = py + image.getHeight() - 1;
+ buffer.appendln("Icon " + px + "," + py + " " + image.getWidth() + "x" + image.getHeight() + " (" + qx + "," + qy + ") " + line());
+ }
+
+ @Override
+ public void drawImage(final Image image, final int x, final int y, final int width, final int height) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+ buffer.appendln("Icon " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + line());
+ }
+
+ @Override
+ public void drawLine(final int x, final int y, final int x2, final int y2, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = offsetX + x2;
+ final int qy = offsetY + y2;
+ buffer.appendln("Line from " + px + "," + py + " to " + qx + "," + qy + " " + color + line());
+ }
+
+ @Override
+ public void drawLine(final Location start, final int xExtent, final int yExtent, final Color color) {
+ indent();
+ buffer.appendln("Line from " + start.getX() + "," + start.getY() + " to " + (start.getX() + xExtent) + "," + (start.getY() + yExtent) + " " + color + line());
+ }
+
+ @Override
+ public void drawOval(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ buffer.appendln("Oval " + px + "," + py + " " + width + "x" + height + " " + color + line());
+ }
+
+ @Override
+ public void drawRectangle(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+
+ buffer.appendln("Rectangle " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + color + line());
+ }
+
+ private String line() {
+ final RuntimeException e = new RuntimeException();
+ StringWriter s;
+ final PrintWriter p = new PrintWriter(s = new StringWriter());
+ e.printStackTrace(p);
+ final StringTokenizer st = new StringTokenizer(s.toString(), "\n\r");
+ st.nextElement();
+ st.nextElement();
+ st.nextElement();
+ final String line = st.nextToken();
+ return line.substring(line.indexOf('('));
+ }
+
+ @Override
+ public void drawRectangleAround(final Bounds bounds, final Color color) {
+ indent();
+ buffer.appendln("Rectangle 0,0 " + bounds.getWidth() + "x" + bounds.getHeight() + " " + color + line());
+ }
+
+ @Override
+ public void drawRoundedRectangle(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+ buffer.appendln("Rounded Rectangle " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + color + line());
+ }
+
+ @Override
+ public void drawShape(final Shape shape, final Color color) {
+ indent();
+ buffer.appendln("Shape " + shape + " " + color);
+ }
+
+ @Override
+ public void drawShape(final Shape shape, final int x, final int y, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ buffer.appendln("Shape " + shape + " at " + px + "," + py + " (left, top)" + " " + color + line());
+ }
+
+ @Override
+ public void drawSolidOval(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+ buffer.appendln("Oval (solid) " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + color + line());
+ }
+
+ @Override
+ public void drawSolidRectangle(final int x, final int y, final int width, final int height, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ final int qx = px + width - 1;
+ final int qy = py + height - 1;
+ buffer.appendln("Rectangle (solid) " + px + "," + py + " " + width + "x" + height + " (" + qx + "," + qy + ") " + color + line());
+ }
+
+ @Override
+ public void drawSolidShape(final Shape shape, final Color color) {
+ indent();
+ buffer.appendln("Shape (solid) " + shape + " " + color);
+ }
+
+ @Override
+ public void drawSolidShape(final Shape shape, final int x, final int y, final Color color) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ buffer.appendln("Shape (solid)" + shape + " at " + px + "," + py + " (left, top)" + " " + color + line());
+ }
+
+ @Override
+ public void drawText(final String text, final int x, final int y, final Color color, final Text style) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ buffer.appendln("Text " + px + "," + py + " \"" + text + "\" " + color + line());
+ }
+
+ @Override
+ public void drawText(final String text, final int x, final int y, final int maxWidth, final Color color, final Text style) {
+ indent();
+ final int px = offsetX + x;
+ final int py = offsetY + y;
+ buffer.appendln("Text " + px + "," + py + " +" + maxWidth + "xh \"" + text + "\" " + color + line());
+ }
+
+ private void indent() {
+ for (int i = 0; i < level; i++) {
+ buffer.append(" ");
+ }
+ }
+
+ @Override
+ public void offset(final int x, final int y) {
+ // indent();
+ offsetX += x;
+ offsetY += y;
+ // buffer.appendln("Offset by " + x + "/" + y + " (left, top)");
+ }
+
+ @Override
+ public boolean overlaps(final Bounds bounds) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Canvas";
+ }
+
+ @Override
+ public void drawDebugOutline(final Bounds bounds, final int baseline, final Color color) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DrawingUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DrawingUtil.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DrawingUtil.java
new file mode 100644
index 0000000..69e1b48
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/DrawingUtil.java
@@ -0,0 +1,40 @@
+/*
+ * 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.drawing;
+
+public class DrawingUtil {
+ public static void drawHatching(final Canvas canvas, final int x, final int y, final int width, final int height, final Color foreground, final Color shadow) {
+ final int bottom = y + height;
+ for (int p = y; p < bottom; p += 4) {
+ drawDots(canvas, x, p, width, foreground, shadow);
+ if (p + 2 < bottom) {
+ drawDots(canvas, x + 2, p + 2, width - 2, foreground, shadow);
+ }
+ }
+ }
+
+ private static void drawDots(final Canvas canvas, final int x, final int y, final int width, final Color foreground, final Color shadow) {
+ final int x2 = x + width;
+ for (int p = x; p < x2; p += 4) {
+ canvas.drawLine(p, y, p, y, shadow);
+ canvas.drawLine(p + 1, y + 1, p + 1, y + 1, foreground);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Image.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Image.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Image.java
new file mode 100644
index 0000000..33d25f2
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Image.java
@@ -0,0 +1,28 @@
+/*
+ * 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.drawing;
+
+public interface Image {
+ int getHeight();
+
+ int getWidth();
+
+ Size getSize();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ImageFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ImageFactory.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ImageFactory.java
new file mode 100644
index 0000000..83440fd
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/ImageFactory.java
@@ -0,0 +1,179 @@
+/*
+ * 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.drawing;
+
+/*
+ import java.awt.Toolkit;
+ import java.awt.image.FilteredImageSource;
+ import java.awt.image.RGBImageFilter;
+ */
+import java.util.Hashtable;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.util.Properties;
+
+public abstract class ImageFactory {
+ private static final String DEFAULT_IMAGE_NAME = "Default";
+ private static final String DEFAULT_IMAGE_PROPERTY = Properties.PROPERTY_BASE + "default-image";
+ private static ImageFactory instance;
+ private static final String SEPARATOR = "_";
+
+ public static ImageFactory getInstance() {
+ if (instance == null) {
+ throw new IllegalStateException("Instance not set up yet");
+ }
+ return instance;
+ }
+
+ /**
+ * Keyed list of icons (each derived from an image, of a specific size etc),
+ * where the key is the name of the icon and its size.
+ */
+ private final Hashtable<String, Image> templateImages = new Hashtable<String, Image>();
+
+ // ////////////////////////////////////////////////////////////////////
+ // Constructor
+ // ////////////////////////////////////////////////////////////////////
+
+ public ImageFactory() {
+ instance = this;
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // loadIcon for Specifications
+ // ////////////////////////////////////////////////////////////////////
+
+ public Image loadIcon(final ObjectSpecification specification, final int iconHeight, final Color tint) {
+ return findIcon(specification, iconHeight, null);
+ }
+
+ private Image findIcon(final ObjectSpecification specification, final int iconHeight, final Color tint) {
+ Image loadIcon = null;
+ if (loadIcon == null) {
+ final String fullClassNameSlashes = specification.getFullIdentifier().replace(".", "/");
+ loadIcon = loadIcon(fullClassNameSlashes, iconHeight, tint);
+ }
+ if (loadIcon == null) {
+ final String fullClassNameUnderscores = specification.getFullIdentifier().replace('.', '_');
+ loadIcon = loadIcon(fullClassNameUnderscores, iconHeight, tint);
+ }
+ if (loadIcon == null) {
+ final String shortClassNameUnderscores = specification.getShortIdentifier().replace('.', '_');
+ loadIcon = loadIcon(shortClassNameUnderscores, iconHeight, tint);
+ }
+ if (loadIcon == null) {
+ loadIcon = findIconForSuperClass(specification, iconHeight, tint);
+ }
+ if (loadIcon == null) {
+ loadIcon = findIconForInterfaces(specification, iconHeight, tint);
+ }
+ return loadIcon;
+ }
+
+ private Image findIconForSuperClass(final ObjectSpecification specification, final int iconHeight, final Color tint) {
+ final ObjectSpecification superclassSpecification = specification.superclass();
+ Image loadIcon;
+ if (superclassSpecification == null) {
+ loadIcon = null;
+ } else {
+ loadIcon = findIcon(superclassSpecification, iconHeight, tint);
+ }
+ return loadIcon;
+ }
+
+ private Image findIconForInterfaces(final ObjectSpecification specification, final int iconHeight, final Color tint) {
+ Image loadIcon = null;
+ for (final ObjectSpecification interfaceSpecification : specification.interfaces()) {
+ loadIcon = findIcon(interfaceSpecification, iconHeight, tint);
+ if (loadIcon != null) {
+ return loadIcon;
+ }
+ }
+ return loadIcon;
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // loadIcon for arbitrary path
+ // ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Loads an icon of the specified size, and with the specified tint. If
+ * color is null then no tint is applied.
+ */
+ public Image loadIcon(final String name, final int height, final Color tint) {
+ final String id = name + SEPARATOR + height + SEPARATOR + tint;
+
+ if (templateImages.containsKey(id)) {
+ return templateImages.get(id);
+ }
+ final Image icon = loadImage(name, height, tint);
+ if (icon != null) {
+ templateImages.put(id, icon);
+ }
+ return icon;
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // loadDefaultIcon
+ // ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Loads the fall back icon image, for use when no specific image can be
+ * found
+ */
+ public Image loadDefaultIcon(final int height, final Color tint) {
+ final String fallbackImage = getConfiguration().getString(DEFAULT_IMAGE_PROPERTY, DEFAULT_IMAGE_NAME);
+ Image icon = loadIcon(fallbackImage, height, tint);
+ if (icon == null) {
+ icon = loadIcon("unknown", height, tint);
+ }
+ if (icon == null) {
+ throw new IsisException("Failed to find default icon: " + fallbackImage);
+ }
+ return icon;
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // loadImage
+ // ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Load an image with the given name.
+ */
+ public abstract Image loadImage(final String path);
+
+ /**
+ * Load an image with the given name, but of a specific height and of a
+ * specific hint.
+ */
+ protected abstract Image loadImage(final String name, final int height, final Color tint);
+
+ // ////////////////////////////////////////////////////////////////////
+ // Dependencies (from singleton)
+ // ////////////////////////////////////////////////////////////////////
+
+ private IsisConfiguration getConfiguration() {
+ return IsisContext.getConfiguration();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Location.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Location.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Location.java
new file mode 100644
index 0000000..c3e1bd6
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Location.java
@@ -0,0 +1,113 @@
+/*
+ * 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.drawing;
+
+public class Location {
+ int x;
+ int y;
+
+ public Location() {
+ x = 0;
+ y = 0;
+ }
+
+ public Location(final int x, final int y) {
+ super();
+ this.x = x;
+ this.y = y;
+ }
+
+ public Location(final Location location) {
+ x = location.x;
+ y = location.y;
+ }
+
+ public void add(final int x, final int y) {
+ move(x, y);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Location) {
+ final Location object = (Location) obj;
+
+ return object.x == this.x && object.y == this.y;
+ }
+
+ return false;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public void move(final int dx, final int dy) {
+ x += dx;
+ y += dy;
+ }
+
+ public Offset offsetFrom(final Location location) {
+
+ Offset offset;
+ offset = new Offset(x - location.x, y - location.y);
+ return offset;
+ }
+
+ public void setX(final int x) {
+ this.x = x;
+ }
+
+ public void setY(final int y) {
+ this.y = y;
+ }
+
+ public void subtract(final int x, final int y) {
+ move(-x, -y);
+ }
+
+ public void subtract(final Location location) {
+ move(-location.x, -location.y);
+ }
+
+ public void subtract(final Offset offset) {
+ move(-offset.getDeltaX(), -offset.getDeltaY());
+ }
+
+ @Override
+ public String toString() {
+ return x + "," + y;
+ }
+
+ public void translate(final Location offset) {
+ move(offset.x, offset.y);
+ }
+
+ public void translate(final Offset offset) {
+ move(offset.getDeltaX(), offset.getDeltaY());
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Offset.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Offset.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Offset.java
new file mode 100644
index 0000000..d36852d
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Offset.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.drawing;
+
+public class Offset {
+
+ private int dx;
+ private int dy;
+
+ public Offset(final Location locationInViewer, final Location locationInView) {
+ dx = locationInViewer.getX() - locationInView.getX();
+ dy = locationInViewer.getY() - locationInView.getY();
+ }
+
+ public Offset(final int dx, final int dy) {
+ this.dx = dx;
+ this.dy = dy;
+ }
+
+ public Offset(final Location location) {
+ this.dx = location.getX();
+ this.dy = location.getY();
+ }
+
+ public int getDeltaX() {
+ return dx;
+ }
+
+ public int getDeltaY() {
+ return dy;
+ }
+
+ public Location offset(final Location locationInViewer) {
+ final Location location = new Location(locationInViewer);
+ location.move(dx, dy);
+ return location;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Offset) {
+ Offset offset;
+ offset = (Offset) obj;
+ return offset.dx == dx && offset.dy == dy;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Offset " + dx + ", " + dy;
+ }
+
+ public void add(final int dx, final int dy) {
+ this.dx += dx;
+ this.dy += dy;
+ }
+
+ public void subtract(final int dx, final int dy) {
+ add(-dx, -dy);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Padding.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Padding.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Padding.java
new file mode 100644
index 0000000..e5f346d
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/drawing/Padding.java
@@ -0,0 +1,136 @@
+/*
+ * 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.drawing;
+
+public class Padding {
+ int bottom;
+ int left;
+ int right;
+ int top;
+
+ public Padding(final int top, final int left, final int bottom, final int right) {
+ this.top = top;
+ this.bottom = bottom;
+ this.left = left;
+ this.right = right;
+ }
+
+ public Padding() {
+ top = 0;
+ bottom = 0;
+ left = 0;
+ right = 0;
+ }
+
+ public Padding(final Padding padding) {
+ this.top = padding.top;
+ this.bottom = padding.bottom;
+ this.left = padding.left;
+ this.right = padding.right;
+ }
+
+ public void setBottom(final int bottom) {
+ this.bottom = bottom;
+ }
+
+ public int getBottom() {
+ return bottom;
+ }
+
+ public void setLeft(final int left) {
+ this.left = left;
+ }
+
+ public int getLeft() {
+ return left;
+ }
+
+ public int getLeftRight() {
+ return left + right;
+ }
+
+ public void setRight(final int right) {
+ this.right = right;
+ }
+
+ public int getRight() {
+ return right;
+ }
+
+ public void setTop(final int top) {
+ this.top = top;
+ }
+
+ public int getTop() {
+ return top;
+ }
+
+ public int getTopBottom() {
+ return top + bottom;
+ }
+
+ /**
+ * Extend the padding on the bottom by the specified amount.
+ */
+ public void extendBottom(final int pad) {
+ bottom += pad;
+ }
+
+ /**
+ * Extend the padding on the left by the specified amount.
+ */
+ public void extendLeft(final int pad) {
+ left += pad;
+ }
+
+ /**
+ * Extend the padding on the right by the specified amount.
+ */
+ public void extendRight(final int pad) {
+ right += pad;
+ }
+
+ /**
+ * Extend the padding on the top by the specified amount.
+ */
+ public void extendTop(final int pad) {
+ top += pad;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Padding) {
+ final Padding object = (Padding) obj;
+
+ return object.top == this.top && object.bottom == this.bottom && object.left == this.left && object.right == this.right;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Padding [top=" + top + ",bottom=" + bottom + ",left=" + left + ",right=" + right + "]";
+ }
+}