/******************************************************************************* * Copyright (c) 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.scenegraph.g2d.nodes.provisional; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.simantics.scenegraph.g2d.G2DNode; /** * @author Antti Villberg */ public abstract class GraphPropertyNode extends G2DNode { private static final long serialVersionUID = 245761992671850588L; private static Map, Map> fieldCache = new ConcurrentHashMap, Map>(); protected transient final Map fields; private PropertyChangeListener fieldListener = null; protected GraphPropertyNode() { this.fields = getFields(getClass()); } @Override public void init() { super.init(); addEventHandler(this); } @Override public void cleanup() { removeEventHandler(this); super.cleanup(); } public void setFieldListener(PropertyChangeListener listener) { this.fieldListener = listener; } public void propertyChange(String field, Object value) { } public void setProperty(String field, Object value) { Field f = fields.get(field); if (f == null) { System.err.println("GraphPropertyNode tried to set undefined property '" + field + "'"); return; } try { //System.out.println("setting field '" + field + "'"); f.set(this, value); propertyChange(field, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } public void commitProperty(String field, Object value) { if (fieldListener != null) { fieldListener.propertyChange(new PropertyChangeEvent(this, field, null, value)); } } public boolean hitTest(double x, double y, double tolerance) { return false; } @Override public Rectangle2D getBoundsInLocal() { return null; } private static Map getFields(Class clazz) { Map fields = fieldCache.get(clazz); if (fields != null) return fields; fields = calculateFields(clazz); fieldCache.put(clazz, fields); return fields; } private static Map calculateFields(Class clazz) { Map result = new HashMap(); for (Class cls = clazz; cls != null && !GraphPropertyNode.class.equals(cls); cls = clazz.getSuperclass()) { for (Field f : cls.getFields()) { int mod = f.getModifiers(); if (Modifier.isStatic(mod)) continue; if (Modifier.isTransient(mod)) continue; if (Modifier.isFinal(mod)) continue; if (!result.containsKey(f.getName())) result.put(f.getName(), f); } } return result; } }