]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Delay expression
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 30 Nov 2011 10:22:57 +0000 (10:22 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 30 Nov 2011 10:22:57 +0000 (10:22 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@23372 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/VariableInformationTab.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
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SysdynSchema.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java

index cd6af74170674cf7ce2a1346f2b858a30e23754d..0aa3881667b586aa86a20722a26973b0068bbd65 100644 (file)
@@ -11,7 +11,6 @@
  *******************************************************************************/\r
 package org.simantics.sysdyn.ui.properties;\r
 \r
-import org.eclipse.jface.dialogs.IInputValidator;\r
 import org.eclipse.jface.layout.GridDataFactory;\r
 import org.eclipse.jface.layout.GridLayoutFactory;\r
 import org.eclipse.swt.SWT;\r
@@ -36,7 +35,13 @@ import org.simantics.sysdyn.ui.properties.widgets.ValveTextLocationGroup;
 import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory;\r
 import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier;\r
 import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.ui.validators.DoubleValidator;\r
 \r
+/**\r
+ * Information tab for additional information of variables. \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 public class VariableInformationTab extends LabelPropertyTabContributor implements Widget {\r
     Composite orientationComposite;\r
     WidgetSupport support;\r
@@ -54,16 +59,19 @@ public class VariableInformationTab extends LabelPropertyTabContributor implemen
         informationGroup.setText("Information");\r
         GridDataFactory.fillDefaults().grab(false, true).applyTo(informationGroup);\r
         GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(informationGroup);\r
-\r
+        \r
+        // Textual format documentation\r
         TrackedText information = new TrackedText(informationGroup, support, SWT.MULTI | SWT.BORDER);\r
         information.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasDescription));\r
         information.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasDescription));\r
         GridDataFactory.fillDefaults().grab(true, true).applyTo(information.getWidget());\r
 \r
+        // Orientation information for valves\r
         orientationComposite = new Composite(composite, SWT.NONE);\r
         GridDataFactory.fillDefaults().span(1, 2).applyTo(orientationComposite);\r
         GridLayoutFactory.fillDefaults().margins(3,3).applyTo(orientationComposite);\r
  \r
+        // Range of a variable (e.g. from 0 to 10). Does not affect simulation, but the infor can be used for example in charts\r
         Group rangeGroup = new Group(composite, SWT.SHADOW_ETCHED_IN);\r
         rangeGroup.setText("Range");\r
         GridDataFactory.fillDefaults().applyTo(rangeGroup);\r
@@ -98,30 +106,12 @@ public class VariableInformationTab extends LabelPropertyTabContributor implemen
         rangeStep.setInputValidator(new DoubleValidator());\r
         GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeStep.getWidget());\r
         \r
-\r
-\r
-    }\r
-\r
-    private class DoubleValidator implements IInputValidator {\r
-\r
-        @Override\r
-        public String isValid(String newText) {\r
-            for(int i = 0; i < newText.length(); i++){\r
-                if(!Character.isDigit(newText.charAt(i))){\r
-                    if(newText.charAt(i) != '.') {\r
-                        return "Invalid character '" + newText.charAt(i) + "'";\r
-                    } else if(newText.indexOf('.') != newText.lastIndexOf('.')) {\r
-                        return "There can be only one '.'";\r
-                    }\r
-                }\r
-            }\r
-            return null;\r
-        }\r
     }\r
 \r
     @Override\r
     public void setInput(ISessionContext context, Object input) {\r
         final Resource valve = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+        // is the displayed variable a valve?\r
         Boolean isValve = false;\r
         try {\r
             isValve = context.getSession().syncRequest(new Read<Boolean>() {\r
@@ -136,6 +126,7 @@ public class VariableInformationTab extends LabelPropertyTabContributor implemen
         } catch (DatabaseException e) {\r
             e.printStackTrace();\r
         }\r
+        // if it is a valve, display the orientation information\r
         if(isValve) {\r
             ValveOrientationGroup vog = new ValveOrientationGroup(orientationComposite, context, support, SWT.NONE);\r
             vog.setInput(context, input);\r
index 967b1ff48f7de18411979afcc4a685c9b84821a5..7b3b20bf981c0b074232e54338c2716b5813cf54 100644 (file)
  *******************************************************************************/\r
 package org.simantics.sysdyn.ui.properties.widgets;\r
 \r
-import java.util.List;\r
-\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
-import org.simantics.db.common.utils.OrderedSetUtils;\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
+/**\r
+ * Expression type representations\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 public class ExpressionTypes {\r
 \r
        public static enum ExpressionType {Auxiliary, Parameter, Constant, Lookup, WithLookup, Stock, Delay, Empty};\r
@@ -29,6 +31,7 @@ public class ExpressionTypes {
                ExpressionType.Auxiliary, \r
                ExpressionType.Parameter, \r
                ExpressionType.Constant, \r
+               ExpressionType.Delay,\r
                // ExpressionType.Lookup, \r
                ExpressionType.WithLookup};\r
 \r
@@ -36,6 +39,7 @@ public class ExpressionTypes {
                ExpressionType.Auxiliary, \r
                ExpressionType.Parameter, \r
                ExpressionType.Constant, \r
+               ExpressionType.Delay,\r
                ExpressionType.WithLookup};\r
 \r
        public static ExpressionType[] stockExpressions = new ExpressionType[] {\r
index f6e40dedb75dab01dc4339d66ec23ee445340f7d..5da8f765a1d517a62a4a8cfef46ce364bdb46129 100644 (file)
@@ -49,6 +49,14 @@ import org.simantics.sysdyn.ui.utils.ExpressionUtils;
 import org.simantics.ui.SimanticsUI;\r
 import org.simantics.ui.utils.AdaptionUtils;\r
 \r
+/**\r
+ * Widget for displaying an expression. Widget creates the IExpression for displaying\r
+ * properties for each expression type and adds validation, saving and other services\r
+ * to the active IExpression.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 public class ExpressionWidget implements Widget {\r
 \r
        private Resource expr;\r
@@ -59,15 +67,25 @@ public class ExpressionWidget implements Widget {
        private FocusListener focusListener;\r
        private Table variableTable;\r
        private VerifyKeyListener verifyKeyListener;\r
-    private Timer updateChartTimer;\r
+    private Timer validationTimer;\r
     private static int VALIDATION_DELAY_TIME = 500;\r
 \r
+    /**\r
+     * Create a new expression widget\r
+     * @param parent\r
+     * @param support\r
+     * @param style\r
+     */\r
     public ExpressionWidget(Composite parent, WidgetSupport support, int style) {\r
                support.register(this);\r
                this.parent = parent;\r
                this.data = new HashMap<String, Object>();\r
                \r
-        updateChartTimer = new Timer(VALIDATION_DELAY_TIME, new ActionListener() {\r
+               /*\r
+                *  Create a validation timer for expression fields. Validation timer\r
+                *  validates the field as the modeler is typing an expression \r
+                */\r
+               validationTimer = new Timer(VALIDATION_DELAY_TIME, new ActionListener() {\r
 \r
             @Override\r
             public void actionPerformed(ActionEvent e) {\r
@@ -82,22 +100,32 @@ public class ExpressionWidget implements Widget {
                        });\r
             }\r
         });\r
-        updateChartTimer.setRepeats(false);\r
+               validationTimer.setRepeats(false);\r
        }\r
 \r
        @Override\r
        public void setInput(ISessionContext context, Object input) {  \r
+           // Update IExpression based on the newly selected expression\r
                expr = AdaptionUtils.adaptToSingle(input, Resource.class);\r
                ExpressionType et = ExpressionTypes.getExpressionType(expr);\r
                displayExpression(et.toString(), true);\r
        }\r
 \r
+       /**\r
+        * Displays IExpression corresponding to expressionType.\r
+        * @param expressionType Expression type\r
+        * @param original Is the displayed expression for a newly selected expression (true) or did the\r
+        * expression change its type (false) \r
+        */\r
        public void displayExpression(String expressionType, boolean original) {\r
                if(expressionType == null) {\r
                        return;\r
                }\r
 \r
+               // Get up-to-date data to data-map\r
                if(this.expression != null) expression.updateData(data);\r
+               \r
+               // Create the new expression\r
                ExpressionType et = ExpressionType.valueOf(expressionType);\r
                IExpression exp = null;\r
                switch (et) {\r
@@ -114,20 +142,25 @@ public class ExpressionWidget implements Widget {
                case Stock: \r
                        exp = new StockExpression(); break;\r
                case Delay: \r
-                       exp = new DelayExpression(); break;\r
+                       exp = new DelayExpression(expr); break;\r
                default: \r
                        exp = new EmptyExpression();\r
                }\r
 \r
                if (exp != null) {\r
+                   // If expression was created, remove the old one\r
                        for(Control c : parent.getChildren()) {\r
                                c.dispose();\r
                        } \r
 \r
+                       // If a completely new expression was selected, read data\r
                        if(original) \r
                                exp.readData(expr, data);\r
 \r
+                       // Create the visual representation of the expression type\r
                        exp.createExpressionFields(parent, data);\r
+                       \r
+                       // Add listeners\r
                        if(modifyListener != null)\r
                                exp.addModifyListener(modifyListener);\r
                        if(focusListener != null)\r
@@ -142,32 +175,50 @@ public class ExpressionWidget implements Widget {
                }  \r
        }\r
 \r
+       /**\r
+        * Get current IExpression\r
+        * @return current IExpression\r
+        */\r
        public IExpression getExpression() {\r
                return expression;\r
        }\r
 \r
+       /**\r
+        * Set the variable table that contains information about variables that are connected \r
+        * to this expression\r
+        * @param table\r
+        */\r
        public void setVariableTable(Table table) {\r
                this.variableTable = table;\r
        }\r
 \r
-\r
+       /**\r
+        * Set timed field validation with default delay time\r
+        */\r
     public void validateFieldsTimed() {        \r
        validateFieldsTimed(VALIDATION_DELAY_TIME);\r
     }\r
     \r
+    /**\r
+     * Set timed field validation\r
+     * @param delay Delay time for validation\r
+     */\r
     public void validateFieldsTimed(int delay) {\r
-       updateChartTimer.setDelay(delay);\r
-        if(!updateChartTimer.isRunning())\r
-            updateChartTimer.start();\r
+        validationTimer.setDelay(delay);\r
+        if(!validationTimer.isRunning())\r
+            validationTimer.start();\r
         else\r
-            updateChartTimer.restart();\r
+            validationTimer.restart();\r
     }\r
     \r
-    \r
+    /**\r
+     * Validates expression fields in current IExpression\r
+     */\r
        public void validateFields() {\r
                if(this.variableTable == null) return;\r
         \r
                try {\r
+                   // Find the variable for this experession\r
                        Resource variable = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
 \r
                                @Override\r
@@ -181,10 +232,10 @@ public class ExpressionWidget implements Widget {
                                        return variable;\r
                                }\r
                        });\r
+                       // Validate the variable\r
                        if(variable != null)\r
                                ExpressionUtils.validateExpressionFields(variable, expression, variableTable);\r
                } catch (DatabaseException e) {\r
-                       // TODO Auto-generated catch block\r
                        e.printStackTrace();\r
                }\r
 \r
index 18083697a394281f45cfb79278224187a45a18ca..96c6268e776de6e308db7f62dd4e30741162c322 100644 (file)
@@ -12,6 +12,7 @@
 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
@@ -42,6 +43,11 @@ import org.simantics.sysdyn.SysdynResource;
 import org.simantics.sysdyn.ui.utils.ExpressionUtils;\r
 import org.simantics.ui.SimanticsUI;\r
 \r
+/**\r
+ * Basic expression that is used with parameter, auxiliary and constant\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 public class BasicExpression implements IExpression {\r
 \r
     private ExpressionField expression;\r
@@ -49,6 +55,7 @@ public class BasicExpression implements IExpression {
 \r
     @Override\r
     public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
+        // Create the single field\r
         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(parent);\r
         String equation = data.get("equation") != null ? (String)data.get("equation") : "";\r
 \r
@@ -127,13 +134,16 @@ public class BasicExpression implements IExpression {
                 throws DatabaseException {\r
                     SysdynResource sr = SysdynResource.getInstance(g);\r
                     Layer0 l0 = Layer0.getInstance(g);\r
-                    \r
+\r
+                    // Force change to parameter, if the equation is a parameter\r
                     if(ExpressionUtils.isParameter(currentText)) {\r
                        if(!expressionType.equals(sr.ConstantExpression))\r
                                expressionType = sr.ParameterExpression;\r
                     } else {\r
                        expressionType = sr.NormalExpression;\r
                     }\r
+                    \r
+                    // If nothing has changed, do nothing\r
                     if (oldEquation != null \r
                             && expression != null \r
                             && g.isInstanceOf(expression, expressionType) \r
@@ -141,8 +151,12 @@ public class BasicExpression implements IExpression {
                         return;\r
                     }\r
                     \r
+                    // If the current expression type is different than the target expression type, create a new expression\r
                     if(!g.isInstanceOf(expression, expressionType)) {\r
-                       Resource ownerList = OrderedSetUtils.getSingleOwnerList(g, expression);\r
+                       Collection<Resource> ownerLists = OrderedSetUtils.getOwnerLists(g, expression, l0.OrderedSet);\r
+                       if(ownerLists.size() != 1)\r
+                           return;\r
+                       Resource ownerList = ownerLists.iterator().next();\r
                        final Resource newExpression = GraphUtils.create2(g, expressionType, \r
                                        sr.HasEquation, currentText);\r
                        String arrayRange = g.getPossibleRelatedValue(expression, sr.HasArrayRange, Bindings.STRING);\r
@@ -169,6 +183,7 @@ public class BasicExpression implements IExpression {
                                                }\r
                                                );\r
                     } else {\r
+                        // Claim value for the expression\r
                        g.claimLiteral(expression, sr.HasEquation, currentText);\r
                     }\r
                 }\r
index dc7b724d32e29c5d5564341d7c4daa910143c1ea..18b2e8cdf9f953fdd55c8930d4918c05c9c45393 100644 (file)
  *******************************************************************************/\r
 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.layout.GridLayoutFactory;\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.custom.VerifyKeyListener;\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.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Spinner;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
 \r
+/**\r
+ * IExpression for displaying fields of DelayExpression\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 public class DelayExpression implements IExpression {\r
 \r
+    private ExpressionField equation, delayTime, initialValue;\r
+    private ExpressionField lastSelectedText = equation;\r
+    private Spinner order;\r
+    private Resource expression;\r
+\r
+    /**\r
+     * Creates a new DelayExpression\r
+     * @param expression\r
+     */\r
+    public DelayExpression(Resource expression) {\r
+        this.expression = expression;\r
+    }\r
+\r
+    /**\r
+     * Displays the fields for delayExpression\r
+     */\r
     @Override\r
-    public void createExpressionFields(Composite parent, Map<String, Object> data) {\r
-        // TODO Auto-generated method stub\r
-        \r
+    public void createExpressionFields(Composite parent, final Map<String, Object> data) {\r
+        // Get possible existing data\r
+        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(parent);\r
+        String eq = data.get("equation") != null ? (String)data.get("equation") : "";\r
+        String dt = data.get("delayTime") != null ? (String)data.get("delayTime") : "";\r
+        String iv = data.get("initialValue") != null ? (String)data.get("initialValue") : "";\r
+        int o = data.get("order") != null ? (Integer)data.get("order") : 3;\r
+\r
+        Label l = new Label(parent, SWT.NONE);\r
+        l.setText("expression");\r
+\r
+        // Equation that is delayed\r
+        equation = new ExpressionField(parent, SWT.BORDER);\r
+        equation.setExpression(eq);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(equation);\r
+        equation.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                lastSelectedText = equation;\r
+            }\r
+        });\r
+\r
+        l = new Label(parent, SWT.NONE);\r
+        l.setText("delay time");\r
+\r
+        // How much the equation is delayed\r
+        delayTime = new ExpressionField(parent, SWT.BORDER);\r
+        delayTime.setExpression(dt);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(delayTime);\r
+\r
+        delayTime.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                lastSelectedText = delayTime;\r
+            }\r
+        });\r
+\r
+        l = new Label(parent, SWT.NONE);\r
+        l.setText("initial value");\r
+\r
+        // What is the initial value of the delay (empty == same as equation)\r
+        initialValue = new ExpressionField(parent, SWT.BORDER);\r
+        initialValue.setExpression(iv);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(initialValue);\r
+\r
+        initialValue.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
+\r
+            @Override\r
+            public void focusLost(FocusEvent e) {\r
+                lastSelectedText = initialValue;\r
+            }\r
+        });\r
+\r
+\r
+        l = new Label(parent, SWT.NONE);\r
+        l.setText("order");\r
+\r
+        // The order of the delay (default == 3)\r
+        order = new Spinner(parent, SWT.BORDER);\r
+        order.setMinimum(1);\r
+        order.setSelection(o);\r
+        order.addSelectionListener(new SelectionAdapter() {\r
+            @Override\r
+            public void widgetSelected(SelectionEvent e) {\r
+                save(expression, data);\r
+            }\r
+        });\r
+        GridDataFactory.fillDefaults().applyTo(order);\r
     }\r
 \r
     @Override\r
     public void focus() {\r
-        // TODO Auto-generated method stub\r
-        \r
+        equation.setFocus();\r
     }\r
 \r
     @Override\r
     public List<ExpressionField> getExpressionFields() {\r
-        // TODO Auto-generated method stub\r
-        return null;\r
+        return Arrays.asList(equation, delayTime);\r
     }\r
 \r
     @Override\r
-    public void readData(Resource variable, Map<String, Object> data) {\r
-        // TODO Auto-generated method stub\r
-        \r
+    public void readData(final Resource expression, Map<String, Object> data) {\r
+        class Auxiliary {\r
+            String equation, delayTime, initialValue;\r
+            Integer order;\r
+        }\r
+\r
+        Auxiliary results = null;\r
+\r
+        try {\r
+            results = SimanticsUI.getSession().syncRequest(new Read<Auxiliary>() {\r
+\r
+                @Override\r
+                public Auxiliary perform(ReadGraph graph) throws DatabaseException {\r
+                    Auxiliary results = new Auxiliary();\r
+                    SysdynResource sr = SysdynResource.getInstance(graph);\r
+                    if (expression != null && graph.isInstanceOf(expression, sr.DelayExpression)) {\r
+                        results.equation = graph.getPossibleRelatedValue(expression, sr.DelayExpression_expression);\r
+                        results.delayTime = graph.getPossibleRelatedValue(expression, sr.DelayExpression_delayTime);\r
+                        results.initialValue = graph.getPossibleRelatedValue(expression, sr.DelayExpression_initialValue);\r
+                        results.order = graph.getPossibleRelatedValue(expression, sr.DelayExpression_order);\r
+                    } else {\r
+                        results.equation = "";\r
+                        results.delayTime = "";\r
+                        results.order = 1;\r
+                    }\r
+                    return results;\r
+                }\r
+            });\r
+        } catch (DatabaseException e1) {\r
+            e1.printStackTrace();\r
+        }\r
+        if(results.equation != null)\r
+            data.put("equation", results.equation);\r
+        if(results.delayTime != null)\r
+            data.put("delayTime", results.delayTime);\r
+        if(results.initialValue != null)\r
+            data.put("initialValue", results.initialValue);\r
+        if(results.order != null)\r
+            data.put("order", results.order);\r
     }\r
 \r
     @Override\r
     public void replaceSelection(String var) {\r
-        // TODO Auto-generated method stub\r
-        \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(Resource variable, Map<String, Object> data) {\r
-        // TODO Auto-generated method stub\r
-        \r
+    public void save(Resource expr, Map<String, Object> data) {\r
+        this.expression = expr;\r
+        final String currentEquation = this.equation.getExpression();\r
+        final String currentDelayTime =  this.delayTime.getExpression();\r
+        final String currentInitialValue = this.initialValue.getExpression();\r
+        final Integer currentOrder = this.order.getSelection();\r
+\r
+        String oldEquation = (String)data.get("equation");\r
+        String oldDelayTime = (String)data.get("delayTime");\r
+        String oldInitialValue = (String)data.get("initialValue");\r
+        Integer oldOrder = (Integer)data.get("order");\r
+\r
+        if((oldEquation == null || oldDelayTime == null || oldOrder == null || oldInitialValue == null) ||\r
+                !oldEquation.equals(currentEquation) || !oldDelayTime.equals(currentDelayTime) ||\r
+                !oldOrder.equals(currentOrder) || !oldInitialValue.equals(currentInitialValue)) {\r
+            // old value was null or value has changed -> Do save\r
+\r
+            data.putAll(data);\r
+            data.put("equation", currentEquation);\r
+            data.put("delayTime", currentDelayTime);\r
+            data.put("initialValue", currentInitialValue);\r
+            data.put("order", currentOrder);\r
+\r
+            SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+                @Override\r
+                public void perform(WriteGraph g)\r
+                        throws DatabaseException {\r
+                    SysdynResource sr = SysdynResource.getInstance(g);\r
+                    Layer0 l0 = Layer0.getInstance(g);\r
+\r
+                    if(!g.isInstanceOf(expression, sr.DelayExpression)) {\r
+                        // Create a new DelayExpression, if the old expression was something else\r
+                        Resource ownerList = OrderedSetUtils.getSingleOwnerList(g, expression);\r
+                        final Resource newExpression = GraphUtils.create2(g, sr.DelayExpression);\r
+                        String arrayRange = g.getPossibleRelatedValue(expression, sr.HasArrayRange, Bindings.STRING);\r
+                        if(arrayRange != null)\r
+                            g.claimLiteral(newExpression, sr.HasArrayRange, arrayRange);\r
+\r
+                        final Resource variable = g.getSingleObject(ownerList, sr.HasExpressions_Inverse);\r
+                        OrderedSetUtils.replace(g, ownerList, expression, newExpression);\r
+                        g.deny(expression, l0.PartOf);\r
+                        g.claim(newExpression, l0.PartOf, variable);\r
+\r
+                        VirtualGraph runtime = g.getService(VirtualGraph.class);\r
+                        g.syncRequest(new WriteRequest(runtime) {\r
+                            @Override\r
+                            public void perform(WriteGraph graph) throws DatabaseException {\r
+                                SysdynResource sr = SysdynResource.getInstance(graph);\r
+                                if(graph.hasStatement(variable, sr.HasActiveExpression))\r
+                                    graph.deny(variable, sr.HasActiveExpression);\r
+                                graph.claim(variable, sr.HasActiveExpression, newExpression);\r
+                            }\r
+                        }\r
+                                );\r
+                        expression = newExpression;\r
+                    }\r
+                    \r
+                    // Claim values\r
+                    g.claimLiteral(expression, sr.DelayExpression_expression, currentEquation);\r
+                    g.claimLiteral(expression, sr.DelayExpression_delayTime, currentDelayTime);\r
+                    g.claimLiteral(expression, sr.DelayExpression_initialValue, currentInitialValue);\r
+                    g.claimLiteral(expression, sr.DelayExpression_order, currentOrder);\r
+                }\r
+            });\r
+        }\r
+\r
     }\r
 \r
     @Override\r
     public void updateData(Map<String, Object> data) {\r
-        // TODO Auto-generated method stub\r
-        \r
+        if(this.equation != null && this.equation.getExpression() != null)\r
+            data.put("equation", this.equation.getExpression());\r
+        if(this.delayTime != null && this.delayTime.getExpression() != null)\r
+            data.put("delayTime", this.delayTime.getExpression());   \r
+        if(this.initialValue != null && this.initialValue.getExpression() != null)\r
+            data.put("initialValue", this.initialValue.getExpression());   \r
+        if(this.order != null)\r
+            data.put("order", this.order.getSelection());   \r
     }\r
 \r
     @Override\r
     public void addKeyListener(KeyListener listener) {\r
-        // TODO Auto-generated method stub\r
-        \r
+        this.equation.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+        this.delayTime.getSourceViewer().getTextWidget().addKeyListener(listener);\r
+        this.initialValue.getSourceViewer().getTextWidget().addKeyListener(listener);\r
     }\r
 \r
     @Override\r
     public void addModifyListener(ModifyListener listener) {\r
-        // TODO Auto-generated method stub\r
-        \r
+        this.equation.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+        this.delayTime.getSourceViewer().getTextWidget().addModifyListener(listener);\r
+        this.initialValue.getSourceViewer().getTextWidget().addModifyListener(listener);\r
     }\r
 \r
     @Override\r
     public void addFocusListener(FocusListener listener) {\r
-        // TODO Auto-generated method stub\r
-        \r
+        this.equation.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+        this.delayTime.getSourceViewer().getTextWidget().addFocusListener(listener);\r
+        this.initialValue.getSourceViewer().getTextWidget().addFocusListener(listener);\r
     }\r
 \r
-       @Override\r
-       public void addVerifyKeyListener(VerifyKeyListener listener) {\r
-               // TODO Auto-generated method stub\r
-               \r
-       }\r
+    @Override\r
+    public void addVerifyKeyListener(VerifyKeyListener listener) {\r
+        this.equation.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
+        this.delayTime.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
+        this.initialValue.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
+    }\r
 \r
 }\r
index 3c6a6eede7aedbfcbb856941edbe40fc7e3020a9..aadf2a0fc1bbf80853c21bdf842b4a158324cc81 100644 (file)
@@ -16,6 +16,7 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.objmap.schema.MappingSchemas;\r
 import org.simantics.objmap.schema.SimpleSchema;\r
 import org.simantics.sysdyn.representation.expressions.ConstantExpression;\r
+import org.simantics.sysdyn.representation.expressions.DelayExpression;\r
 import org.simantics.sysdyn.representation.expressions.Expressions;\r
 import org.simantics.sysdyn.representation.expressions.LookupExpression;\r
 import org.simantics.sysdyn.representation.expressions.NormalExpression;\r
@@ -54,6 +55,7 @@ public class SysdynSchema extends SimpleSchema {
             addLinkType(MappingSchemas.fromAnnotations(g, Book.class));\r
             addLinkType(MappingSchemas.fromAnnotations(g, Sheet.class));\r
             addLinkType(MappingSchemas.fromAnnotations(g, DiagramContainerDummy.class));\r
+            addLinkType(MappingSchemas.fromAnnotations(g, DelayExpression.class));\r
         } catch (DatabaseException e) {\r
             e.printStackTrace();\r
         } catch (InstantiationException e) {\r
index 1f9fe8356c13a727bf7a279cf504a57d73366984..6aea3fc565fb590f8252984d07fd94d7f3e9acb8 100644 (file)
  *******************************************************************************/\r
 package org.simantics.sysdyn.representation.expressions;\r
 \r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+\r
 import org.simantics.objmap.annotations.GraphType;\r
+import org.simantics.objmap.annotations.RelatedValue;\r
+import org.simantics.sysdyn.representation.ArrayIndexes;\r
+import org.simantics.sysdyn.representation.Enumeration;\r
+import org.simantics.sysdyn.representation.IndependentVariable;\r
+import org.simantics.sysdyn.representation.Variable;\r
+import org.simantics.sysdyn.representation.utils.FormatUtils;\r
+import org.simantics.sysdyn.representation.utils.IndexUtils;\r
 \r
+/**\r
+ * Representation of a delay expression. The order of the \r
+ * delay can be 1-n.\r
+ * \r
+ * Delay with n = 3:\r
+ * \r
+ * DELAY3=LV3/DL\r
+ * LV3=INTEG(RT2-DELAY3,DL*input)\r
+ * RT2=LV2/DL\r
+ * LV2=INTEG(RT1-RT2,LV3)\r
+ * RT1=LV1/DL\r
+ * LV1=INTEG(input-RT1,LV3)\r
+ * DL=delay time/3\r
+ * \r
+ * DELAY3I=LV3/DL\r
+ * LV3=INTEG(RT2-DELAY3I,initial value*DL) \r
+ * RT2=LV2/DL\r
+ * LV2=INTEG(RT1-RT2,LV3)\r
+ * RT1=LV1/DL\r
+ * LV1=INTEG(input-RT1,LV3)\r
+ * DL=delay time/3\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
 @GraphType("http://www.simantics.org/Sysdyn-1.1/DelayExpression")\r
 public class DelayExpression extends Expression {\r
 \r
+    @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/initialValue")\r
+    private String initialValue;\r
+\r
+    @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/delayTime")\r
+    private String delayTime;\r
+\r
+    @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/order")\r
+    private Integer order;\r
+\r
+    @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/expression")\r
+    private String equation;\r
+\r
+    @Override\r
+    public String getDeclaration(IndependentVariable variable) {\r
+\r
+        // Calculate range for the variable\r
+        ArrayIndexes ai = variable.getArrayIndexes();\r
+        ArrayList<Enumeration> enumerations = null;\r
+        if(ai != null) \r
+            enumerations = ai.getEnumerations();\r
+\r
+        String range = "";\r
+        if(enumerations != null && enumerations.size() > 0) {\r
+            StringBuilder sb = new StringBuilder();\r
+            sb.append("[");\r
+            Iterator<Enumeration> iterator = enumerations.iterator();\r
+            while(iterator.hasNext()) {\r
+                sb.append(iterator.next().getName() + ".size");\r
+                if(iterator.hasNext()) {\r
+                    sb.append(", ");\r
+                }\r
+            }\r
+            sb.append("]");\r
+            range = sb.toString();\r
+        }\r
+        \r
+        /* Build the declaration */\r
+        StringBuilder declaration = new StringBuilder();\r
+        // Variable declaration\r
+        declaration.append("    " + variable.getType() + " " + variable.getName() + range + ";\n");\r
+        // Delay declaration\r
+        declaration.append("    " + variable.getName() + "_delayClass " + variable.getName() + "_delayClass_instance");\r
+        // Change enumeration sizes from the delay class. Supports overridden enumerations in modules.\r
+        if(range.length() > 0) {\r
+            declaration.append("(");\r
+            String[] ranges = range.substring(1, range.length() - 1).split(",");\r
+            for(int i = 0; i < ranges.length; i++ ) {\r
+                String r = ranges[i];\r
+                declaration.append(r.replace(".size", "size") + " = " + r);\r
+                if(i < ranges.length - 1) {\r
+                    declaration.append(", ");\r
+                }\r
+            }\r
+            declaration.append(")");\r
+        }\r
+        declaration.append(";\n");\r
+        \r
+        // Write the delay class\r
+        declaration.append(getDelayClass(variable, range, order));\r
+        return declaration.toString();\r
+    }\r
+\r
+    /**\r
+     * Creates a class that is used to implement the delay. Class contains\r
+     * a basic delay structure with "stocks and flows". The number of \r
+     * stocks and flows is determined by the order of the delay\r
+     * \r
+     * @param variable The variable for which the delay is created\r
+     * @param range Array range\r
+     * @param n Order of the delay\r
+     * @return\r
+     */\r
+    private String getDelayClass(Variable variable, String range, int n) {\r
+        StringBuilder sb = new StringBuilder();\r
+\r
+        sb.append("class " + variable.getName() + "_delayClass\n");\r
+        \r
+        // Auxiliary variable\r
+        sb.append("\tReal DL;\n");\r
+        // Delay time\r
+        sb.append("\tReal delayTime;\n");\r
+\r
+        // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable\r
+        if(range.length() > 0) {\r
+            range = range.replaceAll(".size", "size");\r
+            for(String r : range.substring(1, range.length() - 1).split(",")) {\r
+                sb.append("\t parameter Integer " + r + ";\n");\r
+            }\r
+        }\r
+\r
+        if(initialValue == null || initialValue.length() == 0)\r
+            // Use "random" number as initial value, if initial value is not set\r
+            sb.append("\tReal" + range + " initialValue = " + (range.length() > 0 ? "fill(-137543," + range.substring(1, range.length() - 1) + ")" : -137543) + ";\n");\r
+        else\r
+            // Initial value\r
+            sb.append("\tReal" + range + " initialValue = " + initialValue + ";\n");\r
+        \r
+        // First valve\r
+        sb.append("\tReal" + range + " delay0;\n");\r
+\r
+        // Stocks and valves. Valves are the delayed values of the variable\r
+        for(int i = 1; i <= n; i++) {\r
+            sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n");\r
+            sb.append("\tReal" + range + " delay" + i + ";\n");\r
+        }\r
+\r
+        sb.append("initial equation\n");\r
+        \r
+        // "Generic" structure selection. If the "random" number is not used in initial value, use delay0 as initial value\r
+        sb.append("\tLV" + n +" = DL * " + \r
+                (range.length() > 0 ? "(if max(initialValue) < -137543 or max(initialValue) > -137543 then initialValue else delay0)" :\r
+                        "(if initialValue < -137543 or initialValue > -137543 then initialValue else delay0)") + ";\n");\r
+        \r
+        // Each stock gets the same initial value\r
+        for(int i = 1; i < n; i++)\r
+            sb.append("\tLV" + i + " = LV" + n + ";\n");\r
+\r
+        sb.append("equation\n");\r
+        sb.append("\tDL = delayTime/" + n + ";\n");\r
+\r
+        // Valves and stocks\r
+        for(int i = 1; i <= n; i++) {\r
+            sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n");\r
+            sb.append("\tdelay" + i + " = LV" + i + "/DL;\n");\r
+        }\r
+\r
+        sb.append("end " + variable.getName() + "_delayClass;\n");\r
+        return sb.toString();\r
+    }\r
+\r
+    @Override\r
+    public String getEquation(IndependentVariable variable) {\r
+        String equation = FormatUtils.formatExpressionForModelica(variable, this.equation);\r
+\r
+        // Set delay properties\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("    " + variable.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
+        sb.append("    " + variable.getName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
+\r
+        // Use the delay in the value of variable\r
+        String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
+        sb.append("    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + variable.getName() + "_delayClass_instance.delay" + order + ";\n");\r
+        return sb.toString();\r
+    }\r
+\r
+\r
 }\r