mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-12-23 01:29:33 +00:00
allow simulation delays below real-time
This commit is contained in:
parent
9aee8dbc16
commit
28976d9e15
@ -24,7 +24,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: Simulation.java,v 1.50 2009/07/03 13:37:41 fros4943 Exp $
|
* $Id: Simulation.java,v 1.51 2009/07/06 12:29:57 fros4943 Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.sics.cooja;
|
package se.sics.cooja;
|
||||||
@ -59,7 +59,8 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
|
|
||||||
private Vector<MoteType> moteTypes = new Vector<MoteType>();
|
private Vector<MoteType> moteTypes = new Vector<MoteType>();
|
||||||
|
|
||||||
private int delayTime = 0;
|
private int delayTime=0, delayPeriod=1;
|
||||||
|
private long delayLastSim;
|
||||||
|
|
||||||
private long currentSimulationTime = 0;
|
private long currentSimulationTime = 0;
|
||||||
|
|
||||||
@ -179,13 +180,35 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
|
|
||||||
private TimeEvent delayEvent = new TimeEvent(0) {
|
private TimeEvent delayEvent = new TimeEvent(0) {
|
||||||
public void execute(long t) {
|
public void execute(long t) {
|
||||||
/*logger.info("Delay at: " + t);*/
|
/* As fast as possible: no need to reschedule delay event */
|
||||||
if (delayTime == 0) {
|
if (delayTime == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try { Thread.sleep(delayTime); } catch (InterruptedException e) { }
|
/* Special case: real time */
|
||||||
scheduleEventUnsafe(this, t+MILLISECOND);
|
if (delayPeriod == Integer.MIN_VALUE) {
|
||||||
|
delayLastSim++;
|
||||||
|
long tmp = System.currentTimeMillis();
|
||||||
|
if (delayLastSim > tmp) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(delayLastSim-tmp);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reschedule us next millisecond */
|
||||||
|
scheduleEventUnsafe(this, t+MILLISECOND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normal operation */
|
||||||
|
try {
|
||||||
|
Thread.sleep(delayTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reschedule us next period */
|
||||||
|
scheduleEventUnsafe(this, t+delayPeriod*MILLISECOND);
|
||||||
}
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DELAY";
|
return "DELAY";
|
||||||
@ -227,6 +250,7 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
isRunning = true;
|
isRunning = true;
|
||||||
|
|
||||||
/* Schedule tick events */
|
/* Schedule tick events */
|
||||||
|
delayLastSim = System.currentTimeMillis();
|
||||||
scheduleEventUnsafe(tickEmulatedMotesEvent, currentSimulationTime);
|
scheduleEventUnsafe(tickEmulatedMotesEvent, currentSimulationTime);
|
||||||
scheduleEventUnsafe(delayEvent, currentSimulationTime - (currentSimulationTime % 1000) + 1000);
|
scheduleEventUnsafe(delayEvent, currentSimulationTime - (currentSimulationTime % 1000) + 1000);
|
||||||
scheduleEventUnsafe(millisecondEvent, currentSimulationTime - (currentSimulationTime % 1000) + 1000);
|
scheduleEventUnsafe(millisecondEvent, currentSimulationTime - (currentSimulationTime % 1000) + 1000);
|
||||||
@ -424,7 +448,7 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
|
|
||||||
// Delay time
|
// Delay time
|
||||||
element = new Element("delaytime");
|
element = new Element("delaytime");
|
||||||
element.setText(Integer.toString(delayTime));
|
element.setText("" + getDelayTime());
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
// Random seed
|
// Random seed
|
||||||
@ -505,7 +529,7 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
|
|
||||||
// Delay time
|
// Delay time
|
||||||
if (element.getName().equals("delaytime")) {
|
if (element.getName().equals("delaytime")) {
|
||||||
delayTime = Integer.parseInt(element.getText());
|
setDelayTime(Integer.parseInt(element.getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random seed
|
// Random seed
|
||||||
@ -768,26 +792,57 @@ public class Simulation extends Observable implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set delay time in milliseconds.
|
* Set delay time (ms).
|
||||||
* The simulation loop sleeps this value every simulated millisecond.
|
* The simulation loop delays given value every simulated millisecond.
|
||||||
|
* If the value is zero there is no delay.
|
||||||
|
* If the value is negative, the simulation loop delays 1ms every (-time) simulated milliseconds.
|
||||||
*
|
*
|
||||||
* @param delayTime New delay time (ms)
|
* Examples:
|
||||||
|
* time=0: no sleeping (simulation runs as fast as possible).
|
||||||
|
* time=10: simulation delays 10ms every simulated millisecond.
|
||||||
|
* time=-5: simulation delays 1ms every 5 simulated milliseconds.
|
||||||
|
*
|
||||||
|
* Special case:
|
||||||
|
* time=Integer.MIN_VALUE: simulation tries to execute at real time.
|
||||||
|
*
|
||||||
|
* @param time New delay time value
|
||||||
*/
|
*/
|
||||||
public void setDelayTime(int delayTime) {
|
public void setDelayTime(int time) {
|
||||||
this.delayTime = delayTime;
|
if (time == Integer.MIN_VALUE) {
|
||||||
|
/* Special case: real time */
|
||||||
|
delayTime = Integer.MIN_VALUE;
|
||||||
|
delayPeriod = Integer.MIN_VALUE;
|
||||||
|
delayLastSim = System.currentTimeMillis();
|
||||||
|
} else if (time < 0) {
|
||||||
|
delayTime = 1;
|
||||||
|
delayPeriod = -time;
|
||||||
|
} else {
|
||||||
|
delayTime = time;
|
||||||
|
delayPeriod = 1; /* minimum */
|
||||||
|
}
|
||||||
|
|
||||||
rescheduleEvents = true;
|
rescheduleEvents = true;
|
||||||
|
|
||||||
this.setChanged();
|
this.setChanged();
|
||||||
this.notifyObservers(this);
|
this.notifyObservers(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current delay time.
|
* Returns current delay time value.
|
||||||
|
* Note that this value can be negative.
|
||||||
*
|
*
|
||||||
* @return Delay time (ms)
|
* @see #setDelayTime(int)
|
||||||
|
* @return Delay time value. May be negative, see {@link #setDelayTime(int)}
|
||||||
*/
|
*/
|
||||||
public int getDelayTime() {
|
public int getDelayTime() {
|
||||||
|
/* Special case: real time */
|
||||||
|
if (delayPeriod == Integer.MIN_VALUE) {
|
||||||
|
return Integer.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delayPeriod > 1) {
|
||||||
|
return -delayPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
return delayTime;
|
return delayTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
* Copyright (c) 2009, Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: SimControl.java,v 1.14 2009/05/26 14:27:00 fros4943 Exp $
|
* $Id: SimControl.java,v 1.15 2009/07/06 12:29:57 fros4943 Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.sics.cooja.plugins;
|
package se.sics.cooja.plugins;
|
||||||
@ -40,31 +40,32 @@ import java.util.*;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.Timer;
|
import javax.swing.Timer;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import se.sics.cooja.*;
|
import se.sics.cooja.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Control Panel is a simple control panel for simulations.
|
* Control panel for starting and pausing the current simulation.
|
||||||
|
* Allows for configuring the simulation delay.
|
||||||
*
|
*
|
||||||
* @author Fredrik Osterlind
|
* @author Fredrik Osterlind
|
||||||
*/
|
*/
|
||||||
@ClassDescription("Control Panel")
|
@ClassDescription("Control Panel")
|
||||||
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
@PluginType(PluginType.SIM_STANDARD_PLUGIN)
|
||||||
public class SimControl extends VisPlugin {
|
public class SimControl extends VisPlugin {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 8452253637624664192L;
|
||||||
private static Logger logger = Logger.getLogger(SimControl.class);
|
private static Logger logger = Logger.getLogger(SimControl.class);
|
||||||
|
|
||||||
private Simulation simulation;
|
private Simulation simulation;
|
||||||
|
private static final int SLIDE_MIN = -100;
|
||||||
private static final int SLIDE_MAX = 921; // e^9.21 => ~10000
|
private static final int SLIDE_MAX = 1000;
|
||||||
private static final int TIME_MAX = 10000;
|
|
||||||
|
|
||||||
private static final int LABEL_UPDATE_INTERVAL = 100;
|
private static final int LABEL_UPDATE_INTERVAL = 100;
|
||||||
|
|
||||||
|
private JButton startButton, stopButton;
|
||||||
private JSlider sliderDelay;
|
private JSlider sliderDelay;
|
||||||
private JLabel simulationTime, delayLabel;
|
private JLabel simulationTime, delayLabel;
|
||||||
private JButton startButton, stopButton;
|
|
||||||
private JFormattedTextField stopTimeTextField;
|
private JFormattedTextField stopTimeTextField;
|
||||||
|
|
||||||
private Observer simObserver;
|
private Observer simObserver;
|
||||||
@ -72,53 +73,19 @@ public class SimControl extends VisPlugin {
|
|||||||
/**
|
/**
|
||||||
* Create a new simulation control panel.
|
* Create a new simulation control panel.
|
||||||
*
|
*
|
||||||
* @param simulationToControl Simulation to control
|
* @param simulation Simulation to control
|
||||||
*/
|
*/
|
||||||
public SimControl(Simulation simulationToControl, GUI gui) {
|
public SimControl(Simulation simulation, GUI gui) {
|
||||||
super("Control Panel - " + simulationToControl.getTitle(), gui);
|
super("Control Panel", gui);
|
||||||
|
this.simulation = simulation;
|
||||||
simulation = simulationToControl;
|
|
||||||
|
|
||||||
JButton button;
|
|
||||||
JPanel smallPanel;
|
|
||||||
|
|
||||||
/* Update current time label when simulation is running */
|
/* Update current time label when simulation is running */
|
||||||
if (simulation.isRunning()) {
|
if (simulation.isRunning()) {
|
||||||
updateLabelTimer.start();
|
updateLabelTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Observe current simulation */
|
/* Container */
|
||||||
simulation.addObserver(simObserver = new Observer() {
|
JPanel smallPanel;
|
||||||
public void update(Observable obs, Object obj) {
|
|
||||||
if (simulation.isRunning()) {
|
|
||||||
startButton.setEnabled(false);
|
|
||||||
stopButton.setEnabled(true);
|
|
||||||
|
|
||||||
/* Start label update timer */
|
|
||||||
if (!updateLabelTimer.isRunning()) {
|
|
||||||
updateLabelTimer.start();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
startButton.setEnabled(true);
|
|
||||||
stopButton.setEnabled(false);
|
|
||||||
|
|
||||||
/* Update simulation stop text field */
|
|
||||||
if (!stopEvent.isScheduled()) {
|
|
||||||
stopTimeTextField.setValue(simulation.getSimulationTimeMillis());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
sliderDelay.setValue(convertTimeToSlide(simulation.getDelayTime()));
|
|
||||||
simulationTime.setText("Current simulation time: " + simulation.getSimulationTimeMillis());
|
|
||||||
simulationTime.setToolTipText("Simulation time in microseconds: " + simulation.getSimulationTime());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Main panel
|
|
||||||
JPanel controlPanel = new JPanel();
|
JPanel controlPanel = new JPanel();
|
||||||
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
|
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
@ -129,22 +96,9 @@ public class SimControl extends VisPlugin {
|
|||||||
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
||||||
smallPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
|
smallPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
|
||||||
|
|
||||||
button = new JButton("Start");
|
smallPanel.add(startButton = new JButton(startAction));
|
||||||
button.setActionCommand("start");
|
smallPanel.add(stopButton = new JButton(stopAction));
|
||||||
button.addActionListener(myEventHandler);
|
smallPanel.add(new JButton(stepAction));
|
||||||
startButton = button;
|
|
||||||
smallPanel.add(button);
|
|
||||||
|
|
||||||
button = new JButton("Pause");
|
|
||||||
button.setActionCommand("stop");
|
|
||||||
button.addActionListener(myEventHandler);
|
|
||||||
stopButton = button;
|
|
||||||
smallPanel.add(button);
|
|
||||||
|
|
||||||
button = new JButton("Step millisecond");
|
|
||||||
button.setActionCommand("single_ms");
|
|
||||||
button.addActionListener(myEventHandler);
|
|
||||||
smallPanel.add(button);
|
|
||||||
|
|
||||||
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
controlPanel.add(smallPanel);
|
controlPanel.add(smallPanel);
|
||||||
@ -168,17 +122,16 @@ public class SimControl extends VisPlugin {
|
|||||||
stopEvent.remove();
|
stopEvent.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
JFormattedTextField numberTextField = (JFormattedTextField) e.getSource();
|
long t = ((Number)e.getNewValue()).intValue()*Simulation.MILLISECOND;
|
||||||
long stopTime = ((Number) numberTextField.getValue()).intValue()*Simulation.MILLISECOND;
|
if (t <= SimControl.this.simulation.getSimulationTime()) {
|
||||||
if (stopTime <= simulation.getSimulationTime()) {
|
|
||||||
/* No simulation stop scheduled */
|
/* No simulation stop scheduled */
|
||||||
numberTextField.setBackground(Color.LIGHT_GRAY);
|
stopTimeTextField.setBackground(Color.LIGHT_GRAY);
|
||||||
numberTextField.setToolTipText("Enter future simulation time");
|
stopTimeTextField.setToolTipText("Enter simulation time when to automatically pause");
|
||||||
} else {
|
} else {
|
||||||
/* Schedule simulation stop */
|
/* Schedule simulation stop */
|
||||||
numberTextField.setBackground(Color.WHITE);
|
stopTimeTextField.setBackground(Color.WHITE);
|
||||||
numberTextField.setToolTipText("Simulation will stop at time (us): " + stopTime);
|
stopTimeTextField.setToolTipText("Simulation will stop at time (us): " + t);
|
||||||
simulation.scheduleEvent(stopEvent, stopTime);
|
SimControl.this.simulation.scheduleEvent(stopEvent, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -196,7 +149,7 @@ public class SimControl extends VisPlugin {
|
|||||||
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
||||||
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
||||||
|
|
||||||
label = new JLabel("Current simulation time: " + simulation.getSimulationTimeMillis());
|
label = new JLabel("?");
|
||||||
smallPanel.add(label);
|
smallPanel.add(label);
|
||||||
simulationTime = label;
|
simulationTime = label;
|
||||||
|
|
||||||
@ -208,11 +161,7 @@ public class SimControl extends VisPlugin {
|
|||||||
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
||||||
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
||||||
|
|
||||||
if (simulation.getDelayTime() > 0) {
|
label = new JLabel("?");
|
||||||
label = new JLabel("Delay: " + simulation.getDelayTime() + " ms");
|
|
||||||
} else {
|
|
||||||
label = new JLabel("No simulation delay");
|
|
||||||
}
|
|
||||||
smallPanel.add(label);
|
smallPanel.add(label);
|
||||||
delayLabel = label;
|
delayLabel = label;
|
||||||
|
|
||||||
@ -224,77 +173,111 @@ public class SimControl extends VisPlugin {
|
|||||||
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
|
||||||
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
|
smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
|
||||||
|
|
||||||
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, SLIDE_MAX, convertTimeToSlide(simulation.getDelayTime()));
|
sliderDelay = new JSlider(
|
||||||
slider.addChangeListener(myEventHandler);
|
JSlider.HORIZONTAL,
|
||||||
|
SLIDE_MIN,
|
||||||
|
SLIDE_MAX,
|
||||||
|
convertTimeToSlide(simulation.getDelayTime()));
|
||||||
|
sliderDelay.addChangeListener(new ChangeListener() {
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
SimControl.this.simulation.setDelayTime(
|
||||||
|
convertSlideToTime(sliderDelay.getValue()));
|
||||||
|
updateValues();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Hashtable labelTable = new Hashtable();
|
smallPanel.add(sliderDelay);
|
||||||
for (int i=0; i < 100; i += 10) {
|
|
||||||
labelTable.put(new Integer(convertTimeToSlide(i)), new JLabel("."));
|
|
||||||
}
|
|
||||||
for (int i=200; i < 10000; i += 500) {
|
|
||||||
labelTable.put(new Integer(convertTimeToSlide(i)), new JLabel(":"));
|
|
||||||
}
|
|
||||||
slider.setLabelTable(labelTable);
|
|
||||||
slider.setPaintLabels(true);
|
|
||||||
|
|
||||||
smallPanel.add(slider);
|
|
||||||
sliderDelay = slider;
|
|
||||||
|
|
||||||
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
controlPanel.add(smallPanel);
|
controlPanel.add(smallPanel);
|
||||||
|
|
||||||
pack();
|
/* Observe current simulation */
|
||||||
|
simulation.addObserver(simObserver = new Observer() {
|
||||||
|
public void update(Observable obs, Object obj) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
updateValues();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
/* Set initial values */
|
||||||
|
updateValues();
|
||||||
|
|
||||||
try {
|
pack();
|
||||||
setSelected(true);
|
}
|
||||||
} catch (java.beans.PropertyVetoException e) {
|
|
||||||
// Could not select
|
private void updateValues() {
|
||||||
|
/* Update simulation delay */
|
||||||
|
sliderDelay.setValue(convertTimeToSlide(simulation.getDelayTime()));
|
||||||
|
if (simulation.getDelayTime() == 0) {
|
||||||
|
delayLabel.setText("No simulation delay");
|
||||||
|
} else if (simulation.getDelayTime() == Integer.MIN_VALUE) {
|
||||||
|
delayLabel.setText("Real time");
|
||||||
|
} else if (simulation.getDelayTime() > 0) {
|
||||||
|
delayLabel.setText("Delay: " + simulation.getDelayTime() + " ms");
|
||||||
|
} else {
|
||||||
|
delayLabel.setText("Delay: 1/" + (-simulation.getDelayTime()) + " ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update current time */
|
||||||
|
simulationTime.setText("Current simulation time: "
|
||||||
|
+ simulation.getSimulationTimeMillis()
|
||||||
|
+ " ms");
|
||||||
|
if (simulation.isRunning() && !updateLabelTimer.isRunning()) {
|
||||||
|
updateLabelTimer.start();
|
||||||
|
}
|
||||||
|
if (!simulation.isRunning()) {
|
||||||
|
simulationTime.setToolTipText("Simulation time in microseconds: "
|
||||||
|
+ simulation.getSimulationTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update control buttons */
|
||||||
|
if (simulation.isRunning()) {
|
||||||
|
startAction.setEnabled(false);
|
||||||
|
stopAction.setEnabled(true);
|
||||||
|
stepAction.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
startAction.setEnabled(true);
|
||||||
|
stopAction.setEnabled(false);
|
||||||
|
stepAction.setEnabled(true);
|
||||||
|
|
||||||
|
if (!stopEvent.isScheduled()) {
|
||||||
|
stopTimeTextField.setValue(simulation.getSimulationTimeMillis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int convertSlideToTime(int slide) {
|
private int convertSlideToTime(int slide) {
|
||||||
if (slide == SLIDE_MAX) {
|
if (slide == SLIDE_MIN) {
|
||||||
return TIME_MAX;
|
/* Special case: no delay */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return (int) Math.round(Math.exp(slide/100.0) - 1.0);
|
if (slide == SLIDE_MIN+1) {
|
||||||
|
/* Special case: real time */
|
||||||
|
return Integer.MIN_VALUE;
|
||||||
|
}
|
||||||
|
if (slide <= 0) {
|
||||||
|
return slide-2; /* Ignore special cases */
|
||||||
|
}
|
||||||
|
return slide;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int convertTimeToSlide(int time) {
|
private int convertTimeToSlide(int time) {
|
||||||
if (time == TIME_MAX) {
|
if (time == 0) {
|
||||||
return SLIDE_MAX;
|
/* Special case: no delay */
|
||||||
|
return SLIDE_MIN;
|
||||||
}
|
}
|
||||||
|
if (time == Integer.MIN_VALUE) {
|
||||||
return (int) Math.round((Math.log(time + 1)*100.0));
|
/* Special case: real time */
|
||||||
|
return SLIDE_MIN+1;
|
||||||
|
}
|
||||||
|
if (time < 0) {
|
||||||
|
return time+2; /* Ignore special cases */
|
||||||
|
}
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyEventHandler implements ActionListener, ChangeListener {
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
if (e.getSource() == sliderDelay) {
|
|
||||||
simulation.setDelayTime(convertSlideToTime(sliderDelay.getValue()));
|
|
||||||
if (simulation.getDelayTime() > 0) {
|
|
||||||
delayLabel.setText("Delay: " + simulation.getDelayTime() + " ms");
|
|
||||||
} else {
|
|
||||||
delayLabel.setText("No simulation delay");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.debug("Unhandled state change: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (e.getActionCommand().equals("start")) {
|
|
||||||
simulation.startSimulation();
|
|
||||||
} else if (e.getActionCommand().equals("stop")) {
|
|
||||||
if (simulation.isRunning()) {
|
|
||||||
simulation.stopSimulation();
|
|
||||||
}
|
|
||||||
} else if (e.getActionCommand().equals("single_ms")) {
|
|
||||||
simulation.stepMillisecondSimulation();
|
|
||||||
} else {
|
|
||||||
logger.debug("Unhandled action: " + e.getActionCommand());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} MyEventHandler myEventHandler = new MyEventHandler();
|
|
||||||
|
|
||||||
public void closePlugin() {
|
public void closePlugin() {
|
||||||
/* Remove simulation observer */
|
/* Remove simulation observer */
|
||||||
if (simObserver != null) {
|
if (simObserver != null) {
|
||||||
@ -314,12 +297,21 @@ public class SimControl extends VisPlugin {
|
|||||||
public void execute(long t) {
|
public void execute(long t) {
|
||||||
/* Stop simulation */
|
/* Stop simulation */
|
||||||
simulation.stopSimulation();
|
simulation.stopSimulation();
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
stopTimeTextField.setBackground(Color.LIGHT_GRAY);
|
||||||
|
stopTimeTextField.setToolTipText("Enter simulation time when to automatically pause");
|
||||||
|
stopTimeTextField.requestFocus();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Timer updateLabelTimer = new Timer(LABEL_UPDATE_INTERVAL, new ActionListener() {
|
private Timer updateLabelTimer = new Timer(LABEL_UPDATE_INTERVAL, new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
simulationTime.setText("Current simulation time: " + simulation.getSimulationTimeMillis());
|
simulationTime.setText("Current simulation time: "
|
||||||
|
+ simulation.getSimulationTimeMillis()
|
||||||
|
+ " ms");
|
||||||
|
|
||||||
/* Automatically stop if simulation is no longer running */
|
/* Automatically stop if simulation is no longer running */
|
||||||
if (!simulation.isRunning()) {
|
if (!simulation.isRunning()) {
|
||||||
@ -327,4 +319,22 @@ public class SimControl extends VisPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private Action startAction = new AbstractAction("Start") {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
simulation.startSimulation();
|
||||||
|
stopButton.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private Action stopAction = new AbstractAction("Pause") {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
simulation.stopSimulation();
|
||||||
|
startButton.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private Action stepAction = new AbstractAction("Step millisecond") {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
simulation.stepMillisecondSimulation();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user