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"); + } + } +}