]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/provisional/GraphPropertyNode.java
Merge "Search deeply for generic superclass in ReflectionUtils" into release/1.35.1
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / provisional / GraphPropertyNode.java
1 /*******************************************************************************
2  * Copyright (c) 2010 Association for Decentralized Information Management in
3  * Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.scenegraph.g2d.nodes.provisional;
13
14 import java.awt.geom.Rectangle2D;
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.lang.reflect.Field;
18 import java.lang.reflect.Modifier;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.concurrent.ConcurrentHashMap;
22
23 import org.simantics.scenegraph.g2d.G2DNode;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * @author Antti Villberg
29  */
30 public abstract class GraphPropertyNode extends G2DNode {
31
32     private static final Logger LOGGER = LoggerFactory.getLogger(GraphPropertyNode.class);
33     private static final long serialVersionUID = 245761992671850588L;
34
35     private static Map<Class<? extends GraphPropertyNode>, Map<String, Field>> fieldCache       = new ConcurrentHashMap<Class<? extends GraphPropertyNode>, Map<String, Field>>();
36
37     protected transient final Map<String, Field> fields;
38
39     private PropertyChangeListener               fieldListener = null;
40
41     protected GraphPropertyNode() {
42         this.fields = getFields(getClass());
43     }
44
45     @Override
46     public void init() {
47         super.init();
48         addEventHandler(this);
49     }
50
51     @Override
52     public void cleanup() {
53         removeEventHandler(this);
54         super.cleanup();
55     }
56
57     public void setFieldListener(PropertyChangeListener listener) {
58         this.fieldListener = listener;
59     }
60
61     public void propertyChange(String field, Object value) {
62     }
63
64     public void setProperty(String field, Object value) {
65         Field f = fields.get(field);
66         if (f == null) {
67             LOGGER.warn("GraphPropertyNode tried to set undefined property '" + field + "'");
68             return;
69         }
70         try {
71             //System.out.println("setting field '" + field + "'");
72             f.set(this, value);
73             propertyChange(field, value);
74         } catch (IllegalArgumentException e) {
75             e.printStackTrace();
76         } catch (IllegalAccessException e) {
77             e.printStackTrace();
78         }
79     }
80
81     public void commitProperty(String field, Object value) {
82         if (fieldListener != null) {
83             fieldListener.propertyChange(new PropertyChangeEvent(this, field, null, value));
84         }
85     }
86
87     public boolean hitTest(double x, double y, double tolerance) {
88         return false;
89     }
90
91     @Override
92     public Rectangle2D getBoundsInLocal() {
93         return null;
94     }
95
96     private static Map<String, Field> getFields(Class<? extends GraphPropertyNode> clazz) {
97         Map<String, Field> fields = fieldCache.get(clazz);
98         if (fields != null)
99             return fields;
100         fields = calculateFields(clazz);
101         fieldCache.put(clazz, fields);
102         return fields;
103     }
104
105     private static Map<String, Field> calculateFields(Class<? extends GraphPropertyNode> clazz) {
106         Map<String, Field> result = new HashMap<String, Field>();
107         for (Class<?> cls = clazz; cls != null && !GraphPropertyNode.class.equals(cls); cls = clazz.getSuperclass()) {
108             for (Field f : cls.getFields()) {
109                 int mod = f.getModifiers();
110                 if (Modifier.isStatic(mod))
111                     continue;
112                 if (Modifier.isTransient(mod))
113                     continue;
114                 if (Modifier.isFinal(mod))
115                     continue;
116                 if (!result.containsKey(f.getName()))
117                     result.put(f.getName(), f);
118             }
119         }
120         return result;
121     }
122
123 }