1 package net.sf.openrocket.gui.main;
3 import java.util.Arrays;
5 import javax.swing.SwingWorker;
7 import net.sf.openrocket.document.Simulation;
8 import net.sf.openrocket.simulation.FlightData;
9 import net.sf.openrocket.simulation.SimulationStatus;
10 import net.sf.openrocket.simulation.exception.SimulationCancelledException;
11 import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
12 import net.sf.openrocket.simulation.listeners.SimulationListener;
17 * A SwingWorker that runs a simulation in a background thread. The simulation
18 * always includes a listener that checks whether this SwingWorked has been cancelled,
19 * and throws a {@link SimulationCancelledException} if it has. This allows the
20 * {@link #cancel(boolean)} method to be used to cancel the simulation.
22 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
24 public abstract class SimulationWorker extends SwingWorker<FlightData, SimulationStatus> {
26 protected final Simulation simulation;
27 private Throwable throwable = null;
29 public SimulationWorker(Simulation sim) {
30 this.simulation = sim;
35 * Runs the simulation.
38 protected FlightData doInBackground() {
40 throwable = new SimulationCancelledException("The simulation was interrupted.");
44 SimulationListener[] listeners = getExtraListeners();
46 if (listeners != null) {
47 listeners = Arrays.copyOf(listeners, listeners.length + 1);
49 listeners = new SimulationListener[1];
52 listeners[listeners.length - 1] = new CancelListener();
55 simulation.simulate(listeners);
56 } catch (Throwable e) {
60 return simulation.getSimulatedData();
65 * Return additional listeners to use during the simulation. The default
66 * implementation returns an empty array.
68 * @return additional listeners to use, or <code>null</code>.
70 protected SimulationListener[] getExtraListeners() {
71 return new SimulationListener[0];
76 * Called after a simulation is successfully simulated. This method is not
77 * called if the simulation ends in an exception.
79 protected abstract void simulationDone();
82 * Called if the simulation is interrupted due to an exception.
84 * @param t the Throwable that caused the interruption
86 protected abstract void simulationInterrupted(Throwable t);
91 * Marks this simulation as done and calls the progress update.
94 protected final void done() {
95 if (throwable == null)
98 simulationInterrupted(throwable);
104 * A simulation listener that throws a {@link SimulationCancelledException} if
105 * this SwingWorker has been cancelled. The conditions is checked every time a step
108 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
110 private class CancelListener extends AbstractSimulationListener {
113 public void postStep(SimulationStatus status) throws SimulationCancelledException {
116 throw new SimulationCancelledException("The simulation was interrupted.");