]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/base/SingleSWTViewNode.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.views.swt.client / src / org / simantics / views / swt / client / base / SingleSWTViewNode.java
diff --git a/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/base/SingleSWTViewNode.java b/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/base/SingleSWTViewNode.java
new file mode 100644 (file)
index 0000000..0312cc4
--- /dev/null
@@ -0,0 +1,299 @@
+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.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);\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);\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