From: plaa Date: Sat, 10 Oct 2009 13:13:32 +0000 (+0000) Subject: updates for 0.9.4 X-Git-Tag: upstream/1.0.0~14 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=566a2343c3dfd28e4275d5c17b779a92e8d13f78;p=debian%2Fopenrocket updates for 0.9.4 git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@27 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/.classpath b/.classpath index fdfb5235..a98ed5b2 100644 --- a/.classpath +++ b/.classpath @@ -7,10 +7,6 @@ - - - - diff --git a/ChangeLog b/ChangeLog index 99ac81b1..91949f53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-10 Sampo Niskanen + + * Removed non-ASCII characters from source code files + * Created Chars class for non-ASCII characters + * Added styrofoam materials + 2009-10-04 Sampo Niskanen * [BUG] Fixed too high configuration dialogs diff --git a/TODO b/TODO index 9bca110f..9fff6762 100644 --- a/TODO +++ b/TODO @@ -10,18 +10,17 @@ Must-have: Bugs: -- Simulation plot dialog forces dialog one button row too high (All/None) - Unit tests fail from ant script Maybe: -- Windows executable wrapper (launch4j) - Inform user about software updates Postponed: +- Windows executable wrapper (launch4j) - Allow only one instance of OpenRocket running (RMI communication) - Only schedule rocket figure update instead of each time updating it - Reading (writing) .RKT format @@ -79,4 +78,5 @@ In 0.9.4: - JTree text is cropped unnecessarily - Allow editing user-defined materials - [BUG] All configuration dialogs too high +- Simulation plot dialog forces dialog one button row too high (All/None) diff --git a/build.xml b/build.xml index b77dd04f..94676a62 100644 --- a/build.xml +++ b/build.xml @@ -90,7 +90,7 @@ - + @@ -115,7 +115,7 @@ - + @@ -126,6 +126,9 @@ + + + @@ -134,6 +137,9 @@ + + + @@ -148,6 +154,31 @@ ${criticaltodos} + + + + Checking project for non-ASCII characters. + + + + + + + + + + + + + + + + Non-ASCII characters exist in project: +${nonascii} + No non-ASCII characters in project. + + + Building unit tests @@ -156,7 +187,7 @@ ${criticaltodos} Running unit tests - + @@ -164,6 +195,7 @@ ${criticaltodos} + @@ -173,7 +205,10 @@ ${criticaltodos} - + + + Unit tests passed successfully. + \ No newline at end of file diff --git a/lib-test/hamcrest-core-1.1.jar b/lib-test/hamcrest-core-1.1.jar deleted file mode 100644 index 5f1d5ce0..00000000 Binary files a/lib-test/hamcrest-core-1.1.jar and /dev/null differ diff --git a/lib-test/hamcrest-library-1.1.jar b/lib-test/hamcrest-library-1.1.jar deleted file mode 100644 index 40610c9b..00000000 Binary files a/lib-test/hamcrest-library-1.1.jar and /dev/null differ diff --git a/lib-test/jmock-2.5.1.jar b/lib-test/jmock-2.5.1.jar deleted file mode 100644 index 4415dfbc..00000000 Binary files a/lib-test/jmock-2.5.1.jar and /dev/null differ diff --git a/lib-test/jmock-junit4-2.5.1.jar b/lib-test/jmock-junit4-2.5.1.jar deleted file mode 100644 index fb3697af..00000000 Binary files a/lib-test/jmock-junit4-2.5.1.jar and /dev/null differ diff --git a/src/net/sf/openrocket/database/Databases.java b/src/net/sf/openrocket/database/Databases.java index 9ec9f589..d5d7f465 100644 --- a/src/net/sf/openrocket/database/Databases.java +++ b/src/net/sf/openrocket/database/Databases.java @@ -79,7 +79,7 @@ public class Databases { BULK_MATERIAL.add(new Material.Bulk("Cardboard", 680, false)); BULK_MATERIAL.add(new Material.Bulk("Carbon fiber", 1780, false)); BULK_MATERIAL.add(new Material.Bulk("Cork", 240, false)); - BULK_MATERIAL.add(new Material.Bulk("Depron", 40, false)); + BULK_MATERIAL.add(new Material.Bulk("Depron (XPS)", 40, false)); BULK_MATERIAL.add(new Material.Bulk("Fiberglass", 1850, false)); BULK_MATERIAL.add(new Material.Bulk("Kraft phenolic",950, false)); BULK_MATERIAL.add(new Material.Bulk("Maple", 755, false)); @@ -90,7 +90,8 @@ public class Databases { BULK_MATERIAL.add(new Material.Bulk("Polystyrene", 1050, false)); BULK_MATERIAL.add(new Material.Bulk("PVC", 1390, false)); BULK_MATERIAL.add(new Material.Bulk("Spruce", 450, false)); - // TODO: CRITICAL: Add styrofoam + BULK_MATERIAL.add(new Material.Bulk("Styrofoam generic (EPS)", 20, false)); + BULK_MATERIAL.add(new Material.Bulk("Styrofoam / Blue Foam (XPS)", 32, false)); BULK_MATERIAL.add(new Material.Bulk("Quantum tubing",1050, false)); SURFACE_MATERIAL.add(new Material.Surface("Ripstop nylon", 0.067, false)); diff --git a/src/net/sf/openrocket/gui/components/DescriptionArea.java b/src/net/sf/openrocket/gui/components/DescriptionArea.java index ac26ae83..d3d568b2 100644 --- a/src/net/sf/openrocket/gui/components/DescriptionArea.java +++ b/src/net/sf/openrocket/gui/components/DescriptionArea.java @@ -13,11 +13,15 @@ public class DescriptionArea extends JScrollPane { private final JEditorPane editorPane; + public DescriptionArea(int rows) { - this(rows, -1); + this("", rows, -1); } - public DescriptionArea(int rows, float size) { + this("", rows, size); + } + + public DescriptionArea(String text, int rows, float size) { super(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -41,6 +45,7 @@ public class DescriptionArea extends JScrollPane { this.setPreferredSize(dim); this.setViewportView(editorPane); + this.setText(text); } public void setText(String txt) { diff --git a/src/net/sf/openrocket/gui/dialogs/AboutDialog.java b/src/net/sf/openrocket/gui/dialogs/AboutDialog.java index 41014f49..73d12576 100644 --- a/src/net/sf/openrocket/gui/dialogs/AboutDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/AboutDialog.java @@ -12,6 +12,7 @@ import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.URLLabel; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.GUIUtil; import net.sf.openrocket.util.Icons; import net.sf.openrocket.util.Prefs; @@ -42,7 +43,7 @@ public class AboutDialog extends JDialog { panel.add(new StyledLabel(" ", -1), "ax 50%, growy, wrap para"); } - panel.add(new StyledLabel("Copyright \u00A9 2007-2009 Sampo Niskanen"), + panel.add(new StyledLabel("Copyright " + Chars.COPY +" 2007-2009 Sampo Niskanen"), "ax 50%, growy, wrap para"); panel.add(new URLLabel(OPENROCKET_URL), "ax 50%, growy, wrap para"); diff --git a/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java b/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java index cd7d9c98..6ff42883 100644 --- a/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java @@ -1,6 +1,7 @@ package net.sf.openrocket.gui.dialogs; import static net.sf.openrocket.unit.Unit.NOUNIT2; +import static net.sf.openrocket.util.Chars.ALPHA; import java.awt.Color; import java.awt.Component; @@ -45,8 +46,8 @@ 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.StyledLabel; import net.sf.openrocket.gui.components.StageSelector; +import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.rocketcomponent.Configuration; @@ -203,7 +204,7 @@ public class ComponentAnalysisDialog extends JDialog implements ChangeListener { return unit.toString(cpData.get(row).cp.x); } }, - new Column("CN\u03b1") { + new Column("CN"+ALPHA+"") { @Override public Object getValueAt(int row) { return NOUNIT2.toString(cpData.get(row).cp.weight); } diff --git a/src/net/sf/openrocket/gui/dialogs/EditMotorConfigurationDialog.java b/src/net/sf/openrocket/gui/dialogs/EditMotorConfigurationDialog.java index 550dee56..44eba2e6 100644 --- a/src/net/sf/openrocket/gui/dialogs/EditMotorConfigurationDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/EditMotorConfigurationDialog.java @@ -31,6 +31,7 @@ import net.sf.openrocket.motor.Motor; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.GUIUtil; public class EditMotorConfigurationDialog extends JDialog { @@ -466,7 +467,7 @@ public class EditMotorConfigurationDialog extends JDialog { String str = motor.getDesignation(mount.getMotorDelay(id)); int count = mount.getMotorCount(); if (count > 1) { - str = "" + count + "\u00d7 " + str; + str = "" + count + Chars.TIMES + " " + str; } return str; } @@ -482,15 +483,11 @@ public class EditMotorConfigurationDialog extends JDialog { String name = mount.toString(); int count = mount.getMotorCount(); if (count > 1) { - name = name + " (\u00d7" + count + ")"; + name = name + " (" + Chars.TIMES + count + ")"; } return name; } - } - - - } diff --git a/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java b/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java index 518403c9..f288004f 100644 --- a/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java @@ -14,6 +14,7 @@ import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.communication.UpdateInfo; import net.sf.openrocket.gui.components.URLLabel; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.ComparablePair; import net.sf.openrocket.util.GUIUtil; import net.sf.openrocket.util.Icons; @@ -45,7 +46,8 @@ public class UpdateInfoDialog extends JDialog { if (count >= 4 && n != updates.get(i).getU()) break; n = updates.get(i).getU(); - panel.add(new JLabel(" \u2022 " + updates.get(i).getV()), "wrap 0px"); + panel.add(new JLabel(" " + Chars.BULLET + " " + updates.get(i).getV()), + "wrap 0px"); count++; } } diff --git a/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java b/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java index 38cc36fe..e5f38260 100644 --- a/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java +++ b/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java @@ -12,14 +12,21 @@ import java.util.List; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JProgressBar; import javax.swing.JTabbedPane; +import javax.swing.Timer; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.communication.UpdateInfo; +import net.sf.openrocket.communication.UpdateInfoRetriever; import net.sf.openrocket.gui.components.StyledLabel; +import net.sf.openrocket.gui.dialogs.UpdateInfoDialog; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.GUIUtil; @@ -40,7 +47,7 @@ public class PreferencesDialog extends JDialog { tabbedPane.addTab("Units", null, unitsPane(), "Default units"); tabbedPane.addTab("Materials", null, new MaterialEditPanel(), "Custom materials"); - tabbedPane.addTab("Confirmation", null, confirmationPane(), "Confirmation dialog settings"); + tabbedPane.addTab("Options", null, optionsPane(), "Miscellaneous options"); JButton close = new JButton("Close"); @@ -68,16 +75,39 @@ public class PreferencesDialog extends JDialog { } - private JPanel confirmationPane() { - JPanel panel = new JPanel(new MigLayout("fill")); + private JPanel optionsPane() { + JPanel panel = new JPanel(new MigLayout("fillx, ins 30lp n n n")); - panel.add(new JLabel("Position to insert new body components:")); + + panel.add(new JLabel("Position to insert new body components:"), "gapright para"); panel.add(new JComboBox(new PrefChoiseSelector(Prefs.BODY_COMPONENT_INSERT_POSITION_KEY, - "Always ask", "Insert in middle", "Add to end")), "wrap para, sg combos"); + "Always ask", "Insert in middle", "Add to end")), "wrap para, growx, sg combos"); panel.add(new JLabel("Confirm deletion of simulations:")); panel.add(new JComboBox(new PrefBooleanSelector(Prefs.CONFIRM_DELETE_SIMULATION, - "Delete", "Confirm", true)), "wrap para, sg combos"); + "Delete", "Confirm", true)), "wrap 40lp, growx, sg combos"); + + + final JCheckBox softwareUpdateBox = new JCheckBox("Check for software updates"); + softwareUpdateBox.setSelected(Prefs.getCheckUpdates()); + softwareUpdateBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Prefs.setCheckUpdates(softwareUpdateBox.isSelected()); + } + }); + panel.add(softwareUpdateBox); + + JButton button = new JButton("Check now"); + button.setToolTipText("Check for software updates now"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkForUpdates(); + } + }); + panel.add(button, "right, wrap"); + return panel; } @@ -350,6 +380,73 @@ public class PreferencesDialog extends JDialog { } + private void checkForUpdates() { + final UpdateInfoRetriever retriever = new UpdateInfoRetriever(); + retriever.start(); + + + // Progress dialog + final JDialog dialog = new JDialog(this, ModalityType.APPLICATION_MODAL); + JPanel panel = new JPanel(new MigLayout()); + + panel.add(new JLabel("Checking for updates..."), "wrap"); + + JProgressBar bar = new JProgressBar(); + bar.setIndeterminate(true); + panel.add(bar, "growx, wrap para"); + + JButton cancel = new JButton("Cancel"); + cancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + }); + panel.add(cancel, "right"); + dialog.add(panel); + + GUIUtil.setDisposableDialogOptions(dialog, cancel); + + + // Timer to monitor progress + final Timer timer = new Timer(100, null); + final long startTime = System.currentTimeMillis(); + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!retriever.isRunning() || startTime+10000 < System.currentTimeMillis()) { + timer.stop(); + dialog.dispose(); + } + } + }; + timer.addActionListener(listener); + timer.start(); + + + // Wait for action + dialog.setVisible(true); + + + // Check result + UpdateInfo info = retriever.getUpdateInfo(); + if (info == null) { + JOptionPane.showMessageDialog(this, + "An error occurred while communicating with the server.", + "Unable to retrieve update information", JOptionPane.WARNING_MESSAGE, null); + } else if (info.getLatestVersion() == null || + info.getLatestVersion().equals("") || + Prefs.getVersion().equalsIgnoreCase(info.getLatestVersion())) { + JOptionPane.showMessageDialog(this, + "You are running the latest version of OpenRocket.", + "No updates available", JOptionPane.INFORMATION_MESSAGE, null); + } else { + new UpdateInfoDialog(info).setVisible(true); + } + + } + //////// Singleton implementation //////// diff --git a/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index a70e8731..f573e182 100644 --- a/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -1,5 +1,7 @@ package net.sf.openrocket.gui.figureelements; +import static net.sf.openrocket.util.Chars.*; + import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; @@ -16,7 +18,6 @@ import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Prefs; - /** * A FigureElement that draws text at different positions in the figure * with general data about the rocket. @@ -166,10 +167,10 @@ public class RocketInfo implements FigureElement { at = "at M="+UnitGroup.UNITS_COEFFICIENT.getDefaultUnit().toStringUnit(mach); if (!Double.isNaN(aoa)) { - at += " \u03b1=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa); + at += " "+ALPHA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa); } if (!Double.isNaN(theta)) { - at += " \u0398=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta); + at += " "+THETA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta); } GlyphVector cgValue = createText( diff --git a/src/net/sf/openrocket/gui/main/BasicFrame.java b/src/net/sf/openrocket/gui/main/BasicFrame.java index fcf74ca2..f7777a00 100644 --- a/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -1248,9 +1248,15 @@ public class BasicFrame extends JFrame { public void actionPerformed(ActionEvent e) { if (!updateInfo.isRunning()) { timer.stop(); + + String current = Prefs.getVersion(); + String last = Prefs.getString(Prefs.LAST_UPDATE, ""); UpdateInfo info = updateInfo.getUpdateInfo(); - if (info != null && !Prefs.getVersion().equals(info.getLatestVersion())) { + if (info != null && info.getLatestVersion() != null && + !current.equals(info.getLatestVersion()) && + !last.equals(info.getLatestVersion())) { + Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion()); new UpdateInfoDialog(info).setVisible(true); } } diff --git a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java index 81234d3e..2b3829d7 100644 --- a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java +++ b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java @@ -42,7 +42,7 @@ import net.sf.openrocket.gui.components.SimulationExportPanel; 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; +import net.sf.openrocket.gui.plot.SimulationPlotPanel; import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.simulation.FlightData; import net.sf.openrocket.simulation.FlightDataBranch; @@ -52,6 +52,7 @@ import net.sf.openrocket.simulation.SimulationListener; import net.sf.openrocket.simulation.listeners.CSVSaveListener; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.GUIUtil; import net.sf.openrocket.util.Icons; import net.sf.openrocket.util.Prefs; @@ -393,7 +394,7 @@ public class SimulationEditDialog extends JDialog { spin.setToolTipText(tip); sub.add(spin,"w 65lp!"); - label = new JLabel("\u00b0 N"); + label = new JLabel(Chars.DEGREE + " N"); label.setToolTipText(tip); sub.add(label,"growx"); slider = new BasicSlider(m.getSliderModel(-90, 90)); @@ -745,7 +746,7 @@ public class SimulationEditDialog extends JDialog { if (true) - return new PlotPanel(simulation); + return new SimulationPlotPanel(simulation); JPanel panel = new JPanel(new MigLayout("fill")); diff --git a/src/net/sf/openrocket/gui/plot/PlotPanel.java b/src/net/sf/openrocket/gui/plot/PlotPanel.java deleted file mode 100644 index a2cbea7c..00000000 --- a/src/net/sf/openrocket/gui/plot/PlotPanel.java +++ /dev/null @@ -1,484 +0,0 @@ -package net.sf.openrocket.gui.plot; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.Arrays; -import java.util.EnumSet; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; - -import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.components.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; -import net.sf.openrocket.simulation.FlightDataBranch; -import net.sf.openrocket.simulation.FlightEvent; -import net.sf.openrocket.simulation.FlightDataBranch.Type; -import net.sf.openrocket.unit.Unit; -import net.sf.openrocket.util.GUIUtil; -import net.sf.openrocket.util.Icons; -import net.sf.openrocket.util.Pair; - -public class PlotPanel extends JPanel { - - // TODO: LOW: Should these be somewhere else? - public static final int AUTO = -1; - public static final int LEFT = 0; - public static final int RIGHT = 1; - - public static final String AUTO_NAME = "Auto"; - public static final String LEFT_NAME = "Left"; - public static final String RIGHT_NAME = "Right"; - - private static final String CUSTOM = "Custom"; - - /** The "Custom" configuration - not to be used for anything other than the title. */ - private static final PlotConfiguration CUSTOM_CONFIGURATION; - static { - CUSTOM_CONFIGURATION = new PlotConfiguration(CUSTOM); - } - - /** The array of presets for the combo box. */ - private static final PlotConfiguration[] PRESET_ARRAY; - static { - PRESET_ARRAY = Arrays.copyOf(PlotConfiguration.DEFAULT_CONFIGURATIONS, - PlotConfiguration.DEFAULT_CONFIGURATIONS.length + 1); - PRESET_ARRAY[PRESET_ARRAY.length-1] = CUSTOM_CONFIGURATION; - } - - - - /** The current default configuration, set each time a plot is made. */ - private static PlotConfiguration defaultConfiguration = - PlotConfiguration.DEFAULT_CONFIGURATIONS[0].resetUnits(); - - - private final Simulation simulation; - private final FlightDataBranch.Type[] types; - private PlotConfiguration configuration; - - - private JComboBox configurationSelector; - - private JComboBox domainTypeSelector; - private UnitSelector domainUnitSelector; - - private JPanel typeSelectorPanel; - private FlightEventTableModel eventTableModel; - - - private int modifying = 0; - - - public PlotPanel(final Simulation simulation) { - super(new MigLayout("fill")); - - this.simulation = simulation; - if (simulation.getSimulatedData() == null || - simulation.getSimulatedData().getBranchCount()==0) { - throw new IllegalArgumentException("Simulation contains no data."); - } - FlightDataBranch branch = simulation.getSimulatedData().getBranch(0); - types = branch.getTypes(); - - // TODO: LOW: Revert to custom if data type is not available. - configuration = defaultConfiguration.clone(); - - - //// Configuration selector - - // Setup the combo box - configurationSelector = new JComboBox(PRESET_ARRAY); - for (PlotConfiguration config: PRESET_ARRAY) { - if (config.getName().equals(configuration.getName())) { - configurationSelector.setSelectedItem(config); - } - } - configurationSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - PlotConfiguration conf = (PlotConfiguration)configurationSelector.getSelectedItem(); - if (conf == CUSTOM_CONFIGURATION) - return; - modifying++; - configuration = conf.clone().resetUnits(); - updatePlots(); - modifying--; - } - }); - this.add(new JLabel("Preset plot configurations: "), "spanx, split"); - this.add(configurationSelector,"growx, wrap 30lp"); - - - - //// X axis - - - this.add(new JLabel("X axis type:"), "spanx, split"); - domainTypeSelector = new JComboBox(types); - domainTypeSelector.setSelectedItem(configuration.getDomainAxisType()); - domainTypeSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - FlightDataBranch.Type type = (Type) domainTypeSelector.getSelectedItem(); - configuration.setDomainAxisType(type); - domainUnitSelector.setUnitGroup(type.getUnitGroup()); - domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); - setToCustom(); - } - }); - this.add(domainTypeSelector, "gapright para"); - - - this.add(new JLabel("Unit:")); - domainUnitSelector = new UnitSelector(configuration.getDomainAxisType().getUnitGroup()); - domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); - domainUnitSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - configuration.setDomainAxisUnit(domainUnitSelector.getSelectedUnit()); - } - }); - this.add(domainUnitSelector, "width 40lp, gapright para"); - - - StyledLabel desc = new StyledLabel("

The data will be plotted in time order " + - "even if the X axis type is not time.", -2); - this.add(desc, "width :0px:, growx, wrap para"); - - - - //// Y axis selector panel - - this.add(new JLabel("Y axis types:")); - - this.add(new JLabel("Flight events:"), "wrap rel"); - - typeSelectorPanel = new JPanel(new MigLayout("gapy rel")); - JScrollPane scroll = new JScrollPane(typeSelectorPanel); - this.add(scroll, "spany 2, height 10px, grow 100, gapright para"); - - - //// Flight events - eventTableModel = new FlightEventTableModel(); - JTable table = new JTable(eventTableModel); - table.setTableHeader(null); - table.setShowVerticalLines(false); - table.setRowSelectionAllowed(false); - table.setColumnSelectionAllowed(false); - - TableColumnModel columnModel = table.getColumnModel(); - TableColumn col0 = columnModel.getColumn(0); - int w = table.getRowHeight() + 2; - col0.setMinWidth(w); - col0.setPreferredWidth(w); - col0.setMaxWidth(w); - table.addMouseListener(new GUIUtil.BooleanTableClickListener(table)); - this.add(new JScrollPane(table), "height 1px, width 200lp, grow 1, wrap rel"); - - - //// All + None buttons - JButton button = new JButton("All"); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - for (FlightEvent.Type t: FlightEvent.Type.values()) - configuration.setEvent(t, true); - eventTableModel.fireTableDataChanged(); - } - }); - this.add(button, "split 2, gapleft para, gapright para, growx, sizegroup buttons"); - - button = new JButton("None"); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - for (FlightEvent.Type t: FlightEvent.Type.values()) - configuration.setEvent(t, false); - eventTableModel.fireTableDataChanged(); - } - }); - this.add(button, "gapleft para, gapright para, growx, sizegroup buttons, wrap para"); - - - - - button = new JButton("New Y axis plot type"); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (configuration.getTypeCount() >= 15) { - JOptionPane.showMessageDialog(PlotPanel.this, - "A maximum of 15 plots is allowed.", "Cannot add plot", - JOptionPane.ERROR_MESSAGE); - return; - } - - // Select new type smartly - FlightDataBranch.Type type = null; - for (FlightDataBranch.Type t: - simulation.getSimulatedData().getBranch(0).getTypes()) { - - boolean used = false; - if (configuration.getDomainAxisType().equals(t)) { - used = true; - } else { - for (int i=0; i < configuration.getTypeCount(); i++) { - if (configuration.getType(i).equals(t)) { - used = true; - break; - } - } - } - - if (!used) { - type = t; - break; - } - } - if (type == null) { - type = simulation.getSimulatedData().getBranch(0).getTypes()[0]; - } - - // Add new type - configuration.addPlotDataType(type); - setToCustom(); - updatePlots(); - } - }); - this.add(button, "spanx, split"); - - - this.add(new JPanel(), "growx"); - - button = new JButton("Plot flight"); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - defaultConfiguration = configuration.clone(); - PlotDialog.showPlot(SwingUtilities.getWindowAncestor(PlotPanel.this), - simulation, configuration); - } - }); - this.add(button, "right"); - - - updatePlots(); - } - - - private void setToCustom() { - modifying++; - configuration.setName(CUSTOM); - configurationSelector.setSelectedItem(CUSTOM_CONFIGURATION); - modifying--; - } - - - private void updatePlots() { - domainTypeSelector.setSelectedItem(configuration.getDomainAxisType()); - domainUnitSelector.setUnitGroup(configuration.getDomainAxisType().getUnitGroup()); - domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); - - typeSelectorPanel.removeAll(); - for (int i=0; i < configuration.getTypeCount(); i++) { - FlightDataBranch.Type type = configuration.getType(i); - Unit unit = configuration.getUnit(i); - int axis = configuration.getAxis(i); - - typeSelectorPanel.add(new PlotTypeSelector(i, type, unit, axis), "wrap"); - } - - typeSelectorPanel.repaint(); - - eventTableModel.fireTableDataChanged(); - } - - - - - /** - * A JPanel which configures a single plot of a PlotConfiguration. - */ - private class PlotTypeSelector extends JPanel { - private final String[] POSITIONS = { AUTO_NAME, LEFT_NAME, RIGHT_NAME }; - - private final int index; - private JComboBox typeSelector; - private UnitSelector unitSelector; - private JComboBox axisSelector; - - - public PlotTypeSelector(int index, FlightDataBranch.Type type) { - this (index, type, null, -1); - } - - public PlotTypeSelector(int plotIndex, FlightDataBranch.Type type, Unit unit, int position) { - super(new MigLayout("ins 0")); - - this.index = plotIndex; - - typeSelector = new JComboBox(types); - typeSelector.setSelectedItem(type); - typeSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - FlightDataBranch.Type type = (Type) typeSelector.getSelectedItem(); - configuration.setPlotDataType(index, type); - unitSelector.setUnitGroup(type.getUnitGroup()); - unitSelector.setSelectedUnit(configuration.getUnit(index)); - setToCustom(); - } - }); - this.add(typeSelector, "gapright para"); - - this.add(new JLabel("Unit:")); - unitSelector = new UnitSelector(type.getUnitGroup()); - if (unit != null) - unitSelector.setSelectedUnit(unit); - unitSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - Unit unit = (Unit) unitSelector.getSelectedUnit(); - configuration.setPlotDataUnit(index, unit); - } - }); - this.add(unitSelector, "width 40lp, gapright para"); - - this.add(new JLabel("Axis:")); - axisSelector = new JComboBox(POSITIONS); - if (position == LEFT) - axisSelector.setSelectedIndex(1); - else if (position == RIGHT) - axisSelector.setSelectedIndex(2); - else - axisSelector.setSelectedIndex(0); - axisSelector.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (modifying > 0) - return; - int axis = axisSelector.getSelectedIndex() - 1; - configuration.setPlotDataAxis(index, axis); - } - }); - this.add(axisSelector); - - - JButton button = new JButton(Icons.DELETE); - button.setToolTipText("Remove this plot"); - button.setBorderPainted(false); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - configuration.removePlotDataType(index); - setToCustom(); - updatePlots(); - } - }); - this.add(button, "gapright 0"); - } - } - - - - private class FlightEventTableModel extends AbstractTableModel { - private final FlightEvent.Type[] eventTypes; - - public FlightEventTableModel() { - EnumSet set = EnumSet.noneOf(FlightEvent.Type.class); - for (int i=0; i < simulation.getSimulatedData().getBranchCount(); i++) { - for (Pair e: - simulation.getSimulatedData().getBranch(i).getEvents()) { - set.add(e.getV().getType()); - } - } - set.remove(FlightEvent.Type.ALTITUDE); - int count = set.size(); - - eventTypes = new FlightEvent.Type[count]; - int pos = 0; - for (FlightEvent.Type t: FlightEvent.Type.values()) { - if (set.contains(t)) { - eventTypes[pos] = t; - pos++; - } - } - } - - @Override - public int getColumnCount() { - return 2; - } - - @Override - public int getRowCount() { - return eventTypes.length; - } - - @Override - public Class getColumnClass(int column) { - switch (column) { - case 0: - return Boolean.class; - - case 1: - return String.class; - - default: - throw new IndexOutOfBoundsException("column="+column); - } - } - - @Override - public Object getValueAt(int row, int column) { - switch (column) { - case 0: - return new Boolean(configuration.isEventActive(eventTypes[row])); - - case 1: - return eventTypes[row].toString(); - - default: - throw new IndexOutOfBoundsException("column="+column); - } - } - - @Override - public boolean isCellEditable(int row, int column) { - return column == 0; - } - - @Override - public void setValueAt(Object value, int row, int column) { - if (column != 0 || !(value instanceof Boolean)) { - throw new IllegalArgumentException("column="+column+", value="+value); - } - - configuration.setEvent(eventTypes[row], (Boolean)value); - this.fireTableCellUpdated(row, column); - } - } -} diff --git a/src/net/sf/openrocket/gui/plot/SimulationPlotPanel.java b/src/net/sf/openrocket/gui/plot/SimulationPlotPanel.java new file mode 100644 index 00000000..cac00455 --- /dev/null +++ b/src/net/sf/openrocket/gui/plot/SimulationPlotPanel.java @@ -0,0 +1,486 @@ +package net.sf.openrocket.gui.plot; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Arrays; +import java.util.EnumSet; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.gui.components.DescriptionArea; +import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.simulation.FlightDataBranch; +import net.sf.openrocket.simulation.FlightEvent; +import net.sf.openrocket.simulation.FlightDataBranch.Type; +import net.sf.openrocket.unit.Unit; +import net.sf.openrocket.util.GUIUtil; +import net.sf.openrocket.util.Icons; +import net.sf.openrocket.util.Pair; + +public class SimulationPlotPanel extends JPanel { + + // TODO: LOW: Should these be somewhere else? + public static final int AUTO = -1; + public static final int LEFT = 0; + public static final int RIGHT = 1; + + public static final String AUTO_NAME = "Auto"; + public static final String LEFT_NAME = "Left"; + public static final String RIGHT_NAME = "Right"; + + private static final String CUSTOM = "Custom"; + + /** The "Custom" configuration - not to be used for anything other than the title. */ + private static final PlotConfiguration CUSTOM_CONFIGURATION; + static { + CUSTOM_CONFIGURATION = new PlotConfiguration(CUSTOM); + } + + /** The array of presets for the combo box. */ + private static final PlotConfiguration[] PRESET_ARRAY; + static { + PRESET_ARRAY = Arrays.copyOf(PlotConfiguration.DEFAULT_CONFIGURATIONS, + PlotConfiguration.DEFAULT_CONFIGURATIONS.length + 1); + PRESET_ARRAY[PRESET_ARRAY.length-1] = CUSTOM_CONFIGURATION; + } + + + + /** The current default configuration, set each time a plot is made. */ + private static PlotConfiguration defaultConfiguration = + PlotConfiguration.DEFAULT_CONFIGURATIONS[0].resetUnits(); + + + private final Simulation simulation; + private final FlightDataBranch.Type[] types; + private PlotConfiguration configuration; + + + private JComboBox configurationSelector; + + private JComboBox domainTypeSelector; + private UnitSelector domainUnitSelector; + + private JPanel typeSelectorPanel; + private FlightEventTableModel eventTableModel; + + + private int modifying = 0; + + + public SimulationPlotPanel(final Simulation simulation) { + super(new MigLayout("fill")); + + this.simulation = simulation; + if (simulation.getSimulatedData() == null || + simulation.getSimulatedData().getBranchCount()==0) { + throw new IllegalArgumentException("Simulation contains no data."); + } + FlightDataBranch branch = simulation.getSimulatedData().getBranch(0); + types = branch.getTypes(); + + // TODO: LOW: Revert to custom if data type is not available. + configuration = defaultConfiguration.clone(); + + + //// Configuration selector + + // Setup the combo box + configurationSelector = new JComboBox(PRESET_ARRAY); + for (PlotConfiguration config: PRESET_ARRAY) { + if (config.getName().equals(configuration.getName())) { + configurationSelector.setSelectedItem(config); + } + } + configurationSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + PlotConfiguration conf = (PlotConfiguration)configurationSelector.getSelectedItem(); + if (conf == CUSTOM_CONFIGURATION) + return; + modifying++; + configuration = conf.clone().resetUnits(); + updatePlots(); + modifying--; + } + }); + this.add(new JLabel("Preset plot configurations: "), "spanx, split"); + this.add(configurationSelector,"growx, wrap 20lp"); + + + + //// X axis + + + this.add(new JLabel("X axis type:"), "spanx, split"); + domainTypeSelector = new JComboBox(types); + domainTypeSelector.setSelectedItem(configuration.getDomainAxisType()); + domainTypeSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + FlightDataBranch.Type type = (Type) domainTypeSelector.getSelectedItem(); + configuration.setDomainAxisType(type); + domainUnitSelector.setUnitGroup(type.getUnitGroup()); + domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); + setToCustom(); + } + }); + this.add(domainTypeSelector, "gapright para"); + + + this.add(new JLabel("Unit:")); + domainUnitSelector = new UnitSelector(configuration.getDomainAxisType().getUnitGroup()); + domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); + domainUnitSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + configuration.setDomainAxisUnit(domainUnitSelector.getSelectedUnit()); + } + }); + this.add(domainUnitSelector, "width 40lp, gapright para"); + + + DescriptionArea desc = new DescriptionArea("The data will be plotted in time order " + + "even if the X axis type is not time.", 2, -2f); + desc.setViewportBorder(BorderFactory.createEmptyBorder()); + this.add(desc, "width 1px, growx 1, wrap unrel"); + + + + //// Y axis selector panel + + this.add(new JLabel("Y axis types:")); + + this.add(new JLabel("Flight events:"), "wrap rel"); + + typeSelectorPanel = new JPanel(new MigLayout("gapy rel")); + JScrollPane scroll = new JScrollPane(typeSelectorPanel); + this.add(scroll, "spany 2, height 10px, grow 100, gapright para"); + + + //// Flight events + eventTableModel = new FlightEventTableModel(); + JTable table = new JTable(eventTableModel); + table.setTableHeader(null); + table.setShowVerticalLines(false); + table.setRowSelectionAllowed(false); + table.setColumnSelectionAllowed(false); + + TableColumnModel columnModel = table.getColumnModel(); + TableColumn col0 = columnModel.getColumn(0); + int w = table.getRowHeight() + 2; + col0.setMinWidth(w); + col0.setPreferredWidth(w); + col0.setMaxWidth(w); + table.addMouseListener(new GUIUtil.BooleanTableClickListener(table)); + this.add(new JScrollPane(table), "height 10px, width 200lp, grow 1, wrap rel"); + + + //// All + None buttons + JButton button = new JButton("All"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (FlightEvent.Type t: FlightEvent.Type.values()) + configuration.setEvent(t, true); + eventTableModel.fireTableDataChanged(); + } + }); + this.add(button, "split 2, gapleft para, gapright para, growx, sizegroup buttons"); + + button = new JButton("None"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (FlightEvent.Type t: FlightEvent.Type.values()) + configuration.setEvent(t, false); + eventTableModel.fireTableDataChanged(); + } + }); + this.add(button, "gapleft para, gapright para, growx, sizegroup buttons, wrap para"); + + + + + button = new JButton("New Y axis plot type"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (configuration.getTypeCount() >= 15) { + JOptionPane.showMessageDialog(SimulationPlotPanel.this, + "A maximum of 15 plots is allowed.", "Cannot add plot", + JOptionPane.ERROR_MESSAGE); + return; + } + + // Select new type smartly + FlightDataBranch.Type type = null; + for (FlightDataBranch.Type t: + simulation.getSimulatedData().getBranch(0).getTypes()) { + + boolean used = false; + if (configuration.getDomainAxisType().equals(t)) { + used = true; + } else { + for (int i=0; i < configuration.getTypeCount(); i++) { + if (configuration.getType(i).equals(t)) { + used = true; + break; + } + } + } + + if (!used) { + type = t; + break; + } + } + if (type == null) { + type = simulation.getSimulatedData().getBranch(0).getTypes()[0]; + } + + // Add new type + configuration.addPlotDataType(type); + setToCustom(); + updatePlots(); + } + }); + this.add(button, "spanx, split"); + + + this.add(new JPanel(), "growx"); + + button = new JButton("Plot flight"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + defaultConfiguration = configuration.clone(); + PlotDialog.showPlot(SwingUtilities.getWindowAncestor(SimulationPlotPanel.this), + simulation, configuration); + } + }); + this.add(button, "right"); + + + updatePlots(); + } + + + private void setToCustom() { + modifying++; + configuration.setName(CUSTOM); + configurationSelector.setSelectedItem(CUSTOM_CONFIGURATION); + modifying--; + } + + + private void updatePlots() { + domainTypeSelector.setSelectedItem(configuration.getDomainAxisType()); + domainUnitSelector.setUnitGroup(configuration.getDomainAxisType().getUnitGroup()); + domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit()); + + typeSelectorPanel.removeAll(); + for (int i=0; i < configuration.getTypeCount(); i++) { + FlightDataBranch.Type type = configuration.getType(i); + Unit unit = configuration.getUnit(i); + int axis = configuration.getAxis(i); + + typeSelectorPanel.add(new PlotTypeSelector(i, type, unit, axis), "wrap"); + } + + typeSelectorPanel.repaint(); + + eventTableModel.fireTableDataChanged(); + } + + + + + /** + * A JPanel which configures a single plot of a PlotConfiguration. + */ + private class PlotTypeSelector extends JPanel { + private final String[] POSITIONS = { AUTO_NAME, LEFT_NAME, RIGHT_NAME }; + + private final int index; + private JComboBox typeSelector; + private UnitSelector unitSelector; + private JComboBox axisSelector; + + + public PlotTypeSelector(int index, FlightDataBranch.Type type) { + this (index, type, null, -1); + } + + public PlotTypeSelector(int plotIndex, FlightDataBranch.Type type, Unit unit, int position) { + super(new MigLayout("ins 0")); + + this.index = plotIndex; + + typeSelector = new JComboBox(types); + typeSelector.setSelectedItem(type); + typeSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + FlightDataBranch.Type type = (Type) typeSelector.getSelectedItem(); + configuration.setPlotDataType(index, type); + unitSelector.setUnitGroup(type.getUnitGroup()); + unitSelector.setSelectedUnit(configuration.getUnit(index)); + setToCustom(); + } + }); + this.add(typeSelector, "gapright para"); + + this.add(new JLabel("Unit:")); + unitSelector = new UnitSelector(type.getUnitGroup()); + if (unit != null) + unitSelector.setSelectedUnit(unit); + unitSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + Unit unit = (Unit) unitSelector.getSelectedUnit(); + configuration.setPlotDataUnit(index, unit); + } + }); + this.add(unitSelector, "width 40lp, gapright para"); + + this.add(new JLabel("Axis:")); + axisSelector = new JComboBox(POSITIONS); + if (position == LEFT) + axisSelector.setSelectedIndex(1); + else if (position == RIGHT) + axisSelector.setSelectedIndex(2); + else + axisSelector.setSelectedIndex(0); + axisSelector.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (modifying > 0) + return; + int axis = axisSelector.getSelectedIndex() - 1; + configuration.setPlotDataAxis(index, axis); + } + }); + this.add(axisSelector); + + + JButton button = new JButton(Icons.DELETE); + button.setToolTipText("Remove this plot"); + button.setBorderPainted(false); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + configuration.removePlotDataType(index); + setToCustom(); + updatePlots(); + } + }); + this.add(button, "gapright 0"); + } + } + + + + private class FlightEventTableModel extends AbstractTableModel { + private final FlightEvent.Type[] eventTypes; + + public FlightEventTableModel() { + EnumSet set = EnumSet.noneOf(FlightEvent.Type.class); + for (int i=0; i < simulation.getSimulatedData().getBranchCount(); i++) { + for (Pair e: + simulation.getSimulatedData().getBranch(i).getEvents()) { + set.add(e.getV().getType()); + } + } + set.remove(FlightEvent.Type.ALTITUDE); + int count = set.size(); + + eventTypes = new FlightEvent.Type[count]; + int pos = 0; + for (FlightEvent.Type t: FlightEvent.Type.values()) { + if (set.contains(t)) { + eventTypes[pos] = t; + pos++; + } + } + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public int getRowCount() { + return eventTypes.length; + } + + @Override + public Class getColumnClass(int column) { + switch (column) { + case 0: + return Boolean.class; + + case 1: + return String.class; + + default: + throw new IndexOutOfBoundsException("column="+column); + } + } + + @Override + public Object getValueAt(int row, int column) { + switch (column) { + case 0: + return new Boolean(configuration.isEventActive(eventTypes[row])); + + case 1: + return eventTypes[row].toString(); + + default: + throw new IndexOutOfBoundsException("column="+column); + } + } + + @Override + public boolean isCellEditable(int row, int column) { + return column == 0; + } + + @Override + public void setValueAt(Object value, int row, int column) { + if (column != 0 || !(value instanceof Boolean)) { + throw new IllegalArgumentException("column="+column+", value="+value); + } + + configuration.setEvent(eventTypes[row], (Boolean)value); + this.fireTableCellUpdated(row, column); + } + } +} diff --git a/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index e40ba387..716943c1 100644 --- a/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -59,6 +59,7 @@ import net.sf.openrocket.simulation.listeners.ApogeeEndListener; import net.sf.openrocket.simulation.listeners.InterruptListener; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.ChangeSource; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Prefs; @@ -222,7 +223,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change // Add rotation slider // Minimum size to fit "360deg" - JLabel l = new JLabel("360\u00b0"); + JLabel l = new JLabel("360" + Chars.DEGREE); Dimension d = l.getPreferredSize(); add(new BasicSlider(theta.getSliderModel(0,2*Math.PI),JSlider.VERTICAL,true), diff --git a/src/net/sf/openrocket/rocketcomponent/Rocket.java b/src/net/sf/openrocket/rocketcomponent/Rocket.java index 3bd4dcda..145e4cf0 100644 --- a/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -13,6 +13,7 @@ import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import net.sf.openrocket.motor.Motor; +import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -694,7 +695,7 @@ public class Rocket extends RocketComponent { if (previous != null) { String s = ""; if (count > 1) { - s = "" + count + "\u00d7" + previous; + s = "" + count + Chars.TIMES + previous; } else { s = previous; } @@ -713,7 +714,7 @@ public class Rocket extends RocketComponent { if (previous != null) { String s = ""; if (count > 1) { - s = "" + count + "\u00d7" + previous; + s = "" + count + Chars.TIMES + previous; } else { s = previous; } diff --git a/src/net/sf/openrocket/rocketcomponent/Transition.java b/src/net/sf/openrocket/rocketcomponent/Transition.java index 7155a798..5478545f 100644 --- a/src/net/sf/openrocket/rocketcomponent/Transition.java +++ b/src/net/sf/openrocket/rocketcomponent/Transition.java @@ -1,9 +1,8 @@ package net.sf.openrocket.rocketcomponent; -import static java.lang.Math.sin; -import static java.lang.Math.sqrt; -import static net.sf.openrocket.util.MathUtil.pow2; -import static net.sf.openrocket.util.MathUtil.pow3; +import static java.lang.Math.*; +import static net.sf.openrocket.util.Chars.*; +import static net.sf.openrocket.util.MathUtil.*; import java.util.Collection; @@ -594,14 +593,14 @@ public class Transition extends SymmetricComponent { "Radius × (x / Length)" + "k "+ "where k is the shape parameter. For k=0.5 this is a "+ - "½-power or parabolic nose cone, for k=0.75 a "+ - "¾-power, and for k=1 a conical nose cone.", + "" + FRAC12 +"-power or parabolic nose cone, for k=0.75 a "+ + "" + FRAC34 +"-power, and for k=1 a conical nose cone.", "A power series transition has a profile of "+ "Radius × (x / Length)" + "k "+ "where k is the shape parameter. For k=0.5 the transition is "+ - "½-power or parabolic, for k=0.75 a ¾-power, and for " + - "k=1 conical.",true) { + "" + FRAC12 + "-power or parabolic, for k=0.75 a " + + "" + FRAC34 + "-power, and for k=1 conical.",true) { @Override public boolean usesParameter() { // Range 0...1 return true; diff --git a/src/net/sf/openrocket/unit/DegreeUnit.java b/src/net/sf/openrocket/unit/DegreeUnit.java index e694aa69..240e0b84 100644 --- a/src/net/sf/openrocket/unit/DegreeUnit.java +++ b/src/net/sf/openrocket/unit/DegreeUnit.java @@ -2,10 +2,12 @@ package net.sf.openrocket.unit; import java.text.DecimalFormat; +import net.sf.openrocket.util.Chars; + public class DegreeUnit extends GeneralUnit { public DegreeUnit() { - super(Math.PI/180.0,"\u00b0"); + super(Math.PI/180.0, ""+Chars.DEGREE); } @Override diff --git a/src/net/sf/openrocket/unit/Unit.java b/src/net/sf/openrocket/unit/Unit.java index 55b4f160..53e19c80 100644 --- a/src/net/sf/openrocket/unit/Unit.java +++ b/src/net/sf/openrocket/unit/Unit.java @@ -2,10 +2,12 @@ package net.sf.openrocket.unit; import java.text.DecimalFormat; +import net.sf.openrocket.util.Chars; + public abstract class Unit { /** No unit with 2 digit precision */ - public static final Unit NOUNIT2 = new GeneralUnit(1,"\u200b", 2); // zero-width space + public static final Unit NOUNIT2 = new GeneralUnit(1,""+Chars.ZWSP, 2); protected final double multiplier; // meters = units * multiplier protected final String unit; diff --git a/src/net/sf/openrocket/unit/UnitGroup.java b/src/net/sf/openrocket/unit/UnitGroup.java index 6b6d4997..ffe80f22 100644 --- a/src/net/sf/openrocket/unit/UnitGroup.java +++ b/src/net/sf/openrocket/unit/UnitGroup.java @@ -1,5 +1,6 @@ package net.sf.openrocket.unit; +import static net.sf.openrocket.util.Chars.*; import static net.sf.openrocket.util.MathUtil.pow2; import java.util.ArrayList; @@ -89,11 +90,11 @@ public class UnitGroup { UNITS_DISTANCE.addUnit(new GeneralUnit(1609.344,"mi")); UNITS_AREA = new UnitGroup(); - UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001),"mm\u00b2")); - UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01),"cm\u00b2")); - UNITS_AREA.addUnit(new GeneralUnit(1,"m\u00b2")); - UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254),"in\u00b2")); - UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048),"ft\u00b2")); + UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001),"mm" + SQUARED)); + UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01),"cm" + SQUARED)); + UNITS_AREA.addUnit(new GeneralUnit(1,"m" + SQUARED)); + UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254),"in" + SQUARED)); + UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048),"ft" + SQUARED)); UNITS_AREA.setDefaultUnit(1); @@ -111,8 +112,8 @@ public class UnitGroup { UNITS_VELOCITY.addUnit(new GeneralUnit(0.44704, "mph")); UNITS_ACCELERATION = new UnitGroup(); - UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s\u00b2")); - UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s\u00b2")); + UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s" + SQUARED)); + UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s" + SQUARED)); UNITS_MASS = new UnitGroup(); @@ -126,18 +127,18 @@ public class UnitGroup { UNITS_ANGLE.addUnit(new FixedPrecisionUnit("rad",0.01)); UNITS_DENSITY_BULK = new UnitGroup(); - UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000,"g/cm\u00b3")); - UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1,"kg/m\u00b3")); - UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404,"oz/in\u00b3")); - UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634,"lb/ft\u00b3")); + UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000,"g/cm" + CUBED)); + UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1,"kg/m" + CUBED)); + UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404,"oz/in" + CUBED)); + UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634,"lb/ft" + CUBED)); UNITS_DENSITY_SURFACE = new UnitGroup(); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10,"g/cm\u00b2")); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001,"g/m\u00b2")); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1,"kg/m\u00b2")); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487,"oz/in\u00b2")); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727,"oz/ft\u00b2")); - UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764,"lb/ft\u00b2")); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10,"g/cm" + SQUARED)); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001,"g/m" + SQUARED)); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1,"kg/m" + SQUARED)); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487,"oz/in" + SQUARED)); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727,"oz/ft" + SQUARED)); + UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764,"lb/ft" + SQUARED)); UNITS_DENSITY_SURFACE.setDefaultUnit(1); UNITS_DENSITY_LINE = new UnitGroup(); @@ -152,7 +153,7 @@ public class UnitGroup { UNITS_IMPULSE = new UnitGroup(); UNITS_IMPULSE.addUnit(new GeneralUnit(1,"Ns")); - UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf\u00b7s")); + UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf"+DOT+"s")); UNITS_TIME_STEP = new UnitGroup(); UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("ms", 1, 0.001)); @@ -174,8 +175,8 @@ public class UnitGroup { UNITS_TEMPERATURE = new UnitGroup(); UNITS_TEMPERATURE.addUnit(new FixedPrecisionUnit("K", 1)); - UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, "\u00b0C")); - UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0/9.0, 459.67, "\u00b0F")); + UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, DEGREE+"C")); + UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0/9.0, 459.67, DEGREE+"F")); UNITS_TEMPERATURE.setDefaultUnit(1); UNITS_PRESSURE = new UnitGroup(); @@ -188,18 +189,19 @@ public class UnitGroup { UNITS_PRESSURE.addUnit(new GeneralUnit(1, "Pa")); UNITS_RELATIVE = new UnitGroup(); - UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("\u200b", 0.01)); + UNITS_RELATIVE.addUnit(new FixedPrecisionUnit(""+ZWSP, 0.01, 1.0)); UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("%", 1, 0.01)); + UNITS_RELATIVE.addUnit(new FixedPrecisionUnit(""+PERMILLE, 1, 0.001)); UNITS_RELATIVE.setDefaultUnit(1); UNITS_ROUGHNESS = new UnitGroup(); - UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, "\u03bcm")); + UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO+"m")); UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil")); UNITS_COEFFICIENT = new UnitGroup(); - UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit("\u200b", 0.01)); // zero-width space + UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit(""+ZWSP, 0.01)); // zero-width space HashMap map = new HashMap(); @@ -235,45 +237,45 @@ public class UnitGroup { UNITS_LENGTH.setDefaultUnit("cm"); UNITS_MOTOR_DIMENSIONS.setDefaultUnit("mm"); UNITS_DISTANCE.setDefaultUnit("m"); - UNITS_AREA.setDefaultUnit("cm\u00b2"); + UNITS_AREA.setDefaultUnit("cm"+SQUARED); UNITS_STABILITY.setDefaultUnit("cal"); UNITS_VELOCITY.setDefaultUnit("m/s"); - UNITS_ACCELERATION.setDefaultUnit("m/s\u00b2"); + UNITS_ACCELERATION.setDefaultUnit("m/s"+SQUARED); UNITS_MASS.setDefaultUnit("g"); - UNITS_ANGLE.setDefaultUnit(0); - UNITS_DENSITY_BULK.setDefaultUnit("g/cm\u00b3"); - UNITS_DENSITY_SURFACE.setDefaultUnit("g/m\u00b2"); + UNITS_ANGLE.setDefaultUnit(""+DEGREE); + UNITS_DENSITY_BULK.setDefaultUnit("g/cm"+CUBED); + UNITS_DENSITY_SURFACE.setDefaultUnit("g/m"+SQUARED); UNITS_DENSITY_LINE.setDefaultUnit("g/m"); UNITS_FORCE.setDefaultUnit("N"); UNITS_IMPULSE.setDefaultUnit("Ns"); UNITS_TIME_STEP.setDefaultUnit("s"); UNITS_FLIGHT_TIME.setDefaultUnit("s"); UNITS_ROLL.setDefaultUnit("r/s"); - UNITS_TEMPERATURE.setDefaultUnit(1); + UNITS_TEMPERATURE.setDefaultUnit(DEGREE+"C"); UNITS_PRESSURE.setDefaultUnit("mbar"); UNITS_RELATIVE.setDefaultUnit("%"); - UNITS_ROUGHNESS.setDefaultUnit("\u03bcm"); + UNITS_ROUGHNESS.setDefaultUnit(MICRO+"m"); } public static void setDefaultImperialUnits() { UNITS_LENGTH.setDefaultUnit("in"); UNITS_MOTOR_DIMENSIONS.setDefaultUnit("in"); UNITS_DISTANCE.setDefaultUnit("ft"); - UNITS_AREA.setDefaultUnit("in\u00b2"); + UNITS_AREA.setDefaultUnit("in"+SQUARED); UNITS_STABILITY.setDefaultUnit("cal"); UNITS_VELOCITY.setDefaultUnit("ft/s"); - UNITS_ACCELERATION.setDefaultUnit("ft/s\u00b2"); + UNITS_ACCELERATION.setDefaultUnit("ft/s"+SQUARED); UNITS_MASS.setDefaultUnit("oz"); - UNITS_ANGLE.setDefaultUnit(0); - UNITS_DENSITY_BULK.setDefaultUnit("oz/in\u00b3"); - UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft\u00b2"); + UNITS_ANGLE.setDefaultUnit(""+DEGREE); + UNITS_DENSITY_BULK.setDefaultUnit("oz/in"+CUBED); + UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft"+SQUARED); UNITS_DENSITY_LINE.setDefaultUnit("oz/ft"); UNITS_FORCE.setDefaultUnit("N"); UNITS_IMPULSE.setDefaultUnit("Ns"); UNITS_TIME_STEP.setDefaultUnit("s"); UNITS_FLIGHT_TIME.setDefaultUnit("s"); UNITS_ROLL.setDefaultUnit("r/s"); - UNITS_TEMPERATURE.setDefaultUnit(2); + UNITS_TEMPERATURE.setDefaultUnit(DEGREE+"F"); UNITS_PRESSURE.setDefaultUnit("mbar"); UNITS_RELATIVE.setDefaultUnit("%"); UNITS_ROUGHNESS.setDefaultUnit("mil"); @@ -337,24 +339,20 @@ public class UnitGroup { } /** - * Set the default unit based on the unit name. Does nothing if the name - * does not match any of the units. + * Set the default unit based on the unit name. Throws an exception if a + * unit with the provided name is not available. * - * @param name the unit name (null ok). - * @return true if the the default was set, - * false if a matching unit was not found. + * @param name the unit name. + * @throws IllegalArgumentException if the corresponding unit is not found in the group. */ - public boolean setDefaultUnit(String name) { - if (name == null) - return false; - + public void setDefaultUnit(String name) throws IllegalArgumentException { for (int i=0; i < units.size(); i++) { - if (name.equals(units.get(i).getUnit())) { + if (units.get(i).getUnit().equals(name)) { setDefaultUnit(i); - return true; + return; } } - return false; + throw new IllegalArgumentException("name="+name); } diff --git a/src/net/sf/openrocket/util/Chars.java b/src/net/sf/openrocket/util/Chars.java new file mode 100644 index 00000000..08d2f827 --- /dev/null +++ b/src/net/sf/openrocket/util/Chars.java @@ -0,0 +1,50 @@ +package net.sf.openrocket.util; + +/** + * A class defining various non-ASCII characters for easier use. + * + * @author Sampo Niskanen + */ +public class Chars { + + /** The fraction 1/2 */ + public static final char FRAC12 = '\u00BD'; + /** The fraction 1/4 */ + public static final char FRAC14 = '\u00BC'; + /** The fraction 3/4 */ + public static final char FRAC34 = '\u00BE'; + + /** Degree sign */ + public static final char DEGREE = '\u00B0'; + + /** Squared, superscript 2 */ + public static final char SQUARED = '\u00B2'; + /** Cubed, superscript 3 */ + public static final char CUBED = '\u00B3'; + + /** Per mille sign */ + public static final char PERMILLE = '\u2030'; + + /** Middle dot, multiplication */ + public static final char DOT = '\u00B7'; + /** Multiplication sign, cross */ + public static final char TIMES = '\u00D7'; + + /** No-break space */ + public static final char NBSP = '\u00A0'; + /** Zero-width space */ + public static final char ZWSP = '\u200B'; + + /** Micro sign (Greek letter mu) */ + public static final char MICRO = '\u00B5'; + + /** Alpha */ + public static final char ALPHA = '\u03b1'; + /** Theta */ + public static final char THETA = '\u0398'; + + /** Copyright symbol */ + public static final char COPY = '\u00A9'; + /** A centered bullet */ + public static final char BULLET = '\u2022'; +} diff --git a/src/net/sf/openrocket/util/ConcurrentProgressMonitor.java b/src/net/sf/openrocket/util/ConcurrentProgressMonitor.java index 21017940..7253c890 100644 --- a/src/net/sf/openrocket/util/ConcurrentProgressMonitor.java +++ b/src/net/sf/openrocket/util/ConcurrentProgressMonitor.java @@ -10,7 +10,7 @@ import javax.swing.SwingUtilities; * A thread-safe ProgressMonitor. This class may be instantiated * and the method {@link #setProgress(int)} called safely from any thread. *

- * Why the FSCK&!¤#&%¤ isn't the default API version thread-safe?!?! + * Why the FSCK&!#&% isn't the default API version thread-safe?!?! * * @author Sampo Niskanen */ diff --git a/src/net/sf/openrocket/util/Pair.java b/src/net/sf/openrocket/util/Pair.java index e13b9b94..e95587b5 100644 --- a/src/net/sf/openrocket/util/Pair.java +++ b/src/net/sf/openrocket/util/Pair.java @@ -26,4 +26,40 @@ public class Pair { return v; } + + /** + * Compare both components of the Pair to another object. + * The pair is equal iff both items are equal (or null). + */ + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object other) { + if (!(other instanceof Pair)) + return false; + Object otherU = ((Pair)other).getU(); + Object otherV = ((Pair)other).getV(); + + if (otherU == null) { + if (this.u != null) + return false; + } else { + if (!otherU.equals(this.u)) + return false; + } + + if (otherV == null) { + if (this.v != null) + return false; + } else { + if (!otherV.equals(this.v)) + return false; + } + return true; + } + + @Override + public int hashCode() { + return ((u != null) ? u.hashCode() : 0) + ((v != null) ? v.hashCode() : 0); + } + } diff --git a/src/net/sf/openrocket/util/Prefs.java b/src/net/sf/openrocket/util/Prefs.java index f4f26133..dc3e0db4 100644 --- a/src/net/sf/openrocket/util/Prefs.java +++ b/src/net/sf/openrocket/util/Prefs.java @@ -52,50 +52,62 @@ public class Prefs { */ public static final String NODENAME = (DEBUG?"OpenRocket-debug":"OpenRocket"); - - - private static final String BUILD_VERSION; - private static final String BUILD_SOURCE; + public static final String DEFAULT_BUILD_SOURCE = "default"; - private static final boolean DEFAULT_CHECK_UPDATES; + - static { - try { - InputStream is = ClassLoader.getSystemResourceAsStream("build.properties"); - if (is == null) { - throw new MissingResourceException( - "build.properties not found, distribution built wrong" + - " path:"+System.getProperty("java.class.path"), - "build.properties", "build.version"); - } - - Properties props = new Properties(); - props.load(is); - is.close(); - - BUILD_VERSION = props.getProperty("build.version"); - if (BUILD_VERSION == null) { + /* + * Load property file only when necessary. + */ + private static class BuildPropertyHolder { + + public static final String BUILD_VERSION; + public static final String BUILD_SOURCE; + public static final boolean DEFAULT_CHECK_UPDATES; + + static { + try { + InputStream is = ClassLoader.getSystemResourceAsStream("build.properties"); + if (is == null) { + throw new MissingResourceException( + "build.properties not found, distribution built wrong" + + " classpath:"+System.getProperty("java.class.path"), + "build.properties", "build.version"); + } + + Properties props = new Properties(); + props.load(is); + is.close(); + + String version = props.getProperty("build.version"); + if (version == null) { + throw new MissingResourceException( + "build.version not found in property file", + "build.properties", "build.version"); + } + BUILD_VERSION = version.trim(); + + BUILD_SOURCE = props.getProperty("build.source"); + if (BUILD_SOURCE == null) { + throw new MissingResourceException( + "build.source not found in property file", + "build.properties", "build.source"); + } + + String value = props.getProperty("build.checkupdates"); + if (value != null) + DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value); + else + DEFAULT_CHECK_UPDATES = true; + + } catch (IOException e) { throw new MissingResourceException( - "build.version not found in property file", + "Error reading build.properties", "build.properties", "build.version"); } - - BUILD_SOURCE = props.getProperty("build.source"); - - String value = props.getProperty("build.checkupdates"); - if (value != null) - DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value); - else - DEFAULT_CHECK_UPDATES = true; - - } catch (IOException e) { - throw new MissingResourceException( - "Error reading build.properties", - "build.properties", "build.version"); } } - public static final String BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition"; @@ -111,6 +123,7 @@ public class Prefs { public static final String PLOT_SHOW_POINTS = "ShowPlotPoints"; private static final String CHECK_UPDATES = "CheckUpdates"; + public static final String LAST_UPDATE = "LastUpdateVersion"; /** * Node to this application's preferences. @@ -178,12 +191,12 @@ public class Prefs { public static String getVersion() { - return BUILD_VERSION; + return BuildPropertyHolder.BUILD_VERSION; } public static String getBuildSource() { - return BUILD_SOURCE; + return BuildPropertyHolder.BUILD_SOURCE; } @@ -256,7 +269,7 @@ public class Prefs { public static boolean getCheckUpdates() { - return PREFNODE.getBoolean(CHECK_UPDATES, DEFAULT_CHECK_UPDATES); + return PREFNODE.getBoolean(CHECK_UPDATES, BuildPropertyHolder.DEFAULT_CHECK_UPDATES); } public static void setCheckUpdates(boolean check) { @@ -502,7 +515,9 @@ public class Prefs { if (group == null) continue; - group.setDefaultUnit(prefs.get(key, null)); + try { + group.setDefaultUnit(prefs.get(key, null)); + } catch (IllegalArgumentException ignore) { } } } catch (BackingStoreException e) { diff --git a/test/net/sf/openrocket/motor/ManufacturerTest.java b/test/net/sf/openrocket/motor/ManufacturerTest.java index f9b676f0..6870c5f2 100644 --- a/test/net/sf/openrocket/motor/ManufacturerTest.java +++ b/test/net/sf/openrocket/motor/ManufacturerTest.java @@ -73,7 +73,7 @@ public class ManufacturerTest { assertTrue(m1.matches("a/")); assertTrue(m1.matches("a/rcs")); assertTrue(m1.matches("a/rms")); - assertTrue(m1.matches("aerotech ...-/%¤#_!")); + assertTrue(m1.matches("aerotech ...-/%#_!")); assertTrue(m1.matches(" .isp/")); assertFalse(m1.matches("aero/tech")); diff --git a/test/net/sf/openrocket/util/CoordinateTest.java b/test/net/sf/openrocket/util/CoordinateTest.java index 97c78a7a..0c74a3a1 100644 --- a/test/net/sf/openrocket/util/CoordinateTest.java +++ b/test/net/sf/openrocket/util/CoordinateTest.java @@ -38,11 +38,11 @@ public class CoordinateTest { assertCoordinateEquals(new Coordinate(2,4,6,8), y.multiply(2)); - assertEquals(1+2+3, y.dot(x)); - assertEquals(1+2+3, x.dot(y)); - assertEquals(1+2+3, Coordinate.dot(x,y)); - assertEquals(x.dot(x), x.length2()); - assertEquals(y.dot(y), y.length2()); + assertEquals(1+2+3, y.dot(x), EPS); + assertEquals(1+2+3, x.dot(y), EPS); + assertEquals(1+2+3, Coordinate.dot(x,y), EPS); + assertEquals(x.dot(x), x.length2(), EPS); + assertEquals(y.dot(y), y.length2(), EPS); assertEquals(Math.sqrt(1+4+9), y.length(), EPS); assertEquals(1, y.normalize().length(), EPS); diff --git a/test/net/sf/openrocket/util/MathUtilTest.java b/test/net/sf/openrocket/util/MathUtilTest.java index 8c135c8a..3f410acb 100644 --- a/test/net/sf/openrocket/util/MathUtilTest.java +++ b/test/net/sf/openrocket/util/MathUtilTest.java @@ -17,24 +17,24 @@ public class MathUtilTest { assertEquals(PI*PI*PI, MathUtil.pow3(PI), EPS); assertEquals(PI*PI*PI*PI, MathUtil.pow4(PI), EPS); - assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0)); - assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0)); - assertEquals(2.0, MathUtil.clamp(2 + EPS/100, 1.0, 2.0)); + assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0), 0); + assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0), 0); + assertEquals(2.0, MathUtil.clamp(2 + EPS/100, 1.0, 2.0), 0); - assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f)); - assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f)); - assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f)); + assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f), 0); + assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f), 0); + assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f), 0); assertEquals(1, MathUtil.clamp(-3, 1, 5)); assertEquals(3, MathUtil.clamp(3, 1, 5)); assertEquals(5, MathUtil.clamp(6, 1, 5)); - assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY)); - assertEquals(-1.0, MathUtil.sign(-100)); - assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0))); - assertEquals( 1.0, MathUtil.sign(Math.nextUp(0.0))); - assertEquals( 1.0, MathUtil.sign(100)); - assertEquals( 1.0, MathUtil.sign(Double.POSITIVE_INFINITY)); + assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY), EPS); + assertEquals(-1.0, MathUtil.sign(-100), EPS); + assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0)), EPS); + assertEquals( 1.0, MathUtil.sign(Math.nextUp(0.0)), EPS); + assertEquals( 1.0, MathUtil.sign(100), EPS); + assertEquals( 1.0, MathUtil.sign(Double.POSITIVE_INFINITY), EPS); } @Test @@ -68,33 +68,33 @@ public class MathUtilTest { @Test public void minmaxTest() { - assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0))); - assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY)); - assertEquals(1.0, MathUtil.min(NaN, 1.0)); - assertEquals(1.0, MathUtil.min(1.0, NaN)); - assertEquals(NaN, MathUtil.min(NaN, NaN)); + assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0)), 0); + assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY), 0); + assertEquals(1.0, MathUtil.min(NaN, 1.0), 0); + assertEquals(1.0, MathUtil.min(1.0, NaN), 0); + assertEquals(NaN, MathUtil.min(NaN, NaN), 0); - assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0))); - assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY)); - assertEquals(1.0, MathUtil.max(NaN, 1.0)); - assertEquals(1.0, MathUtil.max(1.0, NaN)); - assertEquals(NaN, MathUtil.max(NaN, NaN)); + assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0)), 0); + assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY), 0); + assertEquals(1.0, MathUtil.max(NaN, 1.0), 0); + assertEquals(1.0, MathUtil.max(1.0, NaN), 0); + assertEquals(NaN, MathUtil.max(NaN, NaN), 0); - assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0)); - assertEquals(1.0, MathUtil.min(1.0, NaN, NaN)); - assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN)); - assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0)); - assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0)); - assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN)); - assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0)); + assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0), 0); + assertEquals(1.0, MathUtil.min(1.0, NaN, NaN), 0); + assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN), 0); + assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0), 0); + assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0), 0); + assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN), 0); + assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0), 0); - assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0)); - assertEquals(1.0, MathUtil.max(1.0, NaN, NaN)); - assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN)); - assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0)); - assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0)); - assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN)); - assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0)); + assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0), 0); + assertEquals(1.0, MathUtil.max(1.0, NaN, NaN), 0); + assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN), 0); + assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0), 0); + assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0), 0); + assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN), 0); + assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0), 0); } @Test