From 02f3d96a74beac56396117f4c8ea3497134ad139 Mon Sep 17 00:00:00 2001 From: plaa Date: Sun, 31 May 2009 17:50:09 +0000 Subject: [PATCH] Bug fixes and startup checks git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@6 180e2498-e6e9-4542-8430-84ac67f01cd8 --- ChangeLog | 13 +- build.xml | 2 +- html/download.html | 2 +- src/net/sf/openrocket/database/Database.java | 33 +-- .../file/openrocket/TransitionSaver.java | 2 +- .../gui/ComponentAnalysisDialog.java | 4 + .../sf/openrocket/gui/PreferencesDialog.java | 1 + .../gui/adaptors/MaterialModel.java | 2 +- .../gui/adaptors/MotorConfigurationModel.java | 2 +- .../gui/{ => components}/BasicSlider.java | 2 +- .../gui/{ => components}/DescriptionArea.java | 2 +- .../gui/{ => components}/ResizeLabel.java | 2 +- .../gui/{ => components}/StageSelector.java | 2 +- .../openrocket/gui/components/URLLabel.java | 51 +++++ .../gui/{ => components}/UnitSelector.java | 2 +- .../gui/configdialog/BodyTubeConfig.java | 4 +- .../configdialog/EllipticalFinSetConfig.java | 4 +- .../configdialog/FreeformFinSetConfig.java | 6 +- .../gui/configdialog/InnerTubeConfig.java | 4 +- .../gui/configdialog/LaunchLugConfig.java | 4 +- .../gui/configdialog/MassComponentConfig.java | 4 +- .../gui/configdialog/MotorConfig.java | 4 +- .../gui/configdialog/NoseConeConfig.java | 6 +- .../gui/configdialog/ParachuteConfig.java | 4 +- .../gui/configdialog/RingComponentConfig.java | 4 +- .../configdialog/RocketComponentConfig.java | 6 +- .../gui/configdialog/ShockCordConfig.java | 4 +- .../gui/configdialog/StreamerConfig.java | 6 +- .../gui/configdialog/TransitionConfig.java | 6 +- .../configdialog/TrapezoidFinSetConfig.java | 4 +- .../sf/openrocket/gui/dialogs/BugDialog.java | 90 +++++++++ .../sf/openrocket/gui/main/AboutDialog.java | 38 +--- .../sf/openrocket/gui/main/BasicFrame.java | 35 +++- .../gui/main/ComponentAddButtons.java | 63 +++--- .../gui/main/DocumentSelectionListener.java | 15 ++ .../gui/main/DocumentSelectionModel.java | 189 ++++++++++++++++++ .../sf/openrocket/gui/main/LicenseDialog.java | 2 +- .../gui/main/MotorChooserDialog.java | 2 +- .../gui/main/OpenRocketClipboard.java | 35 ++++ .../sf/openrocket/gui/main/RocketActions.java | 2 +- .../gui/main/SimulationEditDialog.java | 6 +- .../openrocket/gui/main/SimulationPanel.java | 2 +- src/net/sf/openrocket/gui/plot/PlotPanel.java | 4 +- .../gui/scalefigure/RocketPanel.java | 14 +- .../gui/scalefigure/ScaleScrollPane.java | 2 +- src/net/sf/openrocket/startup/Startup.java | 180 +++++++++++++++++ .../openrocket/unit/FixedPrecisionUnit.java | 2 +- src/net/sf/openrocket/util/JarUtil.java | 50 +++++ .../sf/openrocket/util/PrintProperties.java | 22 ++ 49 files changed, 774 insertions(+), 171 deletions(-) rename src/net/sf/openrocket/gui/{ => components}/BasicSlider.java (94%) rename src/net/sf/openrocket/gui/{ => components}/DescriptionArea.java (96%) rename src/net/sf/openrocket/gui/{ => components}/ResizeLabel.java (95%) rename src/net/sf/openrocket/gui/{ => components}/StageSelector.java (98%) create mode 100644 src/net/sf/openrocket/gui/components/URLLabel.java rename src/net/sf/openrocket/gui/{ => components}/UnitSelector.java (99%) create mode 100644 src/net/sf/openrocket/gui/dialogs/BugDialog.java create mode 100644 src/net/sf/openrocket/gui/main/DocumentSelectionListener.java create mode 100644 src/net/sf/openrocket/gui/main/DocumentSelectionModel.java create mode 100644 src/net/sf/openrocket/gui/main/OpenRocketClipboard.java create mode 100644 src/net/sf/openrocket/startup/Startup.java create mode 100644 src/net/sf/openrocket/util/JarUtil.java create mode 100644 src/net/sf/openrocket/util/PrintProperties.java diff --git a/ChangeLog b/ChangeLog index 9e11801e..7efec8a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,15 @@ +2009-05-28 Sampo Niskanen + + * Added startup check for Java 1.6 and OpenJDK + +2009-05-28 Sampo Niskanen + + * Fixed FixedPrecisionUnit formatting + * Fixed saving of transitions + * Fixed file dialog directory browsing + * Initial shift-click selects second component from figure + * Allow adding body components without selecting stage + 2009-05-24 Sampo Niskanen * Initial release 0.9.0 - diff --git a/build.xml b/build.xml index f5639657..c4892fa8 100644 --- a/build.xml +++ b/build.xml @@ -12,7 +12,7 @@ - + diff --git a/html/download.html b/html/download.html index 0795dc8a..f79600f3 100644 --- a/html/download.html +++ b/html/download.html @@ -76,7 +76,7 @@

The source code for OpenRocket is available from the SourceForge SVN repository. It can be retrieved simply using the command

-
$ svn co https://openrocket.svn.sourceforge.net/svnroot/openrocket openrocket
+
$ svn co https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk OpenRocket

The above URL may be used to connect to the repository with other Subversion clients as well.

diff --git a/src/net/sf/openrocket/database/Database.java b/src/net/sf/openrocket/database/Database.java index b7986cb7..fd901dfa 100644 --- a/src/net/sf/openrocket/database/Database.java +++ b/src/net/sf/openrocket/database/Database.java @@ -5,10 +5,6 @@ import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.security.CodeSource; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Collections; @@ -24,6 +20,7 @@ import javax.swing.event.EventListenerList; import net.sf.openrocket.file.Loader; import net.sf.openrocket.util.ChangeSource; +import net.sf.openrocket.util.JarUtil; @@ -182,17 +179,9 @@ public class Database> extends AbstractSet implements if (!dir.endsWith("/")) { dir += "/"; } - - // Find the jar file this class is contained in and open it - URL jarUrl = null; - CodeSource codeSource = Database.class.getProtectionDomain().getCodeSource(); - if (codeSource != null) - jarUrl = codeSource.getLocation(); - if (jarUrl == null) { - throw new IOException("Could not find containing JAR file."); - } - File file = urlToFile(jarUrl); + // Find and open the jar file this class is contained in + File file = JarUtil.getCurrentJarFile(); JarFile jarFile = new JarFile(file); try { @@ -219,22 +208,6 @@ public class Database> extends AbstractSet implements } - static File urlToFile(URL url) { - URI uri; - try { - uri = url.toURI(); - } catch (URISyntaxException e) { - try { - uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), - url.getPath(), url.getQuery(), url.getRef()); - } catch (URISyntaxException e1) { - throw new IllegalArgumentException("Broken URL: " + url); - } - } - return new File(uri); - } - - public void load(File file) throws IOException { if (loader == null) { diff --git a/src/net/sf/openrocket/file/openrocket/TransitionSaver.java b/src/net/sf/openrocket/file/openrocket/TransitionSaver.java index d597d129..461087f6 100644 --- a/src/net/sf/openrocket/file/openrocket/TransitionSaver.java +++ b/src/net/sf/openrocket/file/openrocket/TransitionSaver.java @@ -33,7 +33,7 @@ public class TransitionSaver extends SymmetricComponentSaver { Transition.Shape shape = trans.getType(); - elements.add("" + shape.getName().toLowerCase() + ""); + elements.add("" + shape.name().toLowerCase() + ""); if (shape.isClippable()) { elements.add("" + trans.isClipped() + ""); } diff --git a/src/net/sf/openrocket/gui/ComponentAnalysisDialog.java b/src/net/sf/openrocket/gui/ComponentAnalysisDialog.java index e44e48bd..7fa39a7a 100644 --- a/src/net/sf/openrocket/gui/ComponentAnalysisDialog.java +++ b/src/net/sf/openrocket/gui/ComponentAnalysisDialog.java @@ -44,6 +44,10 @@ import net.sf.openrocket.gui.adaptors.Column; import net.sf.openrocket.gui.adaptors.ColumnTableModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.MotorConfigurationModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.StageSelector; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.FinSet; diff --git a/src/net/sf/openrocket/gui/PreferencesDialog.java b/src/net/sf/openrocket/gui/PreferencesDialog.java index e42d9f92..2cdb4c45 100644 --- a/src/net/sf/openrocket/gui/PreferencesDialog.java +++ b/src/net/sf/openrocket/gui/PreferencesDialog.java @@ -18,6 +18,7 @@ import javax.swing.JPanel; import javax.swing.JTabbedPane; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.GUIUtil; diff --git a/src/net/sf/openrocket/gui/adaptors/MaterialModel.java b/src/net/sf/openrocket/gui/adaptors/MaterialModel.java index 1af6f2ad..1daf286c 100644 --- a/src/net/sf/openrocket/gui/adaptors/MaterialModel.java +++ b/src/net/sf/openrocket/gui/adaptors/MaterialModel.java @@ -20,7 +20,7 @@ import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.database.Database; import net.sf.openrocket.database.Databases; -import net.sf.openrocket.gui.UnitSelector; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/adaptors/MotorConfigurationModel.java b/src/net/sf/openrocket/gui/adaptors/MotorConfigurationModel.java index fbf367bf..9f96997c 100644 --- a/src/net/sf/openrocket/gui/adaptors/MotorConfigurationModel.java +++ b/src/net/sf/openrocket/gui/adaptors/MotorConfigurationModel.java @@ -30,8 +30,8 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.ResizeLabel; import net.sf.openrocket.gui.TextFieldListener; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Motor; diff --git a/src/net/sf/openrocket/gui/BasicSlider.java b/src/net/sf/openrocket/gui/components/BasicSlider.java similarity index 94% rename from src/net/sf/openrocket/gui/BasicSlider.java rename to src/net/sf/openrocket/gui/components/BasicSlider.java index d22c3e83..0ac92e79 100644 --- a/src/net/sf/openrocket/gui/BasicSlider.java +++ b/src/net/sf/openrocket/gui/components/BasicSlider.java @@ -1,4 +1,4 @@ -package net.sf.openrocket.gui; +package net.sf.openrocket.gui.components; import javax.swing.BoundedRangeModel; import javax.swing.JSlider; diff --git a/src/net/sf/openrocket/gui/DescriptionArea.java b/src/net/sf/openrocket/gui/components/DescriptionArea.java similarity index 96% rename from src/net/sf/openrocket/gui/DescriptionArea.java rename to src/net/sf/openrocket/gui/components/DescriptionArea.java index ba29be47..264953f7 100644 --- a/src/net/sf/openrocket/gui/DescriptionArea.java +++ b/src/net/sf/openrocket/gui/components/DescriptionArea.java @@ -1,4 +1,4 @@ -package net.sf.openrocket.gui; +package net.sf.openrocket.gui.components; import java.awt.Dimension; import java.awt.Rectangle; diff --git a/src/net/sf/openrocket/gui/ResizeLabel.java b/src/net/sf/openrocket/gui/components/ResizeLabel.java similarity index 95% rename from src/net/sf/openrocket/gui/ResizeLabel.java rename to src/net/sf/openrocket/gui/components/ResizeLabel.java index 6951d628..0978252a 100644 --- a/src/net/sf/openrocket/gui/ResizeLabel.java +++ b/src/net/sf/openrocket/gui/components/ResizeLabel.java @@ -1,4 +1,4 @@ -package net.sf.openrocket.gui; +package net.sf.openrocket.gui.components; import java.awt.Font; import javax.swing.JLabel; diff --git a/src/net/sf/openrocket/gui/StageSelector.java b/src/net/sf/openrocket/gui/components/StageSelector.java similarity index 98% rename from src/net/sf/openrocket/gui/StageSelector.java rename to src/net/sf/openrocket/gui/components/StageSelector.java index a0ad4376..5b5e78ae 100644 --- a/src/net/sf/openrocket/gui/StageSelector.java +++ b/src/net/sf/openrocket/gui/components/StageSelector.java @@ -1,4 +1,4 @@ -package net.sf.openrocket.gui; +package net.sf.openrocket.gui.components; import java.awt.event.ActionEvent; import java.util.ArrayList; diff --git a/src/net/sf/openrocket/gui/components/URLLabel.java b/src/net/sf/openrocket/gui/components/URLLabel.java new file mode 100644 index 00000000..be6bdd82 --- /dev/null +++ b/src/net/sf/openrocket/gui/components/URLLabel.java @@ -0,0 +1,51 @@ +package net.sf.openrocket.gui.components; + +import java.awt.Desktop; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.swing.JLabel; + +/** + * A label of a URL that is clickable. Clicking the URL will launch the URL in + * the default browser if the Desktop class is supported. + * + * @author Sampo Niskanen + */ +public class URLLabel extends JLabel { + + private final String url; + + public URLLabel(String urlLabel) { + super(); + + this.url = urlLabel; + + + if (Desktop.isDesktopSupported()) { + + setText("" + url + ""); + + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + Desktop d = Desktop.getDesktop(); + try { + d.browse(new URI(url)); + } catch (URISyntaxException e1) { + throw new RuntimeException("BUG: Illegal URL: " + url, e1); + } catch (IOException e1) { + System.err.println("Unable to launch browser:"); + e1.printStackTrace(); + } + } + }); + + } else { + setText(url); + } + } +} diff --git a/src/net/sf/openrocket/gui/UnitSelector.java b/src/net/sf/openrocket/gui/components/UnitSelector.java similarity index 99% rename from src/net/sf/openrocket/gui/UnitSelector.java rename to src/net/sf/openrocket/gui/components/UnitSelector.java index 37453ef4..962992e2 100644 --- a/src/net/sf/openrocket/gui/UnitSelector.java +++ b/src/net/sf/openrocket/gui/components/UnitSelector.java @@ -1,4 +1,4 @@ -package net.sf.openrocket.gui; +package net.sf.openrocket.gui.components; import java.awt.Color; diff --git a/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java index 7c5776ad..874111a2 100644 --- a/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java @@ -7,11 +7,11 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java index 8092ae4b..51f45318 100644 --- a/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java @@ -14,12 +14,12 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.IntegerModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FreeformFinSet; diff --git a/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java index de59d7a1..889d4adf 100644 --- a/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java @@ -17,13 +17,13 @@ import javax.swing.SwingConstants; import javax.swing.table.AbstractTableModel; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.ResizeLabel; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.IntegerModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.scalefigure.FinPointFigure; import net.sf.openrocket.gui.scalefigure.ScaleScrollPane; import net.sf.openrocket.gui.scalefigure.ScaleSelector; diff --git a/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java b/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java index b8d9534b..b1319b7b 100644 --- a/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java @@ -26,11 +26,11 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.Resettable; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.rocketcomponent.ClusterConfiguration; import net.sf.openrocket.rocketcomponent.Clusterable; import net.sf.openrocket.rocketcomponent.InnerTube; diff --git a/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java b/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java index 9ef72034..909c5d31 100644 --- a/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java @@ -7,11 +7,11 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.unit.UnitGroup; diff --git a/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java index 93a3d472..5bff03a0 100644 --- a/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java @@ -11,11 +11,11 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.unit.UnitGroup; diff --git a/src/net/sf/openrocket/gui/configdialog/MotorConfig.java b/src/net/sf/openrocket/gui/configdialog/MotorConfig.java index 47b94192..cf81eaab 100644 --- a/src/net/sf/openrocket/gui/configdialog/MotorConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/MotorConfig.java @@ -17,13 +17,13 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.MotorConfigurationModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.main.MotorChooserDialog; import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Motor; diff --git a/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java b/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java index 1c75f8c1..f1b6daf2 100644 --- a/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java @@ -12,12 +12,12 @@ import javax.swing.JSlider; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.DescriptionArea; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.DescriptionArea; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java b/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java index 340dfb8c..c058725d 100644 --- a/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java @@ -11,13 +11,13 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.IntegerModel; import net.sf.openrocket.gui.adaptors.MaterialModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.Parachute; diff --git a/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java index 9acbbda0..1b2f12ad 100644 --- a/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java @@ -12,11 +12,11 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.RingComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 9b19bcb8..5e017a4b 100644 --- a/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -25,14 +25,14 @@ import javax.swing.JTextArea; import javax.swing.JTextField; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.ResizeLabel; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.MaterialModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.ExternalComponent; diff --git a/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java b/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java index 9b82ea9f..e3b1ba53 100644 --- a/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java @@ -7,11 +7,11 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.unit.UnitGroup; diff --git a/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java b/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java index 951969e6..132f6a5e 100644 --- a/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java @@ -12,13 +12,13 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.ResizeLabel; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.MaterialModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java b/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java index 61a6ff24..3a908ee8 100644 --- a/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java @@ -11,12 +11,12 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.DescriptionArea; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.DescriptionArea; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.Transition; diff --git a/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java index 4a640ec9..92081be6 100644 --- a/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java @@ -9,12 +9,12 @@ import javax.swing.JSpinner; import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.BasicSlider; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.IntegerModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.RocketComponent; diff --git a/src/net/sf/openrocket/gui/dialogs/BugDialog.java b/src/net/sf/openrocket/gui/dialogs/BugDialog.java new file mode 100644 index 00000000..ae0bee8c --- /dev/null +++ b/src/net/sf/openrocket/gui/dialogs/BugDialog.java @@ -0,0 +1,90 @@ +package net.sf.openrocket.gui.dialogs; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.gui.components.URLLabel; +import net.sf.openrocket.gui.main.AboutDialog; +import net.sf.openrocket.util.GUIUtil; +import net.sf.openrocket.util.JarUtil; +import net.sf.openrocket.util.Prefs; + +public class BugDialog extends JDialog { + + public BugDialog(JFrame parent) { + super(parent, "Bug reporing", true); + + JPanel panel = new JPanel(new MigLayout("fill")); + + panel.add(new JLabel("Please report any bugs you encounter as instructed at "), + "gap para, split 2"); + panel.add(new URLLabel(AboutDialog.OPENROCKET_URL), "wrap rel"); + panel.add(new JLabel("This allows us to make OpenRocket an even better simulator."), + "gap para, wrap para"); + + panel.add(new JLabel("Please copy and paste the following information " + + "to the end of your bug report:"), "gap para, wrap"); + + + StringBuilder sb = new StringBuilder(); + sb.append('\n'); + sb.append("---------- Included system information ----------\n"); + sb.append("OpenRocket version: " + Prefs.getVersion() + "\n"); + sb.append("OpenRocket location: " + JarUtil.getCurrentJarFile() + "\n"); + sb.append("System properties:\n"); + + // Sort the keys + SortedSet keys = new TreeSet(); + for (Object key: System.getProperties().keySet()) { + keys.add((String)key); + } + + for (String key: keys) { + String value = System.getProperty(key); + sb.append(" " + key + "="); + if (key.equals("line.separator")) { + for (char c: value.toCharArray()) { + sb.append(String.format("\\u%04x", (int)c)); + } + } else { + sb.append(value); + } + sb.append('\n'); + } + + sb.append("---------- End system information ----------\n"); + sb.append('\n'); + + JTextArea text = new JTextArea(sb.toString(), 15, 70); + text.setEditable(false); + panel.add(new JScrollPane(text), "grow, wrap para"); + + JButton close = new JButton("Close"); + close.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + BugDialog.this.dispose(); + } + }); + panel.add(close, "right"); + + this.add(panel); + + this.pack(); + this.setLocationRelativeTo(parent); + GUIUtil.installEscapeCloseOperation(this); + GUIUtil.setDefaultButton(close); + } + +} diff --git a/src/net/sf/openrocket/gui/main/AboutDialog.java b/src/net/sf/openrocket/gui/main/AboutDialog.java index ca302bcc..52184f3c 100644 --- a/src/net/sf/openrocket/gui/main/AboutDialog.java +++ b/src/net/sf/openrocket/gui/main/AboutDialog.java @@ -1,22 +1,16 @@ package net.sf.openrocket.gui.main; -import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; -import javax.swing.JLabel; import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.ResizeLabel; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.URLLabel; import net.sf.openrocket.util.GUIUtil; import net.sf.openrocket.util.Prefs; @@ -37,33 +31,7 @@ public class AboutDialog extends JDialog { panel.add(new ResizeLabel("Copyright \u00A9 2007-2009 Sampo Niskanen"), "ax 50%, wrap para"); - JLabel link; - - if (Desktop.isDesktopSupported()) { - - link = new JLabel("" + - OPENROCKET_URL + ""); - link.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - Desktop d = Desktop.getDesktop(); - try { - d.browse(new URI(OPENROCKET_URL)); - - } catch (URISyntaxException e1) { - throw new RuntimeException("BUG: Illegal OpenRocket URL: "+OPENROCKET_URL, - e1); - } catch (IOException e1) { - System.err.println("Unable to launch browser:"); - e1.printStackTrace(); - } - } - }); - - } else { - link = new JLabel(OPENROCKET_URL); - } - panel.add(link, "ax 50%, wrap para"); + panel.add(new URLLabel(OPENROCKET_URL), "ax 50%, wrap para"); JButton close = new JButton("Close"); diff --git a/src/net/sf/openrocket/gui/main/BasicFrame.java b/src/net/sf/openrocket/gui/main/BasicFrame.java index 4bd73ca1..a924db64 100644 --- a/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -59,6 +59,7 @@ import net.sf.openrocket.gui.ComponentAnalysisDialog; import net.sf.openrocket.gui.PreferencesDialog; import net.sf.openrocket.gui.StorageOptionChooser; import net.sf.openrocket.gui.configdialog.ComponentConfigDialog; +import net.sf.openrocket.gui.dialogs.BugDialog; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.ComponentChangeListener; @@ -87,6 +88,8 @@ public class BasicFrame extends JFrame { } @Override public boolean accept(File f) { + if (f.isDirectory()) + return true; String name = f.getName().toLowerCase(); return name.endsWith(".ork") || name.endsWith(".ork.gz"); } @@ -117,7 +120,8 @@ public class BasicFrame extends JFrame { private RocketPanel rocketpanel; private ComponentTree tree = null; - private final TreeSelectionModel selectionModel; + private final TreeSelectionModel componentSelectionModel; + // private final ListSelectionModel simulationSelectionModel; ... /** Actions available for rocket modifications */ private final RocketActions actions; @@ -147,10 +151,10 @@ public class BasicFrame extends JFrame { // Create the selection model that will be used - selectionModel = new DefaultTreeSelectionModel(); - selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + componentSelectionModel = new DefaultTreeSelectionModel(); + componentSelectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - actions = new RocketActions(document, selectionModel, this); + actions = new RocketActions(document, componentSelectionModel, this); // The main vertical split pane @@ -232,7 +236,7 @@ public class BasicFrame extends JFrame { JPanel panel = new JPanel(new MigLayout("fill, flowy","","[grow]")); tree = new ComponentTree(rocket); - tree.setSelectionModel(selectionModel); + tree.setSelectionModel(componentSelectionModel); // Remove JTree key events that interfere with menu accelerators InputMap im = SwingUtilities.getUIInputMap(tree, JComponent.WHEN_FOCUSED); @@ -265,10 +269,10 @@ public class BasicFrame extends JFrame { tree.addMouseListener(ml); // Update dialog when selection is changed - selectionModel.addTreeSelectionListener(new TreeSelectionListener() { + componentSelectionModel.addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { // Scroll tree to the selected item - TreePath path = selectionModel.getSelectionPath(); + TreePath path = componentSelectionModel.getSelectionPath(); if (path == null) return; tree.scrollPathToVisible(path); @@ -313,7 +317,7 @@ public class BasicFrame extends JFrame { scroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scroll.setViewportView(new ComponentAddButtons(document, selectionModel, + scroll.setViewportView(new ComponentAddButtons(document, componentSelectionModel, scroll.getViewport())); scroll.setBorder(null); scroll.setViewportBorder(null); @@ -513,6 +517,8 @@ public class BasicFrame extends JFrame { menu.getAccessibleContext().setAccessibleDescription("Information about OpenRocket"); menubar.add(menu); + + item = new JMenuItem("License",KeyEvent.VK_L); item.getAccessibleContext().setAccessibleDescription("OpenRocket license information"); item.addActionListener(new ActionListener() { @@ -522,6 +528,16 @@ public class BasicFrame extends JFrame { }); menu.add(item); + item = new JMenuItem("Bug report",KeyEvent.VK_B); + item.getAccessibleContext().setAccessibleDescription("Information about reporting " + + "bugs in OpenRocket"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + new BugDialog(BasicFrame.this).setVisible(true); + } + }); + menu.add(item); + item = new JMenuItem("About",KeyEvent.VK_A); item.getAccessibleContext().setAccessibleDescription("About OpenRocket"); item.addActionListener(new ActionListener() { @@ -537,14 +553,13 @@ public class BasicFrame extends JFrame { - // TODO: HIGH: Remember last directory on open/save private void openAction() { JFileChooser chooser = new JFileChooser(); chooser.setFileFilter(ROCKET_DESIGN_FILTER); chooser.setMultiSelectionEnabled(true); chooser.setCurrentDirectory(Prefs.getDefaultDirectory()); - if (chooser.showOpenDialog(BasicFrame.this) != JFileChooser.APPROVE_OPTION) + if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; Prefs.setDefaultDirectory(chooser.getCurrentDirectory()); diff --git a/src/net/sf/openrocket/gui/main/ComponentAddButtons.java b/src/net/sf/openrocket/gui/main/ComponentAddButtons.java index 7d0308ca..0b7454e7 100644 --- a/src/net/sf/openrocket/gui/main/ComponentAddButtons.java +++ b/src/net/sf/openrocket/gui/main/ComponentAddButtons.java @@ -26,7 +26,7 @@ import javax.swing.tree.TreeSelectionModel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.gui.ResizeLabel; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.gui.configdialog.ComponentConfigDialog; import net.sf.openrocket.rocketcomponent.BodyComponent; import net.sf.openrocket.rocketcomponent.BodyTube; @@ -40,12 +40,14 @@ import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.Parachute; +import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.rocketcomponent.Streamer; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.rocketcomponent.TrapezoidFinSet; import net.sf.openrocket.rocketcomponent.TubeCoupler; +import net.sf.openrocket.util.Pair; import net.sf.openrocket.util.Prefs; /** @@ -94,20 +96,6 @@ public class ComponentAddButtons extends JPanel implements Scrollable { //////////////////////////////////////////// -// addButtonRow("Body components",row, -// new ComponentButton(NoseCone.class,"Nose cone") { -// @Override -// public boolean isAddable(RocketComponent c) { -// if (!(c instanceof ComponentAssembly)) -// return false; -// if (c.getSiblingCount() == 0) -// return true; -// return false; -// } -// }, -// new BodyComponentButton(BodyTube.class,"Body tube"), -// new BodyComponentButton(null,"Transition")); - addButtonRow("Body components and fin sets",row, new BodyComponentButton(NoseCone.class,"Nose cone"), @@ -120,7 +108,6 @@ public class ComponentAddButtons extends JPanel implements Scrollable { ); row++; -///// ///////////////////////////////////////////// @@ -328,16 +315,16 @@ public class ComponentAddButtons extends JPanel implements Scrollable { /** * Return the position to add the component if component c is selected currently. * The first element of the returned array is the RocketComponent to add the component - * to, and the second (in any) an Integer telling the position of the component. + * to, and the second (if non-null) an Integer telling the position of the component. * A return value of null means that the user cancelled addition of the component. - * If the array has only one element, the component is added at the end of the sibling + * If the Integer is null, the component is added at the end of the sibling * list. By default returns the end of the currently selected component. * * @param c The component currently selected * @return The position to add the new component to, or null if should not add. */ - public Object[] getAdditionPosition(RocketComponent c) { - return new Object[] { c }; + public Pair getAdditionPosition(RocketComponent c) { + return new Pair(c, null); } /** @@ -381,17 +368,15 @@ public class ComponentAddButtons extends JPanel implements Scrollable { TreePath p = selectionModel.getSelectionPath(); if (p!= null) c = (RocketComponent)p.getLastPathComponent(); - if (c != null) { - Object[] pos = getAdditionPosition(c); - if (pos==null || pos.length==0) { - // Cancel addition - return; - } - c = (RocketComponent)pos[0]; - if (pos.length>1) - position = (Integer)pos[1]; + Pair pos = getAdditionPosition(c); + if (pos==null) { + // Cancel addition + return; } + c = pos.getU(); + position = pos.getV(); + if (c == null) { // Should not occur @@ -460,17 +445,27 @@ public class ComponentAddButtons extends JPanel implements Scrollable { public boolean isAddable(RocketComponent c) { if (super.isAddable(c)) return true; - if (c instanceof BodyComponent) // Handled separately + // Handled separately: + if (c instanceof BodyComponent) + return true; + if (c == null || c instanceof Rocket) return true; return false; } @Override - public Object[] getAdditionPosition(RocketComponent c) { + public Pair getAdditionPosition(RocketComponent c) { if (super.isAddable(c)) // Handled automatically return super.getAdditionPosition(c); - // Handle BodyComponent separately + + if (c == null || c instanceof Rocket) { + // Add as last body component of the last stage + Rocket rocket = document.getRocket(); + return new Pair(rocket.getChild(rocket.getStageCount()-1), + null); + } + if (!(c instanceof BodyComponent)) return null; RocketComponent parent = c.getParent(); @@ -492,10 +487,10 @@ public class ComponentAddButtons extends JPanel implements Scrollable { return null; case 1: // Insert after current position - return new Object[] { parent, new Integer(parent.getChildPosition(c)+1) }; + return new Pair(parent, parent.getChildPosition(c)+1); case 2: // Insert at the end of the parent - return new Object[] { parent }; + return new Pair(parent, null); default: System.err.println("ERROR: Bad position type: "+pos); Thread.dumpStack(); diff --git a/src/net/sf/openrocket/gui/main/DocumentSelectionListener.java b/src/net/sf/openrocket/gui/main/DocumentSelectionListener.java new file mode 100644 index 00000000..055f1116 --- /dev/null +++ b/src/net/sf/openrocket/gui/main/DocumentSelectionListener.java @@ -0,0 +1,15 @@ +package net.sf.openrocket.gui.main; + +public interface DocumentSelectionListener { + + public static final int COMPONENT_SELECTION_CHANGE = 1; + public static final int SIMULATION_SELECTION_CHANGE = 2; + + /** + * Called when the selection changes. + * + * @param changeType a bitmask of the type of change. + */ + public void valueChanged(int changeType); + +} diff --git a/src/net/sf/openrocket/gui/main/DocumentSelectionModel.java b/src/net/sf/openrocket/gui/main/DocumentSelectionModel.java new file mode 100644 index 00000000..94bc39df --- /dev/null +++ b/src/net/sf/openrocket/gui/main/DocumentSelectionModel.java @@ -0,0 +1,189 @@ +package net.sf.openrocket.gui.main; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.rocketcomponent.RocketComponent; + +public class DocumentSelectionModel { + + private static final Simulation[] NO_SIMULATION = new Simulation[0]; + + private final ComponentTreeSelectionListener componentTreeSelectionListener = + new ComponentTreeSelectionListener(); + private final SimulationListSelectionListener simulationListSelectionListener = + new SimulationListSelectionListener(); + + + private final OpenRocketDocument document; + + private RocketComponent componentSelection = null; + private Simulation[] simulationSelection = NO_SIMULATION; + + private TreeSelectionModel componentTreeSelectionModel = null; + private ListSelectionModel simulationListSelectionModel = null; + + private final List listeners = + new ArrayList(); + + + + public DocumentSelectionModel(OpenRocketDocument document) { + this.document = document; + } + + + + + /** + * Return the currently selected simulations. Returns an empty array if none + * are selected. + * + * @return an array of the currently selected simulations, may be of zero length. + */ + public Simulation[] getSelectedSimulations() { + return Arrays.copyOf(simulationSelection, simulationSelection.length); + } + + /** + * Return the currently selected rocket component. Returns null + * if no rocket component is selected. + * + * @return the currently selected rocket component, or null. + */ + public RocketComponent getSelectedComponent() { + return componentSelection; + } + + + + + + public void attachComponentTreeSelectionModel(TreeSelectionModel model) { + if (componentTreeSelectionModel != null) + componentTreeSelectionModel.removeTreeSelectionListener( + componentTreeSelectionListener); + + componentTreeSelectionModel = model; + if (model != null) + model.addTreeSelectionListener(componentTreeSelectionListener); + clearComponentSelection(); + } + + + + public void attachSimulationListSelectionModel(ListSelectionModel model) { + if (simulationListSelectionModel != null) + simulationListSelectionModel.removeListSelectionListener( + simulationListSelectionListener); + + simulationListSelectionModel = model; + if (model != null) + model.addListSelectionListener(simulationListSelectionListener); + clearSimulationSelection(); + } + + + + public void clearSimulationSelection() { + if (simulationSelection.length == 0) + return; + + simulationSelection = NO_SIMULATION; + if (simulationListSelectionModel != null) + simulationListSelectionModel.clearSelection(); + + fireDocumentSelection(DocumentSelectionListener.SIMULATION_SELECTION_CHANGE); + } + + + public void clearComponentSelection() { + if (componentSelection == null) + return; + + componentSelection = null; + if (componentTreeSelectionModel != null) + componentTreeSelectionModel.clearSelection(); + + fireDocumentSelection(DocumentSelectionListener.COMPONENT_SELECTION_CHANGE); + } + + + + public void addDocumentSelectionListener(DocumentSelectionListener l) { + listeners.add(l); + } + + public void removeDocumentSelectionListener(DocumentSelectionListener l) { + listeners.remove(l); + } + + protected void fireDocumentSelection(int type) { + DocumentSelectionListener[] array = + listeners.toArray(new DocumentSelectionListener[0]); + + for (DocumentSelectionListener l: array) { + l.valueChanged(type); + } + } + + + + private class ComponentTreeSelectionListener implements TreeSelectionListener { + + @Override + public void valueChanged(TreeSelectionEvent e) { + TreePath path = componentTreeSelectionModel.getSelectionPath(); + if (path == null) { + componentSelection = null; + fireDocumentSelection(DocumentSelectionListener.COMPONENT_SELECTION_CHANGE); + return; + } + + componentSelection = (RocketComponent)path.getLastPathComponent(); + + clearSimulationSelection(); + fireDocumentSelection(DocumentSelectionListener.COMPONENT_SELECTION_CHANGE); + } + + } + + private class SimulationListSelectionListener implements ListSelectionListener { + + @Override + public void valueChanged(ListSelectionEvent e) { + int min = simulationListSelectionModel.getMinSelectionIndex(); + int max = simulationListSelectionModel.getMaxSelectionIndex(); + if (min < 0 || max < 0) { + simulationSelection = NO_SIMULATION; + fireDocumentSelection(DocumentSelectionListener.SIMULATION_SELECTION_CHANGE); + return; + } + + ArrayList list = new ArrayList(); + for (int i = min; i <= max; i++) { + if (simulationListSelectionModel.isSelectedIndex(i) && + (i < document.getSimulationCount())) { + list.add(document.getSimulation(i)); + } + } + simulationSelection = list.toArray(NO_SIMULATION); + + clearComponentSelection(); + fireDocumentSelection(DocumentSelectionListener.SIMULATION_SELECTION_CHANGE); + } + + } + +} diff --git a/src/net/sf/openrocket/gui/main/LicenseDialog.java b/src/net/sf/openrocket/gui/main/LicenseDialog.java index 77690b9d..6df25692 100644 --- a/src/net/sf/openrocket/gui/main/LicenseDialog.java +++ b/src/net/sf/openrocket/gui/main/LicenseDialog.java @@ -14,7 +14,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.ResizeLabel; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.util.GUIUtil; public class LicenseDialog extends JDialog { diff --git a/src/net/sf/openrocket/gui/main/MotorChooserDialog.java b/src/net/sf/openrocket/gui/main/MotorChooserDialog.java index c6e0f0f3..04a78979 100644 --- a/src/net/sf/openrocket/gui/main/MotorChooserDialog.java +++ b/src/net/sf/openrocket/gui/main/MotorChooserDialog.java @@ -32,7 +32,7 @@ import javax.swing.table.TableRowSorter; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.database.Databases; -import net.sf.openrocket.gui.ResizeLabel; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.rocketcomponent.Motor; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.GUIUtil; diff --git a/src/net/sf/openrocket/gui/main/OpenRocketClipboard.java b/src/net/sf/openrocket/gui/main/OpenRocketClipboard.java new file mode 100644 index 00000000..b50bffc8 --- /dev/null +++ b/src/net/sf/openrocket/gui/main/OpenRocketClipboard.java @@ -0,0 +1,35 @@ +package net.sf.openrocket.gui.main; + +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.rocketcomponent.RocketComponent; + +public class OpenRocketClipboard { + + private static Object clipboard = null; + + private OpenRocketClipboard() { + // Disallow instantiation + } + + + /** + * Return the RocketComponent contained in the clipboard, or + * null. + * + * @return the rocket component contained in the clipboard, or null + * if the clipboard does not currently contain a rocket component. + */ + public static RocketComponent getComponent() { + if (clipboard instanceof RocketComponent) { + return (RocketComponent) clipboard; + } + return null; + } + + + public static Simulation[] getSimulations() { + return null; // TODO + } + + +} diff --git a/src/net/sf/openrocket/gui/main/RocketActions.java b/src/net/sf/openrocket/gui/main/RocketActions.java index 05b31e4b..b0352283 100644 --- a/src/net/sf/openrocket/gui/main/RocketActions.java +++ b/src/net/sf/openrocket/gui/main/RocketActions.java @@ -28,7 +28,7 @@ import net.sf.openrocket.util.Pair; /** - * A class that holds Actions for common rocket operations such as + * A class that holds Actions for common rocket and simulation operations such as * cut/copy/paste/delete etc. * * @author Sampo Niskanen diff --git a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java index f9c1c4c6..5074d112 100644 --- a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java +++ b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java @@ -32,13 +32,13 @@ import javax.swing.event.DocumentListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.aerodynamics.ExtendedISAModel; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.DescriptionArea; import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.MotorConfigurationModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.DescriptionArea; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.plot.Axis; import net.sf.openrocket.gui.plot.PlotConfiguration; import net.sf.openrocket.gui.plot.PlotPanel; diff --git a/src/net/sf/openrocket/gui/main/SimulationPanel.java b/src/net/sf/openrocket/gui/main/SimulationPanel.java index bb3cd3aa..a4046fb8 100644 --- a/src/net/sf/openrocket/gui/main/SimulationPanel.java +++ b/src/net/sf/openrocket/gui/main/SimulationPanel.java @@ -25,9 +25,9 @@ import net.sf.openrocket.aerodynamics.Warning; import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.ResizeLabel; import net.sf.openrocket.gui.adaptors.Column; import net.sf.openrocket.gui.adaptors.ColumnTableModel; +import net.sf.openrocket.gui.components.ResizeLabel; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.ComponentChangeListener; import net.sf.openrocket.simulation.FlightData; diff --git a/src/net/sf/openrocket/gui/plot/PlotPanel.java b/src/net/sf/openrocket/gui/plot/PlotPanel.java index 953ab4a0..b049b2eb 100644 --- a/src/net/sf/openrocket/gui/plot/PlotPanel.java +++ b/src/net/sf/openrocket/gui/plot/PlotPanel.java @@ -16,8 +16,8 @@ import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.ResizeLabel; -import net.sf.openrocket.gui.UnitSelector; +import net.sf.openrocket.gui.components.ResizeLabel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.simulation.FlightDataBranch; import net.sf.openrocket.simulation.FlightDataBranch.Type; import net.sf.openrocket.unit.Unit; diff --git a/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 94bf1017..e40ba387 100644 --- a/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -37,11 +37,11 @@ import net.sf.openrocket.aerodynamics.FlightConditions; import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.BasicSlider; -import net.sf.openrocket.gui.StageSelector; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.MotorConfigurationModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.StageSelector; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.configdialog.ComponentConfigDialog; import net.sf.openrocket.gui.figureelements.CGCaret; import net.sf.openrocket.gui.figureelements.CPCaret; @@ -360,7 +360,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change * * Get the components clicked. * If no component is clicked, do nothing. - * If the primary currently selected component is in the set, keep it, + * If the currently selected component is in the set, keep it, * unless the selector specified is pressed. If it is pressed, cycle to * the next component. Otherwise select the first component in the list. */ @@ -399,7 +399,11 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change // Currently selected component not clicked if (path == null) { - path = ComponentTreeModel.makeTreePath(clicked[0]); + if (event.isShiftDown() && event.getClickCount()==1 && clicked.length>1) { + path = ComponentTreeModel.makeTreePath(clicked[1]); + } else { + path = ComponentTreeModel.makeTreePath(clicked[0]); + } } // Set selection and check for double-click diff --git a/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java b/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java index e1d08b6e..caa28515 100644 --- a/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java +++ b/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java @@ -23,8 +23,8 @@ import javax.swing.ScrollPaneConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import net.sf.openrocket.gui.UnitSelector; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.unit.Tick; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; diff --git a/src/net/sf/openrocket/startup/Startup.java b/src/net/sf/openrocket/startup/Startup.java new file mode 100644 index 00000000..a2120d21 --- /dev/null +++ b/src/net/sf/openrocket/startup/Startup.java @@ -0,0 +1,180 @@ +package net.sf.openrocket.startup; + +import java.awt.GraphicsEnvironment; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.swing.JOptionPane; + + +/** + * A startup class that checks that a suitable JRE environment is being run. + * If the environment is too old the execution is canceled, and if OpenJDK is being + * used warns the user of problems and confirms whether to continue. + *

+ * Note: This class must be Java 1.4 compatible and calls the next class using + * only reflection. + * + * @author Sampo Niskanen + */ +public class Startup { + + public static final String START_CLASS = "net.sf.openrocket.gui.main.BasicFrame"; + + public static final int REQUIRED_MAJOR_VERSION = 1; + public static final int REQUIRED_MINOR_VERSION = 6; + + + public static void main(String[] args) { + + checkVersion(); + checkHead(); + checkOpenJDK(); + + // Load and execute START_CLASS + try { + + Class cls = Class.forName(START_CLASS); + Method m = cls.getMethod("main", String[].class); + m.invoke(null, new Object[] { args }); + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + error("Error starting main class!", "Please report a bug."); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + error("Error starting main class!", "Please report a bug."); + } catch (InvocationTargetException e) { + e.printStackTrace(); + error("Error starting main class!", "Please report a bug."); + } catch (IllegalAccessException e) { + e.printStackTrace(); + error("Error starting main class!", "Please report a bug."); + } + + } + + + /** + * Check that the JRE version is high enough. + */ + private static void checkVersion() { + String[] version = System.getProperty("java.specification.version", "").split("\\."); + + String jreName = System.getProperty("java.vm.name", "(unknown)"); + String jreVersion = System.getProperty("java.runtime.version", "(unknown)"); + String jreVendor = System.getProperty("java.vendor", "(unknown)"); + + int major, minor; + + try { + major = Integer.parseInt(version[0]); + minor = Integer.parseInt(version[1]); + + if (major < REQUIRED_MAJOR_VERSION || + (major == REQUIRED_MAJOR_VERSION && minor < REQUIRED_MINOR_VERSION)) { + error("Java SE version 6 is required to run OpenRocket.", + "You are currently running " + jreName + " version " + + jreVersion + " by " + jreVendor); + } + + } catch (RuntimeException e) { + + confirm("The Java version in use could not be detected.", + "OpenRocket requires at least Java SE 6.", + "Continue anyway?"); + + } + + } + + + /** + * Check that the JRE is not running headless. + */ + private static void checkHead() { + + if (GraphicsEnvironment.isHeadless()) { + System.err.println(); + System.err.println("OpenRocket cannot currently be run without the graphical " + + "user interface."); + System.err.println(); + System.exit(1); + } + + } + + + /** + * Check whether OpenJDK is being used, and if it is warn the user about + * problems and confirm whether to continue. + */ + private static void checkOpenJDK() { + + if (System.getProperty("java.runtime.name", "").toLowerCase().indexOf("icedtea")>=0 || + System.getProperty("java.vm.name", "").toLowerCase().indexOf("openjdk")>=0) { + + String jreName = System.getProperty("java.vm.name", "(unknown)"); + String jreVersion = System.getProperty("java.runtime.version", "(unknown)"); + String jreVendor = System.getProperty("java.vendor", "(unknown)"); + + confirm("OpenJDK is known to have problems running OpenRocket.", + " ", + "You are currently running " + jreName + " version " + + jreVersion + " by " + jreVendor, + "Do you want to continue?"); + + } + } + + + + + /** + * Presents an error message to the user and exits the application. + * + * @param message an array of messages to present. + */ + private static void error(String ... message) { + + System.err.println(); + System.err.println("Error starting OpenRocket:"); + System.err.println(); + for (int i=0; i < message.length; i++) { + System.err.println(message[i]); + } + System.err.println(); + + + if (!GraphicsEnvironment.isHeadless()) { + + JOptionPane.showMessageDialog(null, message, "Error starting OpenRocket", + JOptionPane.ERROR_MESSAGE); + + } + + System.exit(1); + } + + + /** + * Presents the user with a message dialog and asks whether to continue. + * If the user does not select "Yes" the the application exits. + * + * @param message the message Strings to show. + */ + private static void confirm(String ... message) { + + if (!GraphicsEnvironment.isHeadless()) { + + if (JOptionPane.showConfirmDialog(null, message, "Error starting OpenRocket", + JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { + System.exit(1); + } + + } + + } + + +} diff --git a/src/net/sf/openrocket/unit/FixedPrecisionUnit.java b/src/net/sf/openrocket/unit/FixedPrecisionUnit.java index 2946dc70..c175d4ef 100644 --- a/src/net/sf/openrocket/unit/FixedPrecisionUnit.java +++ b/src/net/sf/openrocket/unit/FixedPrecisionUnit.java @@ -47,7 +47,7 @@ public class FixedPrecisionUnit extends Unit { @Override public String toString(double value) { - return String.format(formatString, value); + return String.format(formatString, this.toUnit(value)); } diff --git a/src/net/sf/openrocket/util/JarUtil.java b/src/net/sf/openrocket/util/JarUtil.java new file mode 100644 index 00000000..7e45a653 --- /dev/null +++ b/src/net/sf/openrocket/util/JarUtil.java @@ -0,0 +1,50 @@ +package net.sf.openrocket.util; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.CodeSource; + +import net.sf.openrocket.database.Database; + +public class JarUtil { + + /** + * Return the a File object pointing to the JAR file that this class belongs to, + * or null if it cannot be found. + * + * @return a File object of the current Java archive, or null + */ + public static File getCurrentJarFile() { + // Find the jar file this class is contained in + URL jarUrl = null; + CodeSource codeSource = Database.class.getProtectionDomain().getCodeSource(); + if (codeSource != null) + jarUrl = codeSource.getLocation(); + + if (jarUrl == null) { + return null; + } + return urlToFile(jarUrl); + } + + + + public static File urlToFile(URL url) { + URI uri; + try { + uri = url.toURI(); + } catch (URISyntaxException e) { + try { + uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), + url.getPort(), url.getPath(), url.getQuery(), url.getRef()); + } catch (URISyntaxException e1) { + throw new IllegalArgumentException("Broken URL: " + url); + } + } + return new File(uri); + } + + +} diff --git a/src/net/sf/openrocket/util/PrintProperties.java b/src/net/sf/openrocket/util/PrintProperties.java new file mode 100644 index 00000000..d3d4fe11 --- /dev/null +++ b/src/net/sf/openrocket/util/PrintProperties.java @@ -0,0 +1,22 @@ +package net.sf.openrocket.util; + +import java.util.SortedSet; +import java.util.TreeSet; + +public class PrintProperties { + + public static void main(String[] args) { + + // Sort the keys + SortedSet keys = new TreeSet(); + for (Object key: System.getProperties().keySet()) { + keys.add((String)key); + } + + for (String key: keys) { + System.out.println(key + "=" + System.getProperty((String)key)); + } + + } + +} -- 2.30.2