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:02 UTC
[29/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/window/WindowControl.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/window/WindowControl.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/window/WindowControl.java
new file mode 100644
index 0000000..4cb42ff
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/window/WindowControl.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.view.window;
+
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.view.UserAction;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.control.AbstractControlView;
+
+public abstract class WindowControl extends AbstractControlView {
+ public final static int HEIGHT = 13;
+ public final static int WIDTH = HEIGHT + 2;
+
+ protected WindowControl(final UserAction action, final View target) {
+ super(action, target);
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ 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/viewer/ApplicationOptions.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/ApplicationOptions.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/ApplicationOptions.java
new file mode 100644
index 0000000..6b92684
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/ApplicationOptions.java
@@ -0,0 +1,83 @@
+/*
+ * 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.viewer;
+
+import org.apache.isis.core.metamodel.consent.Allow;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.help.AboutView;
+import org.apache.isis.viewer.dnd.view.MenuOptions;
+import org.apache.isis.viewer.dnd.view.Placement;
+import org.apache.isis.viewer.dnd.view.ShutdownListener;
+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.option.UserActionAbstract;
+
+public class ApplicationOptions implements MenuOptions {
+ private final ShutdownListener listener;
+
+ public ApplicationOptions(final ShutdownListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void menuOptions(final UserActionSet options) {
+ options.add(new UserActionAbstract("About...") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final AboutView dialogView = new AboutView();
+ final Size windowSize = dialogView.getRequiredSize(new Size());
+ final Size workspaceSize = workspace.getSize();
+ final int x = workspaceSize.getWidth() / 2 - windowSize.getWidth() / 2;
+ final int y = workspaceSize.getHeight() / 2 - windowSize.getHeight() / 2;
+ workspace.addDialog(dialogView, new Placement(new Location(x, y)));
+ }
+ });
+
+ options.add(new UserActionAbstract("Log out") {
+ @Override
+ public Consent disabled(final View view) {
+ final boolean runningAsExploration = view.getViewManager().isRunningAsExploration();
+ if (runningAsExploration) {
+ // TODO: move logic to Facet
+ return new Veto("Can't log out in exploration mode");
+ } else {
+ return Allow.DEFAULT;
+ }
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ listener.logOut();
+ }
+ });
+
+ options.add(new UserActionAbstract("Quit") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ listener.quit();
+ }
+ });
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/DefaultContentFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/DefaultContentFactory.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/DefaultContentFactory.java
new file mode 100644
index 0000000..7a35fb2
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/DefaultContentFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.viewer;
+
+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.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.ContentFactory;
+import org.apache.isis.viewer.dnd.view.collection.RootCollection;
+import org.apache.isis.viewer.dnd.view.content.RootObject;
+import org.apache.isis.viewer.dnd.view.field.OneToManyFieldImpl;
+import org.apache.isis.viewer.dnd.view.field.OneToOneFieldImpl;
+import org.apache.isis.viewer.dnd.view.field.TextParseableFieldImpl;
+
+public class DefaultContentFactory implements ContentFactory {
+
+ @Override
+ public Content createRootContent(final ObjectAdapter object) {
+ Assert.assertNotNull(object);
+ final ObjectSpecification objectSpec = object.getSpecification();
+ if (objectSpec.isParentedOrFreeCollection()) {
+ return new RootCollection(object);
+ }
+ if (objectSpec.isNotCollection()) {
+ return new RootObject(object);
+ }
+
+ throw new IllegalArgumentException("Must be an object or collection: " + object);
+ }
+
+ @Override
+ public Content createFieldContent(final ObjectAssociation field, final ObjectAdapter object) {
+ Content content;
+ final ObjectAdapter associatedObject = field.get(object);
+ if (field instanceof OneToManyAssociation) {
+ content = new OneToManyFieldImpl(object, associatedObject, (OneToManyAssociation) field);
+ } else if (field instanceof OneToOneAssociation) {
+ final ObjectSpecification fieldSpecification = field.getSpecification();
+ if (fieldSpecification.isParseable()) {
+ content = new TextParseableFieldImpl(object, associatedObject, (OneToOneAssociation) field);
+ } else {
+ content = new OneToOneFieldImpl(object, associatedObject, (OneToOneAssociation) field);
+ }
+ } else {
+ throw new IsisException();
+ }
+
+ return content;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/SkylarkViewFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/SkylarkViewFactory.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/SkylarkViewFactory.java
new file mode 100644
index 0000000..286360f
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/SkylarkViewFactory.java
@@ -0,0 +1,286 @@
+/*
+ * 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.viewer;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.runtime.userprofile.Options;
+import org.apache.isis.viewer.dnd.dialog.ActionDialogSpecification;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.interaction.ContentDragImpl;
+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.DragEvent;
+import org.apache.isis.viewer.dnd.view.GlobalViewFactory;
+import org.apache.isis.viewer.dnd.view.ObjectContent;
+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.base.DragViewOutline;
+import org.apache.isis.viewer.dnd.view.border.DisposedObjectBorder;
+import org.apache.isis.viewer.dnd.view.collection.CollectionContent;
+import org.apache.isis.viewer.dnd.viewer.basic.FallbackView;
+import org.apache.isis.viewer.dnd.viewer.basic.MinimizedView;
+
+/**
+ * This class holds all the different view types that all the different objects
+ * can be viewed as.
+ */
+public class SkylarkViewFactory implements GlobalViewFactory {
+ private static final ViewSpecification fallback = new FallbackView.Specification();
+ private final ViewSpecification dialogSpec = new ActionDialogSpecification();
+ public static final int INTERNAL = 2;
+ private static final Logger LOG = Logger.getLogger(SkylarkViewFactory.class);
+ public static final int WINDOW = 1;
+
+ private ViewSpecification emptyFieldSpecification;
+ private final Vector rootViews = new Vector();
+ private final Vector subviews = new Vector();
+ private ViewSpecification dragContentSpecification;
+
+ private final List<ViewSpecification> viewSpecifications = new ArrayList<ViewSpecification>();
+ private final List<ViewSpecification> designSpecifications = new ArrayList<ViewSpecification>();
+
+ @Override
+ public void addSpecification(final ViewSpecification specification) {
+ viewSpecifications.add(specification);
+ }
+
+ public void addSpecification(final String specClassName) {
+ ViewSpecification spec;
+ spec = (ViewSpecification) InstanceUtil.createInstance(specClassName);
+ LOG.info("adding view specification: " + spec);
+ addSpecification(spec);
+ }
+
+ public void addDesignSpecification(final ViewSpecification specification) {
+ designSpecifications.add(specification);
+ }
+
+ public void addEmptyFieldSpecification(final ViewSpecification spec) {
+ emptyFieldSpecification = spec;
+ }
+
+ @Override
+ public View createDialog(final Content content) {
+ return createView(dialogSpec, content);
+ }
+
+ private View createView(final ViewSpecification specification, final Content content) {
+ ViewSpecification spec;
+ if (specification == null) {
+ LOG.warn("no suitable view for " + content + " using fallback view");
+ spec = new FallbackView.Specification();
+ } else {
+ spec = specification;
+ }
+ // TODO this should be passed in so that factory created views can be
+ // related to the views that ask
+ // for them
+ final Axes axes = new Axes();
+ View createView = spec.createView(content, axes, -1);
+
+ /*
+ * ObjectSpecification contentSpecification =
+ * content.getSpecification(); if (contentSpecification != null) {
+ * Options viewOptions = Properties.getViewConfigurationOptions(spec);
+ * createView.loadOptions(viewOptions); }
+ */
+ if (content.isObject()) {
+ final ObjectAdapter adapter = content.getAdapter();
+ if (adapter != null && adapter.isDestroyed()) {
+ createView = new DisposedObjectBorder(createView);
+ }
+ }
+ createView.getSubviews();
+ return createView;
+ }
+
+ @Override
+ public void debugData(final DebugBuilder sb) {
+ sb.append("RootsViews\n");
+ Enumeration fields = rootViews.elements();
+ while (fields.hasMoreElements()) {
+ final ViewSpecification spec = (ViewSpecification) fields.nextElement();
+ sb.append(" ");
+ sb.append(spec);
+ sb.append("\n");
+ }
+ sb.append("\n\n");
+
+ sb.append("Subviews\n");
+ fields = subviews.elements();
+ while (fields.hasMoreElements()) {
+ final ViewSpecification spec = (ViewSpecification) fields.nextElement();
+ sb.append(" ");
+ sb.append(spec);
+ sb.append("\n");
+ }
+ sb.append("\n\n");
+
+ sb.append("Specifications\n");
+ for (final ViewSpecification spec : viewSpecifications) {
+ sb.append(" ");
+ sb.append(spec);
+ sb.append("\n");
+ }
+ sb.append("\n\n");
+ }
+
+ @Override
+ public String debugTitle() {
+ return "View factory entries";
+ }
+
+ private ViewSpecification getEmptyFieldSpecification() {
+ if (emptyFieldSpecification == null) {
+ LOG.error("missing empty field specification; using fallback");
+ return fallback;
+ }
+ return emptyFieldSpecification;
+ }
+
+ public void setDragContentSpecification(final ViewSpecification dragContentSpecification) {
+ this.dragContentSpecification = dragContentSpecification;
+ }
+
+ @Override
+ public View createDragViewOutline(final View view) {
+ return new DragViewOutline(view);
+ }
+
+ @Override
+ public DragEvent createDragContentOutline(final View view, final Location location) {
+ final View dragOverlay = dragContentSpecification.createView(view.getContent(), new Axes(), -1);
+ return new ContentDragImpl(view, location, dragOverlay);
+ }
+
+ @Override
+ public View createMinimizedView(final View view) {
+ return new MinimizedView(view);
+ }
+
+ @Override
+ public View createView(final ViewRequirement requirement) {
+ final ViewSpecification objectFieldSpecification = getSpecificationForRequirement(requirement);
+ return createView(objectFieldSpecification, requirement.getContent());
+ }
+
+ public ViewSpecification getSpecificationForRequirement(final ViewRequirement requirement) {
+ final Content content = requirement.getContent();
+ final ObjectSpecification specification = content.getSpecification();
+ final boolean isValue = specification != null && specification.containsFacet(ValueFacet.class);
+ if (content.isObject() && !isValue && content.getAdapter() == null) {
+ return getEmptyFieldSpecification();
+ } else {
+ if (specification != null) {
+ final Options viewOptions = Properties.getDefaultViewOptions(specification);
+ String spec = viewOptions.getString("spec");
+ if (spec == null) {
+ if (content instanceof ObjectContent && requirement.isObject() && requirement.isClosed()) {
+ spec = Properties.getDefaultIconViewOptions();
+ } else if (content instanceof CollectionContent && requirement.isCollection()) {
+ spec = Properties.getDefaultCollectionViewOptions();
+ } else if (content instanceof ObjectContent && requirement.isObject() && requirement.isOpen()) {
+ spec = Properties.getDefaultObjectViewOptions();
+ }
+ }
+ if (spec != null) {
+ final ViewSpecification lookSpec = lookupSpecByName(spec);
+ if (lookSpec != null && lookSpec.canDisplay(requirement)) {
+ return lookSpec;
+ }
+ }
+ }
+ for (final ViewSpecification viewSpecification : viewSpecifications) {
+ if (viewSpecification.canDisplay(requirement)) {
+ return viewSpecification;
+ }
+
+ }
+ LOG.error("missing specification; using fall back");
+ return fallback;
+ }
+ }
+
+ public void loadUserViewSpecifications() {
+ final Options options = Properties.getOptions("views.user-defined");
+ final Iterator<String> names = options.names();
+ while (names.hasNext()) {
+ final String name = names.next();
+ final Options viewOptions = options.getOptions(name);
+ final String specName = viewOptions.getString("design");
+ addSpecification(specName);
+ }
+ }
+
+ private ViewSpecification lookupSpecByName(final String name) {
+ for (final ViewSpecification viewSpecification : viewSpecifications) {
+ if (viewSpecification.getName().equals(name)) {
+ return viewSpecification;
+ }
+ }
+ LOG.warn("No specification found for " + name);
+ return null;
+ }
+
+ private ViewSpecification lookupSpecByClassName(final String className) {
+ for (final ViewSpecification viewSpecification : viewSpecifications) {
+ if (viewSpecification.getClass().getName().equals(className)) {
+ return viewSpecification;
+ }
+ }
+ LOG.warn("No specification found for " + className);
+ return null;
+ }
+
+ @Override
+ public Enumeration<ViewSpecification> availableViews(final ViewRequirement requirement) {
+ return viewsFor(requirement, viewSpecifications);
+ }
+
+ @Override
+ public Enumeration<ViewSpecification> availableDesigns(final ViewRequirement requirement) {
+ return viewsFor(requirement, designSpecifications);
+ }
+
+ private Enumeration<ViewSpecification> viewsFor(final ViewRequirement requirement, final List<ViewSpecification> viewSpecifications) {
+ final Vector<ViewSpecification> v = new Vector<ViewSpecification>();
+ for (final ViewSpecification specification : viewSpecifications) {
+ if (specification.canDisplay(requirement)) {
+ v.addElement(specification);
+ }
+ }
+ return v.elements();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspace.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspace.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspace.java
new file mode 100644
index 0000000..7c28948
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspace.java
@@ -0,0 +1,520 @@
+/*
+ * 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.viewer.basic;
+
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.consent.Allow;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.FreeStandingList;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.runtime.userprofile.PerspectiveEntry;
+import org.apache.isis.runtimes.dflt.runtime.authentication.exploration.MultiUserExplorationSession;
+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.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Padding;
+import org.apache.isis.viewer.dnd.service.PerspectiveContent;
+import org.apache.isis.viewer.dnd.service.ServiceObject;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Click;
+import org.apache.isis.viewer.dnd.view.CompositeViewSpecification;
+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.Feedback;
+import org.apache.isis.viewer.dnd.view.Look;
+import org.apache.isis.viewer.dnd.view.ObjectContent;
+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.ViewDrag;
+import org.apache.isis.viewer.dnd.view.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.base.Layout;
+import org.apache.isis.viewer.dnd.view.composite.CompositeViewUsingBuilder;
+import org.apache.isis.viewer.dnd.view.content.FieldContent;
+import org.apache.isis.viewer.dnd.view.look.LookFactory;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+import org.apache.isis.viewer.dnd.view.window.DialogBorder;
+import org.apache.isis.viewer.dnd.view.window.SubviewFocusManager;
+import org.apache.isis.viewer.dnd.view.window.WindowBorder;
+
+public final class ApplicationWorkspace extends CompositeViewUsingBuilder implements Workspace {
+ protected Vector<View> serviceViews;
+ protected Vector<View> iconViews;
+
+ public ApplicationWorkspace(final Content content, final Axes axes, final CompositeViewSpecification specification, final Layout layout, final ApplicationWorkspaceBuilder builder) {
+ super(content, specification, axes, layout, builder);
+ serviceViews = new Vector<View>();
+ iconViews = new Vector<View>();
+ LookFactory.init();
+ }
+
+ @Override
+ public void addDialog(final View dialogContent, final Placement placement) {
+ final DialogBorder dialogView = new DialogBorder(dialogContent, false);
+ addView(dialogView);
+ placement.position(this, dialogView);
+ // dialogView.setFocusManager( new SubviewFocusManager(dialogView));
+ }
+
+ @Override
+ public void addWindow(final View containedView, final Placement placement) {
+ final boolean scrollable = !containedView.getSpecification().isResizeable();
+ final WindowBorder windowView = new WindowBorder(containedView, scrollable);
+ addView(windowView);
+ placement.position(this, windowView);
+ windowView.setFocusManager(new SubviewFocusManager(windowView));
+ }
+
+ @Override
+ public void addView(final View view) {
+ super.addView(view);
+ getViewManager().setKeyboardFocus(view);
+ view.getFocusManager().focusFirstChildView();
+ }
+
+ @Override
+ public void replaceView(final View toReplace, final View replacement) {
+ if (replacement.getSpecification().isOpen()) {
+ final boolean scrollable = !replacement.getSpecification().isResizeable();
+ final WindowBorder windowView = new WindowBorder(replacement, scrollable);
+ super.replaceView(toReplace, windowView);
+ } else {
+ super.replaceView(toReplace, replacement);
+ }
+ }
+
+ @Override
+ public View addWindowFor(final ObjectAdapter object, final Placement placement) {
+ final Content content = Toolkit.getContentFactory().createRootContent(object);
+ final View view = Toolkit.getViewFactory().createView(new ViewRequirement(content, ViewRequirement.OPEN));
+ addWindow(view, placement);
+ getViewManager().setKeyboardFocus(view);
+ return view;
+ }
+
+ @Override
+ public View addIconFor(final ObjectAdapter object, final Placement placement) {
+ final Content content = Toolkit.getContentFactory().createRootContent(object);
+ final View icon = Toolkit.getViewFactory().createView(new ViewRequirement(content, ViewRequirement.CLOSED | ViewRequirement.ROOT));
+ add(iconViews, icon);
+ placement.position(this, icon);
+ return icon;
+ }
+
+ public void addServiceIconFor(final ObjectAdapter service) {
+ final Content content = new ServiceObject(service);
+ final View serviceIcon = Toolkit.getViewFactory().createView(new ViewRequirement(content, ViewRequirement.CLOSED | ViewRequirement.SUBVIEW));
+ add(serviceViews, serviceIcon);
+ }
+
+ @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 {
+ return null;
+ }
+ }
+
+ // TODO check the dragging in of objects, flag to user that object cannot be
+ // dropped
+ @Override
+ public void drop(final ContentDrag drag) {
+ getFeedbackManager().showDefaultCursor();
+
+ if (!drag.getSourceContent().isObject()) {
+ return;
+ }
+
+ if (drag.getSourceContent().getAdapter() == getPerspective()) {
+ getFeedbackManager().setAction("can' drop self on workspace");
+ return;
+ }
+
+ final ObjectAdapter source = ((ObjectContent) drag.getSourceContent()).getObject();
+ if (source.getSpecification().isService()) {
+ getPerspective().addToServices(source.getObject());
+ invalidateContent();
+ } else {
+ if (!drag.isShift()) {
+ getPerspective().addToObjects(source.getObject());
+ }
+ }
+
+ View newView;
+ if (source.getSpecification().isService()) {
+ return;
+ } else {
+ final Location dropLocation = drag.getTargetLocation();
+ dropLocation.subtract(drag.getOffset());
+
+ if (drag.isShift()) {
+ newView = Toolkit.getViewFactory().createView(new ViewRequirement(getContent(), ViewRequirement.OPEN | ViewRequirement.SUBVIEW));
+ drag.getTargetView().addView(newView);
+ newView.setLocation(dropLocation);
+ } else {
+ // place object onto desktop as icon
+ final View sourceView = drag.getSource();
+ if (!sourceView.getSpecification().isOpen()) {
+ final View[] subviews = getSubviews();
+ for (final View subview : subviews) {
+ if (subview == sourceView) {
+ sourceView.markDamaged();
+ sourceView.setLocation(dropLocation);
+ sourceView.markDamaged();
+ return;
+ }
+ }
+ } else {
+ for (final View view : iconViews) {
+ if (view.getContent().getAdapter() == source) {
+ view.markDamaged();
+ view.setLocation(dropLocation);
+ view.markDamaged();
+ return;
+ }
+ }
+ }
+ addIconFor(source, new Placement(dropLocation));
+ }
+ }
+ }
+
+ @Override
+ public void entered() {
+ // prevents status details about "Persective..."
+ }
+
+ private PerspectiveEntry getPerspective() {
+ return ((PerspectiveContent) getContent()).getPerspective();
+ }
+
+ @Override
+ public void drop(final ViewDrag drag) {
+ getFeedbackManager().showDefaultCursor();
+
+ final View sourceView = drag.getSourceView();
+ final Location newLocation = drag.getViewDropLocation();
+ if (sourceView.getSpecification() != null && sourceView.getSpecification().isSubView()) {
+ if (sourceView.getSpecification().isOpen() && sourceView.getSpecification().isReplaceable()) {
+ // TODO remove the open view from the container and place on
+ // workspace; replace the internal view with an icon
+ } else if (sourceView.getContent() instanceof FieldContent) {
+ final ViewRequirement requirement = new ViewRequirement(sourceView.getContent(), ViewRequirement.OPEN);
+ final View view = Toolkit.getViewFactory().createView(requirement);
+ addWindow(view, new Placement(newLocation));
+ sourceView.getState().clearViewIdentified();
+ } else {
+ addWindowFor(sourceView.getContent().getAdapter(), new Placement(newLocation));
+ sourceView.getState().clearViewIdentified();
+ }
+ } else {
+ sourceView.markDamaged();
+ sourceView.setLocation(newLocation);
+ sourceView.limitBoundsWithin(getSize());
+ sourceView.markDamaged();
+ }
+ }
+
+ @Override
+ public Padding getPadding() {
+ return new Padding();
+ }
+
+ @Override
+ public Workspace getWorkspace() {
+ return this;
+ }
+
+ @Override
+ public void lower(final View view) {
+ if (views.contains(view)) {
+ views.removeElement(view);
+ views.insertElementAt(view, 0);
+ markDamaged();
+ }
+ }
+
+ @Override
+ public void raise(final View view) {
+ if (views.contains(view)) {
+ views.removeElement(view);
+ views.addElement(view);
+ markDamaged();
+ }
+ }
+
+ @Override
+ public void removeView(final View view) {
+ view.markDamaged();
+ if (iconViews.contains(view)) {
+ iconViews.remove(view);
+ getViewManager().removeFromNotificationList(view);
+ removeObject(view.getContent().getAdapter());
+ } else if (serviceViews.contains(view)) {
+ serviceViews.remove(view);
+ getViewManager().removeFromNotificationList(view);
+ removeService(view.getContent().getAdapter());
+ } else {
+ super.removeView(view);
+ }
+ }
+
+ private void removeService(final ObjectAdapter object) {
+ getPerspective().removeFromServices(object.getObject());
+ }
+
+ private void removeObject(final ObjectAdapter object) {
+ getPerspective().removeFromObjects(object.getObject());
+ }
+
+ @Override
+ public void secondClick(final Click click) {
+ final View subview = subviewFor(click.getLocation());
+ if (subview != null) {
+ // ignore double-click on self - don't open up new view
+ super.secondClick(click);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Workspace" + getId();
+ }
+
+ @Override
+ public void viewMenuOptions(final UserActionSet options) {
+ options.setColor(Toolkit.getColor(ColorsAndFonts.COLOR_MENU_WORKSPACE));
+
+ options.add(new UserActionAbstract("Close all") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final View views[] = getWindowViews();
+ for (final View v : views) {
+ // if (v.getSpecification().isOpen()) {
+ v.dispose();
+ // }
+ }
+ markDamaged();
+ }
+ });
+
+ options.add(new UserActionAbstract("Tidy up windows") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ tidyViews(getWindowViews());
+ }
+ });
+
+ options.add(new UserActionAbstract("Tidy up icons") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ tidyViews(getObjectIconViews());
+ }
+ });
+
+ options.add(new UserActionAbstract("Tidy up all") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ tidyViews(getObjectIconViews());
+ tidyViews(getWindowViews());
+ }
+ });
+
+ options.add(new UserActionAbstract("Services...") {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final List<Object> servicePojos = IsisContext.getServices();
+ final List<ObjectAdapter> serviceAdapters = Lists.newArrayList();
+ for (final Object servicePojo : servicePojos) {
+ final AdapterManager adapterManager = getPersistenceSession().getAdapterManager();
+ serviceAdapters.add(adapterManager.adapterFor(servicePojo));
+ }
+ final ObjectSpecification spec = getSpecificationLoader().loadSpecification(Object.class);
+ final FreeStandingList collection = new FreeStandingList(spec, serviceAdapters);
+ addWindowFor(getAdapterManager().adapterFor(collection), new Placement(at));
+ }
+
+ });
+
+ menuForChangingLook(options);
+
+ menuForChangingUsers(options);
+
+ options.add(new UserActionAbstract("Save User Profile", ActionType.USER) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final Feedback feedbackManager = getFeedbackManager();
+ feedbackManager.showBusyState(ApplicationWorkspace.this);
+ getViewManager().saveOpenObjects();
+ feedbackManager.addMessage("Profile saved");
+ feedbackManager.showBusyState(ApplicationWorkspace.this);
+ }
+ });
+ }
+
+ private void menuForChangingLook(final UserActionSet options) {
+ final UserActionSet set = options.addNewActionSet("Change Look", ActionType.USER);
+ for (final Look look : LookFactory.getAvailableLooks()) {
+ menuOptionForChangingLook(set, look, look.getName());
+ }
+ }
+
+ private void menuOptionForChangingLook(final UserActionSet set, final Look look, final String name) {
+ set.add(new UserActionAbstract(name) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ LookFactory.setLook(look);
+ ApplicationWorkspace.this.invalidateLayout();
+ ApplicationWorkspace.this.markDamaged();
+ }
+
+ @Override
+ public Consent disabled(final View view) {
+ return LookFactory.getInstalledLook() == look ? new Veto("Current look") : Allow.DEFAULT;
+ }
+ });
+ }
+
+ private void menuForChangingUsers(final UserActionSet options) {
+ // TODO pick out users from the perspectives, but only show when in
+ // exploration mode
+ if (getAuthenticationSession() instanceof MultiUserExplorationSession) {
+ final MultiUserExplorationSession session = (MultiUserExplorationSession) getAuthenticationSession();
+
+ final Set<String> users = session.getUserNames();
+ final UserActionSet set = options.addNewActionSet("Change user", ActionType.EXPLORATION);
+ for (final String user : users) {
+ menuOptionForChangingUser(set, user, session.getUserName());
+ }
+ }
+ }
+
+ private void menuOptionForChangingUser(final UserActionSet set, final String user, final String currentUser) {
+ set.add(new UserActionAbstract(user) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final MultiUserExplorationSession session = (MultiUserExplorationSession) getAuthenticationSession();
+ session.setCurrentSession(user);
+ }
+
+ @Override
+ public Consent disabled(final View view) {
+ return user.equals(currentUser) ? new Veto("Current user") : Allow.DEFAULT;
+ }
+ });
+ }
+
+ @Override
+ protected View[] subviews() {
+ final Object[] viewsCopy = views.toArray();
+ final Object[] serviceViewsCopy = serviceViews.toArray();
+ final Object[] iconViewsCopy = iconViews.toArray();
+
+ final View v[] = new View[viewsCopy.length + serviceViewsCopy.length + iconViewsCopy.length];
+ int offset = 0;
+ Object[] src = serviceViewsCopy;
+ System.arraycopy(src, 0, v, offset, src.length);
+ offset += src.length;
+ src = iconViewsCopy;
+ System.arraycopy(src, 0, v, offset, src.length);
+ offset += src.length;
+ src = viewsCopy;
+ System.arraycopy(src, 0, v, offset, src.length);
+
+ return v;
+ }
+
+ public void clearServiceViews() {
+ final Enumeration e = serviceViews.elements();
+ while (e.hasMoreElements()) {
+ final View view = (View) e.nextElement();
+ view.markDamaged();
+ }
+ serviceViews.clear();
+ }
+
+ protected View[] getWindowViews() {
+ return createArrayOfViews(views);
+ }
+
+ private View[] createArrayOfViews(final Vector<View> views) {
+ final View[] array = new View[views.size()];
+ views.copyInto(array);
+ return array;
+ }
+
+ protected View[] getServiceIconViews() {
+ return createArrayOfViews(serviceViews);
+ }
+
+ protected View[] getObjectIconViews() {
+ return createArrayOfViews(iconViews);
+ }
+
+ private void tidyViews(final View[] views) {
+ for (final View v : views) {
+ v.setLocation(ApplicationWorkspaceBuilder.UNPLACED);
+ }
+ invalidateLayout();
+ markDamaged();
+ }
+
+ // //////////////////////////////////////////////////////////////////
+ // Dependencies (from singleton)
+ // //////////////////////////////////////////////////////////////////
+
+ private SpecificationLoaderSpi getSpecificationLoader() {
+ return IsisContext.getSpecificationLoader();
+ }
+
+ private PersistenceSession getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+ private AdapterManager getAdapterManager() {
+ return getPersistenceSession().getAdapterManager();
+ }
+
+ private AuthenticationSession getAuthenticationSession() {
+ return IsisContext.getAuthenticationSession();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspaceBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspaceBuilder.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspaceBuilder.java
new file mode 100644
index 0000000..c74983a
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/ApplicationWorkspaceBuilder.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.viewer.basic;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.runtime.userprofile.PerspectiveEntry;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.service.PerspectiveContent;
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Placement;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.Layout;
+import org.apache.isis.viewer.dnd.view.composite.AbstractViewBuilder;
+
+/**
+ * WorkspaceBuilder builds a workspace view for an ObjectContent view by finding
+ * a collection of classes from a field called 'classes' and adding an icon for
+ * each element. Similarly, if there is a collection called 'objects' its
+ * elements are also added to the display.
+ *
+ * <p>
+ * During lay-out any icons that have an UNPLACED location (-1, -1) are given a
+ * location. Objects of type ObjectSpecification are added to the left-hand
+ * side, while all other icons are placed on the right-hand side of the
+ * workspace view. Open windows are displayed in the centre.
+ */
+public class ApplicationWorkspaceBuilder extends AbstractViewBuilder {
+ private static final Logger LOG = Logger.getLogger(ApplicationWorkspaceBuilder.class);
+ private static final int PADDING = 10;
+ public static final Location UNPLACED = new Location(-1, -1);
+
+ public static class ApplicationLayout implements Layout {
+ @Override
+ public Size getRequiredSize(final View view) {
+ return new Size(600, 400);
+ }
+
+ public String getName() {
+ return "Simple Workspace";
+ }
+
+ @Override
+ public void layout(final View view1, final Size maximumSize) {
+ final ApplicationWorkspace view = (ApplicationWorkspace) view1;
+
+ final int widthUsed = layoutServiceIcons(maximumSize, view);
+ layoutObjectIcons(maximumSize, view);
+ layoutWindowViews(maximumSize, view, widthUsed);
+ }
+
+ private void layoutWindowViews(final Size maximumSize, final ApplicationWorkspace view, final int xOffset) {
+ final Size size = view.getSize();
+ size.contract(view.getPadding());
+
+ final int maxHeight = size.getHeight();
+ final int maxWidth = size.getWidth();
+
+ final int xWindow = xOffset + PADDING;
+ int yWindow = PADDING;
+
+ int xMinimized = 1;
+ int yMinimized = maxHeight - 1;
+
+ final View windows[] = view.getWindowViews();
+ for (final View v : windows) {
+ final Size componentSize = v.getRequiredSize(new Size(size));
+ v.setSize(componentSize);
+ if (v instanceof MinimizedView) {
+ final Size s = v.getRequiredSize(Size.createMax());
+ if (xMinimized + s.getWidth() > maxWidth) {
+ xMinimized = 1;
+ yMinimized -= s.getHeight() + 1;
+ }
+ v.setLocation(new Location(xMinimized, yMinimized - s.getHeight()));
+ xMinimized += s.getWidth() + 1;
+
+ } else if (v.getLocation().equals(UNPLACED)) {
+ final int height = componentSize.getHeight() + 6;
+ v.setLocation(new Location(xWindow, yWindow));
+ yWindow += height;
+
+ }
+ v.limitBoundsWithin(maximumSize);
+ }
+
+ for (final View window : windows) {
+ window.layout();
+ }
+ }
+
+ private int layoutServiceIcons(final Size maximumSize, final ApplicationWorkspace view) {
+ final Size size = view.getSize();
+ size.contract(view.getPadding());
+
+ final int maxHeight = size.getHeight();
+
+ int xService = PADDING;
+ int yService = PADDING;
+ int maxServiceWidth = 0;
+
+ final View views[] = view.getServiceIconViews();
+ for (final View v : views) {
+ final Size componentSize = v.getRequiredSize(new Size(size));
+ v.setSize(componentSize);
+ final int height = componentSize.getHeight() + 6;
+
+ final ObjectAdapter object = v.getContent().getAdapter();
+ if (object.getSpecification().isService()) {
+ if (yService + height > maxHeight) {
+ yService = PADDING;
+ xService += maxServiceWidth + PADDING;
+ maxServiceWidth = 0;
+ LOG.debug("creating new column at " + xService + ", " + yService);
+ }
+ LOG.debug("service icon at " + xService + ", " + yService);
+ v.setLocation(new Location(xService, yService));
+ maxServiceWidth = Math.max(maxServiceWidth, componentSize.getWidth());
+ yService += height;
+ }
+ v.limitBoundsWithin(maximumSize);
+ }
+
+ return xService + maxServiceWidth;
+ }
+
+ private void layoutObjectIcons(final Size maximumSize, final ApplicationWorkspace view) {
+ final Size size = view.getSize();
+ size.contract(view.getPadding());
+
+ final int maxWidth = size.getWidth();
+
+ final int xObject = maxWidth - PADDING;
+ int yObject = PADDING;
+
+ final View views[] = view.getObjectIconViews();
+ for (final View v : views) {
+ final Size componentSize = v.getRequiredSize(new Size(size));
+ v.setSize(componentSize);
+ if (v.getLocation().equals(UNPLACED)) {
+ final int height = componentSize.getHeight() + 6;
+ v.setLocation(new Location(xObject - componentSize.getWidth(), yObject));
+ yObject += height;
+ }
+ v.limitBoundsWithin(maximumSize);
+ }
+ }
+ }
+
+ @Override
+ public void build(final View view1, final Axes axes) {
+ final ApplicationWorkspace workspace = (ApplicationWorkspace) view1;
+
+ final PerspectiveContent perspectiveContent = (PerspectiveContent) view1.getContent();
+
+ // REVIEW is this needed?
+ workspace.clearServiceViews();
+
+ final PerspectiveEntry perspective = perspectiveContent.getPerspective();
+ for (final Object object : perspective.getObjects()) {
+ final ObjectAdapter adapter = IsisContext.getPersistenceSession().getAdapterManager().adapterFor(object);
+ workspace.addIconFor(adapter, new Placement(ApplicationWorkspaceBuilder.UNPLACED));
+ }
+
+ for (final Object service : perspective.getServices()) {
+ final ObjectAdapter adapter = IsisContext.getPersistenceSession().getAdapterManager().adapterFor(service);
+ if (isHidden(adapter)) {
+ continue;
+ }
+ workspace.addServiceIconFor(adapter);
+ }
+ }
+
+ private boolean isHidden(final ObjectAdapter serviceNO) {
+ final ObjectSpecification serviceNoSpec = serviceNO.getSpecification();
+ return serviceNoSpec.isHidden();
+ }
+
+ public boolean canDisplay(final ObjectAdapter object) {
+ return object instanceof ObjectAdapter && object != null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/CollectionDisplayIterator.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/CollectionDisplayIterator.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/CollectionDisplayIterator.java
new file mode 100644
index 0000000..e9b7d99
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/CollectionDisplayIterator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.viewer.basic;
+
+import java.util.Enumeration;
+
+public interface CollectionDisplayIterator {
+
+ /**
+ * Return cache to be viewed on current page
+ */
+ public Enumeration displayElements();
+
+ /**
+ * Position cursor at first element
+ */
+ public void first();
+
+ public int getDisplaySize();
+
+ /**
+ * If true there is a next page to display, and 'next' and 'last' options
+ * are valid
+ */
+ public boolean hasNext();
+
+ public boolean hasPrevious();
+
+ /**
+ * Position cursor at last
+ */
+ public void last();
+
+ /**
+ * Position cursor at beginning of next page
+ */
+ public void next();
+
+ public int position();
+
+ /**
+ * Position cursor at beginning of previous page
+ */
+ public void previous();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/DragContentSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/DragContentSpecification.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/DragContentSpecification.java
new file mode 100644
index 0000000..8e20462
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/DragContentSpecification.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.dnd.viewer.basic;
+
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.icon.IconSpecification;
+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.border.LineBorder;
+
+public class DragContentSpecification extends IconSpecification {
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ final View icon = super.createView(content, axes, sequence);
+ return new LineBorder(1, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1), icon);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/FallbackView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/FallbackView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/FallbackView.java
new file mode 100644
index 0000000..7ef7f36
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/FallbackView.java
@@ -0,0 +1,111 @@
+/*
+ * 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.viewer.basic;
+
+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;
+import org.apache.isis.viewer.dnd.view.base.ObjectView;
+
+public class FallbackView extends ObjectView {
+
+ 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) {
+ return new FallbackView(content, this);
+ }
+
+ @Override
+ public String getName() {
+ return "Fallback";
+ }
+
+ @Override
+ public boolean isAligned() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return false;
+ }
+
+ @Override
+ public boolean isReplaceable() {
+ return false;
+ }
+
+ @Override
+ public boolean isResizeable() {
+ return false;
+ }
+
+ @Override
+ public boolean isSubView() {
+ return false;
+ }
+ }
+
+ protected FallbackView(final Content content, final ViewSpecification specification) {
+ super(content, specification);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ super.draw(canvas);
+
+ final Size size = getSize();
+ final int width = size.getWidth() - 1;
+ final int height = size.getHeight() - 1;
+ canvas.drawSolidRectangle(0, 0, width, height, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY3));
+ canvas.drawSolidRectangle(0, 0, 10, height, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2));
+ canvas.drawLine(10, 0, 10, height - 2, Toolkit.getColor(ColorsAndFonts.COLOR_BLACK));
+ canvas.drawRectangle(0, 0, width, height, Toolkit.getColor(ColorsAndFonts.COLOR_BLACK));
+ canvas.drawText(getContent().title(), 14, getBaseline(), Toolkit.getColor(ColorsAndFonts.COLOR_BLACK), Toolkit.getText(ColorsAndFonts.TEXT_NORMAL));
+ }
+
+ @Override
+ public int getBaseline() {
+ return 14;
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ return new Size(150, 20);
+ }
+
+ @Override
+ public ViewAreaType viewAreaType(final Location mouseLocation) {
+ return mouseLocation.getX() <= 10 ? ViewAreaType.VIEW : ViewAreaType.CONTENT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/Identifier.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/Identifier.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/Identifier.java
new file mode 100644
index 0000000..2c44e19
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/Identifier.java
@@ -0,0 +1,82 @@
+/*
+ * 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.viewer.basic;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+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.ContentDrag;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractViewDecorator;
+
+public class Identifier extends AbstractViewDecorator {
+ private boolean identified;
+
+ public Identifier(final View wrappedView) {
+ super(wrappedView);
+ }
+
+ @Override
+ public void debugDetails(final DebugBuilder debug) {
+ debug.append("Identifier");
+ }
+
+ @Override
+ public void dragIn(final ContentDrag drag) {
+ wrappedView.dragIn(drag);
+ markDamaged();
+ }
+
+ @Override
+ public void dragOut(final ContentDrag drag) {
+ wrappedView.dragOut(drag);
+ markDamaged();
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final Size s = getSize();
+ canvas.drawSolidRectangle(0, 0, s.getWidth(), s.getHeight(), Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY3));
+ wrappedView.draw(canvas);
+ }
+
+ @Override
+ public void entered() {
+ getState().setContentIdentified();
+ wrappedView.entered();
+ identified = true;
+ markDamaged();
+ }
+
+ @Override
+ public void exited() {
+ getState().clearObjectIdentified();
+ wrappedView.exited();
+ identified = false;
+ markDamaged();
+ }
+
+ @Override
+ public String toString() {
+ return wrappedView.toString() + "/Identifier [identified=" + identified + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/InnerWorkspaceSpecification.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/InnerWorkspaceSpecification.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/InnerWorkspaceSpecification.java
new file mode 100644
index 0000000..595df22
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/InnerWorkspaceSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * 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.viewer.basic;
+
+import org.apache.isis.viewer.dnd.view.Axes;
+import org.apache.isis.viewer.dnd.view.Content;
+import org.apache.isis.viewer.dnd.view.View;
+
+public class InnerWorkspaceSpecification extends WorkspaceSpecification {
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ return super.createView(content, axes, sequence);
+ }
+
+ @Override
+ public String getName() {
+ return "Workspace";
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/LogoBackground.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/LogoBackground.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/LogoBackground.java
new file mode 100644
index 0000000..00d9fff
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/LogoBackground.java
@@ -0,0 +1,75 @@
+/*
+ * 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.viewer.basic;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Background;
+import org.apache.isis.viewer.dnd.drawing.Canvas;
+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.util.Properties;
+
+public class LogoBackground implements Background {
+ private static final Logger LOG = Logger.getLogger(LogoBackground.class);
+ private static final String PARAMETER_BASE = Properties.PROPERTY_BASE + "logo-background.";
+ private Location location;
+ private Image logo;
+ private Size logoSize;
+
+ public LogoBackground() {
+ final IsisConfiguration configuration = IsisContext.getConfiguration();
+
+ final String fileName = configuration.getString(PARAMETER_BASE + "image", "background");
+ logo = ImageFactory.getInstance().loadImage(fileName);
+
+ if (logo == null) {
+ logo = ImageFactory.getInstance().loadImage("poweredby-logo");
+ }
+
+ if (logo == null) {
+ LOG.debug("logo image not found: " + fileName);
+ } else {
+ location = Properties.getLocation(PARAMETER_BASE + "location", new Location(-30, -30));
+ logoSize = Properties.getSize(PARAMETER_BASE + "size", logo.getSize());
+ }
+ }
+
+ @Override
+ public void draw(final Canvas canvas, final Size viewSize) {
+ if (logo != null) {
+ int x;
+ int y;
+
+ if (location.getX() == 0 && location.getY() == 0) {
+ x = viewSize.getWidth() / 2 - logoSize.getWidth() / 2;
+ y = viewSize.getHeight() / 2 - logoSize.getHeight() / 2;
+ } else {
+ x = (location.getX() >= 0) ? location.getX() : viewSize.getWidth() + location.getX() - logoSize.getWidth();
+ y = (location.getY() >= 0) ? location.getY() : viewSize.getHeight() + location.getY() - logoSize.getHeight();
+ }
+ canvas.drawImage(logo, x, y, logoSize.getWidth(), logoSize.getHeight());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/eb613703/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/MinimizedView.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/MinimizedView.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/MinimizedView.java
new file mode 100644
index 0000000..33910fb
--- /dev/null
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/viewer/basic/MinimizedView.java
@@ -0,0 +1,455 @@
+/*
+ * 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.viewer.basic;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.consent.Allow;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.ActionType;
+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.Padding;
+import org.apache.isis.viewer.dnd.drawing.Size;
+import org.apache.isis.viewer.dnd.icon.SubviewIconSpecification;
+import org.apache.isis.viewer.dnd.view.Axes;
+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.Toolkit;
+import org.apache.isis.viewer.dnd.view.UserAction;
+import org.apache.isis.viewer.dnd.view.UserActionSet;
+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.ViewRequirement;
+import org.apache.isis.viewer.dnd.view.ViewSpecification;
+import org.apache.isis.viewer.dnd.view.ViewState;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.base.AbstractView;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+import org.apache.isis.viewer.dnd.view.window.WindowControl;
+
+public class MinimizedView extends AbstractView {
+ private class CloseWindowControl extends WindowControl {
+
+ public CloseWindowControl(final View target) {
+ super(new UserAction() {
+ @Override
+ public Consent disabled(final View view) {
+ return Allow.DEFAULT;
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ ((MinimizedView) view).close();
+ }
+
+ @Override
+ public String getDescription(final View view) {
+ return "Close " + view.getSpecification().getName();
+ }
+
+ @Override
+ public String getHelp(final View view) {
+ return null;
+ }
+
+ @Override
+ public String getName(final View view) {
+ return "Close view";
+ }
+
+ @Override
+ public ActionType getType() {
+ return ActionType.USER;
+ }
+ }, target);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final int x = 0;
+ final int y = 0;
+ final Color crossColor = Toolkit.getColor(ColorsAndFonts.COLOR_BLACK);
+ canvas.drawLine(x + 4, y + 3, x + 10, y + 9, crossColor);
+ canvas.drawLine(x + 5, y + 3, x + 11, y + 9, crossColor);
+ canvas.drawLine(x + 10, y + 3, x + 4, y + 9, crossColor);
+ canvas.drawLine(x + 11, y + 3, x + 5, y + 9, crossColor);
+ }
+ }
+
+ private class RestoreWindowControl extends WindowControl {
+ public RestoreWindowControl(final View target) {
+ super(new UserAction() {
+
+ @Override
+ public Consent disabled(final View view) {
+ return Allow.DEFAULT;
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ ((MinimizedView) view).restore();
+ }
+
+ @Override
+ public String getDescription(final View view) {
+ return "Restore " + view.getSpecification().getName() + " to normal size";
+ }
+
+ @Override
+ public String getHelp(final View view) {
+ return null;
+ }
+
+ @Override
+ public String getName(final View view) {
+ return "Restore view";
+ }
+
+ @Override
+ public ActionType getType() {
+ return ActionType.USER;
+ }
+ }, target);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final int x = 0;
+ final int y = 0;
+ final Color black = Toolkit.getColor(ColorsAndFonts.COLOR_BLACK);
+ canvas.drawRectangle(x + 1, y + 1, WIDTH - 1, HEIGHT - 1, black);
+ canvas.drawLine(x + 2, y + 2, x + WIDTH - 2, y + 2, black);
+ canvas.drawLine(x + 2, y + 3, x + WIDTH - 2, y + 3, black);
+ }
+ }
+
+ private static class Specification implements ViewSpecification {
+
+ @Override
+ public boolean canDisplay(final ViewRequirement requirement) {
+ return false;
+ }
+
+ @Override
+ public View createView(final Content content, final Axes axes, final int sequence) {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return "minimized view";
+ }
+
+ @Override
+ public boolean isAligned() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return false;
+ }
+
+ @Override
+ public boolean isReplaceable() {
+ return false;
+ }
+
+ @Override
+ public boolean isResizeable() {
+ return false;
+ }
+
+ @Override
+ public boolean isSubView() {
+ return false;
+ }
+
+ }
+
+ private final static int BORDER_WIDTH = 5;
+ private final WindowControl controls[];
+ private View iconView;
+
+ private final View minimizedView;
+
+ public MinimizedView(final View viewToMinimize) {
+ super(viewToMinimize.getContent(), new Specification());
+ this.minimizedView = viewToMinimize;
+ iconView = new SubviewIconSpecification().createView(viewToMinimize.getContent(), viewToMinimize.getViewAxes(), -1);
+ iconView.setParent(this);
+ controls = new WindowControl[] { new RestoreWindowControl(this), new CloseWindowControl(this) };
+ }
+
+ @Override
+ public void debug(final DebugBuilder debug) {
+ super.debug(debug);
+ debug.appendln("minimized view", minimizedView);
+ debug.appendln();
+
+ debug.appendln("icon size", iconView.getSize());
+ debug.append(iconView);
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ iconView.dispose();
+ // viewToMinimize.dispose();
+ }
+
+ @Override
+ public DragEvent dragStart(final DragStart drag) {
+ if (iconView.getBounds().contains(drag.getLocation())) {
+ drag.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ return iconView.dragStart(drag);
+ } else {
+ return super.dragStart(drag);
+ }
+ // View dragOverlay = new DragViewOutline(getView());
+ // return new ViewDrag(this, new Offset(drag.getLocation()),
+ // dragOverlay);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ super.draw(canvas);
+
+ final Size size = getSize();
+ final int width = size.getWidth();
+ final int height = size.getHeight();
+ final int left = 3;
+ final int top = 3;
+
+ final boolean hasFocus = containsFocus();
+ final Color lightColor = hasFocus ? Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1) : Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2);
+ clearBackground(canvas, Toolkit.getColor(ColorsAndFonts.COLOR_WINDOW));
+ canvas.drawRectangle(1, 0, width - 2, height, lightColor);
+ canvas.drawRectangle(0, 1, width, height - 2, lightColor);
+ for (int i = 2; i < left; i++) {
+ canvas.drawRectangle(i, i, width - 2 * i, height - 2 * i, lightColor);
+ }
+ final ViewState state = getState();
+ if (state.isActive()) {
+ final int i = left;
+ canvas.drawRectangle(i, top, width - 2 * i, height - 2 * i - top, Toolkit.getColor(ColorsAndFonts.COLOR_ACTIVE));
+ }
+
+ final int bw = controls[0].getLocation().getX() - 3; // controls.length
+ // *
+ // WindowControl.WIDTH;
+ canvas.drawSolidRectangle(bw, top, width - bw - 3, height - top * 2, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY3));
+ canvas.drawLine(bw - 1, top, bw - 1, height - top * 2, lightColor);
+
+ for (int i = 0; controls != null && i < controls.length; i++) {
+ final Canvas controlCanvas = canvas.createSubcanvas(controls[i].getBounds());
+ controls[i].draw(controlCanvas);
+ }
+
+ final Canvas c = canvas.createSubcanvas(iconView.getBounds());
+ iconView.draw(c);
+ }
+
+ @Override
+ public Size getRequiredSize(final Size availableSpace) {
+ final Size size = new Size();
+
+ size.extendWidth(BORDER_WIDTH);
+ final Size iconMaximumSize = iconView.getRequiredSize(Size.createMax());
+ size.extendWidth(iconMaximumSize.getWidth());
+
+ size.extendHeight(iconMaximumSize.getHeight());
+ size.ensureHeight(WindowControl.HEIGHT);
+ size.extendHeight(BORDER_WIDTH);
+ size.extendHeight(BORDER_WIDTH);
+
+ size.extendWidth(ViewConstants.HPADDING);
+ size.extendWidth(controls.length * (WindowControl.WIDTH + ViewConstants.HPADDING));
+ size.extendWidth(BORDER_WIDTH);
+ return size;
+ }
+
+ @Override
+ public Padding getPadding() {
+ return new Padding(BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH);
+ }
+
+ @Override
+ public void layout() {
+ final Size size = getRequiredSize(Size.createMax());
+
+ layoutControls(size.getWidth());
+
+ size.contractWidth(BORDER_WIDTH * 2);
+ size.contractWidth(ViewConstants.HPADDING);
+ size.contractWidth(controls.length * (WindowControl.WIDTH + ViewConstants.HPADDING));
+
+ size.contractHeight(BORDER_WIDTH * 2);
+
+ iconView.setLocation(new Location(BORDER_WIDTH, BORDER_WIDTH));
+ iconView.setSize(size);
+ }
+
+ private void layoutControls(final int width) {
+ final int widthControl = WindowControl.WIDTH + ViewConstants.HPADDING;
+ int x = width - BORDER_WIDTH + ViewConstants.HPADDING;
+ x -= widthControl * controls.length;
+ final int y = BORDER_WIDTH;
+
+ for (final WindowControl control : controls) {
+ control.setSize(control.getRequiredSize(Size.createMax()));
+ control.setLocation(new Location(x, y));
+ x += widthControl;
+ }
+ }
+
+ private void restore() {
+ final Workspace workspace = getWorkspace();
+ final View[] views = workspace.getSubviews();
+ for (final View view : views) {
+ if (view == this) {
+ dispose();
+
+ minimizedView.setParent(workspace);
+ // workspace.removeView(this);
+ workspace.addView(minimizedView);
+ workspace.invalidateLayout();
+
+ return;
+
+ }
+ }
+ }
+
+ private void close() {
+ final Workspace workspace = getWorkspace();
+ final View[] views = workspace.getSubviews();
+ for (final View view : views) {
+ if (view == this) {
+ dispose();
+
+ minimizedView.setParent(workspace);
+ workspace.invalidateLayout();
+ workspace.addView(minimizedView);
+ minimizedView.dispose();
+
+ return;
+
+ }
+ }
+ }
+
+ @Override
+ public void removeView(final View view) {
+ if (view == iconView) {
+ iconView = null;
+ } else {
+ throw new IsisException("No view " + view + " in " + this);
+ }
+ }
+
+ @Override
+ public void secondClick(final Click click) {
+ restore();
+ }
+
+ @Override
+ public ViewAreaType viewAreaType(final Location location) {
+ location.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ return iconView.viewAreaType(location);
+ }
+
+ @Override
+ public void viewMenuOptions(final UserActionSet options) {
+ options.add(new UserActionAbstract("Restore") {
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ restore();
+ }
+ });
+ super.viewMenuOptions(options);
+ }
+
+ @Override
+ public void firstClick(final Click click) {
+ final View button = overControl(click.getLocation());
+ if (button == null) {
+ /*
+ * if (overBorder(click.getLocation())) { Workspace workspace =
+ * getWorkspace(); if (workspace != null) { if (click.button2()) {
+ * workspace.lower(getView()); } else if (click.button1()) {
+ * workspace.raise(getView()); } } } else { super.firstClick(click);
+ * }
+ */} else {
+ button.firstClick(click);
+ }
+
+ }
+
+ private View overControl(final Location location) {
+ for (final WindowControl control : controls) {
+ if (control.getBounds().contains(location)) {
+ return control;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void dragIn(final ContentDrag drag) {
+ if (iconView.getBounds().contains(drag.getTargetLocation())) {
+ drag.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ iconView.dragIn(drag);
+ }
+ }
+
+ @Override
+ public void dragOut(final ContentDrag drag) {
+ if (iconView.getBounds().contains(drag.getTargetLocation())) {
+ drag.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ iconView.dragOut(drag);
+ }
+ }
+
+ @Override
+ public View identify(final Location location) {
+ if (iconView.getBounds().contains(location)) {
+ location.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ return iconView.identify(location);
+ }
+ return this;
+ }
+
+ @Override
+ public void drop(final ContentDrag drag) {
+ if (iconView.getBounds().contains(drag.getTargetLocation())) {
+ drag.subtract(BORDER_WIDTH, BORDER_WIDTH);
+ iconView.drop(drag);
+ }
+ }
+}