]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Equation view changed to tabbed property view
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 16 Jun 2010 13:09:27 +0000 (13:09 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 16 Jun 2010 13:09:27 +0000 (13:09 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@16180 ac1ea38d-2e2b-0410-8846-a27921b304fc

27 files changed:
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypeWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/NameWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/UnitWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java [new file with mode: 0644]

index 4ced7a1153ecc43b475ad87641073d0be6a796b0..ae0d05349020475475ce034f833c1b6ae21b0b37 100644 (file)
@@ -35,7 +35,7 @@ public class SysdynPerspectiveFactory implements IPerspectiveFactory {
 \r
         IFolderLayout bottom1 = layout.createFolder("bottom1", IPageLayout.BOTTOM, 0.75f, editorArea);\r
         IFolderLayout bottom2 = layout.createFolder("bottom2", IPageLayout.LEFT, 0.4f, "bottom1");\r
-        bottom1.addView("org.simantics.sysdyn.ui.equation.view");\r
+        bottom1.addView("org.simantics.browsing.ui.graph.propertyView");\r
         bottom1.addView(IConsoleConstants.ID_CONSOLE_VIEW);\r
         bottom1.addView("org.simantics.sysdyn.ui.configurationView");\r
         bottom2.addView("org.simantics.sysdyn.ui.trend.view");\r
index 2c628aa7f160a7f6f7c989c948fa21964eb32b9e..9a0972ee719266315e99752317bfe8b417426508 100644 (file)
@@ -3,8 +3,20 @@ package org.simantics.sysdyn.ui.properties;
 import org.eclipse.jface.layout.GridDataFactory;\r
 import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
 import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.graphics.Point;\r
 import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableItem;\r
 import org.eclipse.ui.IWorkbenchSite;\r
 import org.simantics.browsing.ui.swt.PropertyTabContributorImpl;\r
 import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
@@ -13,6 +25,7 @@ import org.simantics.db.Builtins;
 import org.simantics.db.management.ISessionContext;\r
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypeWidget;\r
+import org.simantics.sysdyn.ui.properties.widgets.ExpressionWidget;\r
 import org.simantics.sysdyn.ui.properties.widgets.NameWidget;\r
 import org.simantics.sysdyn.ui.properties.widgets.ShortcutTabWidget;\r
 import org.simantics.sysdyn.ui.properties.widgets.UnitWidget;\r
@@ -20,23 +33,125 @@ import org.simantics.sysdyn.ui.properties.widgets.UnitWidget;
 public class EquationTab extends PropertyTabContributorImpl {\r
 \r
     static public final Font FONT = new Font(null, "Courier New", 12, SWT.NORMAL);\r
-    \r
+\r
+    NameWidget nameWidget;\r
+    ExpressionTypeWidget expressionTypeWidget;\r
+    UnitWidget unitWidget;\r
+    ShortcutTabWidget shortcutTabWidget;\r
+    ExpressionWidget expressionWidget;\r
+\r
     @Override\r
     public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) {\r
         Composite composite = new Composite(body, SWT.NONE);\r
         GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
-        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(composite);\r
-        NameWidget nameWidget = new NameWidget(composite, support, SWT.BORDER);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite);\r
+        nameWidget = new NameWidget(composite, support, SWT.BORDER);\r
         nameWidget.setTextFactory(new StringPropertyFactory(context, Builtins.URIs.HasName));\r
-        \r
-        @SuppressWarnings("unused")\r
-        ExpressionTypeWidget expressionTypeWidget = new ExpressionTypeWidget(composite, support, SWT.NONE);\r
-        \r
-        UnitWidget unitWidget = new UnitWidget(composite, support, SWT.NONE);\r
+\r
+\r
+        Label label = new Label(composite, SWT.SINGLE );\r
+        label.setFont(EquationTab.FONT);\r
+        label.setText("Type:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+        expressionTypeWidget = new ExpressionTypeWidget(composite, support, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);\r
+\r
+\r
+        label = new Label(composite, SWT.SINGLE );\r
+        label.setFont(EquationTab.FONT);\r
+        label.setText("Unit:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+        unitWidget = new UnitWidget(composite, support, SWT.DROP_DOWN | SWT.BORDER);\r
         unitWidget.setTextFactory(new StringPropertyFactory(context, SysdynResource.URIs.HasUnit));\r
+\r
+        shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE);\r
+\r
+\r
+        Composite expressionComposite = new Composite(composite, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).span(5, 1).applyTo(expressionComposite);\r
+        expressionWidget = new ExpressionWidget(expressionComposite, support, SWT.NONE);\r
+\r
+        addListeners();\r
+    }\r
+\r
+    private void addListeners() {\r
+\r
+        expressionTypeWidget.addSelectionListener(new SelectionListener() {\r
+\r
+            @Override\r
+            public void widgetSelected(SelectionEvent e) {\r
+                expressionWidget.displayExpression(expressionTypeWidget.getSelecetedType(), false);\r
+            }\r
+\r
+            @Override\r
+            public void widgetDefaultSelected(SelectionEvent e) {\r
+            }\r
+        });\r
+\r
+        shortcutTabWidget.addMouseListener(new MouseListener(){\r
+\r
+            @Override\r
+            public void mouseDoubleClick(MouseEvent e) {\r
+                Table table = (Table)e.widget;\r
+                TableItem item = table.getItem(new Point(e.x, e.y));\r
+                if(item != null) {\r
+                    final String var = (String)item.getData();\r
+                    table.getDisplay().asyncExec(new Runnable() {\r
+\r
+                        @Override\r
+                        public void run() {\r
+                            if(expressionWidget!= null) {\r
+                                expressionWidget.getExpression().replaceSelection(var);\r
+                            }\r
+                        }\r
+                    });\r
+                }\r
+            }\r
+\r
+            @Override\r
+            public void mouseDown(MouseEvent e) {\r
+                expressionWidget.getExpression().focus();\r
+            }\r
+\r
+            @Override\r
+            public void mouseUp(MouseEvent e) {\r
+                expressionWidget.getExpression().focus();\r
+            }\r
+\r
+        });\r
+        shortcutTabWidget.addFocusListener(new FocusListener() {\r
+\r
+            @Override\r
+            public void focusGained(FocusEvent e) {    \r
+            }\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                ((Table)e.widget).deselectAll();\r
+            }\r
+\r
+        });\r
+\r
+        expressionWidget.addModifyListener(new ModifyListener() {\r
+\r
+            @Override\r
+            public void modifyText(ModifyEvent e) {\r
+                expressionWidget.validateFields(shortcutTabWidget.getVariableTable().getItems());\r
+            }\r
+        });\r
         \r
-        @SuppressWarnings("unused")\r
-        ShortcutTabWidget shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE);\r
-        \r
+        expressionWidget.addFocusListener(new FocusListener() {\r
+            \r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                expressionWidget.save();\r
+            }\r
+            \r
+            @Override\r
+            public void focusGained(FocusEvent e) {\r
+                expressionWidget.validateFields(shortcutTabWidget.getVariableTable().getItems());\r
+            }\r
+        });   \r
     }\r
 }\r
index a3b0f8f6d60ab3f51f40e67f1fee67b68c9bdec0..7e042f2e6a584e8b2fea9d9bf1fbbbaf1c0d0959 100644 (file)
@@ -10,7 +10,6 @@ public class SysdynPropertyPage extends StandardPropertyPage {
     \r
     public SysdynPropertyPage(IWorkbenchPartSite site, Set<String> set) {\r
         super(site, set);\r
-        System.out.println("sysdynpropertypage");\r
     }\r
 \r
 }\r
index fb299a7d8da214c1845bb7524985719797f1b170..ef1da39de655efd1803a5bb3d8f43878079307d2 100644 (file)
@@ -2,14 +2,12 @@ package org.simantics.sysdyn.ui.properties.widgets;
 \r
 \r
 import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.jface.viewers.IStructuredSelection;\r
-import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionListener;\r
 import org.eclipse.swt.graphics.FontMetrics;\r
 import org.eclipse.swt.graphics.GC;\r
 import org.eclipse.swt.widgets.Combo;\r
 import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Label;\r
 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
 import org.simantics.db.ReadGraph;\r
@@ -28,17 +26,8 @@ public class ExpressionTypeWidget implements Widget {
 \r
     public ExpressionTypeWidget(Composite parent, WidgetSupport support, int style) {\r
         support.register(this);\r
-        \r
-        Composite composite = new Composite(parent, style);\r
-        GridDataFactory.fillDefaults().applyTo(composite);\r
-        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);\r
 \r
-        Label label = new Label(composite, SWT.SINGLE );\r
-        label.setFont(EquationTab.FONT);\r
-        label.setText("Type:");\r
-        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
-\r
-        typeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);\r
+        typeCombo = new Combo(parent, style);\r
         typeCombo.setFont(EquationTab.FONT);\r
 \r
         int columns = 6;\r
@@ -55,6 +44,7 @@ public class ExpressionTypeWidget implements Widget {
         if(input instanceof IStructuredSelection) {\r
             final Resource variable = ISelectionUtils.filterSingleSelection((IStructuredSelection)input, Resource.class);\r
             if(variable != null) {\r
+                final ExpressionType et = ExpressionTypes.getExpressionTypeForVariable(variable);\r
                 SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
                     @Override\r
                     public void run(ReadGraph graph) throws DatabaseException {\r
@@ -69,40 +59,7 @@ public class ExpressionTypeWidget implements Widget {
                             expressionTypes = ExpressionTypes.valveExpressions;\r
                         else\r
                             expressionTypes = new ExpressionType[] {};\r
-                        \r
-                        \r
-                        final ExpressionType et;\r
-                        Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
-                        if(expression == null) {\r
-                            if(graph.isInstanceOf(variable, sr.Auxiliary)) {\r
-                                et = ExpressionType.Auxiliary;\r
-                            }\r
-                            else if(graph.isInstanceOf(variable, sr.Valve)) {\r
-                                et = ExpressionType.Auxiliary;\r
-                            }\r
-                            else if(graph.isInstanceOf(variable, sr.Stock)) {\r
-                                et = ExpressionType.Stock;\r
-                            } else\r
-                                et = ExpressionType.Empty;\r
-                        } else {\r
-                            if(graph.isInstanceOf(expression, sr.NormalExpression)) {\r
-                                et = ExpressionType.Auxiliary;\r
-                            } else if (graph.isInstanceOf(expression, sr.StockExpression)) {\r
-                                et = ExpressionType.Stock;\r
-                            } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) {\r
-                                et = ExpressionType.Parameter;\r
-                            } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) {\r
-                                et = ExpressionType.Constant;\r
-                            } else if (graph.isInstanceOf(expression, sr.DelayExpression)) {\r
-                                et = ExpressionType.Delay;\r
-                            } else if (graph.isInstanceOf(expression, sr.LookupExpression)) {\r
-                                et = ExpressionType.Lookup;\r
-                            } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
-                                et = ExpressionType.WithLookup;\r
-                            } else {\r
-                                et =  ExpressionType.Empty;\r
-                            }\r
-                        }\r
+                         \r
                         \r
                         typeCombo.getDisplay().asyncExec(new Runnable() {\r
                             \r
@@ -135,4 +92,13 @@ public class ExpressionTypeWidget implements Widget {
             typeCombo.select(index);\r
         }\r
     }\r
+    \r
+    \r
+    public void addSelectionListener(SelectionListener listener) {\r
+        this.typeCombo.addSelectionListener(listener);\r
+    }\r
+\r
+    public String getSelecetedType() {\r
+        return this.typeCombo.getItem(this.typeCombo.getSelectionIndex());\r
+    }\r
 }\r
index 4cebd8a7c013a8c7a9c1351667cd908b50134b93..fdc1f986b8b0dc85eac9f9c1d4b6dff7df1ca640 100644 (file)
@@ -1,5 +1,12 @@
 package org.simantics.sysdyn.ui.properties.widgets;\r
 \r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
 public class ExpressionTypes {\r
     \r
     public static enum ExpressionType {Auxiliary, Parameter, Constant, Lookup, WithLookup, Stock, Delay, Empty};\r
@@ -19,5 +26,54 @@ public class ExpressionTypes {
 \r
     public static ExpressionType[] stockExpressions = new ExpressionType[] {\r
             ExpressionType.Stock};\r
+    \r
+    public static ExpressionType getExpressionTypeForVariable(final Resource variable) {\r
+        try {\r
+            return SimanticsUI.getSession().syncRequest(new Read<ExpressionType>() {\r
+\r
+                @Override\r
+                public ExpressionType perform(ReadGraph graph) throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(graph);\r
+                    final ExpressionType et;\r
+                    Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
+                    if(expression == null) {\r
+                        if(graph.isInstanceOf(variable, sr.Auxiliary)) {\r
+                            et = ExpressionType.Auxiliary;\r
+                        }\r
+                        else if(graph.isInstanceOf(variable, sr.Valve)) {\r
+                            et = ExpressionType.Auxiliary;\r
+                        }\r
+                        else if(graph.isInstanceOf(variable, sr.Stock)) {\r
+                            et = ExpressionType.Stock;\r
+                        } else\r
+                            et = ExpressionType.Empty;\r
+                    } else {\r
+                        if(graph.isInstanceOf(expression, sr.NormalExpression)) {\r
+                            et = ExpressionType.Auxiliary;\r
+                        } else if (graph.isInstanceOf(expression, sr.StockExpression)) {\r
+                            et = ExpressionType.Stock;\r
+                        } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) {\r
+                            et = ExpressionType.Parameter;\r
+                        } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) {\r
+                            et = ExpressionType.Constant;\r
+                        } else if (graph.isInstanceOf(expression, sr.DelayExpression)) {\r
+                            et = ExpressionType.Delay;\r
+                        } else if (graph.isInstanceOf(expression, sr.LookupExpression)) {\r
+                            et = ExpressionType.Lookup;\r
+                        } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
+                            et = ExpressionType.WithLookup;\r
+                        } else {\r
+                            et =  ExpressionType.Empty;\r
+                        }\r
+                    }\r
+                    return et;\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+            return null;\r
+        }\r
+\r
+    }\r
 \r
 }\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java
new file mode 100644 (file)
index 0000000..3aa6b56
--- /dev/null
@@ -0,0 +1,143 @@
+package org.simantics.sysdyn.ui.properties.widgets;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.AuxiliaryExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ConstantExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.DelayExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.EmptyExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionValidation;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ParameterExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.StockExpression;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.WithLookupExpression;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+public class ExpressionWidget implements Widget {\r
+    \r
+    private Resource variable;\r
+    private Composite parent;\r
+    private Map<String, Object> data;\r
+    private IExpression expression;\r
+    private ModifyListener modifyListener;\r
+    private FocusListener focusListener;\r
+    \r
+    \r
+    public ExpressionWidget(Composite parent, WidgetSupport support, int style) {\r
+        support.register(this);\r
+        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(parent);\r
+        this.parent = parent;\r
+        this.data = new HashMap<String, Object>();\r
+    }\r
+\r
+    @Override\r
+    public void setInput(Object input) {\r
+        if(input instanceof ISelection) {\r
+            ISelection selection = (ISelection)input;\r
+            if(selection instanceof IStructuredSelection) {\r
+                Resource resource = ISelectionUtils.filterSingleSelection(selection, Resource.class);\r
+                if(resource != null) {\r
+                    variable = resource;\r
+                }\r
+            }\r
+        }\r
+        \r
+        ExpressionType et = ExpressionTypes.getExpressionTypeForVariable(variable);\r
+        \r
+        displayExpression(et.toString(), true);\r
+    }\r
+    \r
+    \r
+    public void displayExpression(String expressionType, boolean original) {\r
+        if(expressionType == null)\r
+            return;\r
+\r
+        if(this.expression != null) expression.updateData(data);\r
+        ExpressionType et = ExpressionType.valueOf(expressionType);\r
+        IExpression exp = null;\r
+        switch (et) {\r
+            case Auxiliary: \r
+                exp = new AuxiliaryExpression(); break;\r
+            case Parameter: \r
+                exp = new ParameterExpression(); break;\r
+            case Constant: \r
+                exp = new ConstantExpression(); break;\r
+            case Lookup: \r
+                exp = new LookupExpression(); break;\r
+            case WithLookup: \r
+                exp = new WithLookupExpression(variable); break;\r
+            case Stock: \r
+                exp = new StockExpression(); break;\r
+            case Delay: \r
+                exp = new DelayExpression(); break;\r
+            default: \r
+                exp = new EmptyExpression();\r
+        }\r
+\r
+        if (exp != null) {\r
+            for(Control c : parent.getChildren()) {\r
+                c.dispose();\r
+            } \r
+\r
+            if(original) \r
+                exp.readData(variable, data);\r
+            \r
+            exp.createExpressionFields(parent, data);\r
+            exp.addModifyListener(modifyListener);\r
+            exp.addFocusListener(focusListener);\r
+            this.expression = exp;\r
+            this.parent.layout();\r
+        }  \r
+    }\r
+    \r
+    public IExpression getExpression() {\r
+        return expression;\r
+    }\r
+    \r
+    public void validateFields(TableItem[] connectedVariables) {\r
+        try {\r
+            final Resource configuration = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
+\r
+                @Override\r
+                public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                    Resource configuration = graph.getSingleObject(variable, graph.getBuiltins().PartOf);\r
+                    return configuration;\r
+                }\r
+            });\r
+            ExpressionValidation.validateExpressionFields(expression, connectedVariables, configuration);\r
+        } catch (DatabaseException e1) {\r
+            e1.printStackTrace();\r
+        }\r
+    }\r
+    \r
+    public void addModifyListener(ModifyListener listener) {\r
+        this.modifyListener = listener;\r
+    }\r
+    \r
+    public void addFocusListener(FocusListener listener) {\r
+        this.focusListener = listener;\r
+    }\r
+    \r
+    public void save() {\r
+        this.expression.save(variable, data);\r
+    }\r
+\r
+}\r
index ca645a7cdeaf0b498ce9943fcc467cdced99d458..4f6452529be880ba72d6a9b4a01ce6bc1ce6c8ea 100644 (file)
@@ -1,7 +1,12 @@
 package org.simantics.sysdyn.ui.properties.widgets;\r
 \r
+import java.util.ArrayList;\r
+\r
 import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusAdapter;\r
+import org.eclipse.swt.events.FocusEvent;\r
 import org.eclipse.swt.events.KeyEvent;\r
 import org.eclipse.swt.events.KeyListener;\r
 import org.eclipse.swt.events.ModifyEvent;\r
@@ -13,14 +18,30 @@ import org.eclipse.swt.widgets.Text;
 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.procedure.Listener;\r
+import org.simantics.sysdyn.manager.SysdynModel;\r
+import org.simantics.sysdyn.manager.SysdynModelManager;\r
+import org.simantics.sysdyn.representation.Configuration;\r
+import org.simantics.sysdyn.representation.IElement;\r
+import org.simantics.sysdyn.representation.Variable;\r
 import org.simantics.sysdyn.ui.properties.EquationTab;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
 \r
 public class NameWidget implements Widget {\r
 \r
-    final private org.eclipse.swt.widgets.Text nameText;\r
-    String originalName = "";\r
+    private org.eclipse.swt.widgets.Text nameText;\r
+    private String originalName = "";\r
     private ReadFactory<?, String> textFactory;\r
+    private Resource variable;\r
+    private Resource configuration;\r
 \r
     public NameWidget(Composite parent, WidgetSupport support, int style) {\r
         support.register(this);\r
@@ -45,8 +66,11 @@ public class NameWidget implements Widget {
 \r
             @Override\r
             public void modifyText(ModifyEvent e) {\r
-                if(((Text)e.widget).getText().contains(" ")) {\r
-                    ((Text)e.widget).setText(originalName);\r
+                Text t = (Text) e.widget;\r
+                String txt = t.getText();\r
+                // Don't allow this to produce an eternal loop\r
+                if (!txt.equals(originalName) && txt.contains(" ")) {\r
+                    t.setText(originalName);\r
                 }\r
             }\r
         });\r
@@ -66,11 +90,28 @@ public class NameWidget implements Widget {
                 }\r
             }\r
         });\r
+        \r
+        nameText.addFocusListener(new FocusAdapter() {\r
+            public void focusLost(FocusEvent e) {\r
+                save();\r
+            }\r
+        });\r
     }\r
 \r
     @Override\r
     public void setInput(Object input) {\r
-\r
+        if(input instanceof ISelection) {\r
+            variable = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class);\r
+            SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
+                \r
+                @Override\r
+                public void run(ReadGraph graph) throws DatabaseException {\r
+                    configuration = graph.getSingleObject(variable, graph.getBuiltins().PartOf); \r
+                }\r
+            });\r
+            \r
+            \r
+        }\r
         if(textFactory != null) {\r
             textFactory.listen(input, new Listener<String>() {\r
 \r
@@ -91,6 +132,7 @@ public class NameWidget implements Widget {
 \r
                             if(isDisposed()) return;\r
                             nameText.setText(text);\r
+                            originalName = text;\r
 \r
                         }\r
 \r
@@ -112,4 +154,42 @@ public class NameWidget implements Widget {
     }\r
 \r
 \r
+    public void save() {\r
+        final String nameNew = this.nameText.getText();\r
+        if(nameNew != null && !nameNew.equals(this.originalName) && variable != null) {\r
+            SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession());\r
+            SysdynModel model = sdm.getModel(configuration);\r
+            Configuration conf = model.getConfiguration();\r
+            IElement thisElement = model.getElement(variable);\r
+            ArrayList<IElement> elements = conf.elements;\r
+            for(IElement e : elements) {\r
+                if(e instanceof Variable) {\r
+                    Variable v = (Variable)e;\r
+                    if(v != thisElement && v.getName().equals(this.nameText.getText())) {\r
+                        this.nameText.setText(this.originalName);\r
+                        this.nameText.setSelection(this.originalName.length());\r
+                        return;\r
+                    }\r
+                }\r
+            }\r
+\r
+\r
+\r
+            try {\r
+                SimanticsUI.getSession().syncRequest(new WriteRequest() {\r
+\r
+                    @Override\r
+                    public void perform(WriteGraph g)\r
+                    throws DatabaseException {\r
+                        Builtins b = g.getBuiltins();\r
+                        g.claimValue(variable, b.HasName, nameNew);\r
+                    }\r
+                });\r
+            } catch (DatabaseException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+\r
 }\r
index 1de6fb4f696825341f213a8cd6d7c51279c2c82c..a8cd943d179be8528d6b344abc6133d1710a735c 100644 (file)
@@ -7,6 +7,8 @@ import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.jface.viewers.IStructuredSelection;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.MouseListener;\r
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.TabFolder;\r
 import org.eclipse.swt.widgets.TabItem;\r
@@ -121,6 +123,20 @@ public class ShortcutTabWidget implements Widget {
 \r
             return variables;\r
     }\r
+    \r
+    public void addFocusListener(FocusListener listener) {\r
+        this.functionTable.addFocusListener(listener);\r
+        this.variableTable.addFocusListener(listener);\r
+    }\r
+    \r
+    public void addMouseListener(MouseListener listener) {\r
+        this.functionTable.addMouseListener(listener);\r
+        this.variableTable.addMouseListener(listener);\r
+    }\r
+    \r
+    public Table getVariableTable() {\r
+        return variableTable;\r
+    }\r
 \r
 \r
 }\r
index c93676fdb3a3e649f6f177fa24d1bd7b9e9f73a9..c5ef77327e0607c362230fc970d7f2b5b8db9404 100644 (file)
@@ -4,21 +4,25 @@ import java.util.ArrayList;
 import java.util.Collection;\r
 \r
 import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.jface.viewers.ISelection;\r
 import org.eclipse.jface.viewers.IStructuredSelection;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusAdapter;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
 import org.eclipse.swt.graphics.FontMetrics;\r
 import org.eclipse.swt.graphics.GC;\r
 import org.eclipse.swt.widgets.Combo;\r
 import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Label;\r
 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
 import org.simantics.db.Builtins;\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.procedure.Listener;\r
 import org.simantics.db.request.Read;\r
@@ -32,22 +36,13 @@ public class UnitWidget implements Widget {
 \r
     Combo unitCombo;\r
     private ReadFactory<?, String> textFactory;\r
+    Resource variable;\r
+    String unit;\r
 \r
     public UnitWidget(Composite parent, WidgetSupport support, int style) {\r
         support.register(this);\r
 \r
-        Composite composite = new Composite(parent, style);\r
-        GridDataFactory.fillDefaults().applyTo(composite);\r
-        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);\r
-\r
-        Label label = new Label(composite, SWT.SINGLE );\r
-        label.setFont(EquationTab.FONT);\r
-        label.setText("Unit:");\r
-        //label.setAlignment(SWT.RIGHT);\r
-        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
-\r
-\r
-        unitCombo = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER);\r
+        unitCombo = new Combo(parent, style);\r
         unitCombo.setFont(EquationTab.FONT);\r
 \r
         int columns = 6;\r
@@ -57,6 +52,27 @@ public class UnitWidget implements Widget {
         int height = fm.getHeight ();\r
         gc.dispose ();        \r
         GridDataFactory.fillDefaults().hint(unitCombo.computeSize(width, height)).applyTo(unitCombo);\r
+        \r
+        unitCombo.addKeyListener(new KeyListener() {\r
+\r
+            @Override\r
+            public void keyReleased(KeyEvent e) {\r
+\r
+            }\r
+\r
+            @Override\r
+            public void keyPressed(KeyEvent e) {\r
+                if(e.keyCode == SWT.ESC && unit != null) {\r
+                    ((Combo)e.widget).setText(unit);\r
+                }\r
+            }\r
+        });\r
+        \r
+        unitCombo.addFocusListener(new FocusAdapter() {\r
+            public void focusLost(FocusEvent e) {\r
+                save();\r
+            }\r
+        });\r
     }\r
 \r
     public void setTextFactory(ReadFactory<?, String> textFactory) {\r
@@ -65,6 +81,8 @@ public class UnitWidget implements Widget {
 \r
     @Override\r
     public void setInput(final Object input) {\r
+        if(input instanceof ISelection)\r
+            variable = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class);\r
         if(textFactory != null) {\r
             textFactory.listen(input, new Listener<String>() {\r
 \r
@@ -95,8 +113,10 @@ public class UnitWidget implements Widget {
                             \r
                             if(unitCombo.indexOf(text) >= 0)\r
                                 unitCombo.select(unitCombo.indexOf(text));\r
-                            else\r
+                            else \r
                                 unitCombo.setText(text);\r
+                            unit = text;\r
+                                \r
                         }\r
 \r
                     });\r
@@ -151,4 +171,28 @@ public class UnitWidget implements Widget {
         }\r
         return units;\r
     }\r
+    \r
+    public void save() {\r
+        final String unitNew = unitCombo.getText();\r
+\r
+        if(unitNew != null && !unitNew.equals(unit) && variable != null) {\r
+            try {\r
+                SimanticsUI.getSession().syncRequest(new WriteRequest() {\r
+\r
+                    @Override\r
+                    public void perform(WriteGraph g)\r
+                    throws DatabaseException {\r
+                        SysdynResource sr = SysdynResource.getInstance(g);\r
+                        if (!unitNew.equals("")) {\r
+                            g.claimValue(variable, sr.HasUnit, unitNew);\r
+                        }\r
+                        else if (g.getPossibleRelatedValue(variable, sr.HasUnit) != null)\r
+                            g.deny(variable, sr.HasUnit);\r
+                    }\r
+                });\r
+            } catch (DatabaseException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
 }\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java
new file mode 100644 (file)
index 0000000..2f4c190
--- /dev/null
@@ -0,0 +1,26 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class AuxiliaryExpression extends BasicExpression {\r
+\r
+    public AuxiliaryExpression() {\r
+        try {\r
+            this.expressionType = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
+\r
+                @Override\r
+                public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                    return SysdynResource.getInstance(graph).NormalExpression;\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java
new file mode 100644 (file)
index 0000000..ac5b56b
--- /dev/null
@@ -0,0 +1,145 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.properties.EquationTab;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class BasicExpression implements IExpression {\r
+    \r
+    ExpressionField expression;\r
+    Resource expressionType;\r
+    \r
+    @Override\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        String equation = data.get("equation") != null ? (String)data.get("equation") : "";\r
+        \r
+        Label l = new Label(parent, SWT.NONE);\r
+        l.setFont(EquationTab.FONT);\r
+        l.setText("=");\r
+        \r
+        expression = new ExpressionField(parent, SWT.BORDER);\r
+        expression.setExpression(equation);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(expression);\r
+    }\r
+\r
+    @Override\r
+    public void focus() {\r
+        if(this.expression != null) this.expression.focus();\r
+        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        return Arrays.asList(this.expression);\r
+    }\r
+\r
+    @Override\r
+    public void readData(final Resource variable, Map<String, Object> data) {\r
+        String equation = null;\r
+        if (variable != null && data.get("equation") == null && expressionType != null) {\r
+            try {\r
+                equation = SimanticsUI.getSession().syncRequest(new Read<String>() {\r
+\r
+                    @Override\r
+                    public String perform(ReadGraph graph) throws DatabaseException {\r
+                        SysdynResource sr = SysdynResource.getInstance(graph);\r
+                        Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
+                        if (expression != null && graph.isInstanceOf(expression, expressionType)) {\r
+                            return graph.getRelatedValue(expression, sr.HasEquation);\r
+                        } else {\r
+                            return "";\r
+                        }\r
+                    }\r
+\r
+                });\r
+            } catch (DatabaseException e1) {\r
+                e1.printStackTrace();\r
+            }\r
+            data.put("equation", equation);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        if(expression != null) {\r
+            IDocument doc = expression.getDocument();\r
+            try {\r
+                Point selection = expression.getSelection();\r
+                doc.replace(selection.x, selection.y, var);\r
+                expression.setSelection(selection.x + var.length());\r
+            } catch (BadLocationException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void save(final Resource variable, Map<String, Object> data) {\r
+        final String currentText = expression.getExpression();\r
+        if(currentText != null && expressionType != null) {\r
+            data.put("equation", currentText);\r
+            SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+                @Override\r
+                public void perform(WriteGraph g)\r
+                throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(g);\r
+                    Resource expression = g.getPossibleObject(variable, sr.HasExpression);\r
+                    Builtins b = g.getBuiltins();\r
+                    if(expression != null) {\r
+                        g.deny(variable, sr.HasExpression);\r
+                    }\r
+                    expression = g.newResource();\r
+                    g.claim(expression, b.InstanceOf, null, expressionType);\r
+                    g.claim(variable, sr.HasExpression, expression);\r
+                    g.claimValue(expression, sr.HasEquation, currentText);\r
+                }\r
+\r
+            });\r
+        }\r
+        expression.setExpression(currentText);\r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        if(this.expression != null && this.expression.getExpression() != null)\r
+            data.put("equation", this.expression.getExpression());\r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java
new file mode 100644 (file)
index 0000000..9a733b9
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.eclipse.jface.text.source.ISharedTextColors;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+public class ColorManager implements ISharedTextColors {\r
+\r
+    protected HashMap<RGB, Color> colorTable = new HashMap<RGB, Color>();\r
+\r
+    @Override\r
+    public void dispose() {\r
+        for(Color c : colorTable.values())\r
+            c.dispose();\r
+        colorTable.clear();\r
+    }\r
+\r
+    @Override\r
+    public Color getColor(RGB rgb) {\r
+        Color color = colorTable.get(rgb);\r
+        if (color == null) {\r
+            color = new Color(Display.getCurrent(), rgb);\r
+            colorTable.put(rgb, color);\r
+        }\r
+        return color;\r
+\r
+\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java
new file mode 100644 (file)
index 0000000..a0b5254
--- /dev/null
@@ -0,0 +1,25 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class ConstantExpression extends BasicExpression {\r
+\r
+    public ConstantExpression() {\r
+        try {\r
+            this.expressionType = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
+\r
+                @Override\r
+                public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                    return SysdynResource.getInstance(graph).ConstantExpression;\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java
new file mode 100644 (file)
index 0000000..8c9eb5d
--- /dev/null
@@ -0,0 +1,74 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+\r
+public class DelayExpression implements IExpression {\r
+\r
+    @Override\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void focus() {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public void readData(Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void save(Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java
new file mode 100644 (file)
index 0000000..f2a99fd
--- /dev/null
@@ -0,0 +1,74 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+\r
+public class EmptyExpression implements IExpression {\r
+\r
+    @Override\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void focus() {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public void readData(Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void save(Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java
new file mode 100644 (file)
index 0000000..d564d06
--- /dev/null
@@ -0,0 +1,187 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.Document;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.PaintManager;\r
+import org.eclipse.jface.text.Position;\r
+import org.eclipse.jface.text.source.Annotation;\r
+import org.eclipse.jface.text.source.AnnotationModel;\r
+import org.eclipse.jface.text.source.AnnotationPainter;\r
+import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;\r
+import org.eclipse.jface.text.source.IAnnotationAccess;\r
+import org.eclipse.jface.text.source.MatchingCharacterPainter;\r
+import org.eclipse.jface.text.source.SourceViewer;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.simantics.sysdyn.expressionParser.Token;\r
+\r
+public class ExpressionField extends Composite {\r
+\r
+    protected SourceViewer                  _sourceViewer;\r
+    protected IDocument                     _document;\r
+    protected AnnotationModel               _annotationModel;\r
+    \r
+    String oldExpression;\r
+\r
+    ColorManager cManager = new ColorManager();\r
+\r
+    IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess();\r
+\r
+    public ExpressionField(Composite parent, int style) {\r
+        super(parent, style);\r
+        \r
+        GridLayoutFactory.fillDefaults().applyTo(this);\r
+        \r
+        int styles = SWT.V_SCROLL\r
+        | SWT.MULTI\r
+        | SWT.FULL_SELECTION\r
+        | SWT.WRAP;\r
+\r
+        _document = new Document();\r
+        _document.set("");\r
+\r
+        _annotationModel = new AnnotationModel();\r
+        _annotationModel.connect(_document);\r
+\r
+        _sourceViewer = new SourceViewer(this,\r
+\r
+                null,\r
+                null,\r
+                true,\r
+                styles);\r
+        _sourceViewer.configure(new ExpressionFieldConfiguration(cManager));\r
+\r
+        AnnotationPainter painter = new AnnotationPainter(_sourceViewer, annotationAccess);\r
+        _sourceViewer.addPainter(painter);\r
+\r
+        painter.addAnnotationType("MissingLink");\r
+        painter.setAnnotationTypeColor("MissingLink", new Color(this.getDisplay(), 255,0,0));\r
+        painter.addAnnotationType("NoSuchVariable");\r
+        painter.setAnnotationTypeColor("NoSuchVariable", new Color(this.getDisplay(), 255,0,0));\r
+        \r
+        _sourceViewer.setDocument(_document, _annotationModel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(_sourceViewer.getControl());\r
+//        _sourceViewer.getControl().setLayoutData(new GridData(SWT.FILL,\r
+//                SWT.FILL,\r
+//                true,\r
+//                true)); \r
+\r
+        PaintManager paintManager = new PaintManager(_sourceViewer);\r
+        MatchingCharacterPainter matchingCharacterPainter = new MatchingCharacterPainter(_sourceViewer,\r
+                new DefaultCharacterPairMatcher( new char[] {'(', ')', '{', '}', '[', ']'} ));\r
+        matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160)));\r
+        paintManager.addPainter(matchingCharacterPainter);\r
+        \r
+        \r
+        _sourceViewer.getTextWidget().addKeyListener(new KeyListener() {\r
+\r
+            @Override\r
+            public void keyReleased(KeyEvent e) {\r
+            }\r
+\r
+            @Override\r
+            public void keyPressed(KeyEvent e) {\r
+                if(e.keyCode == SWT.ESC && getExpression() != null) {\r
+                    ((StyledText)e.widget).setText(oldExpression);\r
+                    ((StyledText)e.widget).setSelection(getExpression().length());\r
+                }   \r
+            }\r
+        });\r
+       \r
+    }\r
+\r
+    public SourceViewer getSourceViewer() {\r
+        return this._sourceViewer;\r
+    }\r
+\r
+    public void setMissingLinkAnnotations(List<Position> positions){\r
+        for(Position p : positions) {\r
+            Annotation annotation = new Annotation(false);\r
+            annotation.setType("MissingLink");\r
+            annotation.setText("No link to this variable");\r
+            _annotationModel.addAnnotation(annotation, p);        \r
+        }\r
+    }\r
+    \r
+    public void setNoSuchVariableAnnotations(List<Position> positions){\r
+        for(Position p : positions) {\r
+            Annotation annotation = new Annotation(false);\r
+            annotation.setType("NoSuchVariable");\r
+            annotation.setText("No such variable in model");\r
+            _annotationModel.addAnnotation(annotation, p);        \r
+        }\r
+    }\r
+\r
+    public void setSyntaxError(Token token){\r
+        int start = 0;\r
+        int offset = this._document.getLength();\r
+        if(token.image != null && this._document.getLength() > 0) {\r
+            try {\r
+                start = this._document.getLineOffset(token.beginLine - 1) + token.beginColumn - 1;\r
+                offset = this._document.getLineOffset(token.endLine - 1) + token.endColumn - start;\r
+            } catch (BadLocationException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+\r
+        Annotation annotation = new Annotation(false);\r
+        annotation.setType("MissingLink");\r
+        annotation.setText("Syntax error");\r
+        Position p = new Position(start, offset);\r
+        _annotationModel.addAnnotation(annotation, p);      \r
+    }\r
+\r
+    public void resetAnnotations() {\r
+        _annotationModel.removeAllAnnotations();\r
+    }\r
+    public void setExpression(String expression) {\r
+        _document.set(expression);\r
+        this.oldExpression = expression;\r
+    }\r
+\r
+    public String getExpression() {\r
+        return this._document.get();\r
+    }\r
+\r
+    public Point getSelection() {\r
+        return _sourceViewer.getSelectedRange();\r
+    }\r
+\r
+    public void setSelection(int selection) {\r
+        this._sourceViewer.setSelectedRange(selection, 0);\r
+    }\r
+\r
+    public IDocument getDocument() {\r
+        return _document;\r
+    }\r
+\r
+    public void focus() {\r
+        this._sourceViewer.getTextWidget().forceFocus();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java
new file mode 100644 (file)
index 0000000..68d46d8
--- /dev/null
@@ -0,0 +1,180 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.text.DefaultTextHover;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.ITextHover;\r
+import org.eclipse.jface.text.TextAttribute;\r
+import org.eclipse.jface.text.presentation.IPresentationReconciler;\r
+import org.eclipse.jface.text.presentation.PresentationReconciler;\r
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.ITokenScanner;\r
+import org.eclipse.jface.text.rules.IWordDetector;\r
+import org.eclipse.jface.text.rules.RuleBasedScanner;\r
+import org.eclipse.jface.text.rules.Token;\r
+import org.eclipse.jface.text.rules.WordRule;\r
+import org.eclipse.jface.text.source.DefaultAnnotationHover;\r
+import org.eclipse.jface.text.source.IAnnotationHover;\r
+import org.eclipse.jface.text.source.ISourceViewer;\r
+import org.eclipse.jface.text.source.SourceViewerConfiguration;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.RGB;\r
+\r
+public class ExpressionFieldConfiguration extends SourceViewerConfiguration {\r
+\r
+\r
+    ColorManager colorManager;\r
+\r
+    public ExpressionFieldConfiguration(ColorManager colorManager) {\r
+        super();\r
+        this.colorManager = colorManager;\r
+    }\r
+\r
+    public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {\r
+        return new String[] {\r
+                IDocument.DEFAULT_CONTENT_TYPE\r
+        };\r
+    }\r
+\r
+    /*\r
+    @Override\r
+    public IAutoEditStrategy[] getAutoEditStrategies(\r
+            ISourceViewer sourceViewer, String contentType) {\r
+        return new IAutoEditStrategy[] {\r
+                new ReplaceTabsBySpaces(),\r
+                new IndentLineEditStrategy(),\r
+                new MatchingBracketsEditStrategy()\r
+        };\r
+    }\r
+    */\r
+\r
+    public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {\r
+        PresentationReconciler reconciler = new PresentationReconciler();\r
+\r
+        DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner());\r
+\r
+        reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
+        reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
+\r
+        return reconciler;\r
+    }\r
+\r
+    /*\r
+     * \r
+     */\r
+     ITokenScanner getSclTokenScanner() {\r
+        RuleBasedScanner scanner = new RuleBasedScanner();\r
+\r
+        final Token reserved = new Token(\r
+                new TextAttribute(\r
+                        colorManager.getColor(new RGB(127, 0, 85)),\r
+                        null,\r
+                        SWT.BOLD\r
+                ));\r
+        \r
+\r
+        WordRule reservedWord = new WordRule(new IWordDetector() {   \r
+            @Override\r
+            public boolean isWordStart(char c) {\r
+                return Character.isLetter(c);\r
+            }\r
+\r
+            @Override\r
+            public boolean isWordPart(char c) {\r
+                return Character.isLetter(c);\r
+            }\r
+        });\r
+\r
+        for(String s : keywords) {\r
+            reservedWord.addWord(s, reserved);\r
+        }\r
+\r
+        IRule[] rules = new IRule[] {\r
+                reservedWord\r
+        };\r
+        scanner.setRules(rules);\r
+\r
+        return scanner;  \r
+     }\r
+\r
+     @Override\r
+     public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {\r
+         return new DefaultTextHover(sourceViewer);\r
+     }\r
+\r
+     @Override\r
+     public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {\r
+         return new DefaultAnnotationHover();\r
+     }\r
+\r
+     static final Set<String> keywords = new HashSet<String>();\r
+     \r
+     static {\r
+         keywords.add("within");\r
+         keywords.add("final");\r
+         keywords.add("public");\r
+         keywords.add("protected");\r
+         keywords.add("connect");\r
+         keywords.add("when");\r
+         keywords.add("then");\r
+         keywords.add("elsewhen");\r
+         keywords.add("if");\r
+         keywords.add("end");\r
+         keywords.add("elseif");\r
+         keywords.add("else");\r
+         keywords.add("for");\r
+         keywords.add("while");\r
+         keywords.add("loop");\r
+         keywords.add("der");\r
+         keywords.add("enumeration");\r
+         keywords.add("extends");\r
+         keywords.add("class");\r
+         keywords.add("partial");\r
+         keywords.add("encapsulated");\r
+         keywords.add("model");\r
+         keywords.add("record");\r
+         keywords.add("block");\r
+         keywords.add("expandable");\r
+         keywords.add("connector");\r
+         keywords.add("type");\r
+         keywords.add("package");\r
+         keywords.add("function");\r
+         keywords.add("import");\r
+         keywords.add("external");\r
+         keywords.add("constrainedby");\r
+         keywords.add("redeclare");\r
+         keywords.add("replaceable");\r
+         keywords.add("flow");\r
+         keywords.add("discrete");\r
+         keywords.add("parameter");\r
+         keywords.add("constant");\r
+         keywords.add("input");\r
+         keywords.add("output");\r
+         keywords.add("annotation");\r
+         keywords.add("false");\r
+         keywords.add("true");\r
+         keywords.add("each");\r
+         keywords.add("initial");\r
+         keywords.add("algorithm");\r
+         keywords.add("equation");\r
+         keywords.add("or");\r
+         keywords.add("and");\r
+         keywords.add("not");\r
+         keywords.add("break");\r
+         keywords.add("return");     \r
+     }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java
new file mode 100644 (file)
index 0000000..a444821
--- /dev/null
@@ -0,0 +1,132 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.io.StringReader;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.text.Position;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.simantics.db.Resource;\r
+import org.simantics.sysdyn.expressionParser.ExpressionParser;\r
+import org.simantics.sysdyn.expressionParser.ParseException;\r
+import org.simantics.sysdyn.expressionParser.Token;\r
+import org.simantics.sysdyn.manager.SysdynModel;\r
+import org.simantics.sysdyn.manager.SysdynModelManager;\r
+import org.simantics.sysdyn.representation.Configuration;\r
+import org.simantics.sysdyn.representation.IElement;\r
+import org.simantics.sysdyn.representation.Variable;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class ExpressionValidation {\r
+\r
+    static public void validateExpressionFields(IExpression expression, TableItem[] connectedVariables, Resource configuration) {\r
+        ExpressionParser parser = new ExpressionParser(new StringReader(""));\r
+        Set<String> variables = new HashSet<String>();\r
+        HashMap<ExpressionField, HashMap<String, List<Token>>> references = new HashMap<ExpressionField, HashMap<String, List<Token>>>();\r
+\r
+\r
+        // Build references and variable array\r
+        for(ExpressionField ef : expression.getExpressionFields()) {\r
+            ef.resetAnnotations();\r
+            String textString = ef.getExpression();\r
+            parser.ReInit(new StringReader(textString));\r
+            try {\r
+                parser.expr();\r
+                HashMap<String, List<Token>> cr = parser.getReferences();\r
+                references.put(ef, cr);\r
+                for(String t : cr.keySet())\r
+                    variables.add(t);\r
+            } catch (ParseException e1) {\r
+                ef.setSyntaxError(e1.currentToken);\r
+            }\r
+        }\r
+\r
+        // Remove variables from variable array that don't exist in the model. Create annotations\r
+        if(!variables.isEmpty()) {\r
+            ArrayList<String> modelVariables = new ArrayList<String>();\r
+            Set<String> noSuchVariables = new HashSet<String>();\r
+            SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession());\r
+            SysdynModel model = sdm.getModel(configuration);\r
+            Configuration conf = model.getConfiguration();\r
+            ArrayList<IElement> elements = conf.elements;\r
+            for(IElement e : elements) {\r
+                if(e instanceof Variable) {\r
+                    Variable v = (Variable) e;\r
+                    modelVariables.add(v.getName());\r
+                }\r
+            }\r
+\r
+\r
+            for(String v : variables) {\r
+                if(!modelVariables.contains(v)) {\r
+                    noSuchVariables.add(v);\r
+                }\r
+            }\r
+\r
+            if(!noSuchVariables.isEmpty()) {\r
+                // remove no such variables from variable list\r
+                for(String s : noSuchVariables)\r
+                    variables.remove(s);\r
+                // create annotations\r
+                HashMap<ExpressionField ,ArrayList<Position>> positions = getPositionsForVariables(references, noSuchVariables);\r
+                for(ExpressionField ef : positions.keySet()) {\r
+                    ef.setNoSuchVariableAnnotations(positions.get(ef));\r
+                }\r
+            }      \r
+        }\r
+\r
+        // Check that the variables that exist have connections and the connected variables have references in the expressions\r
+        if(!(expression instanceof StockExpression)) { \r
+            for(TableItem ti : connectedVariables) {\r
+                if(!variables.contains(ti.getText())) {\r
+                    ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0));\r
+                } else {\r
+                    ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0));\r
+                    variables.remove(ti.getText());\r
+                }\r
+            }\r
+\r
+            if(!variables.isEmpty()) {\r
+                HashMap<ExpressionField ,ArrayList<Position>> positions = getPositionsForVariables(references, variables);\r
+                for(ExpressionField ef : positions.keySet()) {\r
+                    ef.setMissingLinkAnnotations(positions.get(ef));\r
+                }\r
+\r
+            }\r
+        } \r
+\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    static private HashMap<ExpressionField ,ArrayList<Position>> getPositionsForVariables(HashMap<ExpressionField, HashMap<String, List<Token>>> references, Set<String> variables) {\r
+        HashMap<ExpressionField ,ArrayList<Position>> result = new HashMap<ExpressionField ,ArrayList<Position>>();\r
+        for(String s : variables) {\r
+            List<Token> tlist = new ArrayList<Token>();\r
+            for(ExpressionField ef : references.keySet()) {\r
+                ArrayList<Position> positions = new ArrayList<Position>();\r
+                tlist = references.get(ef).get(s);\r
+                if(tlist != null)\r
+                    for(Token t : tlist) {\r
+                        StyledText st = ef.getSourceViewer().getTextWidget();\r
+                        int start =  st.getOffsetAtLine(t.beginLine - 1) + t.beginColumn - 1;\r
+                        int offset = st.getOffsetAtLine(t.endLine - 1) + t.endColumn - start;\r
+                        positions.add(new Position(\r
+                                start,\r
+                                offset));\r
+                    }\r
+                if(result.keySet().contains(ef)) {\r
+                    result.get(ef).addAll((ArrayList<Position>)positions.clone());\r
+                } else {\r
+                    result.put(ef, (ArrayList<Position>)positions.clone());\r
+                }\r
+            }\r
+        }\r
+        return result;\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java
new file mode 100644 (file)
index 0000000..6c8c152
--- /dev/null
@@ -0,0 +1,33 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+\r
+public interface IExpression {\r
+\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data);\r
+\r
+    public void readData(final Resource variable, Map<String, Object> data);\r
+\r
+    public void save(final Resource variable, Map<String, Object> data);\r
+\r
+    public void focus();\r
+\r
+    public void replaceSelection(String var);\r
+\r
+    public void updateData(Map<String, Object> data);\r
+\r
+    public List<ExpressionField> getExpressionFields();\r
+    \r
+    public void addModifyListener(ModifyListener listener);\r
+    \r
+    public void addKeyListener(KeyListener listener);\r
+\r
+    public void addFocusListener(FocusListener listener);\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java
new file mode 100644 (file)
index 0000000..e556d04
--- /dev/null
@@ -0,0 +1,63 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class LookupChartInfo {\r
+\r
+    String lookupTable, expression;\r
+    Double minX, maxX, minY, maxY;\r
+\r
+    private static Double MINX = 0.0;\r
+    private static Double MAXX = 10.0;\r
+    private static Double MINY = 0.0;\r
+    private static Double MAXY = 10.0;\r
+\r
+    public LookupChartInfo(String expression, String lookupTable, final Resource variable, Map<String, Object> data) {\r
+        this.lookupTable = lookupTable != null ? lookupTable : "";\r
+        this.expression = expression != null ? expression : "";\r
+        this.minX = (Double)data.get("minX");\r
+        this.maxX = (Double)data.get("maxX");\r
+        this.minY = (Double)data.get("minY");\r
+        this.maxY = (Double)data.get("maxY");\r
+        if(variable != null && (minX == null || maxX == null || minY == null || maxY == null)) {\r
+            try {\r
+                SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+                    @Override\r
+                    public void run(ReadGraph graph) throws DatabaseException {\r
+                        SysdynResource sr = SysdynResource.getInstance(graph);\r
+                        Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
+                        if(expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { \r
+                            minX = graph.getPossibleRelatedValue(expression, sr.HasMinX);  \r
+                            if(minX == null) minX = MINX;\r
+                            maxX = graph.getPossibleRelatedValue(expression, sr.HasMaxX); \r
+                            if(maxX == null) maxX = MAXX;\r
+                            minY = graph.getPossibleRelatedValue(expression, sr.HasMinY); \r
+                            if(minY == null) minY = MINY;\r
+                            maxY = graph.getPossibleRelatedValue(expression, sr.HasMaxY);\r
+                            if(maxY == null) maxY = MAXY;\r
+                        } else {\r
+                            defaultValues();\r
+                        }\r
+\r
+                    }\r
+                });\r
+            } catch (DatabaseException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+    \r
+    private void defaultValues() {\r
+        minX = MINX;\r
+        maxX = MAXX;\r
+        minY = MINY;\r
+        maxY = MAXY;\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java
new file mode 100644 (file)
index 0000000..2122433
--- /dev/null
@@ -0,0 +1,152 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.awt.Point;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import org.jfree.chart.ChartPanel;\r
+import org.jfree.chart.ChartRenderingInfo;\r
+import org.jfree.chart.JFreeChart;\r
+import org.jfree.chart.axis.ValueAxis;\r
+import org.jfree.chart.entity.ChartEntity;\r
+import org.jfree.chart.entity.PlotEntity;\r
+import org.jfree.chart.entity.XYItemEntity;\r
+import org.jfree.chart.plot.XYPlot;\r
+import org.jfree.data.xy.XYSeries;\r
+import org.jfree.data.xy.XYSeriesCollection;\r
+\r
+@SuppressWarnings("serial")\r
+public class LookupChartPanel extends ChartPanel {\r
+\r
+    private XYItemEntity dragPrevEntity;\r
+    private boolean drawing;\r
+    private XYSeries series; \r
+    private JFreeChart chart;\r
+    private LookupInputOutputTable table;\r
+\r
+    public LookupChartPanel(JFreeChart chart) {\r
+        super(chart);\r
+        this.chart = chart;\r
+        XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset();\r
+        series = collection.getSeries(0); \r
+    }\r
+\r
+    public void setTable(LookupInputOutputTable table) {\r
+        this.table = table;\r
+    }\r
+\r
+    public void mouseDragged(MouseEvent e)\r
+    {\r
+        if(dragPrevEntity != null) {\r
+\r
+            int item = dragPrevEntity.getItem();\r
+            XYPlot plot = (XYPlot)chart.getPlot();\r
+            ValueAxis rangeAxis = plot.getRangeAxis();\r
+            ValueAxis domainAxis = plot.getDomainAxis();\r
+            Point2D location = getLocationOnChart(getMouseLocation(e));\r
+            Number prevX = item == 0 ? null : series.getX(item - 1);\r
+            Number nextX = item == series.getItemCount() - 1 ? null : series.getX(item + 1);\r
+\r
+\r
+            if(series.indexOf(location.getX()) >= 0 && series.indexOf(location.getX()) != item)\r
+                return;\r
+            else if (prevX != null && location.getX() < prevX.doubleValue())\r
+                location.setLocation(series.getX(item).doubleValue(), location.getY());\r
+            else if (nextX != null && location.getX() > nextX.doubleValue())\r
+                location.setLocation(series.getX(item).doubleValue(), location.getY());\r
+            else if (location.getX() > domainAxis.getUpperBound())\r
+                location.setLocation(domainAxis.getUpperBound(), location.getY());\r
+            else if (location.getX() < domainAxis.getLowerBound()) \r
+                location.setLocation(domainAxis.getLowerBound(), location.getY());    \r
+\r
+            if (location.getY() > rangeAxis.getUpperBound())\r
+                location.setLocation(location.getX(), rangeAxis.getUpperBound());\r
+            else if (location.getY() < rangeAxis.getLowerBound()) \r
+                location.setLocation(location.getX(), rangeAxis.getLowerBound());    \r
+\r
+            removeItemFromSeries(dragPrevEntity.getItem());\r
+            addLocationToSeries(location);\r
+        } else {\r
+            ChartEntity currEntity = this.getEntityForPoint(e.getX(),e.getY());\r
+            if(!drawing && currEntity instanceof XYItemEntity) {\r
+                dragPrevEntity = ((XYItemEntity)currEntity);\r
+            } else if (currEntity instanceof PlotEntity){\r
+                drawing = true;\r
+                Point2D locationOnChart = getLocationOnChart(getMouseLocation(e));\r
+                int item = series.indexOf(locationOnChart.getX());\r
+                if (item >= 0) {\r
+                    Point2D location = new Point2D.Double(series.getX(item).doubleValue(), series.getY(item).doubleValue());\r
+                    Point2D javaLocation = getLocationOnJava2D(location);\r
+                    removeItemFromSeries(item);\r
+                    addLocationToSeries(getLocationOnChart(new Point2D.Double(javaLocation.getX(), e.getY())));\r
+                }\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    public void mouseReleased(MouseEvent e) {\r
+\r
+        dragPrevEntity = null;\r
+        drawing = false;\r
+    }\r
+\r
+    public void mouseClicked(MouseEvent e)\r
+    {\r
+        if(e.getButton() == MouseEvent.BUTTON1) {\r
+            addLocationToSeries(getLocationOnChart(getMouseLocation(e)));\r
+        } else if (e.getButton() == MouseEvent.BUTTON3) {\r
+            ChartEntity entity = this.getEntityForPoint(e.getX(),e.getY());\r
+            if(entity instanceof XYItemEntity) {\r
+                XYItemEntity xyentity = ((XYItemEntity)entity);\r
+                removeItemFromSeries(xyentity.getItem());\r
+            }\r
+        }\r
+    }         \r
+\r
+    private Point2D getLocationOnChart(Point2D coordinates) {\r
+        XYPlot plot = (XYPlot)chart.getPlot();\r
+        ChartRenderingInfo info = getChartRenderingInfo();\r
+        Rectangle2D dataArea = info.getPlotInfo().getDataArea();\r
+        double chartX = plot.getDomainAxis().java2DToValue(coordinates.getX(), dataArea,\r
+                plot.getDomainAxisEdge());\r
+        double chartY = plot.getRangeAxis().java2DToValue(coordinates.getY(), dataArea,\r
+                plot.getRangeAxisEdge());\r
+        return new Point2D.Double(chartX, chartY);\r
+    }\r
+\r
+    private Point2D getLocationOnJava2D(Point2D location) {\r
+        XYPlot plot = (XYPlot)chart.getPlot();\r
+        ChartRenderingInfo info = getChartRenderingInfo();\r
+        Rectangle2D dataArea = info.getPlotInfo().getDataArea();\r
+        double javaX = plot.getDomainAxis().valueToJava2D(location.getX(), dataArea,\r
+                plot.getDomainAxisEdge());\r
+        double javaY = plot.getRangeAxis().valueToJava2D(location.getY(), dataArea,\r
+                plot.getRangeAxisEdge());\r
+        return new Point2D.Double(javaX, javaY);\r
+    }\r
+\r
+    public void addLocationToSeries(Point2D location) {\r
+        if(series.indexOf(location.getX()) < 0) {\r
+            series.add(location.getX(), location.getY());\r
+            table.addLocation(location);\r
+        }\r
+    }\r
+\r
+    public void removeItemFromSeries(int item){\r
+        Point2D location = new Point2D.Double(series.getX(item).doubleValue(),series.getY(item).doubleValue()); \r
+        series.remove(item);\r
+        table.removeLocation(location);\r
+    }\r
+\r
+    private Point2D getMouseLocation(MouseEvent e) {\r
+        int mouseX = e.getX();\r
+        int mouseY = e.getY();\r
+        Point2D p = translateScreenToJava2D(\r
+                new Point(mouseX, mouseY));\r
+        return p;\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java
new file mode 100644 (file)
index 0000000..4bb7fb3
--- /dev/null
@@ -0,0 +1,74 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+\r
+public class LookupExpression implements IExpression {\r
+\r
+    @Override\r
+    public void focus() {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public void readData(final Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void save(final Resource variable, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        // TODO Auto-generated method stub\r
+        \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java
new file mode 100644 (file)
index 0000000..9ed5030
--- /dev/null
@@ -0,0 +1,202 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ArrayContentProvider;\r
+import org.eclipse.jface.viewers.CellEditor;\r
+import org.eclipse.jface.viewers.ITableLabelProvider;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.TableViewer;\r
+import org.eclipse.jface.viewers.TextCellEditor;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.viewers.ViewerComparator;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableColumn;\r
+\r
+public class LookupInputOutputTable extends Composite {\r
+\r
+    public static final String INPUT = "Input";\r
+    public static final String OUTPUT = "Output";\r
+    public static final String[] PROPS = { INPUT, OUTPUT };\r
+\r
+    Table table;\r
+    TableViewer tableViewer;\r
+    List<InputOutput> tableRows;\r
+\r
+    public LookupInputOutputTable(Composite parent, int style) {\r
+        super(parent, style);\r
+\r
+        GridLayoutFactory.fillDefaults().applyTo(this);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(this);\r
+        table = new Table(this, SWT.BORDER|SWT.SINGLE|SWT.FULL_SELECTION);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(table);\r
+        table.setHeaderVisible (true);\r
+        table.setLinesVisible(true);\r
+        table.getVerticalBar().setVisible(true);\r
+        TableColumn column1 = new TableColumn (table, SWT.LEFT);\r
+        column1.setText (INPUT);\r
+        column1.setWidth (85);\r
+        \r
+        TableColumn column2 = new TableColumn (table, SWT.LEFT);\r
+        column2.setText (OUTPUT);\r
+        column2.setWidth (85);\r
+\r
+        // Create the viewer and connect it to the view\r
+        tableViewer = new TableViewer (table);\r
+\r
+        tableViewer.setContentProvider (new ArrayContentProvider());\r
+        tableViewer.setLabelProvider (new InputOutputLabelProvider());\r
+\r
+        tableRows = new ArrayList<InputOutput>();     \r
+        tableViewer.setInput(tableRows);\r
+\r
+        CellEditor[] editors = new CellEditor[2];\r
+        editors[0] = new TextCellEditor(table);\r
+        editors[1] = new TextCellEditor(table);\r
+        tableViewer.setCellEditors(editors);\r
+        tableViewer.setColumnProperties(PROPS);\r
+        \r
+    }\r
+\r
+    private class InputOutputLabelProvider extends LabelProvider implements ITableLabelProvider {\r
+        public Image getColumnImage (Object element, int columnIndex) {\r
+            return null;\r
+        }\r
+        public String getColumnText (Object element, int columnIndex) {\r
+            if(element instanceof InputOutput) {\r
+                InputOutput io = (InputOutput)element;\r
+                switch (columnIndex) {\r
+                    case 0: return (String)io.getInput(String.class);\r
+                    case 1: return (String)io.getOutput(String.class);\r
+                }\r
+            }\r
+            return "";\r
+        }\r
+    }\r
+\r
+    public void addLocation(Point2D location) {\r
+        tableRows.add(new InputOutput(location.getX(), location.getY()));\r
+        tableViewer.getTable().getDisplay().asyncExec(new Runnable() {\r
+\r
+            @Override\r
+            public void run() {\r
+                refresh();\r
+            }\r
+        });\r
+\r
+    }\r
+\r
+    public void removeLocation(Point2D location) {\r
+        for(InputOutput io : tableRows) {\r
+            if((Double)io.getInput(Double.class) == location.getX()) {\r
+                tableRows.remove(io);\r
+                tableViewer.getTable().getDisplay().asyncExec(new Runnable() {\r
+\r
+                    @Override\r
+                    public void run() {\r
+                        refresh();\r
+                    }\r
+                });\r
+                break;\r
+            }\r
+        }\r
+\r
+    }\r
+\r
\r
+    class InputOutput {\r
+        private double input, output;\r
+\r
+        public InputOutput(double input, double output) {\r
+            this.input = input;\r
+            this.output = output;\r
+        }\r
+\r
+        /**\r
+         * \r
+         * @param clazz String.class or Double.class\r
+         * @return input as string or double or null if asked for something else\r
+         */\r
+        @SuppressWarnings("unchecked")\r
+        public Object getInput(Class clazz) {\r
+            if(clazz == String.class) {\r
+                return "" + input;\r
+            } else if (clazz == Double.class) {\r
+                return input;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public Double setInput(String input) {\r
+            try {\r
+                this.input = Double.parseDouble(input);\r
+                return this.input;\r
+            } catch (NumberFormatException e) {\r
+                return null;\r
+            }\r
+        }\r
+\r
+        public void setInput(double input) {\r
+            this.input = input;\r
+        }\r
+\r
+        /**\r
+         * \r
+         * @param clazz String.class or Double.class\r
+         * @return output as string or double or null if asked for something else\r
+         */\r
+        @SuppressWarnings("unchecked")\r
+        public Object getOutput(Class clazz) {\r
+            if(clazz == String.class) {\r
+                return "" + output;\r
+            } else if (clazz == Double.class) {\r
+                return output;\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public void setOutput(String output) {\r
+            try {\r
+                this.output = Double.parseDouble(output);\r
+            } catch (NumberFormatException e) {\r
+\r
+            }\r
+        }\r
+\r
+        public void setOutput(double output) {\r
+            this.output = output;\r
+        }\r
+\r
+    }\r
+\r
+    class InputOutputComparator extends ViewerComparator {\r
+        @Override\r
+        public int compare(Viewer viewer, Object e1, Object e2) {\r
+            if ((e1 instanceof InputOutput) &&\r
+                    (e2 instanceof InputOutput)) {\r
+                InputOutput io1 = (InputOutput)e1;\r
+                InputOutput io2 = (InputOutput)e2;\r
+                Double d1 = (Double)io1.getInput((Double.class));\r
+                Double d2 = (Double)io2.getInput((Double.class));\r
+                return d1.compareTo(d2);\r
+            }\r
+            return 0;\r
+        }\r
+    }\r
+    \r
+    public TableViewer getTableViewer() {\r
+        return this.tableViewer;\r
+    }\r
+    \r
+    public void refresh() {\r
+        tableViewer.setComparator(new InputOutputComparator());\r
+        tableViewer.refresh();\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java
new file mode 100644 (file)
index 0000000..c7d3cfd
--- /dev/null
@@ -0,0 +1,435 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.GridLayout;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.Point2D;\r
+import java.io.StringReader;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import javax.swing.JComponent;\r
+import javax.swing.JPanel;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.dialogs.IDialogConstants;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ICellModifier;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Item;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.swt.widgets.Widget;\r
+import org.jfree.chart.ChartFactory;\r
+import org.jfree.chart.JFreeChart;\r
+import org.jfree.chart.axis.ValueAxis;\r
+import org.jfree.chart.plot.PlotOrientation;\r
+import org.jfree.chart.plot.XYPlot;\r
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;\r
+import org.jfree.data.xy.XYDataItem;\r
+import org.jfree.data.xy.XYDataset;\r
+import org.jfree.data.xy.XYSeries;\r
+import org.jfree.data.xy.XYSeriesCollection;\r
+import org.simantics.g2d.chassis.SWTAWTComponent;\r
+import org.simantics.sysdyn.tableParser.ParseException;\r
+import org.simantics.sysdyn.tableParser.Token;\r
+import org.simantics.sysdyn.tableParser.TableParser;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupInputOutputTable.InputOutput;\r
+\r
+public class LookupPopup extends Dialog {\r
+\r
+    JFreeChart chart;\r
+    LookupInputOutputTable table;\r
+    ArrayList<Point2D> dataPoints;\r
+    Text input, output;\r
+    Text minX, maxX, minY, maxY;\r
+    Label unit;\r
+    LookupChartInfo chartInfo;\r
+\r
+    protected LookupPopup(Shell parentShell, LookupChartInfo chartInfo) {\r
+        super(parentShell);\r
+        this.chartInfo = chartInfo;\r
+        this.dataPoints = new ArrayList<Point2D>();\r
+        TableParser parser = new TableParser(new StringReader(""));\r
+        parser.ReInit(new StringReader(chartInfo.lookupTable));\r
+        try {\r
+            parser.table();\r
+            ArrayList<Token> xTokens = parser.getXTokens();\r
+            for(Token token : xTokens) {\r
+                dataPoints.add(new Point2D.Double(\r
+                        Double.parseDouble(token.image), \r
+                        Double.parseDouble(token.next.next.image)));\r
+            }\r
+        } catch (ParseException e1) {\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    protected Control createDialogArea(Composite parent) {\r
+        KeyListener enterListener = new KeyListener() {\r
+\r
+            @Override\r
+            public void keyReleased(KeyEvent e) {}\r
+\r
+            @Override\r
+            public void keyPressed(KeyEvent e) {\r
+                if(e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR)\r
+                    getButton(IDialogConstants.OK_ID).forceFocus();\r
+            }\r
+        };\r
+\r
+        final LookupChartPanel chartPanel = new LookupChartPanel(createChart());\r
+        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));\r
+        chartPanel.setMouseZoomable(true, false);\r
+        chartPanel.setDomainZoomable(false);\r
+        chartPanel.setRangeZoomable(false);\r
+\r
+        XYPlot plot = (XYPlot) chart.getPlot();\r
+        ValueAxis rangeAxis = plot.getRangeAxis();\r
+        ValueAxis domainAxis = plot.getDomainAxis();\r
+\r
+        Composite container = new Composite(parent, SWT.None);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(container);\r
+\r
+        Composite yAxis = new Composite(container, SWT.NONE);\r
+        GridLayoutFactory.fillDefaults().applyTo(yAxis);\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(yAxis);\r
+        maxY = new Text(yAxis, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxY);\r
+        maxY.addKeyListener(enterListener);\r
+        maxY.addModifyListener(getAxisBoundModifyListener());\r
+        maxY.setText("" + rangeAxis.getUpperBound());\r
+        Composite fillY = new Composite(yAxis, SWT.NONE);\r
+        GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(false, true).applyTo(fillY);\r
+        GridLayoutFactory.fillDefaults().applyTo(fillY);\r
+        unit = new Label(fillY, SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(unit);\r
+        unit.setText(""); //TODO: how to get and update units?\r
+        unit.addKeyListener(enterListener);\r
+        minY = new Text(yAxis, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minY);\r
+        minY.addKeyListener(enterListener);\r
+        minY.addModifyListener(getAxisBoundModifyListener());\r
+        minY.setText("" + rangeAxis.getLowerBound());\r
+\r
+        SWTAWTComponent c = new SWTAWTComponent(container, SWT.BORDER) {\r
+            @Override\r
+            protected JComponent createSwingComponent() {\r
+                JPanel panel = new JPanel();\r
+                panel.setLayout(new GridLayout(1, 1));\r
+                panel.setPreferredSize(new java.awt.Dimension(500, 270));\r
+                panel.add(chartPanel);\r
+                panel.doLayout();\r
+                return panel;\r
+            }\r
+        };\r
+        GridDataFactory.fillDefaults().hint(500, 300).applyTo(c);\r
+        c.populate();\r
+\r
+\r
+        Composite valueTableComposite = new Composite(container, SWT.NONE);\r
+        GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(valueTableComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(valueTableComposite);\r
+\r
+\r
+        table = new LookupInputOutputTable(valueTableComposite, SWT.NONE);\r
+        GridDataFactory.fillDefaults().span(3, 1).grab(true, true).applyTo(table);\r
+        chartPanel.setTable(table);\r
+        table.getTableViewer().setCellModifier(new InputOutputCellModifier());\r
+        table.getTableViewer().getTable().addMouseListener(new MouseListener() {\r
+\r
+            @Override\r
+            public void mouseUp(org.eclipse.swt.events.MouseEvent e) {\r
+                if(e.button == MouseEvent.BUTTON3) {\r
+                    Table table = (Table)e.widget;\r
+                    TableItem item = (TableItem)table.getItem(new org.eclipse.swt.graphics.Point(e.x, e.y));\r
+                    chartPanel.removeItemFromSeries(table.indexOf(item));\r
+                }\r
+            }\r
+            @Override\r
+            public void mouseDown(org.eclipse.swt.events.MouseEvent e) { }\r
+            @Override\r
+            public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) { }\r
+        });\r
+        for(Point2D location : this.dataPoints) {\r
+            chartPanel.addLocationToSeries(location);\r
+        }\r
+\r
+        input = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(input);\r
+        input.setText("");\r
+        output = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(output);\r
+        output.setText("");\r
+\r
+        Button add = new Button(valueTableComposite, SWT.None);\r
+        add.setText("Add");\r
+        add.addSelectionListener(new SelectionListener() {\r
+\r
+            @Override\r
+            public void widgetSelected(SelectionEvent e) {\r
+                try {\r
+                    Double in = Double.parseDouble(input.getText());\r
+                    Double out = Double.parseDouble(output.getText());\r
+                    chartPanel.addLocationToSeries(new Point2D.Double(in, out));\r
+                } catch (NumberFormatException e1) {\r
+                    input.setText("");\r
+                    output.setText("");\r
+                }\r
+            }\r
+\r
+            @Override\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+        });\r
+\r
+        FocusListener flistener = new FocusListener() {\r
+            @Override\r
+            public void focusGained(FocusEvent e) {\r
+                Text text = (Text)e.widget;\r
+                text.setSelection(0, text.getCharCount());\r
+            }\r
+            @Override\r
+            public void focusLost(FocusEvent e) { }\r
+        };\r
+\r
+\r
+        KeyListener listener = new KeyListener() {\r
+\r
+            @Override\r
+            public void keyPressed(KeyEvent e) {\r
+                if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+                    try {\r
+                        Double in = Double.parseDouble(input.getText());\r
+                        Double out = Double.parseDouble(output.getText());\r
+                        chartPanel.addLocationToSeries(new Point2D.Double(in, out));\r
+                    } catch (NumberFormatException e1) {\r
+                        if(input.getText().isEmpty() && output.getText().isEmpty()) {\r
+                            getButton(IDialogConstants.OK_ID).forceFocus();\r
+                            return;\r
+                        }\r
+                    }\r
+                    input.setText("");\r
+                    output.setText("");\r
+                    input.setFocus();\r
+                }          \r
+            }\r
+\r
+            @Override\r
+            public void keyReleased(KeyEvent e) { }\r
+\r
+        };\r
+\r
+        input.addFocusListener(flistener);\r
+        input.addKeyListener(listener);\r
+        output.addFocusListener(flistener);\r
+        output.addKeyListener(listener);\r
+\r
+        Label l = new Label(container, SWT.NONE);\r
+        l.setText("");\r
+\r
+        Composite xAxis = new Composite(container, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xAxis);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(xAxis);\r
+        minX = new Text(xAxis, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minX); \r
+        minX.addKeyListener(enterListener);\r
+        minX.addModifyListener(getAxisBoundModifyListener());\r
+        minX.setText("" + domainAxis.getLowerBound());\r
+        Composite fillX = new Composite(xAxis, SWT.CENTER);\r
+        GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(true, false).applyTo(fillX);\r
+        GridLayoutFactory.fillDefaults().applyTo(fillX);\r
+        l = new Label(fillX, SWT.NONE);\r
+        l.setText(chartInfo.expression);\r
+        maxX = new Text(xAxis, SWT.BORDER | SWT.RIGHT);\r
+        GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxX);\r
+        maxX.addKeyListener(enterListener);\r
+        maxX.addModifyListener(getAxisBoundModifyListener());\r
+        maxX.setText("" + domainAxis.getUpperBound());\r
+\r
+        return null;\r
+    }\r
+\r
+    protected void createButtonsForButtonBar(Composite parent) {\r
+        // create OK and Cancel buttons by default\r
+        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,\r
+                false);\r
+        createButton(parent, IDialogConstants.CANCEL_ID,\r
+                IDialogConstants.CANCEL_LABEL, false);\r
+    }\r
+\r
+    public LookupChartInfo open(Boolean bool) {\r
+        Shell shell = this.getShell();\r
+        if (shell == null || shell.isDisposed()) {\r
+            shell = null;\r
+            create();\r
+            shell = this.getShell();\r
+        }\r
+        constrainShellSize();\r
+        shell.open();\r
+        getButton(IDialogConstants.OK_ID).setFocus();\r
+        Display display = getParentShell().getDisplay();\r
+        while (!shell.isDisposed()) {\r
+            if (!display.readAndDispatch()) {\r
+                display.sleep();\r
+            }\r
+        }\r
+        return chartInfo;\r
+    }\r
+   \r
+    @Override\r
+    public void okPressed() {\r
+        chartInfo.lookupTable = graphToModelicaTable();\r
+        chartInfo.minX = Double.parseDouble(minX.getText());\r
+        chartInfo.maxX = Double.parseDouble(maxX.getText());\r
+        chartInfo.minY = Double.parseDouble(minY.getText());\r
+        chartInfo.maxY = Double.parseDouble(maxY.getText());\r
+        super.okPressed();\r
+    }\r
+    \r
+    @SuppressWarnings("unchecked")\r
+    private String graphToModelicaTable() {\r
+        StringBuilder b = new StringBuilder();\r
+        b.append("{");\r
+        XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset();\r
+        XYSeries series = collection.getSeries(0);\r
+        if(series.isEmpty())\r
+            return "";\r
+        Iterator iterator = series.getItems().iterator();\r
+        while(iterator.hasNext()){\r
+            XYDataItem item = (XYDataItem)iterator.next();\r
+            b.append("{" + item.getX() + "," + item.getY() + "}");\r
+            if(iterator.hasNext())\r
+                b.append(",");\r
+        }\r
+        b.append("}");\r
+        return b.toString();\r
+    }\r
+\r
+    private JFreeChart createChart() {\r
+        XYDataset dataset = createDataset();\r
+        chart = ChartFactory.createXYLineChart(null, null, null,\r
+                dataset, PlotOrientation.VERTICAL, false, true, false);\r
+        XYPlot plot = (XYPlot) chart.getPlot();\r
+        XYLineAndShapeRenderer renderer\r
+        = (XYLineAndShapeRenderer) plot.getRenderer();\r
+        renderer.setBaseShapesVisible(true);\r
+        renderer.setDrawOutlines(true);\r
+        renderer.setUseFillPaint(true);\r
+        renderer.setBaseFillPaint(Color.white);\r
+        renderer.setSeriesStroke(0, new BasicStroke(3.0f));\r
+        renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f));\r
+        renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0));\r
+\r
+        ValueAxis rangeAxis = plot.getRangeAxis();\r
+        rangeAxis.setAutoRange(false);\r
+        rangeAxis.setRange(chartInfo.minY, chartInfo.maxY);\r
+        ValueAxis domainAxis = plot.getDomainAxis();\r
+        domainAxis.setAutoRange(false);\r
+        domainAxis.setRange(chartInfo.minX, chartInfo.maxX);\r
+        return chart;\r
+    }\r
+\r
+    public XYDataset createDataset() {\r
+        XYSeries series = new XYSeries("Series");\r
+        XYSeriesCollection dataset = new XYSeriesCollection();\r
+        dataset.addSeries(series);\r
+        return dataset;\r
+    }\r
+\r
+    private ModifyListener getAxisBoundModifyListener() {\r
+        return new ModifyListener() {\r
+\r
+            @Override\r
+            public void modifyText(ModifyEvent e) {\r
+                Widget widget = e.widget;\r
+                if(widget instanceof Text) {\r
+                    Text text = (Text)widget;\r
+                    Double value;\r
+                    try {\r
+                        value = Double.parseDouble(text.getText());\r
+                    } catch (NumberFormatException e1 ) {\r
+                        return;\r
+                    }\r
+                    XYPlot plot = (XYPlot) chart.getPlot();\r
+                    ValueAxis rangeAxis = plot.getRangeAxis();\r
+                    ValueAxis domainAxis = plot.getDomainAxis();\r
+                    if(text == minX) {\r
+                        domainAxis.setLowerBound(value);\r
+                    } else if (text == maxX) {\r
+                        domainAxis.setUpperBound(value);\r
+                    } else if (text == minY) {\r
+                        rangeAxis.setLowerBound(value);\r
+                    } else if (text == maxY) {\r
+                        rangeAxis.setUpperBound(value);\r
+                    }\r
+                }\r
+            }\r
+        };\r
+    }\r
+\r
+    private class InputOutputCellModifier implements ICellModifier {\r
+\r
+        XYSeries series;\r
+\r
+        public InputOutputCellModifier() {\r
+            XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset();\r
+            series = collection.getSeries(0); \r
+        }\r
+\r
+        public boolean canModify(Object element, String property) {\r
+            return true;\r
+        }\r
+\r
+        public Object getValue(Object element, String property) {\r
+            InputOutput io = (InputOutput)element;\r
+            if (LookupInputOutputTable.INPUT.equals(property))\r
+                return (String)io.getInput(String.class);\r
+            else if (LookupInputOutputTable.OUTPUT.equals(property))\r
+                return (String)io.getOutput(String.class);\r
+            else\r
+                return null;\r
+        }\r
+\r
+        public void modify(Object element, String property, Object value) {\r
+            if (element instanceof Item) element = ((Item) element).getData();\r
+\r
+            InputOutput io = (InputOutput)element;\r
+            Double x = (Double)io.getInput(Double.class);\r
+            int item = series.indexOf(x);\r
+            series.remove(item);\r
+\r
+            if (LookupInputOutputTable.INPUT.equals(property)) {\r
+                Double newX = io.setInput((String)value);\r
+                // if has the same x-value, revert back\r
+                if(newX != null && series.indexOf(newX) >= 0) {\r
+                    io.setInput(x);\r
+                }\r
+            } else if (LookupInputOutputTable.OUTPUT.equals(property)) {\r
+                io.setOutput((String)value);\r
+            }\r
+\r
+            series.add((Double)io.getInput(Double.class), (Double)io.getOutput(Double.class));\r
+\r
+            table.refresh();\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java
new file mode 100644 (file)
index 0000000..7cc116d
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class ParameterExpression extends BasicExpression {\r
+    \r
+\r
+    public ParameterExpression() {\r
+        try {\r
+            this.expressionType = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
+\r
+                @Override\r
+                public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                    return SysdynResource.getInstance(graph).ParameterExpression;\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java
new file mode 100644 (file)
index 0000000..398858e
--- /dev/null
@@ -0,0 +1,216 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.properties.EquationTab;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class StockExpression implements IExpression {\r
+\r
+    private Text integral;\r
+    private ExpressionField expression;\r
+    \r
+    @Override\r
+    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        String initialEquation = data.get("initialEquation") != null ? (String)data.get("initialEquation") : "";\r
+        String integralEquation = data.get("integral") != null ? (String)data.get("integral") : "";\r
+\r
+        \r
+        Label label = new Label(parent, SWT.NONE);\r
+        label.setFont(EquationTab.FONT);\r
+        label.setText("Integral");\r
+        \r
+        integral = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER);\r
+        integral.setEditable(false);\r
+        integral.setFont(EquationTab.FONT);\r
+        integral.setText(integralEquation);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(integral);\r
+        \r
+        \r
+        label = new Label(parent, SWT.NONE);\r
+        label.setFont(EquationTab.FONT);\r
+        label.setText("Initial\nValue");\r
+        \r
+        expression = new ExpressionField(parent, SWT.BORDER);\r
+        expression.setExpression(initialEquation);\r
+        \r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(expression);\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void focus() {\r
+        if(this.expression != null) this.expression.focus();\r
+        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        return Arrays.asList(this.expression);\r
+    }\r
+\r
+    @Override\r
+    public void readData(final Resource variable, Map<String, Object> data) {\r
+        String initialEquation = null;\r
+\r
+        if (variable != null && data.get("initialEquation") == null) {\r
+            try {\r
+                initialEquation = SimanticsUI.getSession().syncRequest(new Read<String>() {\r
+\r
+                    @Override\r
+                    public String perform(ReadGraph graph) throws DatabaseException {\r
+                        SysdynResource sr = SysdynResource.getInstance(graph);\r
+                        Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
+                        if (expression != null && graph.isInstanceOf(expression, sr.StockExpression)) {\r
+                            return graph.getRelatedValue(expression, sr.HasInitialEquation);\r
+                        } else {\r
+                            return "";\r
+                        }\r
+                    }\r
+\r
+                });\r
+            } catch (DatabaseException e1) {\r
+                e1.printStackTrace();\r
+            }\r
+            data.put("initialEquation", initialEquation);\r
+        }\r
+\r
+        data.put("integral", getIntegral(variable));\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        if(expression != null) {\r
+            IDocument doc = expression.getDocument();\r
+            try {\r
+                Point selection = expression.getSelection();\r
+                doc.replace(selection.x, selection.y, var);\r
+                expression.setSelection(selection.x + var.length());\r
+            } catch (BadLocationException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void save(final Resource variable, Map<String, Object> data) {\r
+        final String currentText = expression.getExpression();\r
+        if(currentText != null) {\r
+            SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+\r
+                @Override\r
+                public void perform(WriteGraph g)\r
+                throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(g);\r
+                    Resource expression = g.getPossibleObject(variable, sr.HasExpression);\r
+                    Builtins b = g.getBuiltins();\r
+                    if(expression != null) {\r
+                        g.deny(variable, sr.HasExpression);\r
+                    }\r
+                    expression = g.newResource();\r
+                    g.claim(expression, b.InstanceOf, null, sr.StockExpression);\r
+                    g.claim(variable, sr.HasExpression, expression);\r
+                    g.claimValue(expression, sr.HasInitialEquation, currentText);\r
+                }\r
+\r
+            });\r
+        }\r
+        expression.setExpression(currentText);\r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        if(this.expression != null && this.expression.getExpression() != null)\r
+            data.put("initialEquation", this.expression.getExpression());\r
+        if(this.integral != null && this.integral.getText() != null)\r
+            data.put("integral", this.integral.getText());\r
+    }\r
+    \r
+    \r
+    private String getIntegral(final Resource variable) {\r
+        String integral = "";\r
+        try {\r
+            integral = SimanticsUI.getSession().syncRequest(new Read<String>() {\r
+\r
+                @Override\r
+                public String perform(ReadGraph graph) throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(graph);\r
+                    Builtins b = graph.getBuiltins();\r
+                    Collection<Resource> heads = graph.getObjects(variable, sr.IsHeadOf);\r
+                    Collection<Resource> tails = graph.getObjects(variable, sr.IsTailOf);\r
+\r
+                    StringBuilder builder = new StringBuilder();\r
+                    builder.append("");\r
+                    for (Resource r : heads) {\r
+                        if(graph.isInstanceOf(r, sr.Flow)) {\r
+                            Resource tail = graph.getPossibleObject(r, sr.HasTail);\r
+                            if(tail != null) {\r
+                                Object name = graph.getPossibleRelatedValue(tail, b.HasName);\r
+                                if (name != null)\r
+                                    builder.append(" + " + name);\r
+                            }\r
+                        }\r
+                    }\r
+                    for (Resource r : tails) {\r
+                        if(graph.isInstanceOf(r, sr.Flow)) {\r
+                            Resource head = graph.getPossibleObject(r, sr.HasHead);\r
+                            if(head != null) {\r
+                                Object name = graph.getPossibleRelatedValue(head, b.HasName);\r
+                                if (name != null)\r
+                                    builder.append(" - " + name);\r
+                            }\r
+                        }\r
+                    }\r
+                    if (builder.indexOf(" + ") == 0)\r
+                        builder.delete(0, 3);\r
+                    return builder.toString().trim();\r
+                }\r
+\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return integral;\r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java
new file mode 100644 (file)
index 0000000..ea0bbc7
--- /dev/null
@@ -0,0 +1,227 @@
+package org.simantics.sysdyn.ui.properties.widgets.expressions;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusAdapter;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.properties.EquationTab;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class WithLookupExpression implements IExpression {\r
+\r
+    private ExpressionField expression;\r
+    private ExpressionField lookup;\r
+    private Button asGraph;\r
+    private ExpressionField lastSelectedText = expression;\r
+    private Resource variable;\r
+    private LookupChartInfo chartInfo;\r
+\r
+    public WithLookupExpression(Resource variable) {\r
+        this.variable = variable;\r
+    }\r
+\r
+    @Override\r
+    public void createExpressionFields(Composite parent, final Map<String, Object> data) {\r
+\r
+        String equation = data.get("equation") != null ? (String)data.get("equation") : "";\r
+        String lookupTable = data.get("lookup") != null ? (String)data.get("lookup") : "";\r
+\r
+        Label l = new Label(parent, SWT.NONE);\r
+        l.setFont(EquationTab.FONT);\r
+        l.setText("With\nLookup");\r
+\r
+        expression = new ExpressionField(parent, SWT.BORDER);\r
+        expression.setExpression(equation);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(expression);\r
+\r
+        expression.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                lastSelectedText = expression;\r
+            }\r
+        });\r
+\r
+\r
+        l = new Label(parent, SWT.NONE);\r
+        l.setFont(EquationTab.FONT);\r
+        l.setText("Lookup\ntable");\r
+\r
+        lookup = new ExpressionField(parent, SWT.BORDER);\r
+        lookup.setExpression(lookupTable);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(lookup);\r
+\r
+        lookup.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                lastSelectedText = lookup;\r
+            }\r
+        });\r
+\r
+        asGraph = new Button(parent, SWT.None);\r
+        asGraph.setText("As graph");\r
+        asGraph.setFont(EquationTab.FONT);\r
+        asGraph.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if(chartInfo == null) chartInfo = new LookupChartInfo(expression.getExpression(), lookup.getExpression(), variable, data);\r
+                LookupPopup pud = new LookupPopup(asGraph.getParent().getShell(), chartInfo);\r
+                LookupChartInfo newInfo = pud.open(false);\r
+                if(pud.getReturnCode() == org.eclipse.jface.window.Window.OK) {\r
+                    chartInfo = newInfo;\r
+                    lookup.setExpression(chartInfo.lookupTable);\r
+                    lookup.focus();\r
+                }\r
+            }\r
+        });\r
+\r
+    }\r
+\r
+    @Override\r
+    public void focus() {\r
+        if(this.lastSelectedText != null) this.lastSelectedText.focus();        \r
+    }\r
+\r
+    @Override\r
+    public List<ExpressionField> getExpressionFields() {\r
+        return Arrays.asList(this.expression, this.lookup);\r
+    }\r
+\r
+    @Override\r
+    public void readData(final Resource variable, Map<String, Object> data) {\r
+        String[] results = null;\r
+        if (variable != null && data.get("equation") == null) {\r
+            try {\r
+                results = SimanticsUI.getSession().syncRequest(new Read<String[]>() {\r
+\r
+                    @Override\r
+                    public String[] perform(ReadGraph graph) throws DatabaseException {\r
+                        String[] results = new String[2];\r
+                        SysdynResource sr = SysdynResource.getInstance(graph);\r
+                        Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
+                        if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
+                            results[0] = graph.getRelatedValue(expression, sr.HasEquation);\r
+                            results[1] = graph.getRelatedValue(expression, sr.HasLookup);\r
+                        } else {\r
+                            results[0] = "";\r
+                            results[1] = "";\r
+                        }\r
+                        return results;\r
+                    }\r
+\r
+                });\r
+            } catch (DatabaseException e1) {\r
+                e1.printStackTrace();\r
+            }\r
+            data.put("equation", results[0]);\r
+            data.put("lookup", results[1]);\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    public void replaceSelection(String var) {\r
+        if(lastSelectedText != null) {\r
+            IDocument doc = lastSelectedText.getDocument();\r
+            try {\r
+                Point selection = lastSelectedText.getSelection();\r
+                doc.replace(selection.x, selection.y, var);\r
+                lastSelectedText.setSelection(selection.x + var.length());\r
+            } catch (BadLocationException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }        \r
+    }\r
+\r
+    @Override\r
+    public void save(final Resource variable, Map<String, Object> data) {\r
+        final String currentExpression = expression.getExpression();\r
+        final String currentLookupTable = lookup.getExpression();\r
+\r
+        if(currentExpression != null && currentLookupTable != null) {\r
+            data.putAll(data);\r
+            data.put("equation", currentExpression);\r
+            data.put("lookup", currentLookupTable);\r
+            SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+                @Override\r
+                public void perform(WriteGraph g)\r
+                throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(g);\r
+                    Resource expression = g.getPossibleObject(variable, sr.HasExpression);\r
+                    Builtins b = g.getBuiltins();\r
+                    if(expression != null) {\r
+                        g.deny(variable, sr.HasExpression);\r
+                    }\r
+                    expression = g.newResource();\r
+                    g.claim(expression, b.InstanceOf, null, sr.WithLookupExpression);\r
+                    g.claim(variable, sr.HasExpression, expression);\r
+                    g.claimValue(expression, sr.HasEquation, currentExpression);\r
+                    g.claimValue(expression, sr.HasLookup, currentLookupTable);\r
+                    if(chartInfo != null) {\r
+                        g.claimValue(expression, sr.HasMinX, chartInfo.minX);\r
+                        g.claimValue(expression, sr.HasMaxX, chartInfo.maxX);\r
+                        g.claimValue(expression, sr.HasMinY, chartInfo.minY);\r
+                        g.claimValue(expression, sr.HasMaxY, chartInfo.maxY);\r
+                    }\r
+                }\r
+            });\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    public void updateData(Map<String, Object> data) {\r
+        if(this.expression != null && this.expression.getExpression() != null)\r
+            data.put("equation", this.expression.getExpression());\r
+        if(this.lookup != null && this.lookup.getExpression() != null)\r
+            data.put("lookup", this.lookup.getExpression());\r
+        if(this.chartInfo != null) {\r
+            data.put("minX", chartInfo.minX);\r
+            data.put("maxX", chartInfo.maxX);\r
+            data.put("minY", chartInfo.minY);\r
+            data.put("maxY", chartInfo.maxY);\r
+        }        \r
+    }\r
+\r
+    @Override\r
+    public void addKeyListener(KeyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+        this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+    }\r
+\r
+    @Override\r
+    public void addModifyListener(ModifyListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+        this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+    }\r
+\r
+    @Override\r
+    public void addFocusListener(FocusListener listener) {\r
+        this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+        this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+    }\r
+\r
+}\r