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) {
57 // System.out.println("Simulation interrupted:");
58 // e.printStackTrace();
62 return simulation.getSimulatedData();
67 * Return additional listeners to use during the simulation. The default
68 * implementation returns an empty array.
70 * @return additional listeners to use, or <code>null</code>.
72 protected SimulationListener[] getExtraListeners() {
73 return new SimulationListener[0];
78 * Called after a simulation is successfully simulated. This method is not
79 * called if the simulation ends in an exception.
81 * @param sim the simulation including the flight data
83 protected abstract void simulationDone();
86 * Called if the simulation is interrupted due to an exception.
88 * @param t the Throwable that caused the interruption
90 protected abstract void simulationInterrupted(Throwable t);
95 * Marks this simulation as done and calls the progress update.
98 protected final void done() {
99 if (throwable == null)
102 simulationInterrupted(throwable);
108 * A simulation listener that throws a {@link SimulationCancelledException} if
109 * this SwingWorker has been cancelled. The conditions is checked every time a step
112 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
114 private class CancelListener extends AbstractSimulationListener {
117 public void postStep(SimulationStatus status) throws SimulationCancelledException {
120 throw new SimulationCancelledException("The simulation was interrupted.");