1 package net.sf.openrocket.startup;
3 import java.awt.GraphicsEnvironment;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
8 import java.util.concurrent.atomic.AtomicInteger;
10 import javax.swing.SwingUtilities;
11 import javax.swing.Timer;
12 import javax.swing.ToolTipManager;
14 import net.sf.openrocket.communication.UpdateInfo;
15 import net.sf.openrocket.communication.UpdateInfoRetriever;
16 import net.sf.openrocket.database.Databases;
17 import net.sf.openrocket.database.ThrustCurveMotorSet;
18 import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
19 import net.sf.openrocket.file.iterator.DirectoryIterator;
20 import net.sf.openrocket.file.iterator.FileIterator;
21 import net.sf.openrocket.file.motor.MotorLoaderHelper;
22 import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
23 import net.sf.openrocket.gui.main.BasicFrame;
24 import net.sf.openrocket.gui.main.Splash;
25 import net.sf.openrocket.gui.main.SwingExceptionHandler;
26 import net.sf.openrocket.gui.util.GUIUtil;
27 import net.sf.openrocket.gui.util.SimpleFileFilter;
28 import net.sf.openrocket.gui.util.SwingPreferences;
29 import net.sf.openrocket.logging.LogHelper;
30 import net.sf.openrocket.motor.Motor;
31 import net.sf.openrocket.motor.ThrustCurveMotor;
32 import net.sf.openrocket.util.BuildProperties;
35 * The second class in the OpenRocket startup sequence. This class can assume the
36 * Application class to be properly set up, and can use any classes safely.
38 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
40 public class Startup2 {
41 private static final LogHelper log = Application.getLogger();
44 private static final String THRUSTCURVE_DIRECTORY = "datafiles/thrustcurves/";
46 /** Block motor loading for this many milliseconds */
47 private static AtomicInteger blockLoading = new AtomicInteger(Integer.MAX_VALUE);
52 * Run when starting up OpenRocket after Application has been set up.
54 * @param args command line arguments
56 static void runMain(final String[] args) throws Exception {
58 log.info("Starting up OpenRocket version " + BuildProperties.getVersion());
60 // Check that we're not running headless
61 log.info("Checking for graphics head");
64 // Check that we're running a good version of a JRE
65 log.info("Checking JRE compatibility");
66 VersionHelper.checkVersion();
67 VersionHelper.checkOpenJDK();
69 // Run the actual startup method in the EDT since it can use progress dialogs etc.
70 log.info("Moving startup to EDT");
71 SwingUtilities.invokeAndWait(new Runnable() {
78 log.info("Startup complete");
83 * Run in the EDT when starting up OpenRocket.
85 * @param args command line arguments
87 private static void runInEDT(String[] args) {
89 // Initialize the splash screen with version info
90 log.info("Initializing the splash screen");
93 // Setup the uncaught exception handler
94 log.info("Registering exception handler");
95 SwingExceptionHandler exceptionHandler = new SwingExceptionHandler();
96 Application.setExceptionHandler(exceptionHandler);
97 exceptionHandler.registerExceptionHandler();
99 // Start update info fetching
100 final UpdateInfoRetriever updateInfo;
101 if ( Application.getPreferences().getCheckUpdates()) {
102 log.info("Starting update check");
103 updateInfo = new UpdateInfoRetriever();
106 log.info("Update check disabled");
110 // Set the best available look-and-feel
111 log.info("Setting best LAF");
112 GUIUtil.setBestLAF();
114 // Set tooltip delay time. Tooltips are used in MotorChooserDialog extensively.
115 ToolTipManager.sharedInstance().setDismissDelay(30000);
118 ((SwingPreferences) Application.getPreferences()).loadDefaultUnits();
121 log.info("Loading databases");
123 Databases.fakeMethod();
125 // Starting action (load files or open new document)
126 log.info("Opening main application window");
127 if (!handleCommandLine(args)) {
128 BasicFrame.newAction();
131 // Check whether update info has been fetched or whether it needs more time
132 log.info("Checking update status");
133 checkUpdateStatus(updateInfo);
135 // Block motor loading for 1.5 seconds to allow window painting to be faster
136 blockLoading.set(1500);
141 * Check that the JRE is not running headless.
143 private static void checkHead() {
145 if (GraphicsEnvironment.isHeadless()) {
146 log.error("Application is headless.");
147 System.err.println();
148 System.err.println("OpenRocket cannot currently be run without the graphical " +
150 System.err.println();
157 private static void loadMotor() {
159 log.info("Starting motor loading from " + THRUSTCURVE_DIRECTORY + " in background thread.");
160 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(true) {
163 protected void loadMotors() {
165 // Block loading until timeout occurs or database is taken into use
166 log.info("Blocking motor loading while starting up");
167 while (!inUse && blockLoading.addAndGet(-100) > 0) {
170 } catch (InterruptedException e) {
173 log.info("Blocking ended, inUse=" + inUse + " blockLoading=" + blockLoading.get());
176 log.info("Loading motors from " + THRUSTCURVE_DIRECTORY);
177 long t0 = System.currentTimeMillis();
179 int thrustCurveCount;
181 // Load the packaged thrust curves
183 FileIterator iterator = DirectoryIterator.findDirectory(THRUSTCURVE_DIRECTORY,
184 new SimpleFileFilter("", false, "eng", "rse"));
185 if (iterator == null) {
186 throw new IllegalStateException("Thrust curve directory " + THRUSTCURVE_DIRECTORY +
187 "not found, distribution built wrong");
189 list = MotorLoaderHelper.load(iterator);
190 for (Motor m : list) {
191 this.addMotor((ThrustCurveMotor) m);
193 fileCount = iterator.getFileCount();
195 thrustCurveCount = list.size();
197 // Load the user-defined thrust curves
198 for (File file : ((SwingPreferences) Application.getPreferences()).getUserThrustCurveFiles()) {
199 log.info("Loading motors from " + file);
200 list = MotorLoaderHelper.load(file);
201 for (Motor m : list) {
202 this.addMotor((ThrustCurveMotor) m);
205 thrustCurveCount += list.size();
208 long t1 = System.currentTimeMillis();
211 int distinctMotorCount = 0;
212 int distinctThrustCurveCount = 0;
213 distinctMotorCount = motorSets.size();
214 for (ThrustCurveMotorSet set : motorSets) {
215 distinctThrustCurveCount += set.getMotorCount();
217 log.info("Motor loading done, took " + (t1 - t0) + " ms to load "
218 + fileCount + " files/directories containing "
219 + thrustCurveCount + " thrust curves which contained "
220 + distinctMotorCount + " distinct motors with "
221 + distinctThrustCurveCount + " distinct thrust curves.");
226 Application.setMotorSetDatabase(db);
229 private static void checkUpdateStatus(final UpdateInfoRetriever updateInfo) {
230 if (updateInfo == null)
234 if (!updateInfo.isRunning())
237 final Timer timer = new Timer(delay, null);
239 ActionListener listener = new ActionListener() {
240 private int count = 5;
243 public void actionPerformed(ActionEvent e) {
244 if (!updateInfo.isRunning()) {
247 String current = BuildProperties.getVersion();
248 String last = Application.getPreferences().getString(Preferences.LAST_UPDATE, "");
250 UpdateInfo info = updateInfo.getUpdateInfo();
251 if (info != null && info.getLatestVersion() != null &&
252 !current.equals(info.getLatestVersion()) &&
253 !last.equals(info.getLatestVersion())) {
255 UpdateInfoDialog infoDialog = new UpdateInfoDialog(info);
256 infoDialog.setVisible(true);
257 if (infoDialog.isReminderSelected()) {
258 Application.getPreferences().putString(Preferences.LAST_UPDATE, "");
260 Application.getPreferences().putString(Preferences.LAST_UPDATE, info.getLatestVersion());
269 timer.addActionListener(listener);
274 * Handles arguments passed from the command line. This may be used either
275 * when starting the first instance of OpenRocket or later when OpenRocket is
276 * executed again while running.
278 * @param args the command-line arguments.
279 * @return whether a new frame was opened or similar user desired action was
280 * performed as a result.
282 private static boolean handleCommandLine(String[] args) {
284 // Check command-line for files
285 boolean opened = false;
286 for (String file : args) {
287 if (BasicFrame.open(new File(file), null)) {