1 package net.sf.openrocket.gui.main;
3 import java.util.Arrays;
4 import java.util.Collection;
6 import javax.swing.SwingWorker;
8 import net.sf.openrocket.document.Simulation;
9 import net.sf.openrocket.simulation.FlightData;
10 import net.sf.openrocket.simulation.FlightEvent;
11 import net.sf.openrocket.simulation.SimulationListener;
12 import net.sf.openrocket.simulation.SimulationStatus;
13 import net.sf.openrocket.simulation.exception.SimulationCancelledException;
14 import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
19 * A SwingWorker that runs a simulation in a background thread. The simulation
20 * always includes a listener that checks whether this SwingWorked has been cancelled,
21 * and throws a {@link SimulationCancelledException} if it has. This allows the
22 * {@link #cancel(boolean)} method to be used to cancel the simulation.
24 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
26 public abstract class SimulationWorker extends SwingWorker<FlightData, SimulationStatus> {
28 protected final Simulation simulation;
29 private Throwable throwable = null;
31 public SimulationWorker(Simulation sim) {
32 this.simulation = sim;
37 * Runs the simulation.
40 protected FlightData doInBackground() {
42 throwable = new SimulationCancelledException("The simulation was interrupted.");
46 SimulationListener[] listeners = getExtraListeners();
48 if (listeners != null) {
49 listeners = Arrays.copyOf(listeners, listeners.length+1);
51 listeners = new SimulationListener[1];
54 listeners[listeners.length-1] = new CancelListener();
57 simulation.simulate(listeners);
58 } catch (Throwable e) {
59 // System.out.println("Simulation interrupted:");
60 // e.printStackTrace();
64 return simulation.getSimulatedData();
69 * Return additional listeners to use during the simulation. The default
70 * implementation returns an empty array.
72 * @return additional listeners to use, or <code>null</code>.
74 protected SimulationListener[] getExtraListeners() {
75 return new SimulationListener[0];
80 * Called after a simulation is successfully simulated. This method is not
81 * called if the simulation ends in an exception.
83 * @param sim the simulation including the flight data
85 protected abstract void simulationDone();
88 * Called if the simulation is interrupted due to an exception.
90 * @param t the Throwable that caused the interruption
92 protected abstract void simulationInterrupted(Throwable t);
97 * Marks this simulation as done and calls the progress update.
100 protected final void done() {
101 if (throwable == null)
104 simulationInterrupted(throwable);
110 * A simulation listener that throws a {@link SimulationCancelledException} if
111 * this SwingWorker has been cancelled. The conditions is checked every time a step
114 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
116 private class CancelListener extends AbstractSimulationListener {
119 public Collection<FlightEvent> stepTaken(SimulationStatus status)
120 throws SimulationCancelledException {
123 throw new SimulationCancelledException("The simulation was interrupted.");