]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/SGNodeReflection.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / canvas / impl / SGNodeReflection.java
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 (file)
index 0000000..0dc2d9d
--- /dev/null
@@ -0,0 +1,180 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+package org.simantics.g2d.canvas.impl;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.g2d.canvas.SGDesignation;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+\r
+\r
+public class SGNodeReflection {\r
+\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.METHOD)\r
+    public static @interface SGInit {\r
+        SGDesignation designation() default SGDesignation.CANVAS;\r
+    }\r
+\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.METHOD)\r
+    public static @interface SGCleanup {\r
+    }\r
+\r
+    /**\r
+     * Scans an object with reflection for all painter methods and returns\r
+     * an array of ICanvasPainters and priorities.\r
+     * <p>\r
+     * The corresponding class of obj must contain methods that meet the following\r
+     * criteria:\r
+     *  1) no return value\r
+     *  2) 1 argument, which is Graphics2D\r
+     *  3) has annotation Painter\r
+     *  4) may not throw any Exception\r
+     *  5) method must be accessible\r
+     * <p>\r
+     * Example:\r
+     *\r
+     *         @Painter(priority = Integer.MIN_VALUE)\r
+     *  public void prePaint(GraphicsContext gc) {\r
+     *  }\r
+     *\r
+     * @param obj object to scan\r
+     * @return an array of painters and their priorities\r
+     */\r
+    public static CanvasSGNodeDefinition[] getSGHandlers(final Object obj)\r
+    {\r
+        List<CanvasSGNodeDefinition> result = new ArrayList<CanvasSGNodeDefinition>();\r
+        Class<?> clazz = obj.getClass();\r
+\r
+        for (final Method m : clazz.getMethods()) {\r
+            SGInit initAnno = m.getAnnotation(SGInit.class);\r
+            if (initAnno==null) continue;\r
+\r
+            SGDesignation initDesignation = initAnno.designation();\r
+\r
+            Class<?> returnType = m.getReturnType();\r
+            if (!returnType.equals(void.class))\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");\r
+\r
+            @SuppressWarnings("rawtypes")\r
+            Class[] argTypes = m.getParameterTypes();\r
+            if (argTypes.length!=1 || !argTypes[0].equals(G2DParentNode.class))\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");\r
+\r
+            @SuppressWarnings("rawtypes")\r
+            Class[] exceptionTypes = m.getExceptionTypes();\r
+            if (exceptionTypes.length!=0)\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");\r
+\r
+            try {\r
+                m.setAccessible(true);\r
+            } catch (Throwable t)\r
+            {\r
+                t.printStackTrace();\r
+                throw new Error(t);\r
+            }\r
+\r
+            CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(m, initDesignation, null, obj);\r
+            result.add(def);\r
+        }\r
+\r
+        for (final Method m : clazz.getMethods()) {\r
+            SGCleanup cleanupAnno = m.getAnnotation(SGCleanup.class);\r
+            if (cleanupAnno==null) continue;\r
+\r
+            Class<?> returnType = m.getReturnType();\r
+            if (!returnType.equals(void.class))\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");\r
+\r
+            @SuppressWarnings("rawtypes")\r
+            Class[] argTypes = m.getParameterTypes();\r
+            if (argTypes.length!=0)\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");\r
+\r
+            @SuppressWarnings("rawtypes")\r
+            Class[] exceptionTypes = m.getExceptionTypes();\r
+            if (exceptionTypes.length!=0)\r
+                throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");\r
+\r
+            try {\r
+                m.setAccessible(true);\r
+            } catch (Throwable t)\r
+            {\r
+                t.printStackTrace();\r
+                throw new Error(t);\r
+            }\r
+\r
+            CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(null, null, m, obj);\r
+            result.add(def);\r
+        }\r
+\r
+        return result.toArray(new CanvasSGNodeDefinition[0]);\r
+    }\r
+\r
+    public static class CanvasSGNodeDefinition { // FIXME: own classes for init and cleanup\r
+        public final Method initMethod;\r
+        public final SGDesignation initDesignation;\r
+        public final Method cleanupMethod;\r
+        public final Object obj;\r
+\r
+        public void init(G2DParentNode parent) {\r
+            if(initMethod == null) return;\r
+            try {\r
+                initMethod.invoke(obj, parent);\r
+            } catch (IllegalArgumentException e) {\r
+                throw new Error(e);\r
+            } catch (IllegalAccessException e) {\r
+                throw new Error(e);\r
+            } catch (InvocationTargetException e) {\r
+                throw new RuntimeException(e.getCause());\r
+            }\r
+        }\r
+        public void cleanup() {\r
+            if(cleanupMethod == null) return;\r
+            try {\r
+                cleanupMethod.invoke(obj);\r
+            } catch (IllegalArgumentException e) {\r
+                throw new Error(e);\r
+            } catch (IllegalAccessException e) {\r
+                throw new Error(e);\r
+            } catch (InvocationTargetException e) {\r
+                throw new RuntimeException(e.getCause());\r
+            }\r
+        }\r
+        public CanvasSGNodeDefinition(Method initMethod, SGDesignation initDesignation, Method cleanupMethod, Object obj) {\r
+            this.initMethod = initMethod;\r
+            this.initDesignation = initDesignation;\r
+            this.cleanupMethod = cleanupMethod;\r
+            this.obj = obj;\r
+        }\r
+        @Override\r
+        public String toString() {\r
+            return String.format("%s %s %s %s",\r
+                    obj.getClass().getSimpleName(),\r
+                    initMethod != null ? initMethod.getName() : "no init method",\r
+                    initDesignation != null ? initDesignation.toString() : "no init designation",\r
+                    cleanupMethod != null ? cleanupMethod.getName() : "no cleanup method");\r
+        }\r
+    }\r
+}\r