2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Clement DAVID
4 * Copyright (C) 2013 - Scilab Enterprises - Clement DAVID
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
14 package org.scilab.modules.xcos.actions.dialog;
16 import java.awt.Component;
17 import java.awt.GridBagConstraints;
18 import java.awt.GridBagLayout;
19 import java.awt.Image;
20 import java.awt.Insets;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.ItemEvent;
24 import java.awt.event.ItemListener;
25 import java.beans.PropertyVetoException;
26 import java.math.BigDecimal;
27 import java.text.DecimalFormat;
28 import java.text.DecimalFormatSymbols;
29 import java.util.Arrays;
30 import java.util.EnumSet;
31 import java.util.logging.Logger;
33 import javax.swing.DefaultListCellRenderer;
34 import javax.swing.ImageIcon;
35 import javax.swing.InputVerifier;
36 import javax.swing.JButton;
37 import javax.swing.JComboBox;
38 import javax.swing.JComponent;
39 import javax.swing.JDialog;
40 import javax.swing.JFormattedTextField;
41 import javax.swing.JLabel;
42 import javax.swing.JList;
44 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
45 import org.scilab.modules.xcos.actions.SetupAction;
46 import org.scilab.modules.xcos.graph.ScicosParameters;
47 import org.scilab.modules.xcos.graph.XcosDiagram;
48 import org.scilab.modules.xcos.utils.XcosMessages;
51 * Dialog associated with the {@link SetupAction}.
53 * Note that this dialog break the Data Abstraction Coupling metric because of
54 * the numbers of graphical components involved in the GUI creation. For the
55 * same reason (GUI class), constants are not used on this code.
57 // CSOFF: ClassDataAbstractionCoupling
58 // CSOFF: ClassFanOutComplexity
60 @SuppressWarnings(value = { "serial" })
61 public class SetupDialog extends JDialog {
62 private static final DecimalFormatSymbols FORMAT_SYMBOL = DecimalFormatSymbols.getInstance();
63 private static final DecimalFormat CURRENT_FORMAT = new DecimalFormat("0.0####E00", FORMAT_SYMBOL);
64 private static final BigDecimal MAX_DOUBLE = BigDecimal.valueOf(Double.MAX_VALUE);
67 * Modifiers used to disable some parameters for a specific solver
69 private static enum SolverModifiers {
78 * Describe a solver, its compilation value, name and tooltip.
80 * Also contains a field with enable modifier set.
82 private static class SolverDescriptor implements Comparable<SolverDescriptor> {
83 private final int number;
84 private final String name;
85 private final String tooltip;
86 private final EnumSet<SolverModifiers> modifiers;
88 public SolverDescriptor(int number, String name, String tooltip, EnumSet<SolverModifiers> modifiers) {
92 this.tooltip = tooltip;
93 this.modifiers = modifiers;
96 public SolverDescriptor(double number) {
98 this.number = (int) number;
101 this.modifiers = null;
104 public int getNumber() {
108 public String getTooltip() {
113 public String toString() {
117 public void applyModifiers(
118 JFormattedTextField integrator,
119 JFormattedTextField integratorRel,
120 JFormattedTextField toleranceOnTime,
121 JFormattedTextField maxIntegrationTime,
122 JFormattedTextField maxStepSize) {
123 integrator.setEnabled(modifiers.contains(SolverModifiers.ABSOLUTE_TOLERANCE));
124 integratorRel.setEnabled(modifiers.contains(SolverModifiers.RELATIVE_TOLERANCE));
125 toleranceOnTime.setEnabled(modifiers.contains(SolverModifiers.TOLERANCE_ON_TIME));
126 maxIntegrationTime.setEnabled(modifiers.contains(SolverModifiers.MAX_INTEGRATION_TIME));
127 maxStepSize.setEnabled(modifiers.contains(SolverModifiers.MAX_STEP_SIZE));
131 public int compareTo(SolverDescriptor o) {
132 // inline Integer.compare(number, o.number) to be java 1.6 compatible
133 return (number < o.number) ? -1 : ((number == o.number) ? 0 : 1);
137 private static final SolverDescriptor[] AVAILABLE_SOLVERS = new SolverDescriptor[] {
138 new SolverDescriptor(0, "LSodar",
139 "Method: dynamic, Nonlinear solver= dynamic",
140 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
142 new SolverDescriptor(1, "Sundials/CVODE - BDF - NEWTON",
143 "Method: BDF, Nonlinear solver= NEWTON",
144 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
146 new SolverDescriptor(2, "Sundials/CVODE - BDF - FUNCTIONAL",
147 "Method: BDF, Nonlinear solver= FUNCTIONAL",
148 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
150 new SolverDescriptor(3, "Sundials/CVODE - ADAMS - NEWTON",
151 "Method: ADAMS, Nonlinear solver= NEWTON",
152 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
154 new SolverDescriptor(4, "Sundials/CVODE - ADAMS - FUNCTIONAL",
155 "Method: ADAMS, Nonlinear solver= FUNCTIONAL",
156 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
158 new SolverDescriptor(5, "DOPRI5 - Dormand-Prince 4(5)",
159 "Method: Fixed step",
160 EnumSet.of(SetupDialog.SolverModifiers.MAX_STEP_SIZE)),
162 new SolverDescriptor(6, "RK45 - Runge-Kutta 4(5)",
163 "Method: Fixed step",
164 EnumSet.of(SetupDialog.SolverModifiers.MAX_STEP_SIZE)),
166 new SolverDescriptor(7, "Implicit RK45 - Runge-Kutta 4(5)",
167 "Method: Fixed step, Nonlinear solver= FIXED-POINT",
168 EnumSet.of(SetupDialog.SolverModifiers.MAX_STEP_SIZE,
169 SetupDialog.SolverModifiers.RELATIVE_TOLERANCE)),
171 new SolverDescriptor(100, "Sundials/IDA",
172 "Method: BDF, Nonlinear solver= NEWTON",
173 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
175 new SolverDescriptor(101, "DDaskr - Newton",
176 "Method: BDF, Nonlinear solver= NEWTON",
177 EnumSet.allOf(SetupDialog.SolverModifiers.class)),
179 new SolverDescriptor(102, "DDaskr - GMRes",
180 "Method: BDF, Nonlinear solver= GMRES",
181 EnumSet.allOf(SetupDialog.SolverModifiers.class))
185 * Validate the user entry and format it.
187 * Without formatting the entry, bug #7143 appears on jdk6.
189 private static final InputVerifier VALIDATE_POSITIVE_DOUBLE = new InputVerifier() {
192 public boolean verify(javax.swing.JComponent arg0) {
194 JFormattedTextField textField = (JFormattedTextField) arg0;
196 BigDecimal value = new BigDecimal(textField.getText());
197 if (value.compareTo(BigDecimal.ZERO) >= 0 && value.compareTo(MAX_DOUBLE) <= 0) {
201 // bug #7143 workaround
202 textField.setValue(value);
203 } catch (NumberFormatException e) {
212 * Initialize static final fields
215 FORMAT_SYMBOL.setDecimalSeparator('.');
216 CURRENT_FORMAT.setDecimalFormatSymbols(FORMAT_SYMBOL);
217 CURRENT_FORMAT.setParseIntegerOnly(false);
218 CURRENT_FORMAT.setParseBigDecimal(true);
220 // assert that the array is sorted
221 Arrays.sort(AVAILABLE_SOLVERS);
224 private final ScicosParameters parameters;
225 private final XcosDiagram rootGraph;
227 private JFormattedTextField integration;
228 private JFormattedTextField rts;
229 private JFormattedTextField integrator;
230 private JFormattedTextField integratorRel;
231 private JFormattedTextField toleranceOnTime;
232 private JFormattedTextField maxIntegrationTime;
233 private JComboBox solver;
234 private JFormattedTextField maxStepSize;
237 * Instanciate a new dialog.
240 * the current selected graph component
242 * the current parameters
244 public SetupDialog(Component parent, XcosDiagram graph, ScicosParameters parameters) {
247 this.parameters = parameters;
249 ImageIcon scilabIcon = new ImageIcon(ScilabSwingUtilities.findIcon("scilab"));
250 Image imageForIcon = scilabIcon.getImage();
251 setLayout(new GridBagLayout());
252 setIconImage(imageForIcon);
253 setTitle(XcosMessages.SETUP_TITLE);
255 setLocationRelativeTo(parent);
257 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
258 ScilabSwingUtilities.closeOnEscape(this);
264 * Initialize the dialog components.
266 * As this method perform a complex initialization, It doesn't pass NCSS.
269 private void initComponents() {
270 JLabel integrationLabel = new JLabel(XcosMessages.FINAL_INTEGRATION_TIME);
271 integration = new JFormattedTextField(CURRENT_FORMAT);
272 integration.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
273 integration.setValue(new BigDecimal(parameters.getFinalIntegrationTime()));
275 JLabel rtsLabel = new JLabel(XcosMessages.REAL_TIME_SCALING);
276 rts = new JFormattedTextField(CURRENT_FORMAT);
277 rts.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
278 rts.setValue(new BigDecimal(parameters.getRealTimeScaling()));
280 JLabel integratorAbsLabel = new JLabel(XcosMessages.INTEGRATOR_ABSOLUTE_TOLERANCE);
281 integrator = new JFormattedTextField(CURRENT_FORMAT);
282 integrator.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
283 integrator.setValue(new BigDecimal(parameters.getIntegratorAbsoluteTolerance()));
285 JLabel integratorRelLabel = new JLabel(XcosMessages.INTEGRATOR_RELATIVE_TOLERANCE);
286 integratorRel = new JFormattedTextField(CURRENT_FORMAT);
287 integratorRel.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
288 integratorRel.setValue(new BigDecimal(parameters.getIntegratorRelativeTolerance()));
290 JLabel toleranceOnTimeLabel = new JLabel(XcosMessages.TOLERANCE_ON_TIME);
291 toleranceOnTime = new JFormattedTextField(CURRENT_FORMAT);
292 toleranceOnTime.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
293 toleranceOnTime.setValue(new BigDecimal(parameters.getToleranceOnTime()));
295 JLabel maxIntegrationTimeLabel = new JLabel(XcosMessages.MAX_INTEGRATION_TIME_INTERVAL);
296 maxIntegrationTime = new JFormattedTextField(CURRENT_FORMAT);
297 maxIntegrationTime.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
298 maxIntegrationTime.setValue(new BigDecimal(parameters.getMaxIntegrationTimeInterval()));
300 JLabel solverLabel = new JLabel(XcosMessages.SOLVER_CHOICE);
303 solver = new JComboBox(AVAILABLE_SOLVERS);
304 double solverValue = parameters.getSolver();
305 final int currentIndex = Arrays.binarySearch(AVAILABLE_SOLVERS, new SolverDescriptor(solverValue));
306 final SolverDescriptor current = AVAILABLE_SOLVERS[currentIndex];
307 solver.setSelectedIndex(currentIndex);
309 final class ComboboxToolTipRenderer extends DefaultListCellRenderer {
311 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
312 JComponent comp = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
314 if (-1 < index && null != value) {
315 list.setToolTipText(AVAILABLE_SOLVERS[index].getTooltip());
320 solver.setRenderer(new ComboboxToolTipRenderer());
322 solver.addItemListener(new ItemListener() {
324 public void itemStateChanged(ItemEvent e) {
325 SolverDescriptor current = (SolverDescriptor) e.getItem();
326 current.applyModifiers(integrator, integratorRel, toleranceOnTime, maxIntegrationTime, maxStepSize);
330 JLabel maxStepSizeLabel = new JLabel(XcosMessages.MAXIMUN_STEP_SIZE);
331 maxStepSize = new JFormattedTextField(CURRENT_FORMAT);
332 maxStepSize.setInputVerifier(VALIDATE_POSITIVE_DOUBLE);
333 maxStepSize.setValue(new BigDecimal(parameters.getMaximumStepSize()));
335 JButton cancelButton = new JButton(XcosMessages.CANCEL);
336 JButton okButton = new JButton(XcosMessages.OK);
337 JButton defaultButton = new JButton(XcosMessages.DEFAULT);
338 JButton setContextButton = new JButton(XcosMessages.SET_CONTEXT);
339 okButton.setPreferredSize(cancelButton.getPreferredSize());
341 GridBagConstraints gbc = new GridBagConstraints();
347 gbc.insets = new Insets(0, 10, 0, 0);
353 gbc.fill = GridBagConstraints.NONE;
354 gbc.insets = new Insets(0, 10, 0, 0);
356 add(integrationLabel, gbc);
362 add(integratorAbsLabel, gbc);
365 add(integratorRelLabel, gbc);
368 add(toleranceOnTimeLabel, gbc);
371 add(maxIntegrationTimeLabel, gbc);
374 add(solverLabel, gbc);
377 add(maxStepSizeLabel, gbc);
380 add(setContextButton, gbc);
384 gbc.gridwidth = GridBagConstraints.REMAINDER;
385 gbc.fill = GridBagConstraints.HORIZONTAL;
386 gbc.insets = new Insets(5, 10, 0, 10);
387 add(integration, gbc);
393 add(integrator, gbc);
396 add(integratorRel, gbc);
399 add(toleranceOnTime, gbc);
402 add(maxIntegrationTime, gbc);
408 add(maxStepSize, gbc);
415 gbc.fill = GridBagConstraints.NONE;
416 gbc.insets = new Insets(5, 0, 10, 5);
421 gbc.insets = new Insets(5, 0, 10, 10);
422 add(cancelButton, gbc);
426 gbc.insets = new Insets(5, 0, 10, 10);
427 add(defaultButton, gbc);
429 installActionListeners(cancelButton, okButton, defaultButton, setContextButton);
431 // at the end, update the enable status of some components
432 current.applyModifiers(integrator, integratorRel, toleranceOnTime, maxIntegrationTime, maxStepSize);
438 * Install the action listeners on the buttons
440 * @param cancelButton
441 * the cancel button (Cancel)
443 * the OK button (Validate)
444 * @param defaultButton
445 * the default button (Reset)
446 * @param setContextButton
447 * the context button (Shortcut to set context)
449 private void installActionListeners(JButton cancelButton, JButton okButton, JButton defaultButton, JButton setContextButton) {
450 cancelButton.addActionListener(new ActionListener() {
452 public void actionPerformed(ActionEvent e) {
457 defaultButton.addActionListener(new ActionListener() {
459 public void actionPerformed(ActionEvent e) {
460 integration.setValue(new BigDecimal(ScicosParameters.FINAL_INTEGRATION_TIME));
461 rts.setValue(new BigDecimal(ScicosParameters.REAL_TIME_SCALING));
462 integrator.setValue(new BigDecimal(ScicosParameters.INTEGRATOR_ABSOLUTE_TOLERANCE));
463 integratorRel.setValue(new BigDecimal(ScicosParameters.INTEGRATOR_RELATIVE_TOLERANCE));
464 toleranceOnTime.setValue(new BigDecimal(ScicosParameters.TOLERANCE_ON_TIME));
465 maxIntegrationTime.setValue(new BigDecimal(ScicosParameters.MAX_INTEGRATION_TIME_INTERVAL));
466 solver.setSelectedIndex((int) ScicosParameters.SOLVER);
467 maxStepSize.setValue(new BigDecimal(ScicosParameters.MAXIMUM_STEP_SIZE));
471 okButton.addActionListener(new ActionListener() {
473 public void actionPerformed(ActionEvent e) {
476 * FIXME This logic must be deported to a vetoable
479 int solverSelectedIndex = solver.getSelectedIndex();
480 parameters.setSolver(AVAILABLE_SOLVERS[solverSelectedIndex].getNumber());
482 parameters.setFinalIntegrationTime(((BigDecimal) integration.getValue()).doubleValue());
483 parameters.setRealTimeScaling(((BigDecimal) rts.getValue()).doubleValue());
484 parameters.setIntegratorAbsoluteTolerance(((BigDecimal) integrator.getValue()).doubleValue());
485 parameters.setIntegratorRelativeTolerance(((BigDecimal) integratorRel.getValue()).doubleValue());
486 parameters.setToleranceOnTime(((BigDecimal) toleranceOnTime.getValue()).doubleValue());
487 parameters.setMaxIntegrationTimeInterval(((BigDecimal) maxIntegrationTime.getValue()).doubleValue());
488 parameters.setMaximumStepSize(((BigDecimal) maxStepSize.getValue()).doubleValue());
492 } catch (PropertyVetoException ex) {
493 Logger.getLogger(SetupAction.class.getName()).severe(ex.toString());
498 setContextButton.addActionListener(new ActionListener() {
500 public void actionPerformed(ActionEvent e) {
501 final SetContextDialog dialog = new SetContextDialog(SetupDialog.this, rootGraph, parameters);
504 dialog.setVisible(true);
509 // CSON: ClassDataAbstractionCoupling
510 // CSON: ClassFanOutComplexity