X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FSGNodeReflection.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FSGNodeReflection.java;h=0dc2d9d7ece65ca096a94613317b6bb945722413;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/SGNodeReflection.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/SGNodeReflection.java
new file mode 100644
index 000000000..0dc2d9d7e
--- /dev/null
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/SGNodeReflection.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/*
+ *
+ * @author Toni Kalajainen
+ */
+package org.simantics.g2d.canvas.impl;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.g2d.canvas.SGDesignation;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+
+
+public class SGNodeReflection {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface SGInit {
+ SGDesignation designation() default SGDesignation.CANVAS;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface SGCleanup {
+ }
+
+ /**
+ * Scans an object with reflection for all painter methods and returns
+ * an array of ICanvasPainters and priorities.
+ *
+ * The corresponding class of obj must contain methods that meet the following
+ * criteria:
+ * 1) no return value
+ * 2) 1 argument, which is Graphics2D
+ * 3) has annotation Painter
+ * 4) may not throw any Exception
+ * 5) method must be accessible
+ *
+ * Example:
+ *
+ * @Painter(priority = Integer.MIN_VALUE)
+ * public void prePaint(GraphicsContext gc) {
+ * }
+ *
+ * @param obj object to scan
+ * @return an array of painters and their priorities
+ */
+ public static CanvasSGNodeDefinition[] getSGHandlers(final Object obj)
+ {
+ List result = new ArrayList();
+ Class> clazz = obj.getClass();
+
+ for (final Method m : clazz.getMethods()) {
+ SGInit initAnno = m.getAnnotation(SGInit.class);
+ if (initAnno==null) continue;
+
+ SGDesignation initDesignation = initAnno.designation();
+
+ Class> returnType = m.getReturnType();
+ if (!returnType.equals(void.class))
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
+
+ @SuppressWarnings("rawtypes")
+ Class[] argTypes = m.getParameterTypes();
+ if (argTypes.length!=1 || !argTypes[0].equals(G2DParentNode.class))
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
+
+ @SuppressWarnings("rawtypes")
+ Class[] exceptionTypes = m.getExceptionTypes();
+ if (exceptionTypes.length!=0)
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
+
+ try {
+ m.setAccessible(true);
+ } catch (Throwable t)
+ {
+ t.printStackTrace();
+ throw new Error(t);
+ }
+
+ CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(m, initDesignation, null, obj);
+ result.add(def);
+ }
+
+ for (final Method m : clazz.getMethods()) {
+ SGCleanup cleanupAnno = m.getAnnotation(SGCleanup.class);
+ if (cleanupAnno==null) continue;
+
+ Class> returnType = m.getReturnType();
+ if (!returnType.equals(void.class))
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
+
+ @SuppressWarnings("rawtypes")
+ Class[] argTypes = m.getParameterTypes();
+ if (argTypes.length!=0)
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
+
+ @SuppressWarnings("rawtypes")
+ Class[] exceptionTypes = m.getExceptionTypes();
+ if (exceptionTypes.length!=0)
+ throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
+
+ try {
+ m.setAccessible(true);
+ } catch (Throwable t)
+ {
+ t.printStackTrace();
+ throw new Error(t);
+ }
+
+ CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(null, null, m, obj);
+ result.add(def);
+ }
+
+ return result.toArray(new CanvasSGNodeDefinition[0]);
+ }
+
+ public static class CanvasSGNodeDefinition { // FIXME: own classes for init and cleanup
+ public final Method initMethod;
+ public final SGDesignation initDesignation;
+ public final Method cleanupMethod;
+ public final Object obj;
+
+ public void init(G2DParentNode parent) {
+ if(initMethod == null) return;
+ try {
+ initMethod.invoke(obj, parent);
+ } catch (IllegalArgumentException e) {
+ throw new Error(e);
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+ public void cleanup() {
+ if(cleanupMethod == null) return;
+ try {
+ cleanupMethod.invoke(obj);
+ } catch (IllegalArgumentException e) {
+ throw new Error(e);
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+ public CanvasSGNodeDefinition(Method initMethod, SGDesignation initDesignation, Method cleanupMethod, Object obj) {
+ this.initMethod = initMethod;
+ this.initDesignation = initDesignation;
+ this.cleanupMethod = cleanupMethod;
+ this.obj = obj;
+ }
+ @Override
+ public String toString() {
+ return String.format("%s %s %s %s",
+ obj.getClass().getSimpleName(),
+ initMethod != null ? initMethod.getName() : "no init method",
+ initDesignation != null ? initDesignation.toString() : "no init designation",
+ cleanupMethod != null ? cleanupMethod.getName() : "no cleanup method");
+ }
+ }
+}