-package org.simantics.views.swt.client.base;\r
-\r
-import java.lang.reflect.Field;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-import org.eclipse.jface.resource.ColorDescriptor;\r
-import org.eclipse.jface.resource.FontDescriptor;\r
-import org.eclipse.jface.resource.ResourceManager;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.binding.ArrayBinding;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.reflection.BindingRequest;\r
-import org.simantics.datatypes.literal.Font;\r
-import org.simantics.datatypes.literal.RGB;\r
-import org.simantics.scenegraph.LoaderNode;\r
-import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.scl.runtime.function.Function2;\r
-import org.simantics.scl.runtime.function.FunctionImpl1;\r
-import org.simantics.ui.colors.Colors;\r
-import org.simantics.ui.fonts.Fonts;\r
-import org.simantics.utils.threads.IThreadWorkQueue;\r
-import org.simantics.utils.threads.SWTThread;\r
-import org.simantics.views.ViewUtils.GridDataBean;\r
-\r
-abstract public class SingleSWTViewNode<T extends Control> extends SWTParentNode implements LoaderNode {\r
- \r
- private static final long serialVersionUID = -5810308021930769003L;\r
- \r
- private Map<String, Object> genericProperties = new HashMap<String, Object>();\r
- \r
- public Function2<String, Object, Boolean> propertyCallback;\r
- public GridDataBean layoutData;\r
- public int style;\r
- public String text;\r
- public RGB.Integer background;\r
- public RGB.Integer foreground;\r
- public Font font;\r
- protected transient ColorDescriptor backgroundDesc;\r
- protected transient ColorDescriptor foregroundDesc;\r
- protected transient FontDescriptor fontDesc;\r
-\r
- protected T control;\r
- \r
- @Override\r
- public Control getControl() {\r
- return control;\r
- }\r
- \r
- @Override\r
- public void reset() {\r
- control = null;\r
- }\r
-\r
- final protected boolean isDisposed() {\r
- Control c = getControl();\r
- return c == null ? false : c.isDisposed();\r
- }\r
-\r
- final protected void dispatch(final Runnable runnable) {\r
- if(isNodeDisposed()) return;\r
- IThreadWorkQueue thread = SWTThread.getThreadAccess();\r
- if(thread.currentThreadAccess()) runnable.run();\r
- else thread.asyncExec(new Runnable() {\r
-\r
- @Override\r
- public void run() {\r
- if(isDisposed()) return;\r
- Control c = control;\r
- if(c == null || c.isDisposed()) return;\r
- runnable.run();\r
- }\r
- \r
- });\r
- }\r
- \r
- private Field getPropertyField(String propertyName) {\r
- assert(!isNodeDisposed());\r
- return ScenegraphLoaderUtils.getPropertyField(this, propertyName);\r
- }\r
-\r
- private Class<?> getPropertyType(Field field) {\r
- return field.getType();\r
- }\r
- \r
- private Binding getPropertyBinding(Field field) {\r
- try {\r
- Binding b = Bindings.getBinding( BindingRequest.create( field ) );\r
-\r
- // Safety checks for unusable bindings.\r
- if (b instanceof ArrayBinding && ((ArrayBinding) b).type().componentType() == null)\r
- return null;\r
-\r
- return b;\r
- } catch (BindingConstructionException e) {\r
- return null;\r
- } catch (Throwable t) {\r
- return null;\r
- }\r
- }\r
- \r
- /**\r
- * Convert binding to generic binding \r
- * @param binding\r
- * @return\r
- */\r
- private Binding getGenericPropertyBinding(Binding binding) {\r
- if (binding == null) return null;\r
- return Bindings.getBinding(binding.type());\r
- }\r
-\r
- @Override\r
- public Function1<Object, Boolean> getPropertyFunction(final String propertyName) {\r
-\r
- if(isNodeDisposed()) return null;\r
- \r
-// assert(!isNodeDisposed());\r
-\r
- final Field field = getPropertyField(propertyName);\r
- if(field != null) {\r
-\r
- return new FunctionImpl1<Object, Boolean>() {\r
-\r
- final Method method = ScenegraphLoaderUtils.getSynchronizeMethod(SingleSWTViewNode.this, propertyName);\r
- final Class<?> type = getPropertyType(field);\r
- final Binding binding = getPropertyBinding(field);\r
- final Binding genericBinding = getGenericPropertyBinding(binding);\r
-\r
- private Object setField(Object value) {\r
-\r
- try {\r
- if(type.isPrimitive() || (value == null) || type.isInstance(value) || type.isArray()) {\r
- field.set(SingleSWTViewNode.this, value);\r
- return value;\r
- } else {\r
- Object instance = binding.createDefaultUnchecked();\r
- binding.readFrom(genericBinding, value, instance);\r
- field.set(SingleSWTViewNode.this, instance);\r
- return instance;\r
- }\r
- } catch (IllegalArgumentException e1) {\r
- e1.printStackTrace();\r
- } catch (IllegalAccessException e1) {\r
- e1.printStackTrace();\r
- } catch (BindingException e) {\r
- e.printStackTrace();\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- }\r
-\r
- return null;\r
-\r
- }\r
-\r
- @Override\r
- public Boolean apply(Object value) {\r
-\r
- if(isNodeDisposed()) return true;\r
-\r
- final Object translated = setField(value);\r
-\r
- if(method != null) {\r
- dispatch(new Runnable() {\r
- \r
- @Override\r
- public void run() {\r
- \r
- try {\r
- method.invoke(SingleSWTViewNode.this, translated);\r
- } catch (IllegalArgumentException e) {\r
- e.printStackTrace();\r
- } catch (IllegalAccessException e) {\r
- e.printStackTrace();\r
- } catch (InvocationTargetException e) {\r
- e.getCause().printStackTrace();\r
- }\r
- }\r
- \r
- });\r
- }\r
- return isDisposed();\r
- }\r
-\r
- };\r
-\r
- } else {\r
-\r
- return new FunctionImpl1<Object, Boolean>() {\r
-\r
- @Override\r
- public Boolean apply(Object p0) {\r
- assert(!isNodeDisposed());\r
- genericProperties.put(propertyName, p0);\r
- return isDisposed();\r
- }\r
-\r
- };\r
-\r
- }\r
-\r
- }\r
-\r
- @Override\r
- public void setPropertyCallback(Function2<String, Object, Boolean> callback) {\r
- this.propertyCallback = callback;\r
- }\r
- \r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T2> T2 getProperty(String propertyName) {\r
-\r
- Method m = ScenegraphLoaderUtils.getReadMethod(this, propertyName);\r
- if(m != null) {\r
-\r
- try {\r
- return (T2)m.invoke(this);\r
- } catch (IllegalArgumentException e) {\r
- throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);\r
- } catch (IllegalAccessException e) {\r
- throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);\r
- } catch (InvocationTargetException e) {\r
- throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e.getCause());\r
- }\r
- \r
- } else {\r
- return (T2)genericProperties.get(propertyName);\r
- }\r
- \r
- }\r
- \r
- protected void setProperties() {\r
- for(Method m : getClass().getMethods()) {\r
- if(m.getName().startsWith("synchronize")) {\r
- String upperFieldName = m.getName().substring("synchronize".length());\r
- String fieldName = upperFieldName.substring(0,1).toLowerCase() + upperFieldName.substring(1);\r
- Field f = ScenegraphLoaderUtils.getPropertyField(this, fieldName);\r
- try {\r
- m.invoke(this, f.get(this));\r
- } catch (IllegalArgumentException e) {\r
- throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);\r
- } catch (IllegalAccessException e) {\r
- throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);\r
- } catch (InvocationTargetException e) {\r
- throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e.getCause());\r
- }\r
- }\r
- }\r
- }\r
- \r
- public void synchronizeText(String text) {\r
- }\r
-\r
- final public void synchronizeFont(Font font) {\r
- if (font == null && fontDesc == null)\r
- return;\r
- ResourceManager rm = getResourceManager();\r
- FontDescriptor oldDesc = fontDesc;\r
- if (font != null)\r
- control.setFont( getResourceManager().createFont( fontDesc = Fonts.swt(font) ) );\r
- if (oldDesc != null)\r
- rm.destroy(oldDesc);\r
- }\r
- \r
- final public void synchronizeForeground(RGB.Integer foreground) {\r
- if (foreground == null && foregroundDesc == null)\r
- return;\r
- ResourceManager rm = getResourceManager();\r
- ColorDescriptor oldDesc = foregroundDesc;\r
- if (foreground != null)\r
- control.setForeground( getResourceManager().createColor( foregroundDesc = Colors.swt(foreground) ) );\r
- if (oldDesc != null)\r
- rm.destroy(oldDesc);\r
- }\r
-\r
- final public void synchronizeBackground(RGB.Integer background) {\r
- if (background == null && backgroundDesc == null)\r
- return;\r
- ResourceManager rm = getResourceManager();\r
- ColorDescriptor oldDesc = backgroundDesc;\r
- if (background != null)\r
- control.setBackground( getResourceManager().createColor( backgroundDesc = Colors.swt(background) ) );\r
- if (oldDesc != null)\r
- rm.destroy(oldDesc);\r
- }\r
-\r
- final public void synchronizeStyle(int style) {\r
- }\r
-\r
- final public void synchronizeLayoutData(GridDataBean layoutData) {\r
- if(layoutData != null) control.setLayoutData(SWTViewUtils.toGridData(layoutData));\r
- }\r
- \r
-}\r
+package org.simantics.views.swt.client.base;
+
+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.eclipse.jface.resource.ColorDescriptor;
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.swt.widgets.Control;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.ArrayBinding;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.reflection.BindingRequest;
+import org.simantics.datatypes.literal.Font;
+import org.simantics.datatypes.literal.RGB;
+import org.simantics.scenegraph.LoaderNode;
+import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.Function2;
+import org.simantics.scl.runtime.function.FunctionImpl1;
+import org.simantics.ui.colors.Colors;
+import org.simantics.ui.fonts.Fonts;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.SWTThread;
+import org.simantics.views.ViewUtils.LayoutDataBean;
+
+abstract public class SingleSWTViewNode<T extends Control> extends SWTParentNode implements LoaderNode {
+
+ private static final long serialVersionUID = -5810308021930769003L;
+
+ private Map<String, Object> genericProperties = new HashMap<String, Object>();
+
+ public Function2<String, Object, Boolean> propertyCallback;
+ public LayoutDataBean layoutData;
+ public int style;
+ public String text;
+ public RGB.Integer background;
+ public RGB.Integer foreground;
+ public Font font;
+ protected transient ColorDescriptor backgroundDesc;
+ protected transient ColorDescriptor foregroundDesc;
+ protected transient FontDescriptor fontDesc;
+
+ protected T control;
+
+ @Override
+ public Control getControl() {
+ return control;
+ }
+
+ @Override
+ public void reset() {
+ control = null;
+ }
+
+ final protected boolean isDisposed() {
+ Control c = getControl();
+ return c == null ? false : c.isDisposed();
+ }
+
+ final protected void dispatch(final Runnable runnable) {
+ if(isNodeDisposed()) return;
+ IThreadWorkQueue thread = SWTThread.getThreadAccess();
+ if(thread.currentThreadAccess()) runnable.run();
+ else thread.asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ if(isDisposed()) return;
+ Control c = control;
+ if(c == null || c.isDisposed()) return;
+ runnable.run();
+ }
+
+ });
+ }
+
+ private Field getPropertyField(String propertyName) {
+ assert(!isNodeDisposed());
+ return ScenegraphLoaderUtils.getPropertyField(this, propertyName);
+ }
+
+ private Class<?> getPropertyType(Field field) {
+ return field.getType();
+ }
+
+ private Binding getPropertyBinding(Field field) {
+ try {
+ Binding b = Bindings.getBinding( BindingRequest.create( field ) );
+
+ // Safety checks for unusable bindings.
+ if (b instanceof ArrayBinding && ((ArrayBinding) b).type().componentType() == null)
+ return null;
+
+ return b;
+ } catch (BindingConstructionException e) {
+ return null;
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ /**
+ * Convert binding to generic binding
+ * @param binding
+ * @return
+ */
+ private Binding getGenericPropertyBinding(Binding binding) {
+ if (binding == null) return null;
+ return Bindings.getBinding(binding.type());
+ }
+
+ @Override
+ public Function1<Object, Boolean> getPropertyFunction(final String propertyName) {
+
+ if(isNodeDisposed()) return null;
+
+// assert(!isNodeDisposed());
+
+ final Field field = getPropertyField(propertyName);
+ if(field != null) {
+
+ return new FunctionImpl1<Object, Boolean>() {
+
+ final Method method = ScenegraphLoaderUtils.getSynchronizeMethod(SingleSWTViewNode.this, propertyName);
+ final Class<?> type = getPropertyType(field);
+ final Binding binding = getPropertyBinding(field);
+ final Binding genericBinding = getGenericPropertyBinding(binding);
+
+ private Object setField(Object value) {
+
+ try {
+ if(type.isPrimitive() || (value == null) || type.isInstance(value) || type.isArray()) {
+ field.set(SingleSWTViewNode.this, value);
+ return value;
+ } else {
+ Object instance = binding.createDefaultUnchecked();
+ binding.readFrom(genericBinding, value, instance);
+ field.set(SingleSWTViewNode.this, instance);
+ return instance;
+ }
+ } catch (IllegalArgumentException e1) {
+ e1.printStackTrace();
+ } catch (IllegalAccessException e1) {
+ e1.printStackTrace();
+ } catch (BindingException e) {
+ e.printStackTrace();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public Boolean apply(Object value) {
+
+ if(isNodeDisposed()) return true;
+
+ final Object translated = setField(value);
+
+ if(method != null) {
+ dispatch(new Runnable() {
+
+ @Override
+ public void run() {
+
+ try {
+ method.invoke(SingleSWTViewNode.this, translated);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.getCause().printStackTrace();
+ }
+ }
+
+ });
+ }
+ return isDisposed();
+ }
+
+ };
+
+ } else {
+
+ return new FunctionImpl1<Object, Boolean>() {
+
+ @Override
+ public Boolean apply(Object p0) {
+ assert(!isNodeDisposed());
+ genericProperties.put(propertyName, p0);
+ return isDisposed();
+ }
+
+ };
+
+ }
+
+ }
+
+ @Override
+ public void setPropertyCallback(Function2<String, Object, Boolean> callback) {
+ this.propertyCallback = callback;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T2> T2 getProperty(String propertyName) {
+
+ Method m = ScenegraphLoaderUtils.getReadMethod(this, propertyName);
+ if(m != null) {
+
+ try {
+ return (T2)m.invoke(this);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Failed to get property '" + propertyName + "' for " + getClass().getName(), e.getCause());
+ }
+
+ } else {
+ return (T2)genericProperties.get(propertyName);
+ }
+
+ }
+
+ protected void setProperties() {
+ for(Method m : getClass().getMethods()) {
+ if(m.getName().startsWith("synchronize")) {
+ String upperFieldName = m.getName().substring("synchronize".length());
+ String fieldName = upperFieldName.substring(0,1).toLowerCase() + upperFieldName.substring(1);
+ Field f = ScenegraphLoaderUtils.getPropertyField(this, fieldName);
+ try {
+ m.invoke(this, f.get(this));
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Failed to set property '" + fieldName + "' for " + getClass().getName(), e.getCause());
+ }
+ }
+ }
+ }
+
+ public void synchronizeText(String text) {
+ }
+
+ final public void synchronizeFont(Font font) {
+ if (font == null && fontDesc == null)
+ return;
+ ResourceManager rm = getResourceManager();
+ FontDescriptor oldDesc = fontDesc;
+ if (font != null)
+ control.setFont( getResourceManager().createFont( fontDesc = Fonts.swt(font) ) );
+ if (oldDesc != null)
+ rm.destroy(oldDesc);
+ }
+
+ final public void synchronizeForeground(RGB.Integer foreground) {
+ if (foreground == null && foregroundDesc == null)
+ return;
+ ResourceManager rm = getResourceManager();
+ ColorDescriptor oldDesc = foregroundDesc;
+ if (foreground != null)
+ control.setForeground( getResourceManager().createColor( foregroundDesc = Colors.swt(foreground) ) );
+ if (oldDesc != null)
+ rm.destroy(oldDesc);
+ }
+
+ final public void synchronizeBackground(RGB.Integer background) {
+ if (background == null && backgroundDesc == null)
+ return;
+ ResourceManager rm = getResourceManager();
+ ColorDescriptor oldDesc = backgroundDesc;
+ if (background != null)
+ control.setBackground( getResourceManager().createColor( backgroundDesc = Colors.swt(background) ) );
+ if (oldDesc != null)
+ rm.destroy(oldDesc);
+ }
+
+ final public void synchronizeStyle(int style) {
+ }
+
+ final public void synchronizeLayoutData(LayoutDataBean layoutData) {
+ if(layoutData != null) control.setLayoutData(SWTViewUtils.toLayoutData(layoutData));
+ }
+
+}