X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FHintReflection.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FHintReflection.java;h=3edd342b70b13049c4c5ae9531a9207f890ce612;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java
new file mode 100644
index 000000000..3edd342b7
--- /dev/null
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * 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.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.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.utils.datastructures.hints.IHintListener;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+
+/**
+ * @author Toni Kalajainen
+ */
+public class HintReflection {
+
+ private final static HintListenerDefinition[] EMPTY = new HintListenerDefinition[0];
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public static @interface HintListener {
+ Class> Class();
+ String Field();
+ }
+
+ /**
+ * Scans an object for reflections of hint listeners
+ *
+ * Example:
+ *
+ * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ * public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ * ...
+ * }
+ * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ * public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
+ * ...
+ * }
+ *
+ * @param obj object to scan
+ * @return an array of painters and their priorities
+ */
+ public static HintListenerDefinition[] getDependencies(final Object obj)
+ {
+ Map result = new HashMap();
+ Class> clazz = obj.getClass();
+ _add(obj, clazz, result);
+ //if (result==null) return EMPTY;
+ return result.values().toArray(EMPTY);
+ }
+
+ private static void _add(final Object obj, Class> clazz, Map result)
+ {
+ try {
+ for (final Method m : clazz.getDeclaredMethods()) {
+ HintListener anno = (HintListener) m
+ .getAnnotation(HintListener.class);
+ if (anno == null)
+ continue;
+
+ Class> keyContainerClass = anno.Class();
+ assert (keyContainerClass != null);
+ String fieldName = anno.Field();
+ assert (fieldName != null);
+ Field field;
+ field = keyContainerClass.getField(fieldName);
+ assert (field != null);
+ field.setAccessible(true);
+ Object value = field.get(field != null);
+ assert (value != null);
+ assert (value instanceof Key);
+ Key key = (Key) value;
+
+ Class> returnType = m.getReturnType();
+ assert (returnType == void.class);
+ Class>[] params = m.getParameterTypes();
+ assert (params.length == 4 || params.length == 3);
+ assert (params[0].equals(IHintObservable.class));
+ assert (params[1].equals(Key.class));
+ assert (params[2].equals(Object.class));
+
+ if (params.length == 4)
+ assert (params[3].equals(Object.class));
+
+ HintListenerDefinition def = result.get(key);
+ if (def==null) {
+ def = new HintListenerDefinition(key, obj);
+ result.put(key, def);
+ }
+
+ m.setAccessible(true);
+ if (params.length == 4)
+ def.changedHandlerMethod = m;
+ else
+ def.removedHandlerMethod = m;
+ }
+ } catch (SecurityException e) {
+ throw new Error(e);
+ } catch (NoSuchFieldException e) {
+ throw new Error(e);
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ }
+ /*
+ for (final Field f : clazz.getDeclaredFields()) {
+ Class c = f.getType();
+ Dependency dep = (Dependency) f.getAnnotation(Dependency.class);
+ Reference ref = (Reference) f.getAnnotation(Reference.class);
+ if (dep==null && ref==null) continue;
+ assert(ICanvasParticipant.class.isAssignableFrom( c ));
+ assert(!(dep!=null && ref!=null));
+ ReferenceDefinition rd = new ReferenceDefinition();
+ rd.dependency = dep!=null;
+ rd.field = f;
+ rd.requirement = c;
+ f.setAccessible(true);
+ result.add(rd);
+ }
+ */
+
+ Class> superClass = clazz.getSuperclass();
+ if (superClass!=null)
+ _add(obj, superClass, result);
+ }
+
+
+ public final static class HintListenerDefinition implements IHintListener {
+ public final Key key;
+ public final Object object;
+ public Method changedHandlerMethod;
+ public Method removedHandlerMethod;
+
+ public HintListenerDefinition(Key key, Object object) {
+ this.key = key;
+ this.object = object;
+ }
+
+ @Override
+ public void hintChanged(IHintObservable sender, Key key,
+ Object oldValue, Object newValue) {
+ if (changedHandlerMethod==null) return;
+ try {
+ changedHandlerMethod.invoke(object, sender, key, oldValue, newValue);
+ } catch (IllegalArgumentException e) {
+ throw new Error(e);
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ @Override
+ public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
+ if (removedHandlerMethod==null) return;
+ try {
+ removedHandlerMethod.invoke(object, sender, key, oldValue);
+ } catch (IllegalArgumentException e) {
+ throw new Error(e);
+ } catch (IllegalAccessException e) {
+ throw new Error(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+
+ }
+
+}