2 * iDMC the interactive Dynamical Model Calculator simulates and performs
3 * graphical and numerical analysis of systems of differential and
4 * difference equations.
6 * Copyright (C) 2004 Marji Lines and Alfredo Medio.
8 * Written by Daniele Pizzoni <auouo@tin.it>.
9 * Extended by Alexei Grigoriev <alexei_grigoriev@libero.it>.
13 * The software program was developed within a research project financed
14 * by the Italian Ministry of Universities, the Universities of Udine and
15 * Ca'Foscari of Venice, the Friuli-Venezia Giulia Region.
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or any
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 package org
.tsho
.dmc2
.ui
.trajectory
;
29 import java
.awt
.event
.ActionEvent
;
30 import java
.awt
.event
.ActionListener
;
31 import java
.awt
.event
.KeyEvent
;
33 import javax
.swing
.Action
;
34 import javax
.swing
.ButtonGroup
;
35 import javax
.swing
.JButton
;
36 import javax
.swing
.JCheckBoxMenuItem
;
37 import javax
.swing
.JMenu
;
38 import javax
.swing
.JMenuItem
;
39 import javax
.swing
.JRadioButtonMenuItem
;
40 import javax
.swing
.JSlider
;
41 import javax
.swing
.JToolBar
;
42 import javax
.swing
.event
.ChangeEvent
;
43 import javax
.swing
.event
.ChangeListener
;
45 import org
.jfree
.data
.Range
;
46 import org
.tsho
.dmc2
.ModelDefaults
;
47 import org
.tsho
.dmc2
.core
.VariableDoubles
;
48 import org
.tsho
.dmc2
.core
.VariableItems
;
49 import org
.tsho
.dmc2
.core
.dlua
.Lua
;
50 import org
.tsho
.dmc2
.core
.model
.Model
;
51 import org
.tsho
.dmc2
.core
.model
.ODE
;
52 import org
.tsho
.dmc2
.core
.model
.SimpleMap
;
53 import org
.tsho
.dmc2
.core
.util
.Dataset
;
54 import org
.tsho
.dmc2
.managers
.ManagerListener2
;
55 import org
.tsho
.dmc2
.managers
.TrajectoryManager
;
56 import org
.tsho
.dmc2
.sm
.Input
;
57 import org
.tsho
.dmc2
.ui
.AbstractPlotComponent
;
58 import org
.tsho
.dmc2
.ui
.MainFrame
;
59 import org
.tsho
.dmc2
.ui
.components
.DmcAction
;
60 import org
.tsho
.dmc2
.ui
.components
.DmcButton
;
61 import org
.tsho
.dmc2
.ui
.components
.DmcMenuItem
;
66 * @author Daniele Pizzoni <auouo@tin.it>
68 public final class TrajectoryComponent
extends AbstractPlotComponent
69 implements ManagerListener2
,
72 private final TrajectoryControlForm2 privateControlForm
;
76 // TODO make a custom action that changes the visibilty
79 * These are here because the machine needs to change
83 private JMenuItem autoBoundsMenuItem
;
84 private JMenuItem manualBoundsMenuItem
;
85 private JMenuItem normalPlotMenuItem
;
86 private JMenuItem timePlotMenuItem
;
87 private JMenuItem variationMenuItem
;
90 private final Action startAction
= new StartAction();
91 private final Action stopAction
= new StopAction();
92 private final DmcAction continueAction
= new ContinueAction();
93 private final DmcAction redrawAction
= new RedrawAction();
94 private final Action clearAction
= new ClearAction();
95 private final DmcAction resetAction
= new ResetAction();
98 boolean autoBoundsDefault
= true;
103 public TrajectoryComponent(final Model model
, MainFrame mainFrame
) {
104 super(model
,mainFrame
,new Dataset(model
.getVarNames()));
105 defaultsSection
= ModelDefaults
.SCATTER_SECTION
;
107 controlForm
= privateControlForm
= new TrajectoryControlForm2(model
,this);
109 init(new TrajectoryManager(this, privateControlForm
),
110 new TrajectorySM(this), controlForm
, "Trajectory");
112 stateMachine
.addSensibleItem(autoBoundsMenuItem
);
113 stateMachine
.addSensibleItem(manualBoundsMenuItem
);
114 stateMachine
.addSensibleItem(variationMenuItem
);
116 stateMachine
.addNoRunItem(clearAction
);
118 stateMachine
.addNoRunItem(getTransparencyAction());
119 stateMachine
.addNoRunItem(getConnectDotsMenuItem());
120 stateMachine
.addNoRunItem(getBigDotsMenuItem());
121 stateMachine
.addNoRunItem(getGridLinesMenuItem());
123 variationMenuItem
.setSelected(false);
125 if (model
instanceof SimpleMap
) {
126 getConnectDotsMenuItem().setSelected(false);
128 else if (model
instanceof ODE
) {
129 getConnectDotsMenuItem().setSelected(true);
132 stateMachine
.parseInput(Input
.go
);
133 finishInit(controlForm
);
136 protected JMenu
createCommandMenu() {
139 menu
= new JMenu("Command");
140 menu
.setMnemonic(KeyEvent
.VK_C
);
142 menu
.add(new JMenuItem(startAction
));
143 menu
.add(new JMenuItem(stopAction
));
147 menu
.add(new DmcMenuItem(continueAction
));
148 menu
.add(new DmcMenuItem(redrawAction
));
149 menu
.add(new DmcMenuItem(resetAction
));
150 menu
.add(new JMenuItem(clearAction
));
155 protected JMenu
createPlotMenu() {
159 menu
= new JMenu("Plot");
163 group
= new ButtonGroup();
164 menuItem
= new JRadioButtonMenuItem("State space plot");
165 menuItem
.setMnemonic(KeyEvent
.VK_N
);
168 menuItem
.addActionListener(new ActionListener() {
169 public void actionPerformed(final ActionEvent e
) {
170 stateMachine
.parseInput(UserMenuInput
.normalMode
);
171 controlForm
.updateSamplesMenu();
172 getSaveDataAction().setEnabled(true);
175 normalPlotMenuItem
= menuItem
;
177 menuItem
= new JRadioButtonMenuItem("Time plot");
178 menuItem
.setMnemonic(KeyEvent
.VK_T
);
181 menuItem
.addActionListener(new ActionListener() {
182 public void actionPerformed(final ActionEvent e
) {
183 stateMachine
.parseInput(UserMenuInput
.timeMode
);
184 controlForm
.updateSamplesMenu();
185 getSaveDataAction().setEnabled(true);
188 timePlotMenuItem
= menuItem
;
192 menuItem
= new JCheckBoxMenuItem("Variation");
193 menuItem
.setMnemonic(KeyEvent
.VK_T
);
195 menuItem
.addActionListener(new ActionListener() {
196 public void actionPerformed(final ActionEvent e
) {
198 state
= ((JCheckBoxMenuItem
) e
.getSource()).isSelected();
199 privateControlForm
.setVariation(state
);
200 privateControlForm
.updateSamplesMenu();
201 getSaveDataAction().setEnabled(false);
204 variationMenuItem
= menuItem
;
208 group
= new ButtonGroup();
209 menuItem
= new JRadioButtonMenuItem("Automatic bounds");
210 menuItem
.setMnemonic(KeyEvent
.VK_A
);
213 menuItem
.addActionListener(new ActionListener() {
214 public void actionPerformed(final ActionEvent e
) {
215 privateControlForm
.setAutoRanges(true);
216 privateControlForm
.updateSamplesMenu();
219 autoBoundsMenuItem
= menuItem
;
221 menuItem
= new JRadioButtonMenuItem("Manual bounds");
222 menuItem
.setMnemonic(KeyEvent
.VK_M
);
225 menuItem
.addActionListener(new ActionListener() {
226 public void actionPerformed(final ActionEvent e
) {
227 privateControlForm
.setAutoRanges(false);
228 controlForm
.updateSamplesMenu();
231 manualBoundsMenuItem
= menuItem
;
232 setAutomaticBounds(autoBoundsDefault
);
236 class SetStepFunctionPerform
implements ActionListener
{
239 SetStepFunctionPerform(final int i
) {
243 public void actionPerformed(final ActionEvent e
) {
244 ((TrajectoryManager
) manager
).setOdeStepFunction(i
);
248 if (model
instanceof ODE
) {
252 JMenu stepFuctionMenu
= new JMenu("Step function");
253 stepFuctionMenu
.setMnemonic(KeyEvent
.VK_S
);
255 group
= new ButtonGroup();
259 String name
= Lua
.getStepFunctionName(i
);
260 if (name
== null) break;
262 menuItem
= new JRadioButtonMenuItem(name
);
264 stepFuctionMenu
.add(menuItem
);
266 menuItem
.setToolTipText(Lua
.getStepFunctionDescription(i
));
268 if (name
.equals("rkf45")) {
269 menuItem
.setSelected(true);
271 menuItem
.addActionListener(new SetStepFunctionPerform(i
));
275 menu
.add(stepFuctionMenu
);
276 stateMachine
.addNoRunItem(stepFuctionMenu
);
283 protected JToolBar
createToolBar() {
284 JToolBar toolBar
= new JToolBar();
287 button
= new JButton(startAction
);
290 button
= new JButton(stopAction
);
293 toolBar
.addSeparator();
295 button
= new DmcButton(continueAction
);
298 button
= new DmcButton(redrawAction
);
301 toolBar
.addSeparator();
303 button
= new DmcButton(resetAction
);
307 toolBar
.addSeparator();
308 toolBar
.addSeparator();
310 slider
= new JSlider(0, 50, 10);
311 slider
.setMajorTickSpacing(10);
312 slider
.setMinorTickSpacing(1);
313 slider
.setSnapToTicks(true);
314 slider
.setPaintTicks(true);
316 slider
.addChangeListener(new ChangeListener() {
318 public void stateChanged(final ChangeEvent e
) {
319 JSlider s
= (JSlider
) e
.getSource();
320 ((TrajectoryManager
) getManager()).setDelay(s
.getValue());
333 protected void fillDefaults(final int index
) {
335 VariableItems
.Iterator ii
;
336 VariableDoubles doubles
;
337 VariableDoubles
.Iterator di
;
339 /* initialization is important: if a key is not present use
341 double hMin
= 1, hMax
= -1, vMin
= 1, vMax
= -1;
342 boolean autoBoundsState
= autoBoundsDefault
;
344 items
= Lua
.loadDefaults(model
, defaultsSection
, index
);
347 doubles
= new VariableDoubles(model
.getParNames());
348 di
= doubles
.iterator();
349 while (di
.hasNext()) {
350 if (items
.containsLabel(di
.nextLabel())) {
351 double value
= Double
.parseDouble((String
)items
.get(di
.label()));
352 doubles
.put(di
.label(), value
);
355 privateControlForm
.setParameterValues(doubles
);
358 doubles
= new VariableDoubles(model
.getVarNames());
359 di
= doubles
.iterator();
360 while (di
.hasNext()) {
361 if (items
.containsLabel(di
.nextLabel())) {
363 Double
.parseDouble((String
) items
.get(di
.label()));
364 doubles
.put(di
.label(), value
);
367 privateControlForm
.setInitialValues(doubles
);
370 ii
= items
.iterator();
371 while (ii
.hasNext()) {
372 String key
= ii
.nextLabel();
373 String value
= (String
) items
.get(ii
.label());
376 System
.out
.println("key: " + key
+ ", value: " + value
);
378 if (key
.equals(ModelDefaults
.ITERATIONS_KEY
)) {
379 doubleValue
= Double
.parseDouble(value
);
380 privateControlForm
.setIterations((int) doubleValue
);
383 else if (key
.equals(ModelDefaults
.TRANSIENTS_KEY
)) {
384 doubleValue
= Double
.parseDouble(value
);
385 privateControlForm
.setTransients((int) doubleValue
);
388 else if (key
.equals(ModelDefaults
.SCATTER_AUTOBOUNDS_ITERATIONS_KEY
)) {
389 doubleValue
= Double
.parseDouble(value
);
390 privateControlForm
.setRangeIterations((int) doubleValue
);
394 else if (key
.equals(ModelDefaults
.SCATTER_BOUNDS_KEY
)) {
395 if (value
.equals(ModelDefaults
.SCATTER_BOUNDS_AUTO_VALUE
)) {
396 autoBoundsState
= true;
398 else if (value
.equals(ModelDefaults
.SCATTER_BOUNDS_MANUAL_VALUE
)) {
399 autoBoundsState
= false;
402 else if (key
.equals(ModelDefaults
.SCATTER_AUTO_BOUNDS_HMIN_KEY
)) {
403 hMin
= Double
.parseDouble(value
);
405 else if (key
.equals(ModelDefaults
.SCATTER_AUTO_BOUNDS_HMAX_KEY
)) {
406 hMax
= Double
.parseDouble(value
);
408 else if (key
.equals(ModelDefaults
.SCATTER_AUTO_BOUNDS_VMIN_KEY
)) {
409 vMin
= Double
.parseDouble(value
);
411 else if (key
.equals(ModelDefaults
.SCATTER_AUTO_BOUNDS_VMAX_KEY
)) {
412 vMax
= Double
.parseDouble(value
);
417 /* post processing */
418 setAutomaticBounds(autoBoundsState
);
422 range
= new Range(hMin
, hMax
);
423 } catch (IllegalArgumentException e
) {
427 privateControlForm
.setXRange(range
);
433 range
= new Range(vMin
, vMax
);
434 } catch (IllegalArgumentException e
) {
438 privateControlForm
.setYRange(range
);
445 private void setAutomaticBounds(final boolean flag
) {
446 autoBoundsMenuItem
.setSelected(flag
);
447 manualBoundsMenuItem
.setSelected(!flag
);
448 privateControlForm
.setAutoRanges(flag
);
452 * @return Returns the normalPlotMenuItem.
454 public JMenuItem
getNormalPlotMenuItem() {
455 return normalPlotMenuItem
;
459 * @return Returns the timePlotMenuItem.
461 public JMenuItem
getTimePlotMenuItem() {
462 return timePlotMenuItem
;
468 public DmcAction
getContinueAction() {
469 return continueAction
;
475 public DmcAction
getRedrawAction() {
482 public DmcAction
getResetAction() {
489 public Action
getStartAction() {
496 public Action
getStopAction() {
503 public int getDelayValue() {
504 return slider
.getValue();
507 public JSlider
getSlider() {
511 public Model
getModel() {
515 public void callUponStart() {