1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
14 * @author Toni Kalajainen
16 package org.simantics.g2d.canvas.impl;
18 import java.lang.annotation.ElementType;
19 import java.lang.annotation.Retention;
20 import java.lang.annotation.RetentionPolicy;
21 import java.lang.annotation.Target;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.ArrayList;
25 import java.util.List;
27 import org.simantics.g2d.canvas.SGDesignation;
28 import org.simantics.scenegraph.g2d.G2DParentNode;
31 public class SGNodeReflection {
33 @Retention(RetentionPolicy.RUNTIME)
34 @Target(ElementType.METHOD)
35 public static @interface SGInit {
36 SGDesignation designation() default SGDesignation.CANVAS;
39 @Retention(RetentionPolicy.RUNTIME)
40 @Target(ElementType.METHOD)
41 public static @interface SGCleanup {
45 * Scans an object with reflection for all painter methods and returns
46 * an array of ICanvasPainters and priorities.
48 * The corresponding class of obj must contain methods that meet the following
51 * 2) 1 argument, which is Graphics2D
52 * 3) has annotation Painter
53 * 4) may not throw any Exception
54 * 5) method must be accessible
58 * @Painter(priority = Integer.MIN_VALUE)
59 * public void prePaint(GraphicsContext gc) {
62 * @param obj object to scan
63 * @return an array of painters and their priorities
65 public static CanvasSGNodeDefinition[] getSGHandlers(final Object obj)
67 List<CanvasSGNodeDefinition> result = new ArrayList<CanvasSGNodeDefinition>();
68 Class<?> clazz = obj.getClass();
70 for (final Method m : clazz.getMethods()) {
71 SGInit initAnno = m.getAnnotation(SGInit.class);
72 if (initAnno==null) continue;
74 SGDesignation initDesignation = initAnno.designation();
76 Class<?> returnType = m.getReturnType();
77 if (!returnType.equals(void.class))
78 throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
80 @SuppressWarnings("rawtypes")
81 Class[] argTypes = m.getParameterTypes();
82 if (argTypes.length!=1 || !argTypes[0].equals(G2DParentNode.class))
83 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
85 @SuppressWarnings("rawtypes")
86 Class[] exceptionTypes = m.getExceptionTypes();
87 if (exceptionTypes.length!=0)
88 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
91 m.setAccessible(true);
98 CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(m, initDesignation, null, obj);
102 for (final Method m : clazz.getMethods()) {
103 SGCleanup cleanupAnno = m.getAnnotation(SGCleanup.class);
104 if (cleanupAnno==null) continue;
106 Class<?> returnType = m.getReturnType();
107 if (!returnType.equals(void.class))
108 throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
110 @SuppressWarnings("rawtypes")
111 Class[] argTypes = m.getParameterTypes();
112 if (argTypes.length!=0)
113 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
115 @SuppressWarnings("rawtypes")
116 Class[] exceptionTypes = m.getExceptionTypes();
117 if (exceptionTypes.length!=0)
118 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
121 m.setAccessible(true);
122 } catch (Throwable t)
128 CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(null, null, m, obj);
132 return result.toArray(new CanvasSGNodeDefinition[0]);
135 public static class CanvasSGNodeDefinition { // FIXME: own classes for init and cleanup
136 public final Method initMethod;
137 public final SGDesignation initDesignation;
138 public final Method cleanupMethod;
139 public final Object obj;
141 public void init(G2DParentNode parent) {
142 if(initMethod == null) return;
144 initMethod.invoke(obj, parent);
145 } catch (IllegalArgumentException e) {
147 } catch (IllegalAccessException e) {
149 } catch (InvocationTargetException e) {
150 throw new RuntimeException(e.getCause());
153 public void cleanup() {
154 if(cleanupMethod == null) return;
156 cleanupMethod.invoke(obj);
157 } catch (IllegalArgumentException e) {
159 } catch (IllegalAccessException e) {
161 } catch (InvocationTargetException e) {
162 throw new RuntimeException(e.getCause());
165 public CanvasSGNodeDefinition(Method initMethod, SGDesignation initDesignation, Method cleanupMethod, Object obj) {
166 this.initMethod = initMethod;
167 this.initDesignation = initDesignation;
168 this.cleanupMethod = cleanupMethod;
172 public String toString() {
173 return String.format("%s %s %s %s",
174 obj.getClass().getSimpleName(),
175 initMethod != null ? initMethod.getName() : "no init method",
176 initDesignation != null ? initDesignation.toString() : "no init designation",
177 cleanupMethod != null ? cleanupMethod.getName() : "no cleanup method");