Xcos modelica init: update the UI 27/14027/2
Clément DAVID [Fri, 14 Mar 2014 12:29:43 +0000 (13:29 +0100)]
Change-Id: I9c27cbbda92689284b2cc64f02dc86cca2e34be0

scilab/modules/scicos/macros/scicos_scicos/compile_init_modelica.sci
scilab/modules/scicos/macros/scicos_scicos/modelicac.sci
scilab/modules/scicos/macros/scicos_scicos/xml2modelica.sci
scilab/modules/xcos/src/java/org/scilab/modules/xcos/modelica/ModelicaController.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/modelica/TerminalAccessor.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/modelica/listener/SolveAction.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/modelica/view/MainPanel.java

index d40e9b6..ec5587c 100644 (file)
@@ -69,7 +69,7 @@ function   [ok]=compile_init_modelica(xmlmodel,paremb,jaco)
     // generates the computational C function associated to the flat model
     instr = exe + Flati + "" + JAC + " -with-init-in """ + strsubst(xmlfile,"\","/") + ..
     """ -with-init-out """ + strsubst(xmlfile,"\","/") + """ -o """ + ..
-    FlatCi + """ > """ + tmpdir + "imodelicac.err""";
+    FlatCi + """";
 
 
     if getos() == "Windows" then
@@ -77,7 +77,8 @@ function   [ok]=compile_init_modelica(xmlmodel,paremb,jaco)
         instr = tmpdir + "igenm.bat";
     end
 
-    if execstr("unix_s(instr)", "errcatch") == 0 then
+    [rep,stat,err]=unix_g(instr);
+    if stat == 0 then
         mprintf("%s"," Init C code   : "+FlatCi);
         mprintf("\n\r");
 
@@ -89,8 +90,7 @@ function   [ok]=compile_init_modelica(xmlmodel,paremb,jaco)
         end
 
     else
-        MSG3 = mgetl(tmpdir + "imodelicac.err");
-        disp(["-------Modelica compiler error flat2C:-------"; MSG3; "Please read the error message in the Scilab window"]);
+        messagebox(err, _("Modelica compiler (flat2C)"), "error", "modal");
         ok = %f;
         return
     end
index ebf4a6b..d166083 100644 (file)
@@ -56,12 +56,6 @@ function  ok = modelicac(Flat, Flat_functions, xmlfileTMP, Jacobian, Cfile, with
         JAC="";
     end
 
-    if init then
-        Errfile = ">""" + tmpdir + "imodelicac.err""";
-    else
-        Errfile = ">""" + tmpdir + "S_modelicac.err""";
-    end
-
     instr = strcat([exe, Flat, Flat_functions, XMLfiles, out, JAC, Errfile], " ");
 
     if getos() == "Windows" then
@@ -74,14 +68,13 @@ function  ok = modelicac(Flat, Flat_functions, xmlfileTMP, Jacobian, Cfile, with
         end
     end
 
-    if execstr("unix_s(instr)", "errcatch") <> 0 then
-        messagebox([_("-------Modelica compiler error (with the translator):-------");_("Please read the error message in the Scilab window")], "error", "modal");
-        if isfile(Errfile) then
-            mgetl(Errfile);
-        end
-
+    [rep,stat,err]=unix_g(instr);
+    if stat <> 0 then
+        messagebox(err, _("Modelica compiler"), "error", "modal");
         ok=%f;
         return
+    else
+        disp(rep)
     end
 
 endfunction
index 58de79e..ff79a18 100644 (file)
@@ -40,20 +40,19 @@ function  ok=xml2modelica(xmlfile,Flati)
     in = """" + xmlfile + """";
     out = "-o """ + Flati + """";
     option = "-init";  // generates a flat modelica file for the initialization
-    Errfile = " > """ + tmpdir + "ixml2modelica.err""";
-    instr = strcat([exe in option out Errfile], " ");
+    instr = strcat([exe in option out], " ");
 
     if getos() == "Windows" then,
         mputl(instr, tmpdir + "igenx.bat");
         instr = tmpdir + "igenx.bat";
     end
 
-    if execstr("unix_s(instr)","errcatch") == 0 then
+    [rep,stat,err]=unix_g(instr);
+    if stat == 0 then
         mprintf("%s\n", " xml->Modelica : " + Flati);
         ok = %t;
     else
-        messagebox([_("-------XML to Modelica error:-------");
-        mgetl(Errfile);], "error", "modal");
+        messagebox(err, _("XML to Modelica"), "error", "modal");
         ok = %f;
         return
     end
index 9de54a6..45ba6ab 100644 (file)
@@ -390,8 +390,8 @@ public final class ModelicaController {
                 final Double notUsed2 = TerminalAccessor.getData(TerminalAccessor.WEIGHT, terminal);
                 final Double notUsed3 = TerminalAccessor.getData(TerminalAccessor.INITIAL, terminal);
 
-                final Double notUsed4 = TerminalAccessor.getData(TerminalAccessor.MAX, terminal);
-                final Double notUsed5 = TerminalAccessor.getData(TerminalAccessor.MIN, terminal);
+                //                final Double notUsed4 = TerminalAccessor.getData(TerminalAccessor.MAX, terminal);
+                //                final Double notUsed5 = TerminalAccessor.getData(TerminalAccessor.MIN, terminal);
 
             } else {
                 // recursive call
index 2a7094d..f769c2d 100644 (file)
@@ -164,81 +164,81 @@ public enum TerminalAccessor {
             firePropertyChange(terminal, value, aValue);
         }
     },
-    /**
-     * Max of the value
-     */
-    MAX(ModelicaMessages.MAX, Double.class, true) {
-        @Override
-        protected Object getData(Terminal terminal) {
-            if (terminal.getMax() == null) {
-                terminal.setMax(new ModelicaValue());
-            }
-
-            if (terminal.getMax().getValue().isEmpty()) {
-                return Double.valueOf(0.0);
-            }
-
-            final String value = terminal.getMax().getValue();
-            return Double.valueOf(value);
-        }
-
-        @Override
-        public void setData(Object aValue, Terminal terminal) {
-            final Object value = getData(terminal);
-            terminal.getMax().setValue(aValue.toString());
-            firePropertyChange(terminal, value, aValue);
-        }
-    },
-    /**
-     * Min of the value
-     */
-    MIN(ModelicaMessages.MIN, Double.class, true) {
-        @Override
-        protected Double getData(Terminal terminal) {
-            if (terminal.getMin() == null) {
-                terminal.setMin(new ModelicaValue());
-            }
-
-            if (terminal.getMin().getValue().isEmpty()) {
-                return Double.valueOf(0.0);
-            }
-
-            final String value = terminal.getMin().getValue();
-            return Double.valueOf(value);
-        }
-
-        @Override
-        public void setData(Object aValue, Terminal terminal) {
-            final Object value = getData(terminal);
-            terminal.getMin().setValue(aValue.toString());
-            firePropertyChange(terminal, value, aValue);
-        }
-    },
-    /**
-     * Nominal value
-     */
-    NOMINAL(ModelicaMessages.NOMINAL, Double.class, true) {
-        @Override
-        protected Double getData(Terminal terminal) {
-            if (terminal.getNominalValue() == null) {
-                terminal.setNominalValue(new ModelicaValue());
-            }
-
-            if (terminal.getNominalValue().getValue().isEmpty()) {
-                return Double.valueOf(0.0);
-            }
-
-            final String value = terminal.getNominalValue().getValue();
-            return Double.valueOf(value);
-        }
-
-        @Override
-        public void setData(Object aValue, Terminal terminal) {
-            final Object value = getData(terminal);
-            terminal.getNominalValue().setValue(aValue.toString());
-            firePropertyChange(terminal, value, aValue);
-        }
-    },
+    //    /**
+    //     * Max of the value
+    //     */
+    //    MAX(ModelicaMessages.MAX, Double.class, true) {
+    //        @Override
+    //        protected Object getData(Terminal terminal) {
+    //            if (terminal.getMax() == null) {
+    //                terminal.setMax(new ModelicaValue());
+    //            }
+    //
+    //            if (terminal.getMax().getValue().isEmpty()) {
+    //                return Double.valueOf(0.0);
+    //            }
+    //
+    //            final String value = terminal.getMax().getValue();
+    //            return Double.valueOf(value);
+    //        }
+    //
+    //        @Override
+    //        public void setData(Object aValue, Terminal terminal) {
+    //            final Object value = getData(terminal);
+    //            terminal.getMax().setValue(aValue.toString());
+    //            firePropertyChange(terminal, value, aValue);
+    //        }
+    //    },
+    //    /**
+    //     * Min of the value
+    //     */
+    //    MIN(ModelicaMessages.MIN, Double.class, true) {
+    //        @Override
+    //        protected Double getData(Terminal terminal) {
+    //            if (terminal.getMin() == null) {
+    //                terminal.setMin(new ModelicaValue());
+    //            }
+    //
+    //            if (terminal.getMin().getValue().isEmpty()) {
+    //                return Double.valueOf(0.0);
+    //            }
+    //
+    //            final String value = terminal.getMin().getValue();
+    //            return Double.valueOf(value);
+    //        }
+    //
+    //        @Override
+    //        public void setData(Object aValue, Terminal terminal) {
+    //            final Object value = getData(terminal);
+    //            terminal.getMin().setValue(aValue.toString());
+    //            firePropertyChange(terminal, value, aValue);
+    //        }
+    //    },
+    //    /**
+    //     * Nominal value
+    //     */
+    //    NOMINAL(ModelicaMessages.NOMINAL, Double.class, true) {
+    //        @Override
+    //        protected Double getData(Terminal terminal) {
+    //            if (terminal.getNominalValue() == null) {
+    //                terminal.setNominalValue(new ModelicaValue());
+    //            }
+    //
+    //            if (terminal.getNominalValue().getValue().isEmpty()) {
+    //                return Double.valueOf(0.0);
+    //            }
+    //
+    //            final String value = terminal.getNominalValue().getValue();
+    //            return Double.valueOf(value);
+    //        }
+    //
+    //        @Override
+    //        public void setData(Object aValue, Terminal terminal) {
+    //            final Object value = getData(terminal);
+    //            terminal.getNominalValue().setValue(aValue.toString());
+    //            firePropertyChange(terminal, value, aValue);
+    //        }
+    //    },
     /**
      * Comment to the terminal
      */
index ee293a7..62829b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2010-2010 - DIGITEO - Clement DAVID <clement.david@scilab.org>
- * Copyright (C) 2011-2011 - Scilab Enterprises - Clement DAVID
+ * Copyright (C) 2011-2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
 package org.scilab.modules.xcos.modelica.listener;
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.io.File;
-import java.io.IOException;
+import java.util.List;
 import java.util.logging.Logger;
 
 import javax.swing.AbstractAction;
-import javax.xml.bind.JAXBException;
+import javax.swing.JProgressBar;
+import javax.swing.SwingWorker;
 
 import org.scilab.modules.action_binding.highlevel.ScilabInterpreterManagement;
-import org.scilab.modules.action_binding.highlevel.ScilabInterpreterManagement.InterpreterException;
 import org.scilab.modules.commons.ScilabConstants;
 import org.scilab.modules.xcos.modelica.ModelStatistics;
 import org.scilab.modules.xcos.modelica.Modelica;
@@ -44,43 +43,43 @@ public final class SolveAction extends AbstractAction {
     private static final String EXTENSION = ".xml";
     private static final String INCIDENCE = "i_incidence_matrix";
 
-    private final ModelicaController controller;
+    private enum ActionToPerform {EXPORT, COMPILE, COMPUTE, FINISH};
+    private class Worker extends SwingWorker<Void, ActionToPerform> {
 
-    /**
-     * Default constructor
-     *
-     * @param controller
-     *            the associated controller
-     */
-    public SolveAction(final ModelicaController controller) {
-        super();
+        private final ModelicaController controller;
+        private final JProgressBar progress;
 
-        putValue(NAME, ModelicaMessages.SOLVE);
-        this.controller = controller;
-    }
+        public Worker(ModelicaController controller, JProgressBar progress) {
+            this.controller = controller;
+            this.progress = progress;
+        }
 
-    /**
-     * action !!!
-     *
-     * @param e
-     *            the event
-     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-     */
-    @Override
-    public void actionPerformed(ActionEvent e) {
-        final String modelName = controller.getRoot().getName();
+        @Override
+        protected Void doInBackground() throws Exception {
+            String cmd;
 
-        // defensive programming
-        if (!controller.isSquare()) {
-            Logger.getLogger(SolveAction.class.getName()).severe(ModelicaMessages.MODEL_INVALID);
-        }
+            final String modelName = controller.getRoot().getName();
+            // creating a temporary status file
+            final File statusFile = File.createTempFile(modelName, null);
+
+            // defensive programming
+            if (!controller.isSquare()) {
+                Logger.getLogger(SolveAction.class.getName()).severe(ModelicaMessages.MODEL_INVALID);
+            }
+
+            /*
+             * Export the compilation data to xml
+             */
+            publish(ActionToPerform.EXPORT);
 
-        initStatus();
-        try {
             // store the updated values
             final File updatedInitFile = new File(ScilabConstants.TMPDIR, modelName + IMF_INIT + EXTENSION);
             Modelica.getInstance().save(controller.getRoot(), updatedInitFile);
 
+            /*
+             * Compile the data from xml to a modelica file
+             */
+            publish(ActionToPerform.COMPILE);
             final int paremb;
             if (controller.isParameterEmbedded()) {
                 paremb = 1;
@@ -95,120 +94,109 @@ public final class SolveAction extends AbstractAction {
                 jaco = 0;
             }
 
-            // creating a temporary status file
-            File statusFile = File.createTempFile(modelName, null);
             statusFile.delete();
-
-            String cmd = String.format(COMPILE_STRING, modelName, paremb, jaco, statusFile.getAbsolutePath());
+            cmd = String.format(COMPILE_STRING, modelName, paremb, jaco, statusFile.getAbsolutePath());
 
             Logger.getLogger(SolveAction.class.getName()).finest("Compiling");
-            ScilabInterpreterManagement.asynchronousScilabExec(new CompileFinished(statusFile), cmd.toString());
-        } catch (InterpreterException e1) {
-            Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-        } catch (IOException e1) {
-            Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-        } catch (JAXBException e1) {
-            Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-        }
-    }
+            ScilabInterpreterManagement.synchronousScilabExec(cmd);
 
-    /**
-     * Initialize the button and error status.
-     */
-    private void initStatus() {
-        putValue(NAME, ModelicaMessages.SOLVE);
-        setEnabled(true);
-    }
+            if (!statusFile.exists()) {
+                publish(ActionToPerform.FINISH);
+                return null;
+            } else {
+                statusFile.delete();
+            }
 
-    /**
-     * Action done at the end of the compilation
-     */
-    private final class CompileFinished implements ActionListener {
-        private final File incidence;
-        private final File status;
-
-        /**
-         * Default constructor
-         *
-         * @param status
-         *            the status file
-         */
-        public CompileFinished(File status) {
-            final String modelName = controller.getRoot().getName();
-            incidence = new File(ScilabConstants.TMPDIR, modelName + INCIDENCE + EXTENSION);
-            this.status = status;
+            /*
+             * Launch a modelica initialization with the generated file
+             */
+            publish(ActionToPerform.COMPUTE);
+
+            // update the model with the computed identifiers
+            final File incidence = new File(ScilabConstants.TMPDIR, modelName + INCIDENCE + EXTENSION);
+            final Model incidenceModel = Modelica.getInstance().load(incidence);
+            controller.getRoot().setIdentifiers(incidenceModel.getIdentifiers());
+            controller.getRoot().setOutputs(incidenceModel.getOutputs());
+
+            // update the statistics
+            controller.getStatistics().fireChange();
+
+            // update state
+            controller.setCompileNeeded(false);
+
+            statusFile.delete();
+            final ModelStatistics stats = controller.getStatistics();
+            long nUnknowns = stats.getUnknowns() - stats.getEquations();
+            cmd = String.format(COMPUTE_STRING, controller.getComputeMethod(), nUnknowns, statusFile.getAbsolutePath());
+
+            // compute now
+            Logger.getLogger(SolveAction.class.getName()).finest("Computing");
+            ScilabInterpreterManagement.synchronousScilabExec(cmd);
+
+            if (!statusFile.exists()) {
+                publish(ActionToPerform.FINISH);
+                return null;
+            } else {
+                statusFile.delete();
+            }
+
+            /*
+             * Finish the action using a state instead of the done() method
+             */
+            publish(ActionToPerform.FINISH);
+
+            return null;
         }
 
-        /**
-         * Update things and compute the compiled model
-         *
-         * @param e
-         *            the event
-         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-         */
         @Override
-        public void actionPerformed(ActionEvent e) {
-            if (status.exists()) {
-                try {
-                    // update the model with the computed identifiers
-                    final Model incidenceModel = Modelica.getInstance().load(incidence);
-                    controller.getRoot().setIdentifiers(incidenceModel.getIdentifiers());
-                    controller.getRoot().setOutputs(incidenceModel.getOutputs());
-
-                    // update the statistics
-                    controller.getStatistics().fireChange();
-
-                    // update state
-                    controller.setCompileNeeded(false);
-
-                    // creating a temporary status file
-                    File statusFile = File.createTempFile(controller.getRoot().getName(), null);
-                    statusFile.delete();
-
-                    final ModelStatistics stats = controller.getStatistics();
-                    long nUnknowns = stats.getUnknowns() - stats.getEquations();
-                    String cmd = String.format(COMPUTE_STRING, controller.getComputeMethod(), nUnknowns, statusFile.getAbsolutePath());
-
-                    // compute now
-                    Logger.getLogger(SolveAction.class.getName()).finest("Computing");
-                    ScilabInterpreterManagement.asynchronousScilabExec(new ComputeFinished(statusFile), cmd);
-                } catch (JAXBException e1) {
-                    Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-                } catch (IOException e1) {
-                    Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-                } catch (InterpreterException e1) {
-                    Logger.getLogger(SolveAction.class.getName()).severe(e1.toString());
-                }
-            } else {
-                // best effort to alert the user.
-                initStatus();
+        protected void process(List<ActionToPerform> chunks) {
+            // only visual notify accordingly to the last performed action
+            final ActionToPerform action = chunks.get(chunks.size() - 1);
+
+            switch (action) {
+                case EXPORT:
+                case COMPILE:
+                case COMPUTE:
+                    if (!progress.isIndeterminate()) {
+                        progress.setIndeterminate(true);
+                    }
+                    break;
+
+                case FINISH:
+                default:
+                    progress.setIndeterminate(false);
+                    break;
             }
         }
     }
 
+    private final ModelicaController controller;
+    private final JProgressBar progress;
+
     /**
-     * Action done at the end of the computation
+     * Default constructor
+     *
+     * @param controller
+     *            the associated controller
      */
-    private final class ComputeFinished implements ActionListener {
-        /**
-         * Default constructor
-         *
-         * @param status
-         *            the status file
-         */
-        public ComputeFinished(File status) {
-        }
+    public SolveAction(final ModelicaController controller, final JProgressBar progress) {
+        super();
 
-        /**
-         * Clean the state
-         *
-         * @param e
-         *            the event
-         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-         */
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            initStatus();
-        }
+        putValue(NAME, ModelicaMessages.SOLVE);
+        this.controller = controller;
+        this.progress = progress;
+
+    }
+
+    /**
+     * action !!!
+     *
+     * @param e
+     *            the event
+     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+     */
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        new Worker(controller, progress).execute();
     }
 }
index d5f354b..378733d 100644 (file)
@@ -17,14 +17,17 @@ import static org.scilab.modules.xcos.modelica.TerminalAccessor.FIXED;
 import static org.scilab.modules.xcos.modelica.TerminalAccessor.WEIGHT;
 import static org.scilab.modules.xcos.modelica.TerminalAccessor.getData;
 
+import java.awt.CardLayout;
 import java.awt.GridLayout;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import javax.lang.model.element.Element;
 import javax.swing.BoxLayout;
 import javax.swing.JPanel;
 import javax.swing.event.ChangeEvent;
@@ -87,6 +90,7 @@ public final class MainPanel extends JPanel {
     private javax.swing.JButton solveButton;
     private javax.swing.JLabel solver;
     private javax.swing.JComboBox solverComboBox;
+    private javax.swing.JProgressBar solverWaitBar;
     private javax.swing.JPanel variableStatusBar;
     private javax.swing.JPanel extendedStatus;
     private javax.swing.JPanel globalStatus;
@@ -188,24 +192,39 @@ public final class MainPanel extends JPanel {
      *            the current path
      * @return the terminals associated with the path
      */
-    private List<Terminal> getTerminals(TreePath path) {
+    private List<Terminal> getTerminals(final TreePath[] path) {
+        final List<Terminal> ret = new ArrayList<Terminal>();
+
+        for (TreePath p : path) {
+            final Object userObject = ((DefaultMutableTreeNode) p.getLastPathComponent()).getUserObject();
+            ret.addAll(getTerminals(userObject));
+        }
+        return ret;
+    }
+
+    private List<Terminal> getTerminals(Object userObject) {
         final List<Terminal> ret;
+        if (userObject instanceof Terminal) {
+            final Terminal t = (Terminal) userObject;
+            ret = Collections.singletonList(t);
+        } else if (userObject instanceof Struct) {
+            final Struct s = (Struct) userObject;
+            final Object subnodes = s.getSubnodes().getStructOrTerminal();
+            ret = getTerminals(subnodes);
+        } else if (userObject instanceof Model) {
+            final Model m = (Model) userObject;
+            ret = getTerminals(m.getElements().getStruct());
+        } else if (userObject instanceof Collection) {
+            final Collection c = (Collection) userObject;
 
-        // the root is not a Struct instance and thus return an empty list.
-        if (path.getPathCount() > 1) {
             ret = new ArrayList<Terminal>();
-            final Struct struct = (Struct) ((DefaultMutableTreeNode) path
-                                            .getLastPathComponent()).getUserObject();
-
-            for (Object child : struct.getSubnodes().getStructOrTerminal()) {
-                if (child instanceof Terminal) {
-                    ret.add((Terminal) child);
-                }
+            for (Object o : c) {
+                ret.addAll(getTerminals(o));
             }
-
         } else {
             ret = Collections.emptyList();
         }
+
         return ret;
     }
 
@@ -220,19 +239,22 @@ public final class MainPanel extends JPanel {
 
         solverComboBox.setModel(new javax.swing.DefaultComboBoxModel(
                                     ModelicaController.ComputationMethod.values()));
-        solverComboBox
-        .setToolTipText(ModelicaMessages.INITIAL_COMPUTING_METHOD);
-
+        solverComboBox.setToolTipText(ModelicaMessages.INITIAL_COMPUTING_METHOD);
         control.add(solverComboBox);
 
         embeddedParametersButton.setText(ModelicaMessages.PARAMETER_EMBEDDING);
         embeddedParametersButton
         .setToolTipText(ModelicaMessages.PARAMETER_EMBEDDING_EXPLAINED);
         control.add(embeddedParametersButton);
+
         generateJacobianButton.setText(ModelicaMessages.GENERATE_JACOBIAN);
         control.add(generateJacobianButton);
-        solveButton.setAction(new SolveAction(controller));
+
+        solveButton.setAction(new SolveAction(controller, solverWaitBar));
         control.add(solveButton);
+
+        control.add(solverWaitBar);
+
         controlBar.add(control);
     }
 
@@ -329,6 +351,7 @@ public final class MainPanel extends JPanel {
         controlBar = new javax.swing.JPanel();
         solver = new javax.swing.JLabel();
         solverComboBox = new javax.swing.JComboBox();
+        solverWaitBar = new javax.swing.JProgressBar();
         embeddedParametersButton = new javax.swing.JCheckBox();
         generateJacobianButton = new javax.swing.JCheckBox();
         solveButton = new javax.swing.JButton();
@@ -347,7 +370,7 @@ public final class MainPanel extends JPanel {
         tree.addTreeSelectionListener(new TreeSelectionListener() {
             @Override
             public void valueChanged(TreeSelectionEvent e) {
-                tableModel.setTerminals(getTerminals(e.getPath()));
+                tableModel.setTerminals(getTerminals(tree.getSelectionPaths()));
             }
         });