]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Add a new listener for EquationTab and make sure new value is accepted 43/4343/3
authorJani Mäkinen <jani.makinen@semantum.fi>
Mon, 13 Jul 2020 07:56:23 +0000 (10:56 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 10 Aug 2020 07:09:24 +0000 (07:09 +0000)
gitlab #49

Change-Id: If3b614d1306f295f506ef51bd0a095806f4c7fac

bundles/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java
bundles/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java

index cfaec04641a0bba81563f76565ff5ed7a094d246..8b62d3ae19a4d77c73fc72f81ef3bfa788873e98 100644 (file)
@@ -30,6 +30,7 @@ import org.eclipse.swt.events.MouseListener;
 import org.eclipse.swt.events.VerifyEvent;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableItem;
@@ -54,10 +55,13 @@ import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.VirtualGraph;
 import org.simantics.db.WriteGraph;
+import org.simantics.db.common.procedure.adapter.ListenerAdapter;
+import org.simantics.db.common.request.ResourceRead;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.common.request.WriteResultRequest;
 import org.simantics.db.common.utils.ListUtils;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.VariableRepresents;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.management.ISessionContext;
@@ -80,8 +84,11 @@ import org.simantics.sysdyn.ui.properties.widgets.expressions.DelayExpression;
 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionComposite;
 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionWidgetInput;
 import org.simantics.sysdyn.ui.properties.widgets.factories.VariableNameInputValidator;
+import org.simantics.utils.DataContainer;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.ui.AdaptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Tab for displaying equation information of a variable
@@ -91,10 +98,12 @@ import org.simantics.utils.ui.AdaptionUtils;
  */
 public class EquationTab extends AdjustableTab implements Widget {
 
+       private static final Logger LOGGER = LoggerFactory.getLogger(EquationTab.class);
+
        private TrackedCombo expressionTypeCombo, unitCombo, arrayEquationCombo;
        private ShortcutTabWidget shortcutTabWidget;
        private ExpressionWidget expressionWidget;
-       private org.eclipse.ui.IPartListener2 focusLostListener;  
+       private org.eclipse.ui.IPartListener2 focusLostListener;
        private IWorkbenchSite site;
        private Button deleteExpression, newExpression;
        private WidgetSupportImpl support;
@@ -105,19 +114,20 @@ public class EquationTab extends AdjustableTab implements Widget {
        private Label typeLabel;
        private Label unitLabel;
        private IsOutputWidget isOutput;
+       private DataContainer<Boolean> lastActiveInput;
 
        public EquationTab(Object input) {
-           super(input);
-    }
+               super(input);
+       }
 
-    @Override
+       @Override
        public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport _support) {
                _support.register(this);
                setSupport();
                this.site = site;
                super.createControls(body, site, context, _support);
        }
-       
+
        @Override
        protected void createControlLayoutHorizontal(boolean wideScreen) {
                GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
@@ -142,12 +152,12 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                GridDataFactory.fillDefaults().span(wideScreen ? 4 : 3, 1).grab(true, true).applyTo(expressionComposite);
        }
-               
+
        @Override
        protected void createControlLayoutVertical() {
                GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
                GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(composite);
-               
+
                GridLayoutFactory.fillDefaults().numColumns(3).applyTo(nameComposite);
                GridDataFactory.fillDefaults().grab(true, true).applyTo(nameComposite);
 
@@ -164,16 +174,16 @@ public class EquationTab extends AdjustableTab implements Widget {
                GridDataFactory.fillDefaults().span(3, 1).align(SWT.END, SWT.CENTER).applyTo(isOutput.getWidget());
 
                GridDataFactory.fillDefaults().span(3, 1).grab(true, true).hint(SWT.DEFAULT, 250).applyTo(expressionComposite);
-               
+
                GridDataFactory.fillDefaults().span(3, 1).grab(true, true).hint(SWT.DEFAULT, 300).applyTo(shortcutTabWidget.getWidget());
        }
-       
+
        @Override
        protected void createAndAddControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport _support) {
                // Composite for the whole tab
                Composite composite = new Composite(body, SWT.NONE);
                this.composite = composite;
-               
+
                // Composite holding name controls and controls for adding and removing expressions
                nameComposite = new Composite(composite, SWT.NONE);
                arrayEquationCombo =  new ArrayExpressionCombo(nameComposite, support, SWT.DROP_DOWN | SWT.BORDER);
@@ -183,10 +193,10 @@ public class EquationTab extends AdjustableTab implements Widget {
                deleteExpression.setText("Delete");
                newExpression = new Button(nameComposite, support, SWT.NONE);
                newExpression.setText("New");
-                               
+
                // Shortcut widget. Tabular widget containing tabs for functions and connected variables
                shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE);
-               
+
                TypeAndUnit = new Composite(nameComposite, SWT.NONE);
                typeLabel = new Label(TypeAndUnit, SWT.SINGLE );
                typeLabel.setText("Type:");
@@ -195,7 +205,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                unitLabel.setText("Unit:");
                unitCombo = new TrackedCombo(TypeAndUnit, support, SWT.DROP_DOWN | SWT.BORDER);
                isOutput = new IsOutputWidget(TypeAndUnit, support, SWT.NULL);
-               
+
                // The actual expression
                expressionComposite = new ExpressionComposite(nameComposite, SWT.NONE);
                expressionWidget = new ExpressionWidget(expressionComposite, expressionSupport, SWT.NONE);
@@ -203,77 +213,84 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                addListeners(context);
        }
-       
+
        private void setSupport() {
                support = new WidgetSupportImpl() {
-                       
-               @Override
-               public void fireInput(ISessionContext context, Object input) {
-                       final Variable var = AdaptionUtils.adaptToSingle(input, Variable.class);
-                       if(var != null) {
-                               Resource r;
-                                       try {
-                                               r = context.getSession().syncRequest(new Read<Resource>() {
 
-                                                       @Override
-                                                       public Resource perform(ReadGraph graph)
-                                                                       throws DatabaseException {
-                                                               return var.getRepresents(graph);
-                                                       }
-                                               });
-                                       input = new StructuredSelection(r);
+                       @Override
+                       public void fireInput(ISessionContext context, Object input) {
+                               final Variable var = AdaptionUtils.adaptToSingle(input, Variable.class);
+                               if(var != null) {
+                                       try {
+                                               Resource r = context.getSession().syncRequest(new VariableRepresents(var));
+                                               input = new StructuredSelection(r);
                                        } catch (DatabaseException e) {
-                                               e.printStackTrace();
+                                               LOGGER.error("VariableRepresents failed", e);
                                        }
-                               
-                       }
-                       
-                       super.fireInput(context, input);
-               }
-       };
+                               }
+
+                               super.fireInput(context, input);
+                       }
+               };
        }
-       
+
        @Override
        public void setInput(ISessionContext context, final Object input) {
                support.fireInput(context, input);
-               
+               if(lastActiveInput != null) {
+                       lastActiveInput.set(false);
+               }
+               lastActiveInput = new DataContainer<Boolean>(true);
                final Variable var = AdaptionUtils.adaptToSingle(input, Variable.class);
                final Resource variable;
-               
+
                // Find variable resource either from Variable var or from input
                if(var != null)
                        try {
-                               variable = Simantics.getSession().syncRequest(new Read<Resource>() {
-
-                                       @Override
-                                       public Resource perform(ReadGraph graph) throws DatabaseException {
-                                               return var.getRepresents(graph);
-                                       }
-                               });
+                               variable = Simantics.getSession().syncRequest(new VariableRepresents(var));
                        } catch (DatabaseException e) {
-                               e.printStackTrace();
+                               LOGGER.error("VariableRepresents failed", e);
                                return;
                        }
                else
                        variable = AdaptionUtils.adaptToSingle(input, Resource.class);
-               
+
                if(var == null && variable == null)
                        return;
-               
-               
+
+               DataContainer<Boolean> isListenerActive = lastActiveInput;
                Resource expression = null;
                try {
-                       expression = Simantics.getSession().syncRequest(new Read<Resource>() {
+                       expression = Simantics.getSession().syncRequest(new ResourceRead<Resource>(variable) {
 
                                @Override
                                public Resource perform(ReadGraph graph) throws DatabaseException {
-                                       return getActiveExpression(graph, variable);
+                                       return getActiveExpression(graph, resource);
+                               }
+                       }, new ListenerAdapter<Resource>() {
+
+                               @Override
+                               public void execute(Resource result) {
+                                       composite.getDisplay().asyncExec(()-> {
+                                               if(Display.getCurrent().isDisposed())
+                                                       return;
+                                               updateExpression(result, variable, context, var);
+                                       });
+                               }
+
+                               @Override
+                               public void exception(Throwable t) {
+                                       LOGGER.error("getActiveExpression failed", t);
                                }
-                       });
+
+                               @Override
+                               public boolean isDisposed() {
+                                       return !isListenerActive.get();
+                               }});
                } catch (DatabaseException e) {
-                       e.printStackTrace();
+                       LOGGER.error("getActiveExpression failed", e);
                }
-               
+
                // The variable has no expressions -> creating a new ordered set expressions and the active expression
                if(expression == null && variable != null) {
                        try {
@@ -281,14 +298,14 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                                        @Override
                                        public Resource perform(WriteGraph graph)
-                                       throws DatabaseException {
-                                           if(!graph.hasStatement(variable)) {
-                                            /* Trying to create empty experiment for removed variable due to 
-                                             * async setInput
-                                             */
-                                               return null; 
-                                           }
-                                           
+                                                       throws DatabaseException {
+                                               if(!graph.hasStatement(variable)) {
+                                                       /* Trying to create empty experiment for removed variable due to
+                                                        * async setInput
+                                                        */
+                                                       return null;
+                                               }
+
                                                SysdynResource sr = SysdynResource.getInstance(graph);
                                                Layer0 l0 = Layer0.getInstance(graph);
                                                Resource expressions = ListUtils.create(graph, Collections.<Resource>emptyList());
@@ -325,26 +342,26 @@ public class EquationTab extends AdjustableTab implements Widget {
                                                                                graph.claim(variable, sr.IndependentVariable_activeExpression, expression);
                                                                        }
                                                                }
-                                                               );
+                                                                               );
                                                        }
                                                });
                                                return expression;
                                        }
                                });
                        } catch (DatabaseException e) {
-                               e.printStackTrace();
+                               LOGGER.error("getActiveExpression failed", e);
                        }
-                       
+
                        if(expression == null)
-                           return;
+                               return;
                }
 
                // Now the variable should have an expression
                Simantics.getSession().asyncRequest(new Read<Pair<Boolean, Boolean>>() {
 
-                   /**
-                    * Find out if user can add a new expression or delete the current expression
-                    */
+                       /**
+                        * Find out if user can add a new expression or delete the current expression
+                        */
                        @Override
                        public Pair<Boolean, Boolean> perform(ReadGraph graph) throws DatabaseException {
                                SysdynResource sr = SysdynResource.getInstance(graph);
@@ -366,7 +383,7 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                                /* If the variable is an array variable, a range has been set to all expressions and none of
                                 * the ranges is the default range, an expression can be added
-                                */ 
+                                */
                                for(Resource expression : expressionList) {
                                        String range = graph.getPossibleRelatedValue(expression, sr.Expression_arrayRange);
                                        if(range == null || range.equals("") || range.equals(defaultRange)) {
@@ -382,13 +399,13 @@ public class EquationTab extends AdjustableTab implements Widget {
                        public void execute(AsyncReadGraph graph,
                                        final Pair<Boolean, Boolean> result) {
                                newExpression.getWidget().getDisplay().asyncExec(new Runnable() {
-                                       
+
                                        @Override
                                        public void run() {
                                                if(!newExpression.getWidget().isDisposed())
                                                        newExpression.getWidget().setEnabled(result.first);
                                                if(!deleteExpression.getWidget().isDisposed())
-                                                       deleteExpression.getWidget().setEnabled(result.second);                                         
+                                                       deleteExpression.getWidget().setEnabled(result.second);
                                        }
                                });
 
@@ -396,7 +413,7 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                        @Override
                        public void exception(AsyncReadGraph graph, Throwable throwable) {
-                               throwable.printStackTrace();
+                               LOGGER.error("Unexpected failure", throwable);
                        }
 
                        @Override
@@ -404,8 +421,8 @@ public class EquationTab extends AdjustableTab implements Widget {
                                return newExpression.getWidget().isDisposed() || deleteExpression.getWidget().isDisposed();
                        }
                });
-               
-        // Set input to widgets using expressionSupport
+
+               // Set input to widgets using expressionSupport
                StructuredSelection ss = new StructuredSelection(new ExpressionWidgetInput(var, expression));
                expressionSupport.fireInput(context, ss);
        }
@@ -417,42 +434,42 @@ public class EquationTab extends AdjustableTab implements Widget {
         */
        private void addListeners(ISessionContext context) {
 
-           // Validate expression fields when a dependency has been added or removed
+               // Validate expression fields when a dependency has been added or removed
                shortcutTabWidget.addDependencyListener(new Runnable() {
-                       
+
                        @Override
                        public void run() {
                                expressionWidget.validateFields();
                        }
                });
-               
+
                // Deletes a selected expression
                deleteExpression.addSelectionListener(new SelectionListenerImpl<Resource>(context) {
 
                        @Override
                        public void apply(WriteGraph graph, final Resource input)
-                       throws DatabaseException {
+                                       throws DatabaseException {
 
                                SysdynResource sr = SysdynResource.getInstance(graph);
                                Layer0 l0 = Layer0.getInstance(graph);
-                               
+
                                // Currently active expression should be located in (Model sr.HasActiveExpression expression)
                                Resource activeExpression = graph.getPossibleObject(input, sr.IndependentVariable_activeExpression);
                                if(activeExpression == null)
                                        return;
 
-                Resource expressionList = graph.getPossibleObject(input, sr.Variable_expressionList);
+                               Resource expressionList = graph.getPossibleObject(input, sr.Variable_expressionList);
 
-                List<Resource> list = ListUtils.toList(graph, expressionList);
-                if(list.size() <= 1)
+                               List<Resource> list = ListUtils.toList(graph, expressionList);
+                               if(list.size() <= 1)
                                        return;
 
                                // Get the previous expression in expression list to be activated
-                int index = list.indexOf(activeExpression);
-                
-                ListUtils.removeElement(graph, expressionList, activeExpression);
+                               int index = list.indexOf(activeExpression);
+
+                               ListUtils.removeElement(graph, expressionList, activeExpression);
                                graph.deny(input, l0.ConsistsOf, activeExpression);
-                               
+
                                final Resource newActive = index == 0 ? list.get(1) : list.get(index - 1);
 
                                // Set newActive as active in virtual graph
@@ -471,7 +488,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                                                                graph.claim(input, sr.IndependentVariable_activeExpression, newActive);
                                                        }
                                                }
-                                               );
+                                                               );
                                        }
                                });
                                Layer0Utils.addCommentMetadata(graph, "Deleted Expression " + activeExpression + " from " + graph.getPossibleRelatedValue2(input, Layer0.getInstance(graph).HasName, Bindings.STRING));
@@ -483,7 +500,7 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                        @Override
                        public void apply(WriteGraph graph, Resource input)
-                       throws DatabaseException {
+                                       throws DatabaseException {
                                SysdynResource sr = SysdynResource.getInstance(graph);
                                Layer0 l0 = Layer0.getInstance(graph);
 
@@ -495,14 +512,14 @@ public class EquationTab extends AdjustableTab implements Widget {
                                Resource activeExpression = graph.getPossibleObject(input, sr.IndependentVariable_activeExpression);
                                Resource newExpression = graph.newResource();
                                if(activeExpression != null) {
-                                   // Create a new expression based on the old expression
+                                       // Create a new expression based on the old expression
                                        graph.claim(newExpression, l0.InstanceOf, graph.getSingleObject(activeExpression, l0.InstanceOf));
                                        if(graph.isInstanceOf(newExpression, sr.StockExpression)) {
                                                graph.claimLiteral(newExpression, sr.StockExpression_initialEquation, "");
                                                Layer0Utils.addCommentMetadata(graph, "Created new Stock Expression " + newExpression + " for " + graph.getPossibleRelatedValue2(input, Layer0.getInstance(graph).HasName, Bindings.STRING));
                                        }
                                } else {
-                                   // If there was no active expression, create a normal expression
+                                       // If there was no active expression, create a normal expression
                                        graph.claim(newExpression, l0.InstanceOf, sr.NormalExpression);
                                        graph.claimLiteral(newExpression, sr.Expression_equation, "");
                                        Layer0Utils.addCommentMetadata(graph, "Created new Normal Expression " + newExpression + " for " + graph.getPossibleRelatedValue2(input, Layer0.getInstance(graph).HasName, Bindings.STRING));
@@ -559,7 +576,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                        @Override
                        public void modifyText(TrackedModifyEvent e) {
                                expressionWidget.displayExpression(e.getText(), false);
-                               expressionWidget.save();                
+                               expressionWidget.save();
                        }
                });
 
@@ -587,7 +604,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                                return map;
                        }
                });
-               
+
                // Set initial selection of unit combo
                unitCombo.setSelectionFactory(new ReadFactoryImpl<Resource, String>() {
 
@@ -596,7 +613,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                                String unit = graph.getPossibleRelatedValue(input, SysdynResource.getInstance(graph).Variable_unit);
                                if(unit == null)
                                        return "";
-                               else 
+                               else
                                        return unit;
                        }
                });
@@ -606,9 +623,9 @@ public class EquationTab extends AdjustableTab implements Widget {
 
                        @Override
                        public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException {
-                           graph.denyValue(input, SysdynResource.getInstance(graph).Variable_unit);
+                               graph.denyValue(input, SysdynResource.getInstance(graph).Variable_unit);
                                graph.claimLiteral(input, SysdynResource.getInstance(graph).Variable_unit, text);
-                               
+
                                Resource conf = graph.getPossibleObject(input, Layer0.getInstance(graph).PartOf);
                                SysdynModelManager smm = SysdynModelManager.getInstance(graph.getSession());
                                SysdynModel sm = smm.getModel(graph, conf);
@@ -636,7 +653,7 @@ public class EquationTab extends AdjustableTab implements Widget {
                                                @Override
                                                public void run() {
                                                        if(expressionWidget!= null) {
-                                                           expressionWidget.getExpression().focus();
+                                                               expressionWidget.getExpression().focus();
                                                                expressionWidget.getExpression().replaceSelection(var);
                                                                expressionWidget.validateFieldsTimed();
                                                        }
@@ -666,13 +683,13 @@ public class EquationTab extends AdjustableTab implements Widget {
                                expressionWidget.validateFieldsTimed();
                        }
                });
-               
+
                // Pressing return without shift key triggers saving the expression
                expressionWidget.addVerifyKeyListener(new VerifyKeyListener() {
 
                        @Override
                        public void verifyKey(VerifyEvent event) {
-                           // Check if some of the expression fields has active completion assistant
+                               // Check if some of the expression fields has active completion assistant
                                boolean isAnyAssistSessionActive = false;
                                for (int i = 0; i < expressionWidget.getExpression().getExpressionFields().size(); ++i) {
                                        if (expressionWidget.getExpression().getExpressionFields().get(i).isAssistSessionActive()) {
@@ -681,69 +698,208 @@ public class EquationTab extends AdjustableTab implements Widget {
                                        }
                                }
                                if(event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR) {
-                                   if (!isAnyAssistSessionActive) {
-                                       if((event.stateMask & SWT.SHIFT) == 0) {
-                                           event.doit = false;
+                                       if (!isAnyAssistSessionActive) {
+                                               if((event.stateMask & SWT.SHIFT) == 0) {
+                                                       event.doit = false;
                                                        ((StyledText)event.widget).getParent().forceFocus();
                                                        expressionWidget.save();
                                                }
-                                   } else {
-                                       // When a proposed expression is selected with enter, fields are validated.
-                           expressionWidget.validateFieldsTimed();
+                                       } else {
+                                               // When a proposed expression is selected with enter, fields are validated.
+                                               expressionWidget.validateFieldsTimed();
+                                       }
+                               }
+                       }
+               });
+
+               // Triggers save when equation tab loses focus
+               if(focusLostListener == null) {
+                       focusLostListener = new org.eclipse.ui.IPartListener2()
+                       {
+                               @Override
+                               public void partInputChanged(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partVisible(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partHidden(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partOpened(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partDeactivated(IWorkbenchPartReference partRef)
+                               {
+                                       if(partRef.getPart(false) instanceof PropertyPageView) {
+                                               PropertyPageView ppv = (PropertyPageView)partRef.getPart(false);
+                                               if(ppv.getCurrentPage() instanceof SysdynPropertyPage) {
+                                                       // Save expressions
+                                                       if(expressionWidget != null) {
+                                                               expressionWidget.save();
+                                                       }
+                                                       //                          site.getPage().removePartListener(this);
+                                               }
+                                       }
+                               }
+                               @Override
+                               public void partClosed(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partBroughtToTop(IWorkbenchPartReference partRef) {}
+                               @Override
+                               public void partActivated(IWorkbenchPartReference partRef) {}
+                       };
+                       site.getPage().addPartListener(focusLostListener);
+               }
+       }
+
+       private void updateExpression(Resource expression, Resource variable, ISessionContext context, Variable var) {
+               // The variable has no expressions -> creating a new ordered set expressions and the active expression
+               if(expression == null && variable != null) {
+                       try {
+                               expression = Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
+
+                                       @Override
+                                       public Resource perform(WriteGraph graph)
+                                                       throws DatabaseException {
+                                               if(!graph.hasStatement(variable)) {
+                                                       /* Trying to create empty experiment for removed variable due to
+                                                        * async setInput
+                                                        */
+                                                       return null;
+                                               }
+
+                                               SysdynResource sr = SysdynResource.getInstance(graph);
+                                               Layer0 l0 = Layer0.getInstance(graph);
+                                               Resource expressions = ListUtils.create(graph, Collections.<Resource>emptyList());
+                                               graph.claim(variable, sr.Variable_expressionList, expressions);
+                                               final Resource expression = graph.newResource();
+
+                                               if(graph.isInstanceOf(variable, sr.Auxiliary) ||
+                                                               graph.isInstanceOf(variable, sr.Valve)) {
+                                                       graph.claim(expression, l0.InstanceOf, null, sr.NormalExpression);
+                                                       graph.claimLiteral(expression, sr.Expression_equation, "");
+                                               }
+                                               else if(graph.isInstanceOf(variable, sr.Stock)) {
+                                                       graph.claim(expression, l0.InstanceOf, null, sr.StockExpression);
+                                                       graph.claimLiteral(expression, sr.StockExpression_initialEquation, "");
+                                               }
+                                               ArrayList<Resource> addition = new ArrayList<Resource>(1);
+                                               addition.add(expression);
+                                               ListUtils.insertBack(graph, expressions, addition);
+
+                                               graph.claim(variable, l0.ConsistsOf, expression);
+
+                                               VirtualGraphSupport support = graph.getService(VirtualGraphSupport.class);
+                                               final Session session = graph.getSession();
+                                               session.asyncRequest(new WriteRequest(support.getWorkspacePersistent("expressions")) {
+                                                       @Override
+                                                       public void perform(WriteGraph graph) throws DatabaseException {
+                                                               VirtualGraph runtime = graph.getService(VirtualGraph.class);
+                                                               session.asyncRequest(new WriteRequest(runtime) {
+                                                                       @Override
+                                                                       public void perform(WriteGraph graph) throws DatabaseException {
+                                                                               SysdynResource sr = SysdynResource.getInstance(graph);
+                                                                               if(graph.hasStatement(variable, sr.IndependentVariable_activeExpression))
+                                                                                       graph.deny(variable, sr.IndependentVariable_activeExpression);
+                                                                               graph.claim(variable, sr.IndependentVariable_activeExpression, expression);
+                                                                       }
+                                                               }
+                                                                               );
+                                                       }
+                                               });
+                                               return expression;
+                                       }
+                               });
+                       } catch (DatabaseException e) {
+                               LOGGER.error("Unexpected failure", e);
+                       }
+
+                       if(expression == null)
+                               return;
+               }
+
+               // Now the variable should have an expression
+               Simantics.getSession().asyncRequest(new Read<Pair<Boolean, Boolean>>() {
+
+                       /**
+                        * Find out if user can add a new expression or delete the current expression
+                        */
+                       @Override
+                       public Pair<Boolean, Boolean> perform(ReadGraph graph) throws DatabaseException {
+                               SysdynResource sr = SysdynResource.getInstance(graph);
+                               Resource expressions = graph.getPossibleObject(variable, sr.Variable_expressionList);
+                               if(expressions == null) {
+                                       return new Pair<Boolean, Boolean>(false, false);
+                               }
+                               List<Resource> expressionList = ListUtils.toList(graph, expressions);
+                               if(expressionList.isEmpty()) {
+                                       return new Pair<Boolean, Boolean>(false, false);
+                               }
+
+                               boolean canAdd = true;
+                               boolean canDelete = false;
+                               // If there are multiple expressions, one can be removed
+                               if(expressionList.size() > 1)
+                                       canDelete = true;
+                               String defaultRange = ArrayExpressionCombo.getDefaultRange(graph, variable);
+
+                               /* If the variable is an array variable, a range has been set to all expressions and none of
+                                * the ranges is the default range, an expression can be added
+                                */ 
+                               for(Resource expression : expressionList) {
+                                       String range = graph.getPossibleRelatedValue(expression, sr.Expression_arrayRange);
+                                       if(range == null || range.equals("") || range.equals(defaultRange)) {
+                                               canAdd = false;
+                                               break;
                                        }
                                }
+                               return new Pair<Boolean, Boolean>(canAdd, canDelete);
+                       }
+               }, new AsyncListener<Pair<Boolean, Boolean>>() {
+
+                       @Override
+                       public void execute(AsyncReadGraph graph,
+                                       final Pair<Boolean, Boolean> result) {
+                               newExpression.getWidget().getDisplay().asyncExec(new Runnable() {
+
+                                       @Override
+                                       public void run() {
+                                               if(!newExpression.getWidget().isDisposed())
+                                                       newExpression.getWidget().setEnabled(result.first);
+                                               if(!deleteExpression.getWidget().isDisposed())
+                                                       deleteExpression.getWidget().setEnabled(result.second);
+                                       }
+                               });
+
+                       }
+
+                       @Override
+                       public void exception(AsyncReadGraph graph, Throwable throwable) {
+                               LOGGER.error("Unexpected failure", throwable);
+                       }
+
+                       @Override
+                       public boolean isDisposed() {
+                               return newExpression.getWidget().isDisposed() || deleteExpression.getWidget().isDisposed();
                        }
                });
-               
-           // Triggers save when equation tab loses focus
-        if(focusLostListener == null) {
-            focusLostListener = new org.eclipse.ui.IPartListener2()
-            {
-                @Override
-                public void partInputChanged(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partVisible(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partHidden(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partOpened(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partDeactivated(IWorkbenchPartReference partRef)
-                {
-                    if(partRef.getPart(false) instanceof PropertyPageView) {
-                        PropertyPageView ppv = (PropertyPageView)partRef.getPart(false);
-                        if(ppv.getCurrentPage() instanceof SysdynPropertyPage) {
-                            // Save expressions
-                            if(expressionWidget != null) {
-                                expressionWidget.save();
-                            }
-//                          site.getPage().removePartListener(this);
-                        }
-                    }
-                }
-                @Override
-                public void partClosed(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partBroughtToTop(IWorkbenchPartReference partRef) {}
-                @Override
-                public void partActivated(IWorkbenchPartReference partRef) {}
-            };
-            site.getPage().addPartListener(focusLostListener);
-        }
+
+               // Set input to widgets using expressionSupport
+               StructuredSelection ss = new StructuredSelection(new ExpressionWidgetInput(var, expression));
+               expressionSupport.fireInput(context, ss);
        }
 
+
        @Override
        public void dispose() {
-        if(expressionWidget != null && !(expressionWidget.getExpression() instanceof DelayExpression)) {
-               // For delay expression this doesn't work, 
-               // but it doesn't matter since the saving is succeeded elsewhere.
-            expressionWidget.save();
-        }
+               if(lastActiveInput != null) lastActiveInput.set(false);
+               if(expressionWidget != null && !(expressionWidget.getExpression() instanceof DelayExpression)) {
+                       // For delay expression this doesn't work,
+                       // but it doesn't matter since the saving is succeeded elsewhere.
+                       expressionWidget.save();
+               }
                if(focusLostListener != null && site != null)
                        site.getPage().removePartListener(focusLostListener);
                super.dispose();
                if(expressionComposite != null && !expressionComposite.isDisposed())
-                   expressionComposite.dispose();
+                       expressionComposite.dispose();
        }
 
        /**
index f66a0c2ff96ead7f3096846867273397c966c979..2b8fc8401cb9a61f765a140a100a3a47f7e0dd31 100644 (file)
@@ -90,7 +90,7 @@ public class BasicExpression implements IExpression {
     @Override
     public void readData(final Resource expression, Map<String, Object> data) {
         String equation = null;
-        if (expression != null && data.get("equation") == null) {
+        if (expression != null) {
             try {
                 equation = Simantics.getSession().syncRequest(new Read<String>() {