X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Felement%2FElementClass.java;h=5d689760143772252b0407340e48620c6bb55e4f;hb=12c9ca9390a5272306deadbe17a6bc0f7a52d76f;hp=124a26cb217476e6f6b10a0acdf4abbb81ebd7ef;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/ElementClass.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/ElementClass.java
index 124a26cb2..5d6897601 100644
--- a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/ElementClass.java
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/ElementClass.java
@@ -1,243 +1,241 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.g2d.element;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.simantics.g2d.diagram.impl.AbstractHandlerClass;
-import org.simantics.g2d.element.handler.ElementHandler;
-import org.simantics.g2d.element.handler.HandleMouseEvent;
-import org.simantics.g2d.element.handler.InternalSize;
-import org.simantics.g2d.element.handler.Move;
-import org.simantics.g2d.element.handler.Rotate;
-import org.simantics.g2d.element.handler.SceneGraph;
-import org.simantics.g2d.element.handler.Transform;
-import org.simantics.g2d.element.handler.Validator;
-
-/**
- * ElementClass is a class of elements. It consists of element handlers.
- * Each handler contributes functions to some aspects of the diagram.
- *
- * Handlers are ordered. For instance, if there are multiple Paint handlers,
- * the paint order is determined by the order of the handlers in the class.
- *
- * The minimum requirement is implementation for the following interfaces:
- * @see Transform
- * @see InternalSize
- *
- * Typical element class has the following implementations:
- * @see Transform
- * @see SceneGraph
- * @see Move
- * @see Rotate
- * @see InternalSize or @see Scale
- * @see Selectable
- *
- * Interactive element classes have implementation to:
- * @see HandleMouseEvent
- *
- * See also:
- * @see Validator
- *
- * See package org.simantics.g2d.element.handler for handler interfaces.
- * See package org.simantics.g2d.element.handler.impl for common implementations.
- * Note that some implementations implement several interface. Also note that
- * some handler interfaces may be implemented several times (e.g. Paint,
- * Validator, ToolTip, Pick). In contrast, some handlers may have at most one
- * implementation, such as Transform, Move, Rotate, Scale, Size.
- *
- * Tip: Use SymbolUtil (CanvasParticipant) to manage graphical resources (images).
- *
- * @author Toni Kalajainen
- */
-public final class ElementClass extends AbstractHandlerClass {
-
- private static final long serialVersionUID = -446421782709451743L;
-
- /** Handler with this annotation may have at most one implementation */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public static @interface Single {}
-
- /** Handler with this annotation must be implemented (once or more) */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public static @interface Required {}
-
- private static final Class>[] REQUIRED_HANDLERS =
- new Class>[] {Transform.class, InternalSize.class};
-
- private String id = "";
-
- /**
- * Compile new element class from a set of handler
- * @param contributions
- * @return
- */
- public static ElementClass compile(Collection contributions)
- {
- assertClassValid(contributions);
- return new ElementClass(contributions);
- }
-
- public static ElementClass compile(Collection contributions, boolean check)
- {
- if(check) assertClassValid(contributions);
- return new ElementClass(contributions, check);
- }
-
- /**
- * Compile new element class from a set of handler
- * @param contributions
- * @return
- */
- public static ElementClass compile(ElementHandler... contributions)
- {
- if (contributions.length == 0)
- return new ElementClass(Arrays.asList(contributions));
- ArrayList al = new ArrayList(contributions.length);
- for (ElementHandler eh : contributions)
- al.add(eh);
- return new ElementClass(al);
- }
-
- ElementClass(Collection contributions) {
- super(contributions);
- assertClassValid(contributions);
- }
-
- ElementClass(Collection contributions, boolean check) {
- super(contributions);
- if(check) assertClassValid(contributions);
- }
-
- /**
- * Validates that handler is valid.
- *
- * @param contributions
- * @return
- */
- public static void assertClassValid(Collection contributions)
- {
- // 1. Verify requirements
- nextRequirement:
- for (Class> requiredClass : REQUIRED_HANDLERS) {
- for (ElementHandler eh : contributions)
- if (requiredClass.isInstance(eh))
- continue nextRequirement;
- throw new Error("Element class does not implement "+requiredClass.getName());
- }
-
- // 2. Verify singletons
- // 2.1. Collect implemented handlers
- Set> implementedHandlerInterfaces = new HashSet>();
- for (ElementHandler eh : contributions)
- _traverseElementHandlerInterfaces(eh.getClass(), implementedHandlerInterfaces);
-
- // 2.2. Verify singletons are implemented only once
- for (Class ehc : implementedHandlerInterfaces)
- {
- if (!_isSingletonHandler(ehc)) continue;
- int implementationCount = 0;
- for (ElementHandler eh : contributions)
- {
- if (!ehc.isInstance(eh)) continue;
- implementationCount++;
- }
- if (implementationCount>1)
- throw new Error("Element class has "+implementationCount+" implementations to a _singleton_ element handler \""+ehc.getName()+"\": " + contributions);
- }
- }
-
- private static boolean _isSingletonHandler(Class elementHandlerClass)
- {
- Single s = elementHandlerClass.getAnnotation(Single.class);
- return s != null;
- }
-
- @SuppressWarnings("unchecked")
- private static void _traverseElementHandlerInterfaces(Class> clazz, Collection> result)
- {
- // Add implemented interfaces (that are inherited from ElementHandler)
- for (Class> inf : clazz.getInterfaces())
- {
- if (!ElementHandler.class.isAssignableFrom(inf)) continue;
- result.add((Class)inf);
- }
-
- // Traverse parent
- Class> superType = clazz.getSuperclass();
- if (superType!=null)
- _traverseElementHandlerInterfaces(superType, result);
- }
-
- @Override
- public String toString() {
- if (!id.isEmpty())
- return id;
-
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- int i=0;
- for (ElementHandler eh : super.getAll())
- {
- if (i++>0) sb.append(", ");
- sb.append( eh.getClass().getSimpleName() );
- }
- sb.append("]");
- return sb.toString();
- }
-
- public ElementClass newClassWith(ElementHandler... addedHandlers) {
- if (addedHandlers.length == 0)
- return this;
- Collection newHandlers = new ArrayList(getAll());
- for (ElementHandler h : addedHandlers)
- newHandlers.add(h);
- return ElementClass.compile(newHandlers).setId(id);
- }
-
- public ElementClass newClassWith(boolean check, ElementHandler... addedHandlers) {
- if (addedHandlers.length == 0)
- return this;
- Collection newHandlers = new ArrayList(getAll());
- for (ElementHandler h : addedHandlers)
- newHandlers.add(h);
- return ElementClass.compile(newHandlers, check).setId(id);
- }
-
- public ElementClass newClassWith(Collection addedHandlers) {
- if (addedHandlers.isEmpty())
- return this;
- Collection newHandlers = new ArrayList(getAll());
- newHandlers.addAll(addedHandlers);
- return ElementClass.compile(newHandlers).setId(id);
- }
-
- public ElementClass setId(String id) {
- this.id = id;
- return this;
- }
-
- public String getId() {
- return id;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g2d.element;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.simantics.g2d.diagram.impl.AbstractHandlerClass;
+import org.simantics.g2d.element.handler.ElementHandler;
+import org.simantics.g2d.element.handler.HandleMouseEvent;
+import org.simantics.g2d.element.handler.InternalSize;
+import org.simantics.g2d.element.handler.Move;
+import org.simantics.g2d.element.handler.Rotate;
+import org.simantics.g2d.element.handler.SceneGraph;
+import org.simantics.g2d.element.handler.Transform;
+import org.simantics.g2d.element.handler.Validator;
+
+/**
+ * ElementClass is a class of elements. It consists of element handlers.
+ * Each handler contributes functions to some aspects of the diagram.
+ *
+ * Handlers are ordered. For instance, if there are multiple Paint handlers,
+ * the paint order is determined by the order of the handlers in the class.
+ *
+ * The minimum requirement is implementation for the following interfaces:
+ * @see Transform
+ * @see InternalSize
+ *
+ * Typical element class has the following implementations:
+ * @see Transform
+ * @see SceneGraph
+ * @see Move
+ * @see Rotate
+ * @see InternalSize or @see Scale
+ * @see Selectable
+ *
+ * Interactive element classes have implementation to:
+ * @see HandleMouseEvent
+ *
+ * See also:
+ * @see Validator
+ *
+ * See package org.simantics.g2d.element.handler for handler interfaces.
+ * See package org.simantics.g2d.element.handler.impl for common implementations.
+ * Note that some implementations implement several interface. Also note that
+ * some handler interfaces may be implemented several times (e.g. Paint,
+ * Validator, ToolTip, Pick). In contrast, some handlers may have at most one
+ * implementation, such as Transform, Move, Rotate, Scale, Size.
+ *
+ * Tip: Use SymbolUtil (CanvasParticipant) to manage graphical resources (images).
+ *
+ * @author Toni Kalajainen
+ */
+public final class ElementClass extends AbstractHandlerClass {
+
+ private static final long serialVersionUID = -446421782709451743L;
+
+ /** Handler with this annotation may have at most one implementation */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public static @interface Single {}
+
+ /** Handler with this annotation must be implemented (once or more) */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public static @interface Required {}
+
+ private static final Class>[] REQUIRED_HANDLERS =
+ new Class>[] {Transform.class, InternalSize.class};
+
+ private String id = "";
+
+ /**
+ * Compile new element class from a set of handler
+ * @param contributions
+ * @return
+ */
+ public static ElementClass compile(Collection contributions)
+ {
+ return new ElementClass(contributions);
+ }
+
+ public static ElementClass compile(Collection contributions, boolean check)
+ {
+ return new ElementClass(contributions, check);
+ }
+
+ /**
+ * Compile new element class from a set of handler
+ * @param contributions
+ * @return
+ */
+ public static ElementClass compile(ElementHandler... contributions)
+ {
+ if (contributions.length == 0)
+ return new ElementClass(Arrays.asList(contributions));
+ ArrayList al = new ArrayList(contributions.length);
+ for (ElementHandler eh : contributions)
+ al.add(eh);
+ return new ElementClass(al);
+ }
+
+ ElementClass(Collection contributions) {
+ super(contributions);
+ assertClassValid(contributions);
+ }
+
+ ElementClass(Collection contributions, boolean check) {
+ super(contributions);
+ if(check) assertClassValid(contributions);
+ }
+
+ /**
+ * Validates that handler is valid.
+ *
+ * @param contributions
+ * @return
+ */
+ public static void assertClassValid(Collection contributions)
+ {
+ // 1. Verify requirements
+ nextRequirement:
+ for (Class> requiredClass : REQUIRED_HANDLERS) {
+ for (ElementHandler eh : contributions)
+ if (requiredClass.isInstance(eh))
+ continue nextRequirement;
+ throw new Error("Element class does not implement "+requiredClass.getName());
+ }
+
+ // 2. Verify singletons
+ // 2.1. Collect implemented handlers
+ Set> implementedHandlerInterfaces = new HashSet>();
+ for (ElementHandler eh : contributions)
+ _traverseElementHandlerInterfaces(eh.getClass(), implementedHandlerInterfaces);
+
+ // 2.2. Verify singletons are implemented only once
+ for (Class ehc : implementedHandlerInterfaces)
+ {
+ if (!_isSingletonHandler(ehc)) continue;
+ int implementationCount = 0;
+ for (ElementHandler eh : contributions)
+ {
+ if (!ehc.isInstance(eh)) continue;
+ implementationCount++;
+ }
+ if (implementationCount>1)
+ throw new Error("Element class has "+implementationCount+" implementations to a _singleton_ element handler \""+ehc.getName()+"\": " + contributions);
+ }
+ }
+
+ private static boolean _isSingletonHandler(Class elementHandlerClass)
+ {
+ Single s = elementHandlerClass.getAnnotation(Single.class);
+ return s != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void _traverseElementHandlerInterfaces(Class> clazz, Collection> result)
+ {
+ // Add implemented interfaces (that are inherited from ElementHandler)
+ for (Class> inf : clazz.getInterfaces())
+ {
+ if (!ElementHandler.class.isAssignableFrom(inf)) continue;
+ result.add((Class)inf);
+ }
+
+ // Traverse parent
+ Class> superType = clazz.getSuperclass();
+ if (superType!=null)
+ _traverseElementHandlerInterfaces(superType, result);
+ }
+
+ @Override
+ public String toString() {
+ if (!id.isEmpty())
+ return id;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ int i=0;
+ for (ElementHandler eh : super.getAll())
+ {
+ if (i++>0) sb.append(", ");
+ sb.append( eh.getClass().getSimpleName() );
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public ElementClass newClassWith(ElementHandler... addedHandlers) {
+ if (addedHandlers.length == 0)
+ return this;
+ Collection newHandlers = new ArrayList(getAll());
+ for (ElementHandler h : addedHandlers)
+ newHandlers.add(h);
+ return ElementClass.compile(newHandlers).setId(id);
+ }
+
+ public ElementClass newClassWith(boolean check, ElementHandler... addedHandlers) {
+ if (addedHandlers.length == 0)
+ return this;
+ Collection newHandlers = new ArrayList(getAll());
+ for (ElementHandler h : addedHandlers)
+ newHandlers.add(h);
+ return ElementClass.compile(newHandlers, check).setId(id);
+ }
+
+ public ElementClass newClassWith(Collection addedHandlers) {
+ if (addedHandlers.isEmpty())
+ return this;
+ Collection newHandlers = new ArrayList(getAll());
+ newHandlers.addAll(addedHandlers);
+ return ElementClass.compile(newHandlers).setId(id);
+ }
+
+ public ElementClass setId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+}