]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/base/SingleSWTViewNode.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.views.swt.client / src / org / simantics / views / swt / client / base / SingleSWTViewNode.java
1 package org.simantics.views.swt.client.base;
2
3 import java.lang.reflect.Field;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Method;
6 import java.util.HashMap;
7 import java.util.Map;
8
9 import org.eclipse.jface.resource.ColorDescriptor;
10 import org.eclipse.jface.resource.FontDescriptor;
11 import org.eclipse.jface.resource.ResourceManager;
12 import org.eclipse.swt.widgets.Control;
13 import org.simantics.databoard.Bindings;
14 import org.simantics.databoard.binding.ArrayBinding;
15 import org.simantics.databoard.binding.Binding;
16 import org.simantics.databoard.binding.error.BindingConstructionException;
17 import org.simantics.databoard.binding.error.BindingException;
18 import org.simantics.databoard.binding.reflection.BindingRequest;
19 import org.simantics.datatypes.literal.Font;
20 import org.simantics.datatypes.literal.RGB;
21 import org.simantics.scenegraph.LoaderNode;
22 import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;
23 import org.simantics.scl.runtime.function.Function1;
24 import org.simantics.scl.runtime.function.Function2;
25 import org.simantics.scl.runtime.function.FunctionImpl1;
26 import org.simantics.ui.colors.Colors;
27 import org.simantics.ui.fonts.Fonts;
28 import org.simantics.utils.threads.IThreadWorkQueue;
29 import org.simantics.utils.threads.SWTThread;
30 import org.simantics.views.ViewUtils.LayoutDataBean;
31
32 abstract public class SingleSWTViewNode<T extends Control> extends SWTParentNode implements LoaderNode {
33         
34         private static final long serialVersionUID = -5810308021930769003L;
35         
36         private Map<String, Object> genericProperties = new HashMap<String, Object>();
37         
38         public Function2<String, Object, Boolean> propertyCallback;
39         public LayoutDataBean layoutData;
40         public int style;
41         public String text;
42         public RGB.Integer background;
43         public RGB.Integer foreground;
44         public Font font;
45         protected transient ColorDescriptor backgroundDesc;
46         protected transient ColorDescriptor foregroundDesc;
47         protected transient FontDescriptor fontDesc;
48
49         protected T control;
50         
51         @Override
52         public Control getControl() {
53                 return control;
54         }
55         
56         @Override
57         public void reset() {
58                 control = null;
59         }
60
61         final protected boolean isDisposed() {
62                 Control c = getControl();
63                 return c == null ? false : c.isDisposed();
64         }
65
66         final protected void dispatch(final Runnable runnable) {
67             if(isNodeDisposed()) return;
68                 IThreadWorkQueue thread = SWTThread.getThreadAccess();
69                 if(thread.currentThreadAccess()) runnable.run();
70                 else thread.asyncExec(new Runnable() {
71
72                         @Override
73                         public void run() {
74                                 if(isDisposed()) return;
75                                 Control c = control;
76                                 if(c == null || c.isDisposed()) return;
77                                 runnable.run();
78                         }
79                         
80                 });
81         }
82         
83         private Field getPropertyField(String propertyName) {
84                 assert(!isNodeDisposed());
85                 return ScenegraphLoaderUtils.getPropertyField(this, propertyName);
86         }
87
88         private Class<?> getPropertyType(Field field) {
89                 return field.getType();
90         }
91         
92         private Binding getPropertyBinding(Field field) {
93                 try {
94                         Binding b = Bindings.getBinding( BindingRequest.create( field ) );
95
96                         // Safety checks for unusable bindings.
97                         if (b instanceof ArrayBinding && ((ArrayBinding) b).type().componentType() == null)
98                                 return null;
99
100                         return b;
101                 } catch (BindingConstructionException e) {
102                         return null;
103                 } catch (Throwable t) {
104                         return null;
105                 }
106         }
107         
108         /**
109          * Convert binding to generic binding 
110          * @param binding
111          * @return
112          */
113         private Binding getGenericPropertyBinding(Binding binding) {
114                 if (binding == null) return null;
115                 return Bindings.getBinding(binding.type());
116         }
117
118         @Override
119         public Function1<Object, Boolean> getPropertyFunction(final String propertyName) {
120
121             if(isNodeDisposed()) return null;
122             
123 //              assert(!isNodeDisposed());
124
125                 final Field field = getPropertyField(propertyName);
126                 if(field != null) {
127
128                         return new FunctionImpl1<Object, Boolean>() {
129
130                                 final Method method = ScenegraphLoaderUtils.getSynchronizeMethod(SingleSWTViewNode.this, propertyName);
131                                 final Class<?> type = getPropertyType(field);
132                                 final Binding binding = getPropertyBinding(field);
133                                 final Binding genericBinding = getGenericPropertyBinding(binding);
134
135                                 private Object setField(Object value) {
136
137                                         try {
138                                                 if(type.isPrimitive() || (value == null) || type.isInstance(value) || type.isArray()) {
139                                                         field.set(SingleSWTViewNode.this, value);
140                                                         return value;
141                                                 } else {
142                                                         Object instance = binding.createDefaultUnchecked();
143                                                         binding.readFrom(genericBinding, value, instance);
144                                                         field.set(SingleSWTViewNode.this, instance);
145                                                         return instance;
146                                                 }
147                                         } catch (IllegalArgumentException e1) {
148                                                 e1.printStackTrace();
149                                         } catch (IllegalAccessException e1) {
150                                                 e1.printStackTrace();
151                                         } catch (BindingException e) {
152                                                 e.printStackTrace();
153                                         } catch (Throwable t) {
154                                                 t.printStackTrace();
155                                         }
156
157                                         return null;
158
159                                 }
160
161                                 @Override
162                                 public Boolean apply(Object value) {
163
164                                         if(isNodeDisposed()) return true;
165
166                                         final Object translated = setField(value);
167
168                                         if(method != null) {
169                                                 dispatch(new Runnable() {
170         
171                                                         @Override
172                                                         public void run() {
173         
174                                                                 try {
175                                                                         method.invoke(SingleSWTViewNode.this, translated);
176                                                                 } catch (IllegalArgumentException e) {
177                                                                         e.printStackTrace();
178                                                                 } catch (IllegalAccessException e) {
179                                                                         e.printStackTrace();
180                                                                 } catch (InvocationTargetException e) {
181                                                                         e.getCause().printStackTrace();
182                                                                 }
183                                                         }
184         
185                                                 });
186                                         }
187                                         return isDisposed();
188                                 }
189
190                         };
191
192                 } else {
193
194                         return new FunctionImpl1<Object, Boolean>() {
195
196                                 @Override
197                                 public Boolean apply(Object p0) {
198                                         assert(!isNodeDisposed());
199                                         genericProperties.put(propertyName, p0);
200                                         return isDisposed();
201                                 }
202
203                         };
204
205                 }
206
207         }
208
209         @Override
210         public void setPropertyCallback(Function2<String, Object, Boolean> callback) {
211                 this.propertyCallback = callback;
212         }
213         
214         @SuppressWarnings("unchecked")
215         @Override
216         public <T2> T2 getProperty(String propertyName) {
217
218                 Method m = ScenegraphLoaderUtils.getReadMethod(this, propertyName);
219                 if(m != null) {
220
221                         try {
222                                 return (T2)m.invoke(this);
223                         } catch (IllegalArgumentException e) {
224                                 throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);
225                         } catch (IllegalAccessException e) {
226                                 throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);
227                         } catch (InvocationTargetException e) {
228                                 throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e.getCause());
229                         }
230                         
231                 } else {
232                         return (T2)genericProperties.get(propertyName);
233                 }
234                 
235         }
236         
237         protected void setProperties() {
238                 for(Method m : getClass().getMethods()) {
239                         if(m.getName().startsWith("synchronize")) {
240                                 String upperFieldName = m.getName().substring("synchronize".length());
241                                 String fieldName = upperFieldName.substring(0,1).toLowerCase() + upperFieldName.substring(1);
242                                 Field f = ScenegraphLoaderUtils.getPropertyField(this, fieldName);
243                                 try {
244                                         m.invoke(this, f.get(this));
245                                 } catch (IllegalArgumentException e) {
246                                         throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);
247                                 } catch (IllegalAccessException e) {
248                                         throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);
249                                 } catch (InvocationTargetException e) {
250                                         throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e.getCause());
251                                 }
252                         }
253                 }
254         }
255         
256         public void synchronizeText(String text) {
257         }
258
259         final public void synchronizeFont(Font font) {
260                 if (font == null && fontDesc == null)
261                         return;
262                 ResourceManager rm = getResourceManager();
263                 FontDescriptor oldDesc = fontDesc;
264                 if (font != null)
265                         control.setFont( getResourceManager().createFont( fontDesc = Fonts.swt(font) ) );
266                 if (oldDesc != null)
267                         rm.destroy(oldDesc);
268         }
269         
270         final public void synchronizeForeground(RGB.Integer foreground) {
271                 if (foreground == null && foregroundDesc == null)
272                         return;
273                 ResourceManager rm = getResourceManager();
274                 ColorDescriptor oldDesc = foregroundDesc;
275                 if (foreground != null)
276                         control.setForeground( getResourceManager().createColor( foregroundDesc = Colors.swt(foreground) ) );
277                 if (oldDesc != null)
278                         rm.destroy(oldDesc);
279         }
280
281         final public void synchronizeBackground(RGB.Integer background) {
282                 if (background == null && backgroundDesc == null)
283                         return;
284                 ResourceManager rm = getResourceManager();
285                 ColorDescriptor oldDesc = backgroundDesc;
286                 if (background != null)
287                         control.setBackground( getResourceManager().createColor( backgroundDesc = Colors.swt(background) ) );
288                 if (oldDesc != null)
289                         rm.destroy(oldDesc);
290         }
291
292         final public void synchronizeStyle(int style) {
293         }
294
295         final public void synchronizeLayoutData(LayoutDataBean layoutData) {
296                 if(layoutData != null) control.setLayoutData(SWTViewUtils.toLayoutData(layoutData));
297         }
298         
299 }