From: plaa Date: Tue, 11 Oct 2011 19:46:02 +0000 (+0000) Subject: component config refactoring, localization fixes X-Git-Tag: upstream/1.1.9^2~6 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=bae4608a5d01ff84ac6d020c0c47931d2e243250;p=debian%2Fopenrocket component config refactoring, localization fixes git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@178 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/ChangeLog b/ChangeLog index 11b8fd24..84038e12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-11 Sampo Niskanen + + * [BUG] Translators fetched before initialization + +2011-10-05 Doug Pedrick + + * Fin tab autocalculation + 2011-09-26 Sampo Niskanen * [BUG] Thrust was computed from dropped stages diff --git a/l10n/messages.properties b/l10n/messages.properties index 73d0a9b7..f9a55ae8 100644 --- a/l10n/messages.properties +++ b/l10n/messages.properties @@ -583,7 +583,7 @@ FinSetConfig.but.Converttofreeform.ttip = Convert this fin set into a freeform f FinSetConfig.Convertfinset = Convert fin set FinSetConfig.but.Splitfins = Split fins FinSetConfig.but.Splitfins.ttip = Split the fin set into separate fins -FinSetConfig.but.Calcheight = Calculate Height +FinSetConfig.but.AutoCalc = Calculate automatically FinSetConfig.lbl.Through-the-wall = Through-the-wall fin tabs: FinSetConfig.lbl.Tablength = Tab length: FinSetConfig.ttip.Tablength = The length of the fin tab. diff --git a/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java index f876d6fa..af272a0d 100644 --- a/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java @@ -1,7 +1,13 @@ package net.sf.openrocket.gui.configdialog; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; + import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; @@ -14,96 +20,91 @@ import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; - public class BodyTubeConfig extends RocketComponentConfig { - + private MotorConfig motorConfigPane = null; private static final Translator trans = Application.getTranslator(); - - public BodyTubeConfig(RocketComponent c) { - super(c); + + public BodyTubeConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::][]","")); + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); //// Body tube length panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Bodytubelength"))); - DoubleModel m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + DoubleModel m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.5, 2.0)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.5, 2.0)), "w 100lp, wrap"); + //// Body tube diameter panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Outerdiameter"))); - - DoubleModel od = new DoubleModel(component,"OuterRadius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "OuterRadius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap 0px"); - JCheckBox check = new JCheckBox(od.getAutomaticAction()); //// Automatic check.setText(trans.get("BodyTubecfg.checkbox.Automatic")); - panel.add(check,"skip, span 2, wrap"); - + panel.add(check, "skip, span 2, wrap"); + //// Inner diameter panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Innerdiameter"))); - + // Diameter = 2*Radius - m = new DoubleModel(component,"InnerRadius",2,UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)),"w 100lp, wrap"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "w 100lp, wrap"); + //// Wall thickness panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Wallthickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap 0px"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 0px"); //// Filled - check = new JCheckBox(new BooleanModel(component,"Filled")); + check = new JCheckBox(new BooleanModel(component, "Filled")); check.setText(trans.get("BodyTubecfg.checkbox.Filled")); - panel.add(check,"skip, span 2, wrap"); - + panel.add(check, "skip, span 2, wrap"); + //// Material panel.add(materialPanel(new JPanel(new MigLayout()), Material.Type.BULK), "cell 4 0, gapleft paragraph, aligny 0%, spany"); //// General and General properties - tabbedPane.insertTab(trans.get("BodyTubecfg.tab.General"), null, panel, + tabbedPane.insertTab(trans.get("BodyTubecfg.tab.General"), null, panel, trans.get("BodyTubecfg.tab.Generalproperties"), 0); - motorConfigPane = new MotorConfig((BodyTube)c); + motorConfigPane = new MotorConfig((BodyTube) c); //// Motor and Motor mount configuration - tabbedPane.insertTab(trans.get("BodyTubecfg.tab.Motor"), null, motorConfigPane, + tabbedPane.insertTab(trans.get("BodyTubecfg.tab.Motor"), null, motorConfigPane, trans.get("BodyTubecfg.tab.Motormountconf"), 1); tabbedPane.setSelectedIndex(0); } diff --git a/src/net/sf/openrocket/gui/configdialog/BulkheadConfig.java b/src/net/sf/openrocket/gui/configdialog/BulkheadConfig.java index bc48b8b1..135ec94e 100644 --- a/src/net/sf/openrocket/gui/configdialog/BulkheadConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/BulkheadConfig.java @@ -3,6 +3,7 @@ package net.sf.openrocket.gui.configdialog; import javax.swing.JPanel; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; @@ -12,8 +13,8 @@ import net.sf.openrocket.startup.Application; public class BulkheadConfig extends RingComponentConfig { private static final Translator trans = Application.getTranslator(); - public BulkheadConfig(RocketComponent c) { - super(c); + public BulkheadConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel tab; diff --git a/src/net/sf/openrocket/gui/configdialog/CenteringRingConfig.java b/src/net/sf/openrocket/gui/configdialog/CenteringRingConfig.java index 7d336b88..dfe6a352 100644 --- a/src/net/sf/openrocket/gui/configdialog/CenteringRingConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/CenteringRingConfig.java @@ -3,6 +3,7 @@ package net.sf.openrocket.gui.configdialog; import javax.swing.JPanel; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; @@ -11,18 +12,18 @@ import net.sf.openrocket.startup.Application; public class CenteringRingConfig extends RingComponentConfig { private static final Translator trans = Application.getTranslator(); - - public CenteringRingConfig(RocketComponent c) { - super(c); + + public CenteringRingConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel tab; //// Outer diameter: and Inner diameter: and Thickness: - tab = generalTab(trans.get("CenteringRingCfg.tab.Outerdiam"), - trans.get("CenteringRingCfg.tab.Innerdiam"), null, + tab = generalTab(trans.get("CenteringRingCfg.tab.Outerdiam"), + trans.get("CenteringRingCfg.tab.Innerdiam"), null, trans.get("CenteringRingCfg.tab.Thickness")); //// General and General properties - tabbedPane.insertTab(trans.get("CenteringRingCfg.tab.General"), null, tab, + tabbedPane.insertTab(trans.get("CenteringRingCfg.tab.General"), null, tab, trans.get("CenteringRingCfg.tab.Generalproperties"), 0); tabbedPane.setSelectedIndex(0); } diff --git a/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java b/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java index 0f9f1159..5bb3448b 100644 --- a/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java +++ b/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java @@ -80,9 +80,6 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis //// configuration setTitle(trans.get("ComponentCfgDlg.configuration1") + " " + component.getComponentName() + " " + trans.get("ComponentCfgDlg.configuration")); - // Dimension pref = getPreferredSize(); - // Dimension real = getSize(); - // if (pref.width > real.width || pref.height > real.height) this.pack(); } @@ -94,7 +91,7 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis findDialogContentsConstructor(component); if (c != null) { try { - return c.newInstance(component); + return c.newInstance(document, component); } catch (InstantiationException e) { throw new BugException("BUG in constructor reflection", e); } catch (IllegalAccessException e) { @@ -162,7 +159,7 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis try { configclass = Class.forName(configclassname); c = (Constructor) - configclass.getConstructor(RocketComponent.class); + configclass.getConstructor(OpenRocketDocument.class, RocketComponent.class); return c; } catch (Exception ignore) { } @@ -212,27 +209,6 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis } - /** - * Add an undo position for the current document. This is intended for use only - * by the currently open dialog. - * - * @param description Description of the undoable action - */ - /*package*/static void addUndoPosition(String description) { - if (dialog == null) { - throw new IllegalStateException("Dialog not open, report bug!"); - } - dialog.document.addUndoPosition(description); - } - - /*package*/ - static String getUndoDescription() { - if (dialog == null) { - throw new IllegalStateException("Dialog not open, report bug!"); - } - return dialog.document.getUndoDescription(); - } - /** * Returns whether the singleton configuration dialog is currently visible or not. */ diff --git a/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java index cfb70b35..321ef6c4 100644 --- a/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java @@ -9,6 +9,7 @@ import javax.swing.JSpinner; import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -24,43 +25,43 @@ import net.sf.openrocket.unit.UnitGroup; public class EllipticalFinSetConfig extends FinSetConfig { private static final Translator trans = Application.getTranslator(); - - public EllipticalFinSetConfig(final RocketComponent component) { - super(component); - + + public EllipticalFinSetConfig(OpenRocketDocument d, final RocketComponent component) { + super(d, component); + DoubleModel m; JSpinner spin; JComboBox combo; JPanel mainPanel = new JPanel(new MigLayout()); - - - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + + + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); //// Number of fins panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Nbroffins"))); - IntegerModel im = new IntegerModel(component,"FinCount",1,8); + IntegerModel im = new IntegerModel(component, "FinCount", 1, 8); spin = new JSpinner(im.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx, wrap"); - + panel.add(spin, "growx, wrap"); + //// Base rotation panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Rotation"))); - m = new DoubleModel(component, "BaseRotation", UnitGroup.UNITS_ANGLE,-Math.PI,Math.PI); + m = new DoubleModel(component, "BaseRotation", UnitGroup.UNITS_ANGLE, -Math.PI, Math.PI); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI,Math.PI)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + //// Fin cant JLabel label = new JLabel(trans.get("EllipticalFinSetCfg.Fincant")); //// "The angle that the fins are canted with respect to the rocket @@ -72,117 +73,117 @@ public class EllipticalFinSetConfig extends FinSetConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT,FinSet.MAX_CANT)), + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT, FinSet.MAX_CANT)), "w 100lp, wrap"); - + //// Root chord panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Rootchord"))); - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.2)), "w 100lp, wrap"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.05,0.2)),"w 100lp, wrap"); - //// Height panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Height"))); - m = new DoubleModel(component,"Height",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Height", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.05,0.2)),"w 100lp, wrap"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.2)), "w 100lp, wrap"); + //// Position //// Position relative to: panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Positionrelativeto"))); - + combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel.add(combo,"spanx, growx, wrap"); + panel.add(combo, "spanx, growx, wrap"); //// plus - panel.add(new JLabel(trans.get("EllipticalFinSetCfg.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel.add(new JLabel(trans.get("EllipticalFinSetCfg.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap"); + - //// Right portion - mainPanel.add(panel,"aligny 20%"); + mainPanel.add(panel, "aligny 20%"); - mainPanel.add(new JSeparator(SwingConstants.VERTICAL),"growy"); + mainPanel.add(new JSeparator(SwingConstants.VERTICAL), "growy"); - - - panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); + + //// Cross section //// Fin cross section: - panel.add(new JLabel(trans.get("EllipticalFinSetCfg.FincrossSection")),"span, split"); + panel.add(new JLabel(trans.get("EllipticalFinSetCfg.FincrossSection")), "span, split"); combo = new JComboBox( - new EnumModel(component,"CrossSection")); - panel.add(combo,"growx, wrap unrel"); + new EnumModel(component, "CrossSection")); + panel.add(combo, "growx, wrap unrel"); //// Thickness: panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Thickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap 30lp"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 30lp"); + //// Material materialPanel(panel, Material.Type.BULK); - - - - - mainPanel.add(panel,"aligny 20%"); + + + + + mainPanel.add(panel, "aligny 20%"); addFinSetButtons(); - + //// General and General properties - tabbedPane.insertTab(trans.get("EllipticalFinSetCfg.General"), null, mainPanel, + tabbedPane.insertTab(trans.get("EllipticalFinSetCfg.General"), null, mainPanel, trans.get("EllipticalFinSetCfg.Generalproperties"), 0); tabbedPane.setSelectedIndex(0); } - + } diff --git a/src/net/sf/openrocket/gui/configdialog/FinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/FinSetConfig.java index b1037a1d..b949b2de 100644 --- a/src/net/sf/openrocket/gui/configdialog/FinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/FinSetConfig.java @@ -1,6 +1,21 @@ package net.sf.openrocket.gui.configdialog; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SwingUtilities; + import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -19,416 +34,409 @@ import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - public abstract class FinSetConfig extends RocketComponentConfig { - private static final LogHelper log = Application.getLogger(); - private static final Translator trans = Application.getTranslator(); - - private JButton split = null; - - public FinSetConfig(RocketComponent component) { - super(component); - - //// Fin tabs and Through-the-wall fin tabs - tabbedPane.insertTab(trans.get("FinSetConfig.tab.Fintabs"), null, finTabPanel(), - trans.get("FinSetConfig.tab.Through-the-wall"), 0); - } - - - protected void addFinSetButtons() { - JButton convert = null; - - //// Convert buttons - if (!(component instanceof FreeformFinSet)) { - //// Convert to freeform - convert = new JButton(trans.get("FinSetConfig.but.Converttofreeform")); - //// Convert this fin set into a freeform fin set - convert.setToolTipText(trans.get("FinSetConfig.but.Converttofreeform.ttip")); - convert.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.user("Converting " + component.getComponentName() + " into freeform fin set"); - - // Do change in future for overall safety - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - //// Convert fin set - ComponentConfigDialog.addUndoPosition(trans.get("FinSetConfig.Convertfinset")); - RocketComponent freeform = - FreeformFinSet.convertFinSet((FinSet) component); - ComponentConfigDialog.showDialog(freeform); - } - }); - - ComponentConfigDialog.hideDialog(); - } - }); - } - - //// Split fins - split = new JButton(trans.get("FinSetConfig.but.Splitfins")); - //// Split the fin set into separate fins - split.setToolTipText(trans.get("FinSetConfig.but.Splitfins.ttip")); - split.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.user("Splitting " + component.getComponentName() + " into separate fins, fin count=" + - ((FinSet) component).getFinCount()); - - // Do change in future for overall safety - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - RocketComponent parent = component.getParent(); - int index = parent.getChildPosition(component); - int count = ((FinSet) component).getFinCount(); - double base = ((FinSet) component).getBaseRotation(); - if (count <= 1) - return; - - ComponentConfigDialog.addUndoPosition("Split fin set"); - parent.removeChild(index); - for (int i = 0; i < count; i++) { - FinSet copy = (FinSet) component.copy(); - copy.setFinCount(1); - copy.setBaseRotation(base + i * 2 * Math.PI / count); - copy.setName(copy.getName() + " #" + (i + 1)); - parent.addChild(copy, index + i); - } - } - }); - - ComponentConfigDialog.hideDialog(); - } - }); - split.setEnabled(((FinSet) component).getFinCount() > 1); - - if (convert == null) - addButtons(split); - else - addButtons(split, convert); - - } - - public JPanel finTabPanel() { - JPanel panel = new JPanel( - new MigLayout("align 50% 20%, fillx, gap rel unrel, ins 20lp 10% 20lp 10%", - "[150lp::][65lp::][30lp::][200lp::]", "")); - // JPanel panel = new JPanel(new MigLayout("fillx, align 20% 20%, gap rel unrel", - // "[40lp][80lp::][30lp::][100lp::]","")); - - //// Through-the-wall fin tabs: - panel.add(new StyledLabel(trans.get("FinSetConfig.lbl.Through-the-wall"), Style.BOLD), - "spanx, wrap 30lp"); - - JLabel label; - DoubleModel length; - DoubleModel length2; - DoubleModel length_2; - JSpinner spin; - JButton calcHeight; - - length = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); - length2 = new DoubleModel(component, "Length", 0.5, UnitGroup.UNITS_LENGTH, 0); - length_2 = new DoubleModel(component, "Length", -0.5, UnitGroup.UNITS_LENGTH, 0); - - register(length); - register(length2); - register(length_2); - - //// Tab length - //// Tab length: - label = new JLabel(trans.get("FinSetConfig.lbl.Tablength")); - //// The length of the fin tab. - label.setToolTipText(trans.get("FinSetConfig.ttip.Tablength")); - panel.add(label, "gapleft para, gapright 40lp, growx 1"); - - final DoubleModel mtl = new DoubleModel(component, "TabLength", UnitGroup.UNITS_LENGTH, 0); - - spin = new JSpinner(mtl.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin, "growx 1"); - - panel.add(new UnitSelector(mtl), "growx 1"); - panel.add(new BasicSlider(mtl.getSliderModel(DoubleModel.ZERO, length)), - "w 100lp, growx 5, wrap"); - - - //// Tab length - //// Tab height: - label = new JLabel(trans.get("FinSetConfig.lbl.Tabheight")); - //// The spanwise height of the fin tab. - label.setToolTipText(trans.get("FinSetConfig.ttip.Tabheight")); - panel.add(label, "gapleft para"); - - final DoubleModel mth = new DoubleModel(component, "TabHeight", UnitGroup.UNITS_LENGTH, 0); - - spin = new JSpinner(mth.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin, "growx"); - - panel.add(new UnitSelector(mth), "growx"); - panel.add(new BasicSlider(mth.getSliderModel(DoubleModel.ZERO, length2)), - "w 100lp, growx 5, wrap para"); - - //// Tab position: - label = new JLabel(trans.get("FinSetConfig.lbl.Tabposition")); - //// The position of the fin tab. - label.setToolTipText(trans.get("FinSetConfig.ttip.Tabposition")); - panel.add(label, "gapleft para"); - - final DoubleModel mts = new DoubleModel(component, "TabShift", UnitGroup.UNITS_LENGTH); - - spin = new JSpinner(mts.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin, "growx"); - - panel.add(new UnitSelector(mts), "growx"); - panel.add(new BasicSlider(mts.getSliderModel(length_2, length2)), "w 100lp, growx 5, wrap"); - - - //// relative to - label = new JLabel(trans.get("FinSetConfig.lbl.relativeto")); - panel.add(label, "right, gapright unrel"); - - final EnumModel em = - new EnumModel(component, "TabRelativePosition"); - - panel.add(new JComboBox(em), "spanx 3, growx"); - - calcHeight = new JButton(trans.get("FinSetConfig.but.Calcheight")); - - // Calculate fin tab height, length, and position - calcHeight.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.user("Computing " + component.getComponentName() + " tab height."); - - // Do change in future for overall safety - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - RocketComponent parent = component.getParent(); - if (parent instanceof Coaxial) { - List children = parent.getChildren(); - List rings = new ArrayList(); - - ComponentConfigDialog.addUndoPosition("Compute fin tab height"); - for (int i = 0; i < children.size(); i++) { - RocketComponent rocketComponent = children.get(i); - if (rocketComponent instanceof InnerTube) { - InnerTube it = (InnerTube) rocketComponent; - if (it.isMotorMount()) { - double depth = ((Coaxial) parent).getOuterRadius() - it.getOuterRadius(); - //Set fin tab depth - if (depth >= 0.0d) { - mth.setValue(depth); - mth.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit()); - } - } - } else if (rocketComponent instanceof CenteringRing) { - rings.add((CenteringRing) rocketComponent); - } - } - //Figure out position and length of the fin tab - if (!rings.isEmpty()) { - FinSet.TabRelativePosition temp = (FinSet.TabRelativePosition) em.getSelectedItem(); - em.setSelectedItem(FinSet.TabRelativePosition.FRONT); - double len = computeFinTabLength(rings, component.asPositionValue(RocketComponent.Position.TOP), - component.getLength(), mts); - mtl.setValue(len); - //Be nice to the user and set the tab relative position enum back the way they had it. - em.setSelectedItem(temp); - } - } - } - }); - } - }); - panel.add(calcHeight, "right, gapright unrel"); - - return panel; - } - - /** - * Scenarios: - *

- * 1. All rings ahead of start of fin. - * 2. First ring ahead of start of fin. Second ring ahead of end of fin. - * 3. First ring ahead of start of fin. Second ring behind end of fin. - * 4. First ring equal or behind start of fin. Second ring ahead of, or equal to, end of fin. - * 5. First ring equal or behind start of fin. Second ring behind end of fin. - * 6. All rings behind end of fin. - * - * @param rings an unordered list of centering rings attached to the parent of the fin set - * @param finPositionFromTop the position from the top of the parent of the start of the fin set root - * @param finLength the length of the root chord - * @param mts the model for the tab shift (position); the model's value is modified as a result of this method call - * @return the length of the fin tab - */ - private static double computeFinTabLength(List rings, Double finPositionFromTop, Double finLength, DoubleModel mts) { - List positionsFromTop = new ArrayList(); - - //Fin tabs will be computed between the last two rings that meet the criteria, represented by top and bottom here. - SortableRing top = null; - SortableRing bottom = null; - - if (rings != null) { - //Sort rings from top of parent to bottom - Collections.sort(rings, new Comparator() { - @Override - public int compare(CenteringRing centeringRing, CenteringRing centeringRing1) { - return (int) (1000d * (centeringRing.asPositionValue(RocketComponent.Position.TOP) - - centeringRing1.asPositionValue(RocketComponent.Position.TOP))); - } - }); - - for (int i = 0; i < rings.size(); i++) { - CenteringRing centeringRing = rings.get(i); - //Handle centering rings that overlap or are adjacent by synthetically merging them into one virtual ring. - if (!positionsFromTop.isEmpty() && - positionsFromTop.get(positionsFromTop.size() - 1).bottomSidePositionFromTop() >= centeringRing.asPositionValue(RocketComponent.Position.TOP)) { - SortableRing adjacent = positionsFromTop.get(positionsFromTop.size() - 1); - adjacent.merge(centeringRing); - } else { - positionsFromTop.add(new SortableRing(centeringRing)); - } - } - - for (int i = 0; i < positionsFromTop.size(); i++) { - SortableRing sortableRing = positionsFromTop.get(i); - if (top == null) { - top = sortableRing; - } else if (sortableRing.bottomSidePositionFromTop() <= finPositionFromTop) { - top = sortableRing; - bottom = null; - } else if (top.bottomSidePositionFromTop() <= finPositionFromTop) { - if (bottom == null) { - //If the current ring is in the upper half of the root chord, make it the top ring - if (sortableRing.bottomSidePositionFromTop() < finPositionFromTop + finLength / 2d) { - top = sortableRing; - } else { - bottom = sortableRing; - } - } - //Is the ring even with or above the end of the root chord? If so, make the existing bottom the top ring, - //and the current ring the bottom - else if (sortableRing.positionFromTop() <= finPositionFromTop + finLength) { - top = bottom; - bottom = sortableRing; - } - } else { - if (bottom == null) { - bottom = sortableRing; - } - } - } - } - - // Edge case where there are no centering rings or for some odd reason top and bottom are identical. - if (top == null || top == bottom) { - mts.setValue(0); - return finLength; - } - - if (bottom == null) { - // If there is no bottom ring and the top ring's bottom edge is within the span of the root chord, then - // set the position of the fin tab starting at the bottom side of the top ring. - if (top.bottomSidePositionFromTop() >= finPositionFromTop) { - mts.setValue(top.bottomSidePositionFromTop() - finPositionFromTop); - return (finPositionFromTop + finLength - top.bottomSidePositionFromTop()); - } else { - // Otherwise the top ring is outside the span of the root chord so set the tab length to be the entire - // root chord. - mts.setValue(0); - return finLength; - } - } - // If the bottom edge of the top centering ring is above the start of the fin's root chord, then make the - // fin tab align with the start of the root chord. - if (top.bottomSidePositionFromTop() < finPositionFromTop) { - mts.setValue(0); - return bottom.positionFromTop - finPositionFromTop; - } else { - // Otherwise the rings are within the span of the root chord. Place the tab between them. - mts.setValue(top.bottomSidePositionFromTop() - finPositionFromTop); - return (bottom.positionFromTop() - top.bottomSidePositionFromTop()); - } - } - - @Override - public void updateFields() { - super.updateFields(); - if (split != null) - split.setEnabled(((FinSet) component).getFinCount() > 1); - } - - /** - * A container class to store pertinent info about centering rings. This is used in the computation to figure - * out tab length and position. - */ - static class SortableRing { - - /** - * The length of the ring (more commonly called the thickness). - */ - private double thickness; - /** - * The position of the ring from the top of the parent. - */ - private double positionFromTop; - - /** - * Constructor. - * - * @param r the source centering ring - */ - SortableRing(CenteringRing r) { - thickness = r.getLength(); - positionFromTop = r.asPositionValue(RocketComponent.Position.TOP); - } - - /** - * Merge an adjacent ring. - * - * @param adjacent the adjacent ring - */ - public void merge(CenteringRing adjacent) { - double v = adjacent.asPositionValue(RocketComponent.Position.TOP); - if (positionFromTop < v) { - thickness = (v + adjacent.getLength()) - positionFromTop; - } else { - double tmp = positionFromTop + thickness; - positionFromTop = v; - thickness = tmp - v; - } - } - - /** - * Compute the position of the bottom edge of the ring, relative to the top of the parent. - * - * @return the distance from the top of the parent to the bottom edge of the ring - */ - public double bottomSidePositionFromTop() { - return positionFromTop + thickness; - } - - /** - * Compute the position of the top edge of the ring, relative to the top of the parent. - * - * @return the distance from the top of the parent to the top edge of the ring - */ - public double positionFromTop() { - return positionFromTop; - } - } + private static final LogHelper log = Application.getLogger(); + private static final Translator trans = Application.getTranslator(); + + private JButton split = null; + + public FinSetConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); + + //// Fin tabs and Through-the-wall fin tabs + tabbedPane.insertTab(trans.get("FinSetConfig.tab.Fintabs"), null, finTabPanel(), + trans.get("FinSetConfig.tab.Through-the-wall"), 0); + } + + + protected void addFinSetButtons() { + JButton convert = null; + + //// Convert buttons + if (!(component instanceof FreeformFinSet)) { + //// Convert to freeform + convert = new JButton(trans.get("FinSetConfig.but.Converttofreeform")); + //// Convert this fin set into a freeform fin set + convert.setToolTipText(trans.get("FinSetConfig.but.Converttofreeform.ttip")); + convert.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + log.user("Converting " + component.getComponentName() + " into freeform fin set"); + + // Do change in future for overall safety + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + //// Convert fin set + document.addUndoPosition(trans.get("FinSetConfig.Convertfinset")); + RocketComponent freeform = + FreeformFinSet.convertFinSet((FinSet) component); + ComponentConfigDialog.showDialog(freeform); + } + }); + + ComponentConfigDialog.hideDialog(); + } + }); + } + + //// Split fins + split = new JButton(trans.get("FinSetConfig.but.Splitfins")); + //// Split the fin set into separate fins + split.setToolTipText(trans.get("FinSetConfig.but.Splitfins.ttip")); + split.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + log.user("Splitting " + component.getComponentName() + " into separate fins, fin count=" + + ((FinSet) component).getFinCount()); + + // Do change in future for overall safety + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + RocketComponent parent = component.getParent(); + int index = parent.getChildPosition(component); + int count = ((FinSet) component).getFinCount(); + double base = ((FinSet) component).getBaseRotation(); + if (count <= 1) + return; + + document.addUndoPosition("Split fin set"); + parent.removeChild(index); + for (int i = 0; i < count; i++) { + FinSet copy = (FinSet) component.copy(); + copy.setFinCount(1); + copy.setBaseRotation(base + i * 2 * Math.PI / count); + copy.setName(copy.getName() + " #" + (i + 1)); + parent.addChild(copy, index + i); + } + } + }); + + ComponentConfigDialog.hideDialog(); + } + }); + split.setEnabled(((FinSet) component).getFinCount() > 1); + + if (convert == null) + addButtons(split); + else + addButtons(split, convert); + + } + + public JPanel finTabPanel() { + JPanel panel = new JPanel( + new MigLayout("align 50% 20%, fillx, gap rel unrel, ins 20lp 10% 20lp 10%", + "[150lp::][65lp::][30lp::][200lp::]", "")); + // JPanel panel = new JPanel(new MigLayout("fillx, align 20% 20%, gap rel unrel", + // "[40lp][80lp::][30lp::][100lp::]","")); + + //// Through-the-wall fin tabs: + panel.add(new StyledLabel(trans.get("FinSetConfig.lbl.Through-the-wall"), Style.BOLD), + "spanx, wrap 30lp"); + + JLabel label; + DoubleModel length; + DoubleModel length2; + DoubleModel length_2; + JSpinner spin; + JButton autoCalc; + + length = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); + length2 = new DoubleModel(component, "Length", 0.5, UnitGroup.UNITS_LENGTH, 0); + length_2 = new DoubleModel(component, "Length", -0.5, UnitGroup.UNITS_LENGTH, 0); + + register(length); + register(length2); + register(length_2); + + //// Tab length + //// Tab length: + label = new JLabel(trans.get("FinSetConfig.lbl.Tablength")); + //// The length of the fin tab. + label.setToolTipText(trans.get("FinSetConfig.ttip.Tablength")); + panel.add(label, "gapleft para, gapright 40lp, growx 1"); + + final DoubleModel mtl = new DoubleModel(component, "TabLength", UnitGroup.UNITS_LENGTH, 0); + + spin = new JSpinner(mtl.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + panel.add(spin, "growx 1"); + + panel.add(new UnitSelector(mtl), "growx 1"); + panel.add(new BasicSlider(mtl.getSliderModel(DoubleModel.ZERO, length)), + "w 100lp, growx 5, wrap"); + + + //// Tab length + //// Tab height: + label = new JLabel(trans.get("FinSetConfig.lbl.Tabheight")); + //// The spanwise height of the fin tab. + label.setToolTipText(trans.get("FinSetConfig.ttip.Tabheight")); + panel.add(label, "gapleft para"); + + final DoubleModel mth = new DoubleModel(component, "TabHeight", UnitGroup.UNITS_LENGTH, 0); + + spin = new JSpinner(mth.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(mth), "growx"); + panel.add(new BasicSlider(mth.getSliderModel(DoubleModel.ZERO, length2)), + "w 100lp, growx 5, wrap"); + + //// Tab position: + label = new JLabel(trans.get("FinSetConfig.lbl.Tabposition")); + //// The position of the fin tab. + label.setToolTipText(trans.get("FinSetConfig.ttip.Tabposition")); + panel.add(label, "gapleft para"); + + final DoubleModel mts = new DoubleModel(component, "TabShift", UnitGroup.UNITS_LENGTH); + + spin = new JSpinner(mts.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(mts), "growx"); + panel.add(new BasicSlider(mts.getSliderModel(length_2, length2)), "w 100lp, growx 5, wrap"); + + + //// relative to + label = new JLabel(trans.get("FinSetConfig.lbl.relativeto")); + panel.add(label, "right, gapright unrel"); + + final EnumModel em = + new EnumModel(component, "TabRelativePosition"); + + panel.add(new JComboBox(em), "spanx 3, growx, wrap para"); + + + // Calculate fin tab height, length, and position + autoCalc = new JButton(trans.get("FinSetConfig.but.AutoCalc")); + + autoCalc.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + log.user("Computing " + component.getComponentName() + " tab height."); + + RocketComponent parent = component.getParent(); + if (parent instanceof Coaxial) { + try { + document.startUndo("Compute fin tabs"); + + List children = parent.getChildren(); + List rings = new ArrayList(); + + for (int i = 0; i < children.size(); i++) { + RocketComponent rocketComponent = children.get(i); + if (rocketComponent instanceof InnerTube) { + InnerTube it = (InnerTube) rocketComponent; + if (it.isMotorMount()) { + double depth = ((Coaxial) parent).getOuterRadius() - it.getOuterRadius(); + //Set fin tab depth + if (depth >= 0.0d) { + mth.setValue(depth); + mth.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit()); + } + } + } else if (rocketComponent instanceof CenteringRing) { + rings.add((CenteringRing) rocketComponent); + } + } + //Figure out position and length of the fin tab + if (!rings.isEmpty()) { + FinSet.TabRelativePosition temp = (FinSet.TabRelativePosition) em.getSelectedItem(); + em.setSelectedItem(FinSet.TabRelativePosition.FRONT); + double len = computeFinTabLength(rings, component.asPositionValue(RocketComponent.Position.TOP), + component.getLength(), mts); + mtl.setValue(len); + //Be nice to the user and set the tab relative position enum back the way they had it. + em.setSelectedItem(temp); + } + + } finally { + document.stopUndo(); + } + } + } + }); + panel.add(autoCalc, "skip 1, spanx"); + + return panel; + } + + /** + * Scenarios: + *

+ * 1. All rings ahead of start of fin. + * 2. First ring ahead of start of fin. Second ring ahead of end of fin. + * 3. First ring ahead of start of fin. Second ring behind end of fin. + * 4. First ring equal or behind start of fin. Second ring ahead of, or equal to, end of fin. + * 5. First ring equal or behind start of fin. Second ring behind end of fin. + * 6. All rings behind end of fin. + * + * @param rings an unordered list of centering rings attached to the parent of the fin set + * @param finPositionFromTop the position from the top of the parent of the start of the fin set root + * @param finLength the length of the root chord + * @param mts the model for the tab shift (position); the model's value is modified as a result of this method call + * @return the length of the fin tab + */ + private static double computeFinTabLength(List rings, Double finPositionFromTop, Double finLength, DoubleModel mts) { + List positionsFromTop = new ArrayList(); + + //Fin tabs will be computed between the last two rings that meet the criteria, represented by top and bottom here. + SortableRing top = null; + SortableRing bottom = null; + + if (rings != null) { + //Sort rings from top of parent to bottom + Collections.sort(rings, new Comparator() { + @Override + public int compare(CenteringRing centeringRing, CenteringRing centeringRing1) { + return (int) (1000d * (centeringRing.asPositionValue(RocketComponent.Position.TOP) - + centeringRing1.asPositionValue(RocketComponent.Position.TOP))); + } + }); + + for (int i = 0; i < rings.size(); i++) { + CenteringRing centeringRing = rings.get(i); + //Handle centering rings that overlap or are adjacent by synthetically merging them into one virtual ring. + if (!positionsFromTop.isEmpty() && + positionsFromTop.get(positionsFromTop.size() - 1).bottomSidePositionFromTop() >= centeringRing.asPositionValue(RocketComponent.Position.TOP)) { + SortableRing adjacent = positionsFromTop.get(positionsFromTop.size() - 1); + adjacent.merge(centeringRing); + } else { + positionsFromTop.add(new SortableRing(centeringRing)); + } + } + + for (int i = 0; i < positionsFromTop.size(); i++) { + SortableRing sortableRing = positionsFromTop.get(i); + if (top == null) { + top = sortableRing; + } else if (sortableRing.bottomSidePositionFromTop() <= finPositionFromTop) { + top = sortableRing; + bottom = null; + } else if (top.bottomSidePositionFromTop() <= finPositionFromTop) { + if (bottom == null) { + //If the current ring is in the upper half of the root chord, make it the top ring + if (sortableRing.bottomSidePositionFromTop() < finPositionFromTop + finLength / 2d) { + top = sortableRing; + } else { + bottom = sortableRing; + } + } + //Is the ring even with or above the end of the root chord? If so, make the existing bottom the top ring, + //and the current ring the bottom + else if (sortableRing.positionFromTop() <= finPositionFromTop + finLength) { + top = bottom; + bottom = sortableRing; + } + } else { + if (bottom == null) { + bottom = sortableRing; + } + } + } + } + + // Edge case where there are no centering rings or for some odd reason top and bottom are identical. + if (top == null || top == bottom) { + mts.setValue(0); + return finLength; + } + + if (bottom == null) { + // If there is no bottom ring and the top ring's bottom edge is within the span of the root chord, then + // set the position of the fin tab starting at the bottom side of the top ring. + if (top.bottomSidePositionFromTop() >= finPositionFromTop) { + mts.setValue(top.bottomSidePositionFromTop() - finPositionFromTop); + return (finPositionFromTop + finLength - top.bottomSidePositionFromTop()); + } else { + // Otherwise the top ring is outside the span of the root chord so set the tab length to be the entire + // root chord. + mts.setValue(0); + return finLength; + } + } + // If the bottom edge of the top centering ring is above the start of the fin's root chord, then make the + // fin tab align with the start of the root chord. + if (top.bottomSidePositionFromTop() < finPositionFromTop) { + mts.setValue(0); + return bottom.positionFromTop - finPositionFromTop; + } else { + // Otherwise the rings are within the span of the root chord. Place the tab between them. + mts.setValue(top.bottomSidePositionFromTop() - finPositionFromTop); + return (bottom.positionFromTop() - top.bottomSidePositionFromTop()); + } + } + + @Override + public void updateFields() { + super.updateFields(); + if (split != null) + split.setEnabled(((FinSet) component).getFinCount() > 1); + } + + /** + * A container class to store pertinent info about centering rings. This is used in the computation to figure + * out tab length and position. + */ + static class SortableRing { + + /** + * The length of the ring (more commonly called the thickness). + */ + private double thickness; + /** + * The position of the ring from the top of the parent. + */ + private double positionFromTop; + + /** + * Constructor. + * + * @param r the source centering ring + */ + SortableRing(CenteringRing r) { + thickness = r.getLength(); + positionFromTop = r.asPositionValue(RocketComponent.Position.TOP); + } + + /** + * Merge an adjacent ring. + * + * @param adjacent the adjacent ring + */ + public void merge(CenteringRing adjacent) { + double v = adjacent.asPositionValue(RocketComponent.Position.TOP); + if (positionFromTop < v) { + thickness = (v + adjacent.getLength()) - positionFromTop; + } else { + double tmp = positionFromTop + thickness; + positionFromTop = v; + thickness = tmp - v; + } + } + + /** + * Compute the position of the bottom edge of the ring, relative to the top of the parent. + * + * @return the distance from the top of the parent to the bottom edge of the ring + */ + public double bottomSidePositionFromTop() { + return positionFromTop + thickness; + } + + /** + * Compute the position of the top edge of the ring, relative to the top of the parent. + * + * @return the distance from the top of the parent to the top edge of the ring + */ + public double positionFromTop() { + return positionFromTop; + } + } } diff --git a/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java index 06c877c7..56609bcf 100644 --- a/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java @@ -17,6 +17,7 @@ import javax.swing.SwingConstants; import javax.swing.table.AbstractTableModel; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -50,8 +51,8 @@ public class FreeformFinSetConfig extends FinSetConfig { private FinPointFigure figure = null; - public FreeformFinSetConfig(RocketComponent component) { - super(component); + public FreeformFinSetConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); this.finset = (FreeformFinSet) component; //// General and General properties diff --git a/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java b/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java index 35347fd3..a1c69938 100644 --- a/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java @@ -27,6 +27,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.Resettable; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; @@ -47,25 +48,25 @@ import net.sf.openrocket.util.Coordinate; public class InnerTubeConfig extends ThicknessRingComponentConfig { private static final Translator trans = Application.getTranslator(); - - public InnerTubeConfig(RocketComponent c) { - super(c); + + public InnerTubeConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel tab; tab = new MotorConfig((MotorMount) c); //// Motor and Motor mount configuration - tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Motor"), null, tab, + tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Motor"), null, tab, trans.get("InnerTubeCfg.tab.ttip.Motor"), 1); tab = clusterTab(); //// Cluster and Cluster configuration - tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Cluster"), null, tab, + tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Cluster"), null, tab, trans.get("InnerTubeCfg.tab.ttip.Cluster"), 2); tab = positionTab(); //// Radial position - tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Radialpos"), null, tab, + tabbedPane.insertTab(trans.get("InnerTubeCfg.tab.Radialpos"), null, tab, trans.get("InnerTubeCfg.tab.ttip.Radialpos"), 3); tabbedPane.setSelectedIndex(0); @@ -156,7 +157,7 @@ public class InnerTubeConfig extends ThicknessRingComponentConfig { if (tube.getClusterCount() <= 1) return; - ComponentConfigDialog.addUndoPosition("Split cluster"); + document.addUndoPosition("Split cluster"); Coordinate[] coords = { Coordinate.NUL }; coords = component.shiftCoordinates(coords); diff --git a/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java b/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java index 56f1231f..947b205a 100644 --- a/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java @@ -1,7 +1,13 @@ package net.sf.openrocket.gui.configdialog; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; + import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -13,140 +19,135 @@ import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; - public class LaunchLugConfig extends RocketComponentConfig { - + private MotorConfig motorConfigPane = null; private static final Translator trans = Application.getTranslator(); - - public LaunchLugConfig(RocketComponent c) { - super(c); + + public LaunchLugConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel primary = new JPanel(new MigLayout("fill")); - - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::][]","")); + + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); //// Body tube length //// Length: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Length"))); - DoubleModel m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + DoubleModel m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.02, 0.1)),"w 100lp, wrap para"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.02, 0.1)), "w 100lp, wrap para"); + //// Body tube diameter //// Outer diameter: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Outerdiam"))); - - DoubleModel od = new DoubleModel(component,"OuterRadius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "OuterRadius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap rel"); - + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap rel"); + //// Inner diameter: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Innerdiam"))); - + // Diameter = 2*Radius - m = new DoubleModel(component,"InnerRadius",2,UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)),"w 100lp, wrap rel"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "w 100lp, wrap rel"); + //// Wall thickness //// Thickness: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Thickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap 20lp"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 20lp"); //// Radial position: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Radialpos"))); - m = new DoubleModel(component,"RadialDirection",UnitGroup.UNITS_ANGLE, + m = new DoubleModel(component, "RadialDirection", UnitGroup.UNITS_ANGLE, -Math.PI, Math.PI); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)),"w 100lp, wrap"); - - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + + + primary.add(panel, "grow, gapright 20lp"); - panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::][]","")); - - + panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); + + //// Position relative to: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"))); - + JComboBox combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel.add(combo,"spanx, growx, wrap"); + panel.add(combo, "spanx, growx, wrap"); //// plus - panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap para"); - - + + //// Material materialPanel(panel, Material.Type.BULK); - - primary.add(panel,"grow"); + + primary.add(panel, "grow"); //// General and General properties - tabbedPane.insertTab(trans.get("LaunchLugCfg.tab.General"), null, primary, + tabbedPane.insertTab(trans.get("LaunchLugCfg.tab.General"), null, primary, trans.get("LaunchLugCfg.tab.Generalprop"), 0); tabbedPane.setSelectedIndex(0); } diff --git a/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java index 659714f4..b199d209 100644 --- a/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java @@ -3,7 +3,6 @@ package net.sf.openrocket.gui.configdialog; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; - import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; @@ -11,6 +10,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -25,125 +25,125 @@ import net.sf.openrocket.unit.UnitGroup; public class MassComponentConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); - - public MassComponentConfig(RocketComponent component) { - super(component); - - - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); - + + public MassComponentConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); + + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); + + //// Mass panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Mass"))); - DoubleModel m = new DoubleModel(component,"ComponentMass",UnitGroup.UNITS_MASS,0); + DoubleModel m = new DoubleModel(component, "ComponentMass", UnitGroup.UNITS_MASS, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.5)),"w 100lp, wrap"); - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.5)), "w 100lp, wrap"); + + //// Mass length //// Length panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Length"))); - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)), "w 100lp, wrap"); + //// Tube diameter //// Diameter: panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Diameter"))); - - DoubleModel od = new DoubleModel(component,"Radius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "Radius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap"); - + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap"); + //// Position //// Position relative to: panel.add(new JLabel(trans.get("MassComponentCfg.lbl.PosRelativeto"))); - + JComboBox combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel.add(combo,"spanx, growx, wrap"); + panel.add(combo, "spanx, growx, wrap"); //// plus - panel.add(new JLabel(trans.get("MassComponentCfg.lbl.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel.add(new JLabel(trans.get("MassComponentCfg.lbl.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap"); - + //// General and General properties - tabbedPane.insertTab(trans.get("MassComponentCfg.tab.General"), null, panel, + tabbedPane.insertTab(trans.get("MassComponentCfg.tab.General"), null, panel, trans.get("MassComponentCfg.tab.ttip.General"), 0); //// Radial position and Radial position configuration - tabbedPane.insertTab(trans.get("MassComponentCfg.tab.Radialpos"), null, positionTab(), + tabbedPane.insertTab(trans.get("MassComponentCfg.tab.Radialpos"), null, positionTab(), trans.get("MassComponentCfg.tab.ttip.Radialpos"), 1); tabbedPane.setSelectedIndex(0); } protected JPanel positionTab() { - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); //// Radial position //// Radial distance: panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Radialdistance"))); - DoubleModel m = new DoubleModel(component,"RadialPosition",UnitGroup.UNITS_LENGTH,0); + DoubleModel m = new DoubleModel(component, "RadialPosition", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap"); + //// Radial direction: panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Radialdirection"))); - m = new DoubleModel(component,"RadialDirection",UnitGroup.UNITS_ANGLE,0); + m = new DoubleModel(component, "RadialDirection", UnitGroup.UNITS_ANGLE, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)),"w 100lp, wrap"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + //// Reset button JButton button = new JButton(trans.get("MassComponentCfg.but.Reset")); button.addActionListener(new ActionListener() { @@ -153,7 +153,7 @@ public class MassComponentConfig extends RocketComponentConfig { ((MassComponent) component).setRadialPosition(0.0); } }); - panel.add(button,"spanx, right"); + panel.add(button, "spanx, right"); return panel; } diff --git a/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java b/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java index a9d4f61a..682f6d35 100644 --- a/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java @@ -12,6 +12,7 @@ import javax.swing.JSlider; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; @@ -27,7 +28,7 @@ import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; public class NoseConeConfig extends RocketComponentConfig { - + private JComboBox typeBox; private DescriptionArea description; @@ -36,146 +37,147 @@ public class NoseConeConfig extends RocketComponentConfig { private JSpinner shapeSpinner; private JSlider shapeSlider; private static final Translator trans = Application.getTranslator(); - + // Prepended to the description from NoseCone.DESCRIPTIONS private static final String PREDESC = ""; - public NoseConeConfig(RocketComponent c) { - super(c); + public NoseConeConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); DoubleModel m; - JPanel panel = new JPanel(new MigLayout("","[][65lp::][30lp::]")); - - + JPanel panel = new JPanel(new MigLayout("", "[][65lp::][30lp::]")); + + //// Shape selection //// Nose cone shape: panel.add(new JLabel(trans.get("NoseConeCfg.lbl.Noseconeshape"))); - - Transition.Shape selected = ((NoseCone)component).getType(); + + Transition.Shape selected = ((NoseCone) component).getType(); Transition.Shape[] typeList = Transition.Shape.values(); typeBox = new JComboBox(typeList); typeBox.setEditable(false); typeBox.setSelectedItem(selected); typeBox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - Transition.Shape s = (Transition.Shape)typeBox.getSelectedItem(); - ((NoseCone)component).setType(s); + Transition.Shape s = (Transition.Shape) typeBox.getSelectedItem(); + ((NoseCone) component).setType(s); description.setText(PREDESC + s.getNoseConeDescription()); updateEnabled(); } }); - panel.add(typeBox,"span, wrap rel"); - - + panel.add(typeBox, "span, wrap rel"); + + //// Shape parameter //// Shape parameter: shapeLabel = new JLabel(trans.get("NoseConeCfg.lbl.Shapeparam")); panel.add(shapeLabel); - m = new DoubleModel(component,"ShapeParameter"); + m = new DoubleModel(component, "ShapeParameter"); shapeSpinner = new JSpinner(m.getSpinnerModel()); shapeSpinner.setEditor(new SpinnerEditor(shapeSpinner)); - panel.add(shapeSpinner,"growx"); + panel.add(shapeSpinner, "growx"); - DoubleModel min = new DoubleModel(component,"ShapeParameterMin"); - DoubleModel max = new DoubleModel(component,"ShapeParameterMax"); - shapeSlider = new BasicSlider(m.getSliderModel(min,max)); - panel.add(shapeSlider,"skip, w 100lp, wrap para"); + DoubleModel min = new DoubleModel(component, "ShapeParameterMin"); + DoubleModel max = new DoubleModel(component, "ShapeParameterMax"); + shapeSlider = new BasicSlider(m.getSliderModel(min, max)); + panel.add(shapeSlider, "skip, w 100lp, wrap para"); updateEnabled(); - + //// Length //// Nose cone length: panel.add(new JLabel(trans.get("NoseConeCfg.lbl.Noseconelength"))); - - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.7)),"w 100lp, wrap"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.7)), "w 100lp, wrap"); //// Diameter //// Base diameter: panel.add(new JLabel(trans.get("NoseConeCfg.lbl.Basediam"))); - - m = new DoubleModel(component,"AftRadius",2.0,UnitGroup.UNITS_LENGTH,0); // Diameter = 2*Radius + + m = new DoubleModel(component, "AftRadius", 2.0, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap 0px"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); JCheckBox check = new JCheckBox(m.getAutomaticAction()); //// Automatic check.setText(trans.get("NoseConeCfg.checkbox.Automatic")); - panel.add(check,"skip, span 2, wrap"); + panel.add(check, "skip, span 2, wrap"); //// Wall thickness: panel.add(new JLabel(trans.get("NoseConeCfg.lbl.Wallthickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap 0px"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 0px"); - check = new JCheckBox(new BooleanModel(component,"Filled")); + check = new JCheckBox(new BooleanModel(component, "Filled")); //// Filled check.setText(trans.get("NoseConeCfg.checkbox.Filled")); - panel.add(check,"skip, span 2, wrap"); - + panel.add(check, "skip, span 2, wrap"); + panel.add(new JLabel(""), "growy"); - - + + //// Description JPanel panel2 = new JPanel(new MigLayout("ins 0")); description = new DescriptionArea(5); - description.setText(PREDESC + ((NoseCone)component).getType().getNoseConeDescription()); + description.setText(PREDESC + ((NoseCone) component).getType().getNoseConeDescription()); panel2.add(description, "wmin 250lp, spanx, growx, wrap para"); //// Material - + materialPanel(panel2, Material.Type.BULK); panel.add(panel2, "cell 4 0, gapleft paragraph, aligny 0%, spany"); //// General and General properties - tabbedPane.insertTab(trans.get("NoseConeCfg.tab.General"), null, panel, + tabbedPane.insertTab(trans.get("NoseConeCfg.tab.General"), null, panel, trans.get("NoseConeCfg.tab.ttip.General"), 0); //// Shoulder and Shoulder properties - tabbedPane.insertTab(trans.get("NoseConeCfg.tab.Shoulder"), null, shoulderTab(), + tabbedPane.insertTab(trans.get("NoseConeCfg.tab.Shoulder"), null, shoulderTab(), trans.get("NoseConeCfg.tab.ttip.Shoulder"), 1); tabbedPane.setSelectedIndex(0); } - + private void updateEnabled() { - boolean e = ((NoseCone)component).getType().usesParameter(); + boolean e = ((NoseCone) component).getType().usesParameter(); shapeLabel.setEnabled(e); shapeSpinner.setEnabled(e); shapeSlider.setEnabled(e); } - + } diff --git a/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java b/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java index 4dcd5104..311b42af 100644 --- a/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java @@ -11,6 +11,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -19,263 +20,263 @@ import net.sf.openrocket.gui.adaptors.MaterialModel; import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.HtmlLabel; import net.sf.openrocket.gui.components.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.components.StyledLabel.Style; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.MassObject; +import net.sf.openrocket.rocketcomponent.MotorMount.IgnitionEvent; import net.sf.openrocket.rocketcomponent.Parachute; import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.rocketcomponent.MotorMount.IgnitionEvent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; public class ParachuteConfig extends RecoveryDeviceConfig { private static final Translator trans = Application.getTranslator(); - - public ParachuteConfig(final RocketComponent component) { - super(component); - - JPanel primary = new JPanel(new MigLayout()); + + public ParachuteConfig(OpenRocketDocument d, final RocketComponent component) { + super(d, component); - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::][]","")); + JPanel primary = new JPanel(new MigLayout()); + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); + //// Canopy panel.add(new StyledLabel(trans.get("ParachuteCfg.lbl.Canopy"), Style.BOLD), "wrap unrel"); //// Diameter: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Diameter"))); - DoubleModel m = new DoubleModel(component,"Diameter",UnitGroup.UNITS_LENGTH,0); + DoubleModel m = new DoubleModel(component, "Diameter", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.4, 1.5)),"w 100lp, wrap"); - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.4, 1.5)), "w 100lp, wrap"); + //// Material: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Material"))); - JComboBox combo = new JComboBox(new MaterialModel(panel, component, + JComboBox combo = new JComboBox(new MaterialModel(panel, component, Material.Type.SURFACE)); //// The component material affects the weight of the component. combo.setToolTipText(trans.get("ParachuteCfg.combo.MaterialModel")); - panel.add(combo,"spanx 3, growx, wrap paragraph"); - -// materialPanel(panel, Material.Type.SURFACE, "Material:", null); - + panel.add(combo, "spanx 3, growx, wrap paragraph"); + // materialPanel(panel, Material.Type.SURFACE, "Material:", null); + + // CD //// Drag coefficient CD: JLabel label = new HtmlLabel(trans.get("ParachuteCfg.lbl.longA1")); String tip = trans.get("ParachuteCfg.lbl.longB1") + - trans.get("ParachuteCfg.lbl.longB2") + " " + - trans.get("ParachuteCfg.lbl.longB3"); + trans.get("ParachuteCfg.lbl.longB2") + " " + + trans.get("ParachuteCfg.lbl.longB3"); label.setToolTipText(tip); panel.add(label); - m = new DoubleModel(component,"CD",UnitGroup.UNITS_COEFFICIENT,0); + m = new DoubleModel(component, "CD", UnitGroup.UNITS_COEFFICIENT, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setToolTipText(tip); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); //// Reset button JButton button = new JButton(trans.get("ParachuteCfg.but.Reset")); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - Parachute p = (Parachute)component; + Parachute p = (Parachute) component; p.setCD(Parachute.DEFAULT_CD); } }); - panel.add(button,"spanx, wrap 30lp"); - - + panel.add(button, "spanx, wrap 30lp"); + + //// Shroud lines panel.add(new StyledLabel(trans.get("ParachuteCfg.lbl.Shroudlines"), Style.BOLD), "wrap unrel"); - + //// Number of lines: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Numberoflines"))); - IntegerModel im = new IntegerModel(component,"LineCount",0); + IntegerModel im = new IntegerModel(component, "LineCount", 0); spin = new JSpinner(im.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx, wrap"); + panel.add(spin, "growx, wrap"); //// Line length: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Linelength"))); - - m = new DoubleModel(component,"LineLength",UnitGroup.UNITS_LENGTH,0); + + m = new DoubleModel(component, "LineLength", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.4, 1.5)),"w 100lp, wrap"); - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.4, 1.5)), "w 100lp, wrap"); + //// Material: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Material"))); - combo = new JComboBox(new MaterialModel(panel, component, Material.Type.LINE, + combo = new JComboBox(new MaterialModel(panel, component, Material.Type.LINE, "LineMaterial")); - panel.add(combo,"spanx 3, growx, wrap"); - - + panel.add(combo, "spanx 3, growx, wrap"); - primary.add(panel, "grow, gapright 20lp"); - panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::][]","")); + + primary.add(panel, "grow, gapright 20lp"); + panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); - - + + + //// Position //// Position relative to: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Posrelativeto"))); - + combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel.add(combo,"spanx, growx, wrap"); + panel.add(combo, "spanx, growx, wrap"); //// plus - panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap"); - + //// Spatial length //// Packed length: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Packedlength"))); - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)), "w 100lp, wrap"); + //// Tube diameter //// Packed diameter: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Packeddiam"))); - - DoubleModel od = new DoubleModel(component,"Radius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "Radius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap 30lp"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 30lp"); + //// Deployment //// Deploys at: - panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")),""); + panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")), ""); combo = new JComboBox(new EnumModel(component, "DeployEvent")); - panel.add(combo,"spanx 3, growx, wrap"); + panel.add(combo, "spanx 3, growx, wrap"); // ... and delay //// plus - panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plusdelay")),"right"); + panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plusdelay")), "right"); - m = new DoubleModel(component,"DeployDelay",0); + m = new DoubleModel(component, "DeployDelay", 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"spanx, split"); + panel.add(spin, "spanx, split"); //// seconds - panel.add(new JLabel(trans.get("ParachuteCfg.lbl.seconds")),"wrap paragraph"); - + panel.add(new JLabel(trans.get("ParachuteCfg.lbl.seconds")), "wrap paragraph"); + // Altitude: label = new JLabel(trans.get("ParachuteCfg.lbl.Altitude")); altitudeComponents.add(label); panel.add(label); - m = new DoubleModel(component,"DeployAltitude",UnitGroup.UNITS_DISTANCE,0); + m = new DoubleModel(component, "DeployAltitude", UnitGroup.UNITS_DISTANCE, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); altitudeComponents.add(spin); - panel.add(spin,"growx"); + panel.add(spin, "growx"); UnitSelector unit = new UnitSelector(m); altitudeComponents.add(unit); - panel.add(unit,"growx"); + panel.add(unit, "growx"); BasicSlider slider = new BasicSlider(m.getSliderModel(100, 1000)); altitudeComponents.add(slider); - panel.add(slider,"w 100lp, wrap"); - + panel.add(slider, "w 100lp, wrap"); + primary.add(panel, "grow"); updateFields(); - + //// General and General properties tabbedPane.insertTab(trans.get("ParachuteCfg.tab.General"), null, primary, trans.get("ParachuteCfg.tab.ttip.General"), 0); //// Radial position and Radial position configuration - tabbedPane.insertTab(trans.get("ParachuteCfg.tab.Radialpos"), null, positionTab(), + tabbedPane.insertTab(trans.get("ParachuteCfg.tab.Radialpos"), null, positionTab(), trans.get("ParachuteCfg.tab.ttip.Radialpos"), 1); tabbedPane.setSelectedIndex(0); } - + protected JPanel positionTab() { - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); //// Radial position //// Radial distance: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Radialdistance"))); - DoubleModel m = new DoubleModel(component,"RadialPosition",UnitGroup.UNITS_LENGTH,0); + DoubleModel m = new DoubleModel(component, "RadialPosition", UnitGroup.UNITS_LENGTH, 0); JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap"); + //// Radial direction: panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Radialdirection"))); - m = new DoubleModel(component,"RadialDirection",UnitGroup.UNITS_ANGLE,0); + m = new DoubleModel(component, "RadialDirection", UnitGroup.UNITS_ANGLE, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)),"w 100lp, wrap"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + //// Reset button JButton button = new JButton(trans.get("ParachuteCfg.but.Reset")); button.addActionListener(new ActionListener() { @@ -285,7 +286,7 @@ public class ParachuteConfig extends RecoveryDeviceConfig { ((MassObject) component).setRadialPosition(0.0); } }); - panel.add(button,"spanx, right"); + panel.add(button, "spanx, right"); return panel; } diff --git a/src/net/sf/openrocket/gui/configdialog/RecoveryDeviceConfig.java b/src/net/sf/openrocket/gui/configdialog/RecoveryDeviceConfig.java index a6b2ef8a..f93613c9 100644 --- a/src/net/sf/openrocket/gui/configdialog/RecoveryDeviceConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RecoveryDeviceConfig.java @@ -5,20 +5,21 @@ import java.util.List; import javax.swing.JComponent; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RocketComponent; public abstract class RecoveryDeviceConfig extends RocketComponentConfig { - + protected final List altitudeComponents = new ArrayList(); - public RecoveryDeviceConfig(RocketComponent component) { - super(component); + public RecoveryDeviceConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); } - + @Override public void updateFields() { super.updateFields(); @@ -26,10 +27,10 @@ public abstract class RecoveryDeviceConfig extends RocketComponentConfig { if (altitudeComponents == null) return; - boolean enabled = (((RecoveryDevice)component).getDeployEvent() - == RecoveryDevice.DeployEvent.ALTITUDE); + boolean enabled = (((RecoveryDevice) component).getDeployEvent() + == RecoveryDevice.DeployEvent.ALTITUDE); - for (JComponent c: altitudeComponents) { + for (JComponent c : altitudeComponents) { c.setEnabled(enabled); } } diff --git a/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java index c520e66a..23906d6f 100644 --- a/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java @@ -12,6 +12,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -29,8 +30,8 @@ import net.sf.openrocket.unit.UnitGroup; public class RingComponentConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); - public RingComponentConfig(RocketComponent component) { - super(component); + public RingComponentConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); } diff --git a/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 3779f548..802434d7 100644 --- a/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -24,6 +24,7 @@ import javax.swing.JTextArea; import javax.swing.JTextField; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; @@ -40,7 +41,6 @@ import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish; import net.sf.openrocket.rocketcomponent.NoseCone; -import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; @@ -53,6 +53,7 @@ public class RocketComponentConfig extends JPanel { private static final Translator trans = Application.getTranslator(); + protected final OpenRocketDocument document; protected final RocketComponent component; protected final JTabbedPane tabbedPane; @@ -69,8 +70,9 @@ public class RocketComponentConfig extends JPanel { private JLabel massLabel; - public RocketComponentConfig(RocketComponent component) { + public RocketComponentConfig(OpenRocketDocument document, RocketComponent component) { setLayout(new MigLayout("fill", "[grow, fill]")); + this.document = document; this.component = component; //// Component name: @@ -92,14 +94,14 @@ public class RocketComponentConfig extends JPanel { this.add(tabbedPane, "growx, growy 1, wrap"); //// Override and Mass and CG override options - tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(), + tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(), trans.get("RocketCompCfg.tab.MassandCGoverride")); if (component.isMassive()) //// Figure and Figure style options - tabbedPane.addTab(trans.get("RocketCompCfg.tab.Figure"), null, figureTab(), + tabbedPane.addTab(trans.get("RocketCompCfg.tab.Figure"), null, figureTab(), trans.get("RocketCompCfg.tab.Figstyleopt")); //// Comment and Specify a comment for the component - tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(), + tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(), trans.get("RocketCompCfg.tab.Specifyacomment")); addButtons(); @@ -165,14 +167,14 @@ public class RocketComponentConfig extends JPanel { String overridetext = null; if (component.isMassOverridden()) { //// (overridden to - overridetext = trans.get("RocketCompCfg.lbl.overriddento")+" " + UnitGroup.UNITS_MASS.getDefaultUnit(). + overridetext = trans.get("RocketCompCfg.lbl.overriddento") + " " + UnitGroup.UNITS_MASS.getDefaultUnit(). toStringUnit(component.getOverrideMass()) + ")"; } for (RocketComponent c = component.getParent(); c != null; c = c.getParent()) { if (c.isMassOverridden() && c.getOverrideSubcomponents()) { ///// (overridden by - overridetext = trans.get("RocketCompCfg.lbl.overriddenby")+" " + c.getName() + ")"; + overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + c.getName() + ")"; } } @@ -226,24 +228,19 @@ public class RocketComponentConfig extends JPanel { @Override public void actionPerformed(ActionEvent e) { Finish f = ((ExternalComponent) component).getFinish(); - Rocket rocket = component.getRocket(); try { - rocket.freeze(); - // Store previous undo description - String desc = ComponentConfigDialog.getUndoDescription(); - ComponentConfigDialog.addUndoPosition("Set rocket finish"); + document.startUndo("Set rocket finish"); + // Do changes - Iterator iter = rocket.iterator(); + Iterator iter = component.getRoot().iterator(); while (iter.hasNext()) { RocketComponent c = iter.next(); if (c instanceof ExternalComponent) { ((ExternalComponent) c).setFinish(f); } } - // Restore undo description - ComponentConfigDialog.addUndoPosition(desc); } finally { - rocket.thaw(); + document.stopUndo(); } } }); @@ -337,7 +334,7 @@ public class RocketComponentConfig extends JPanel { //// The overridden mass does not include motors.
panel.add(new StyledLabel(trans.get("RocketCompCfg.lbl.longB1") + //// The center of gravity is measured from the front end of the - trans.get("RocketCompCfg.lbl.longB2") +" " + + trans.get("RocketCompCfg.lbl.longB2") + " " + component.getComponentName().toLowerCase() + ".", -1), "spanx, wrap, gap para, height 0::30lp"); @@ -349,7 +346,7 @@ public class RocketComponentConfig extends JPanel { JPanel panel = new JPanel(new MigLayout("fill")); //// Comments on the - panel.add(new StyledLabel(trans.get("RocketCompCfg.lbl.Commentsonthe") +" " + component.getComponentName() + ":", + panel.add(new StyledLabel(trans.get("RocketCompCfg.lbl.Commentsonthe") + " " + component.getComponentName() + ":", Style.BOLD), "wrap"); // TODO: LOW: Changes in comment from other sources not reflected in component diff --git a/src/net/sf/openrocket/gui/configdialog/RocketConfig.java b/src/net/sf/openrocket/gui/configdialog/RocketConfig.java index 07be2395..701295c2 100644 --- a/src/net/sf/openrocket/gui/configdialog/RocketConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/RocketConfig.java @@ -11,6 +11,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; @@ -27,8 +28,8 @@ public class RocketConfig extends RocketComponentConfig { private final Rocket rocket; - public RocketConfig(RocketComponent c) { - super(c); + public RocketConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); rocket = (Rocket) c; diff --git a/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java b/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java index 0a21fc4c..fbc99f85 100644 --- a/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java @@ -7,6 +7,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -20,17 +21,17 @@ import net.sf.openrocket.unit.UnitGroup; public class ShockCordConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); - - public ShockCordConfig(RocketComponent component) { - super(component); + + public ShockCordConfig(OpenRocketDocument d, RocketComponent component) { + super(d, component); - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); JLabel label; DoubleModel m; JSpinner spin; String tip; - + ////// Left side // Cord length @@ -38,14 +39,14 @@ public class ShockCordConfig extends RocketComponentConfig { label = new JLabel(trans.get("ShockCordCfg.lbl.Shockcordlength")); panel.add(label); - m = new DoubleModel(component,"CordLength",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "CordLength", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 1, 10)),"w 100lp, wrap"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 1, 10)), "w 100lp, wrap"); // Material @@ -53,77 +54,77 @@ public class ShockCordConfig extends RocketComponentConfig { materialPanel(panel, Material.Type.LINE, trans.get("ShockCordCfg.lbl.Shockcordmaterial"), null); - + ///// Right side - JPanel panel2 = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + JPanel panel2 = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); panel.add(panel2, "cell 4 0, gapleft paragraph, aligny 0%, spany"); - + //// Position //// Position relative to: panel2.add(new JLabel(trans.get("ShockCordCfg.lbl.Posrelativeto"))); - + JComboBox combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel2.add(combo,"spanx, growx, wrap"); + panel2.add(combo, "spanx, growx, wrap"); //// plus - panel2.add(new JLabel(trans.get("ShockCordCfg.lbl.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel2.add(new JLabel(trans.get("ShockCordCfg.lbl.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel2.add(spin,"growx"); + panel2.add(spin, "growx"); - panel2.add(new UnitSelector(m),"growx"); + panel2.add(new UnitSelector(m), "growx"); panel2.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap"); - + //// Spatial length //// Packed length: panel2.add(new JLabel(trans.get("ShockCordCfg.lbl.Packedlength"))); - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel2.add(spin,"growx"); - - panel2.add(new UnitSelector(m),"growx"); - panel2.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)),"w 100lp, wrap"); + panel2.add(spin, "growx"); + panel2.add(new UnitSelector(m), "growx"); + panel2.add(new BasicSlider(m.getSliderModel(0, 0.1, 0.5)), "w 100lp, wrap"); + //// Tube diameter //// Packed diameter: panel2.add(new JLabel(trans.get("ShockCordCfg.lbl.Packeddiam"))); - - DoubleModel od = new DoubleModel(component,"Radius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "Radius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel2.add(spin,"growx"); - - panel2.add(new UnitSelector(od),"growx"); - panel2.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap"); - + panel2.add(spin, "growx"); + panel2.add(new UnitSelector(od), "growx"); + panel2.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap"); + + //// General and General properties tabbedPane.insertTab(trans.get("ShockCordCfg.tab.General"), null, panel, trans.get("ShockCordCfg.tab.ttip.General"), 0); -// tabbedPane.insertTab("Radial position", null, positionTab(), -// "Radial position configuration", 1); + // tabbedPane.insertTab("Radial position", null, positionTab(), + // "Radial position configuration", 1); tabbedPane.setSelectedIndex(0); } - + } diff --git a/src/net/sf/openrocket/gui/configdialog/SleeveConfig.java b/src/net/sf/openrocket/gui/configdialog/SleeveConfig.java index 67160b81..32192765 100644 --- a/src/net/sf/openrocket/gui/configdialog/SleeveConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/SleeveConfig.java @@ -3,6 +3,7 @@ package net.sf.openrocket.gui.configdialog; import javax.swing.JPanel; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; @@ -12,18 +13,18 @@ import net.sf.openrocket.startup.Application; public class SleeveConfig extends RingComponentConfig { private static final Translator trans = Application.getTranslator(); - public SleeveConfig(RocketComponent c) { - super(c); + public SleeveConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel tab; //// Outer diameter: //// Inner diameter: //// Wall thickness: //// Length: - tab = generalTab(trans.get("SleeveCfg.tab.Outerdiam"), trans.get("SleeveCfg.tab.Innerdiam"), + tab = generalTab(trans.get("SleeveCfg.tab.Outerdiam"), trans.get("SleeveCfg.tab.Innerdiam"), trans.get("SleeveCfg.tab.Wallthickness"), trans.get("SleeveCfg.tab.Length")); //// General and General properties - tabbedPane.insertTab(trans.get("SleeveCfg.tab.General"), null, tab, + tabbedPane.insertTab(trans.get("SleeveCfg.tab.General"), null, tab, trans.get("SleeveCfg.tab.Generalproperties"), 0); tabbedPane.setSelectedIndex(0); } diff --git a/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java b/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java index 3aef4acc..8d7be304 100644 --- a/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java @@ -12,6 +12,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -31,8 +32,8 @@ import net.sf.openrocket.unit.UnitGroup; public class StreamerConfig extends RecoveryDeviceConfig { private static final Translator trans = Application.getTranslator(); - public StreamerConfig(final RocketComponent component) { - super(component); + public StreamerConfig(OpenRocketDocument d, final RocketComponent component) { + super(d, component); JPanel primary = new JPanel(new MigLayout()); diff --git a/src/net/sf/openrocket/gui/configdialog/ThicknessRingComponentConfig.java b/src/net/sf/openrocket/gui/configdialog/ThicknessRingComponentConfig.java index 2b1bb6f3..3013b7c9 100644 --- a/src/net/sf/openrocket/gui/configdialog/ThicknessRingComponentConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/ThicknessRingComponentConfig.java @@ -3,6 +3,7 @@ package net.sf.openrocket.gui.configdialog; import javax.swing.JPanel; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; @@ -12,8 +13,8 @@ import net.sf.openrocket.startup.Application; public class ThicknessRingComponentConfig extends RingComponentConfig { private static final Translator trans = Application.getTranslator(); - public ThicknessRingComponentConfig(RocketComponent c) { - super(c); + public ThicknessRingComponentConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); JPanel tab; @@ -21,11 +22,11 @@ public class ThicknessRingComponentConfig extends RingComponentConfig { //// Inner diameter: //// Wall thickness: //// Length: - tab = generalTab(trans.get("ThicknessRingCompCfg.tab.Outerdiam"), + tab = generalTab(trans.get("ThicknessRingCompCfg.tab.Outerdiam"), trans.get("ThicknessRingCompCfg.tab.Innerdiam"), trans.get("ThicknessRingCompCfg.tab.Wallthickness"), trans.get("ThicknessRingCompCfg.tab.Length")); //// General and General properties - tabbedPane.insertTab(trans.get("ThicknessRingCompCfg.tab.General"), null, tab, + tabbedPane.insertTab(trans.get("ThicknessRingCompCfg.tab.General"), null, tab, trans.get("ThicknessRingCompCfg.tab.Generalprop"), 0); tabbedPane.setSelectedIndex(0); } diff --git a/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java b/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java index 513c49eb..5e0286d8 100644 --- a/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java @@ -11,6 +11,7 @@ import javax.swing.JPanel; import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; @@ -25,7 +26,7 @@ import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; public class TransitionConfig extends RocketComponentConfig { - + private static final Translator trans = Application.getTranslator(); private JComboBox typeBox; //private JLabel description; @@ -40,168 +41,169 @@ public class TransitionConfig extends RocketComponentConfig { private static final String PREDESC = ""; - public TransitionConfig(RocketComponent c) { - super(c); + public TransitionConfig(OpenRocketDocument d, RocketComponent c) { + super(d, c); DoubleModel m; JSpinner spin; JCheckBox checkbox; - - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); //// Shape selection //// Transition shape: panel.add(new JLabel(trans.get("TransitionCfg.lbl.Transitionshape"))); - - Transition.Shape selected = ((Transition)component).getType(); + + Transition.Shape selected = ((Transition) component).getType(); Transition.Shape[] typeList = Transition.Shape.values(); typeBox = new JComboBox(typeList); typeBox.setEditable(false); typeBox.setSelectedItem(selected); typeBox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - Transition.Shape s = (Transition.Shape)typeBox.getSelectedItem(); - ((Transition)component).setType(s); + Transition.Shape s = (Transition.Shape) typeBox.getSelectedItem(); + ((Transition) component).setType(s); description.setText(PREDESC + s.getTransitionDescription()); updateEnabled(); } }); - panel.add(typeBox,"span, split 2"); - + panel.add(typeBox, "span, split 2"); + //// Clipped - checkbox = new JCheckBox(new BooleanModel(component,"Clipped")); + checkbox = new JCheckBox(new BooleanModel(component, "Clipped")); //// Clipped checkbox.setText(trans.get("TransitionCfg.checkbox.Clipped")); - panel.add(checkbox,"wrap"); - + panel.add(checkbox, "wrap"); + //// Shape parameter: shapeLabel = new JLabel(trans.get("TransitionCfg.lbl.Shapeparam")); panel.add(shapeLabel); - m = new DoubleModel(component,"ShapeParameter"); + m = new DoubleModel(component, "ShapeParameter"); shapeSpinner = new JSpinner(m.getSpinnerModel()); shapeSpinner.setEditor(new SpinnerEditor(shapeSpinner)); - panel.add(shapeSpinner,"growx"); + panel.add(shapeSpinner, "growx"); - DoubleModel min = new DoubleModel(component,"ShapeParameterMin"); - DoubleModel max = new DoubleModel(component,"ShapeParameterMax"); - shapeSlider = new BasicSlider(m.getSliderModel(min,max)); - panel.add(shapeSlider,"skip, w 100lp, wrap"); + DoubleModel min = new DoubleModel(component, "ShapeParameterMin"); + DoubleModel max = new DoubleModel(component, "ShapeParameterMax"); + shapeSlider = new BasicSlider(m.getSliderModel(min, max)); + panel.add(shapeSlider, "skip, w 100lp, wrap"); updateEnabled(); - + //// Length //// Transition length: panel.add(new JLabel(trans.get("TransitionCfg.lbl.Transitionlength"))); - m = new DoubleModel(component,"Length",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.3)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.3)), "w 100lp, wrap"); + //// Transition diameter 1 //// Fore diameter: panel.add(new JLabel(trans.get("TransitionCfg.lbl.Forediam"))); - - DoubleModel od = new DoubleModel(component,"ForeRadius",2,UnitGroup.UNITS_LENGTH,0); + + DoubleModel od = new DoubleModel(component, "ForeRadius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap 0px"); - checkbox = new JCheckBox(od.getAutomaticAction()); //// Automatic checkbox.setText(trans.get("TransitionCfg.checkbox.Automatic")); - panel.add(checkbox,"skip, span 2, wrap"); - + panel.add(checkbox, "skip, span 2, wrap"); + //// Transition diameter 2 //// Aft diameter: panel.add(new JLabel(trans.get("TransitionCfg.lbl.Aftdiam"))); - - od = new DoubleModel(component,"AftRadius",2,UnitGroup.UNITS_LENGTH,0); + + od = new DoubleModel(component, "AftRadius", 2, UnitGroup.UNITS_LENGTH, 0); // Diameter = 2*Radius - + spin = new JSpinner(od.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(od), "growx"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - panel.add(new UnitSelector(od),"growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)),"w 100lp, wrap 0px"); - checkbox = new JCheckBox(od.getAutomaticAction()); //// Automatic checkbox.setText(trans.get("TransitionCfg.checkbox.Automatic")); - panel.add(checkbox,"skip, span 2, wrap"); - + panel.add(checkbox, "skip, span 2, wrap"); + //// Wall thickness: panel.add(new JLabel(trans.get("TransitionCfg.lbl.Wallthickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap 0px"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 0px"); //// Filled - checkbox = new JCheckBox(new BooleanModel(component,"Filled")); + checkbox = new JCheckBox(new BooleanModel(component, "Filled")); //// Filled checkbox.setText(trans.get("TransitionCfg.checkbox.Filled")); - panel.add(checkbox,"skip, span 2, wrap"); - - + panel.add(checkbox, "skip, span 2, wrap"); + + //// Description JPanel panel2 = new JPanel(new MigLayout("ins 0")); description = new DescriptionArea(5); - description.setText(PREDESC + ((Transition)component).getType(). + description.setText(PREDESC + ((Transition) component).getType(). getTransitionDescription()); panel2.add(description, "wmin 250lp, spanx, growx, wrap para"); //// Material - + materialPanel(panel2, Material.Type.BULK); panel.add(panel2, "cell 4 0, gapleft paragraph, aligny 0%, spany"); //// General and General properties - tabbedPane.insertTab(trans.get("TransitionCfg.tab.General"), null, panel, + tabbedPane.insertTab(trans.get("TransitionCfg.tab.General"), null, panel, trans.get("TransitionCfg.tab.Generalproperties"), 0); //// Shoulder and Shoulder properties - tabbedPane.insertTab(trans.get("TransitionCfg.tab.Shoulder"), null, shoulderTab(), + tabbedPane.insertTab(trans.get("TransitionCfg.tab.Shoulder"), null, shoulderTab(), trans.get("TransitionCfg.tab.Shoulderproperties"), 1); tabbedPane.setSelectedIndex(0); } - + private void updateEnabled() { - boolean e = ((Transition)component).getType().usesParameter(); + boolean e = ((Transition) component).getType().usesParameter(); shapeLabel.setEnabled(e); shapeSpinner.setEnabled(e); shapeSlider.setEnabled(e); } - + } diff --git a/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java b/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java index d4482de1..47650ffd 100644 --- a/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java +++ b/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java @@ -9,6 +9,7 @@ import javax.swing.JSpinner; import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; @@ -27,8 +28,8 @@ import net.sf.openrocket.unit.UnitGroup; public class TrapezoidFinSetConfig extends FinSetConfig { private static final Translator trans = Application.getTranslator(); - public TrapezoidFinSetConfig(final RocketComponent component) { - super(component); + public TrapezoidFinSetConfig(OpenRocketDocument d, final RocketComponent component) { + super(d, component); DoubleModel m; JSpinner spin; @@ -36,8 +37,8 @@ public class TrapezoidFinSetConfig extends FinSetConfig { JPanel mainPanel = new JPanel(new MigLayout()); - - JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); //// Number of fins: JLabel label = new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Nbroffins")); @@ -45,15 +46,15 @@ public class TrapezoidFinSetConfig extends FinSetConfig { label.setToolTipText(trans.get("TrapezoidFinSetCfg.lbl.ttip.Nbroffins")); panel.add(label); - IntegerModel im = new IntegerModel(component,"FinCount",1,8); + IntegerModel im = new IntegerModel(component, "FinCount", 1, 8); spin = new JSpinner(im.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); //// The number of fins in the fin set. spin.setToolTipText(trans.get("TrapezoidFinSetCfg.lbl.ttip.Nbroffins")); - panel.add(spin,"growx, wrap"); - + panel.add(spin, "growx, wrap"); + //// Base rotation //// Fin rotation: label = new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Finrotation")); @@ -61,16 +62,16 @@ public class TrapezoidFinSetConfig extends FinSetConfig { label.setToolTipText(trans.get("TrapezoidFinSetCfg.lbl.ttip.Finrotation")); panel.add(label); - m = new DoubleModel(component, "BaseRotation", UnitGroup.UNITS_ANGLE,-Math.PI,Math.PI); + m = new DoubleModel(component, "BaseRotation", UnitGroup.UNITS_ANGLE, -Math.PI, Math.PI); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI,Math.PI)),"w 100lp, wrap"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + //// Fin cant: label = new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Fincant")); //// The angle that the fins are canted with respect to the rocket @@ -82,158 +83,158 @@ public class TrapezoidFinSetConfig extends FinSetConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT,FinSet.MAX_CANT)), + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT, FinSet.MAX_CANT)), "w 100lp, wrap"); - + //// Root chord: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Rootchord"))); - m = new DoubleModel(component,"RootChord",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "RootChord", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.2)), "w 100lp, wrap"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.05,0.2)),"w 100lp, wrap"); - //// Tip chord: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Tipchord"))); - m = new DoubleModel(component,"TipChord",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "TipChord", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.05,0.2)),"w 100lp, wrap"); - + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.2)), "w 100lp, wrap"); + //// Height: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Height"))); - m = new DoubleModel(component,"Height",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Height", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.05,0.2)),"w 100lp, wrap"); - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.2)), "w 100lp, wrap"); + + //// Sweep length: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Sweeplength"))); - m = new DoubleModel(component,"Sweep",UnitGroup.UNITS_LENGTH); + m = new DoubleModel(component, "Sweep", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(m), "growx"); - panel.add(new UnitSelector(m),"growx"); - // sweep slider from -1.1*TipChord to 1.1*RootChord - DoubleModel tc = new DoubleModel(component,"TipChord",-1.1,UnitGroup.UNITS_LENGTH); - DoubleModel rc = new DoubleModel(component,"RootChord",1.1,UnitGroup.UNITS_LENGTH); - panel.add(new BasicSlider(m.getSliderModel(tc,rc)),"w 100lp, wrap"); - + DoubleModel tc = new DoubleModel(component, "TipChord", -1.1, UnitGroup.UNITS_LENGTH); + DoubleModel rc = new DoubleModel(component, "RootChord", 1.1, UnitGroup.UNITS_LENGTH); + panel.add(new BasicSlider(m.getSliderModel(tc, rc)), "w 100lp, wrap"); + //// Sweep angle: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Sweepangle"))); - m = new DoubleModel(component, "SweepAngle",UnitGroup.UNITS_ANGLE, - -TrapezoidFinSet.MAX_SWEEP_ANGLE,TrapezoidFinSet.MAX_SWEEP_ANGLE); + m = new DoubleModel(component, "SweepAngle", UnitGroup.UNITS_ANGLE, + -TrapezoidFinSet.MAX_SWEEP_ANGLE, TrapezoidFinSet.MAX_SWEEP_ANGLE); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(-Math.PI/4,Math.PI/4)), + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI / 4, Math.PI / 4)), "w 100lp, wrap paragraph"); - - - mainPanel.add(panel,"aligny 20%"); - - mainPanel.add(new JSeparator(SwingConstants.VERTICAL),"growy"); - + + + mainPanel.add(panel, "aligny 20%"); + mainPanel.add(new JSeparator(SwingConstants.VERTICAL), "growy"); - panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]","")); + + panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); - + + //// Fin cross section: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.FincrossSection"))); combo = new JComboBox( - new EnumModel(component,"CrossSection")); - panel.add(combo,"span, growx, wrap"); + new EnumModel(component, "CrossSection")); + panel.add(combo, "span, growx, wrap"); //// Thickness: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Thickness"))); - m = new DoubleModel(component,"Thickness",UnitGroup.UNITS_LENGTH,0); + m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(0,0.01)),"w 100lp, wrap para"); + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap para"); + //// Position //// Position relative to: panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Posrelativeto"))); - + combo = new JComboBox( new EnumModel(component, "RelativePosition", new RocketComponent.Position[] { - RocketComponent.Position.TOP, - RocketComponent.Position.MIDDLE, - RocketComponent.Position.BOTTOM, - RocketComponent.Position.ABSOLUTE + RocketComponent.Position.TOP, + RocketComponent.Position.MIDDLE, + RocketComponent.Position.BOTTOM, + RocketComponent.Position.ABSOLUTE })); - panel.add(combo,"spanx, growx, wrap"); + panel.add(combo, "spanx, growx, wrap"); //// plus - panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.plus")),"right"); - - m = new DoubleModel(component,"PositionValue",UnitGroup.UNITS_LENGTH); + panel.add(new JLabel(trans.get("TrapezoidFinSetCfg.lbl.plus")), "right"); + + m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap para"); - + //// Material materialPanel(panel, Material.Type.BULK); - - - - mainPanel.add(panel,"aligny 20%"); + + + + mainPanel.add(panel, "aligny 20%"); //// General and General properties - tabbedPane.insertTab(trans.get("TrapezoidFinSetCfg.tab.General"), null, mainPanel, + tabbedPane.insertTab(trans.get("TrapezoidFinSetCfg.tab.General"), null, mainPanel, trans.get("TrapezoidFinSetCfg.tab.Generalproperties"), 0); tabbedPane.setSelectedIndex(0); diff --git a/src/net/sf/openrocket/startup/Startup.java b/src/net/sf/openrocket/startup/Startup.java index a975894c..361e53f1 100644 --- a/src/net/sf/openrocket/startup/Startup.java +++ b/src/net/sf/openrocket/startup/Startup.java @@ -1,31 +1,9 @@ package net.sf.openrocket.startup; -import java.awt.GraphicsEnvironment; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; import java.io.PrintStream; -import java.util.List; import java.util.Locale; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.prefs.Preferences; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.ToolTipManager; - -import net.sf.openrocket.communication.UpdateInfo; -import net.sf.openrocket.communication.UpdateInfoRetriever; -import net.sf.openrocket.database.Databases; -import net.sf.openrocket.database.ThrustCurveMotorSet; -import net.sf.openrocket.database.ThrustCurveMotorSetDatabase; -import net.sf.openrocket.file.iterator.DirectoryIterator; -import net.sf.openrocket.file.iterator.FileIterator; -import net.sf.openrocket.file.motor.MotorLoaderHelper; -import net.sf.openrocket.gui.dialogs.UpdateInfoDialog; -import net.sf.openrocket.gui.main.BasicFrame; -import net.sf.openrocket.gui.main.ExceptionHandler; -import net.sf.openrocket.gui.main.Splash; import net.sf.openrocket.l10n.DebugTranslator; import net.sf.openrocket.l10n.L10N; import net.sf.openrocket.l10n.ResourceBundleTranslator; @@ -35,36 +13,34 @@ import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.logging.LogLevel; import net.sf.openrocket.logging.LogLevelBufferLogger; import net.sf.openrocket.logging.PrintStreamLogger; -import net.sf.openrocket.motor.Motor; -import net.sf.openrocket.motor.ThrustCurveMotor; -import net.sf.openrocket.util.GUIUtil; -import net.sf.openrocket.util.Prefs; -import net.sf.openrocket.util.SimpleFileFilter; /** - * 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. + * The first class in the OpenRocket startup sequence. This class is responsible + * for setting up the Application class with the statically used subsystems + * (logging and translation) and then delegating to Startup2 class. + *

+ * This class must be very cautious about what classes it calls. This is because + * the loggers/translators for classes are initialized as static final members during + * class initialization. For example, this class MUST NOT use the Prefs class, because + * using it will cause LineStyle to be initialized, which then receives an invalid + * (not-yet-initialized) translator. * * @author Sampo Niskanen */ public class Startup { - private static LogHelper log; + static LogHelper log; private static final String LOG_STDERR_PROPERTY = "openrocket.log.stderr"; private static final String LOG_STDOUT_PROPERTY = "openrocket.log.stdout"; private static final int LOG_BUFFER_LENGTH = 50; - private static final String THRUSTCURVE_DIRECTORY = "datafiles/thrustcurves/"; - - - /** Block motor loading for this many milliseconds */ - private static AtomicInteger blockLoading = new AtomicInteger(Integer.MAX_VALUE); - + /** + * OpenRocket startup main method. + */ public static void main(final String[] args) throws Exception { // Check for "openrocket.debug" property before anything else @@ -76,33 +52,16 @@ public class Startup { // Setup the translations initializeL10n(); - // Check that we have a head - checkHead(); - - // Check that we're running a good version of a JRE - log.info("Checking JRE compatibility"); - VersionHelper.checkVersion(); - VersionHelper.checkOpenJDK(); - - // Run the actual startup method in the EDT since it can use progress dialogs etc. - log.info("Running main"); - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - runMain(args); - } - }); + // Continue startup in Startup2 class (where Application is already set up) + Startup2.runMain(args); - log.info("Startup complete"); - - // Block motor loading for 1.5 seconds to allow window painting - blockLoading.set(1500); } - - + /** + * Set proper system properties if openrocket.debug is defined. + */ private static void checkDebugStatus() { if (System.getProperty("openrocket.debug") != null) { setPropertyIfNotSet("openrocket.log.stdout", "VBOSE"); @@ -120,252 +79,10 @@ public class Startup { } - /** - * Initializes the localization system. - */ - private static void initializeL10n() { - - String langcode = System.getProperty("openrocket.locale"); - if (langcode != null) { - Locale l = L10N.toLocale(langcode); - log.info("Setting custom locale " + l); - Locale.setDefault(l); - } else { - Locale l = Prefs.getUserLocale(); - if (l != null) { - log.info("Setting user-selected locale " + l); - Locale.setDefault(l); - } else { - log.info("Using default locale " + Locale.getDefault()); - } - } - - Translator t; - t = new ResourceBundleTranslator("l10n.messages"); - if (Locale.getDefault().getLanguage().equals("xx")) { - t = new DebugTranslator(t); - } - - log.info("Set up translation for locale " + Locale.getDefault() + - ", debug.currentFile=" + t.get("debug.currentFile")); - - Application.setBaseTranslator(t); - } - - - private static void runMain(String[] args) { - - // Initialize the splash screen with version info - log.info("Initializing the splash screen"); - Splash.init(); - - // Setup the uncaught exception handler - log.info("Registering exception handler"); - ExceptionHandler.registerExceptionHandler(); - - // Start update info fetching - final UpdateInfoRetriever updateInfo; - if (Prefs.getCheckUpdates()) { - log.info("Starting update check"); - updateInfo = new UpdateInfoRetriever(); - updateInfo.start(); - } else { - log.info("Update check disabled"); - updateInfo = null; - } - - // Set the best available look-and-feel - log.info("Setting best LAF"); - GUIUtil.setBestLAF(); - - // Set tooltip delay time. Tooltips are used in MotorChooserDialog extensively. - ToolTipManager.sharedInstance().setDismissDelay(30000); - - // Load defaults - Prefs.loadDefaultUnits(); - - // Load motors etc. - log.info("Loading databases"); - loadMotor(); - Databases.fakeMethod(); - - // Starting action (load files or open new document) - log.info("Opening main application window"); - if (!handleCommandLine(args)) { - BasicFrame.newAction(); - } - - // Check whether update info has been fetched or whether it needs more time - log.info("Checking update status"); - checkUpdateStatus(updateInfo); - } - - - - private static void loadMotor() { - - log.info("Starting motor loading from " + THRUSTCURVE_DIRECTORY + " in background thread."); - ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(true) { - - @Override - protected void loadMotors() { - - // Block loading until timeout occurs or database is taken into use - log.info("Blocking motor loading while starting up"); - while (!inUse && blockLoading.addAndGet(-100) > 0) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - } - } - log.info("Blocking ended, inUse=" + inUse + " slowLoadingCount=" + blockLoading.get()); - - // Start loading - log.info("Loading motors from " + THRUSTCURVE_DIRECTORY); - long t0 = System.currentTimeMillis(); - int fileCount; - int thrustCurveCount; - - // Load the packaged thrust curves - List list; - FileIterator iterator = DirectoryIterator.findDirectory(THRUSTCURVE_DIRECTORY, - new SimpleFileFilter("", false, "eng", "rse")); - if (iterator == null) { - throw new IllegalStateException("Thrust curve directory " + THRUSTCURVE_DIRECTORY + - "not found, distribution built wrong"); - } - list = MotorLoaderHelper.load(iterator); - for (Motor m : list) { - this.addMotor((ThrustCurveMotor) m); - } - fileCount = iterator.getFileCount(); - - thrustCurveCount = list.size(); - - // Load the user-defined thrust curves - for (File file : Prefs.getUserThrustCurveFiles()) { - // TODO: LOW: This counts a directory as one file - log.info("Loading motors from " + file); - list = MotorLoaderHelper.load(file); - for (Motor m : list) { - this.addMotor((ThrustCurveMotor) m); - } - fileCount++; - thrustCurveCount += list.size(); - } - - long t1 = System.currentTimeMillis(); - - // Count statistics - int distinctMotorCount = 0; - int distinctThrustCurveCount = 0; - distinctMotorCount = motorSets.size(); - for (ThrustCurveMotorSet set : motorSets) { - distinctThrustCurveCount += set.getMotorCount(); - } - log.info("Motor loading done, took " + (t1 - t0) + " ms to load " - + fileCount + " files/directories containing " - + thrustCurveCount + " thrust curves which contained " - + distinctMotorCount + " distinct motors with " - + distinctThrustCurveCount + " distinct thrust curves."); - } - - }; - db.startLoading(); - Application.setMotorSetDatabase(db); - } - - - - private static void checkUpdateStatus(final UpdateInfoRetriever updateInfo) { - if (updateInfo == null) - return; - - int delay = 1000; - if (!updateInfo.isRunning()) - delay = 100; - - final Timer timer = new Timer(delay, null); - - ActionListener listener = new ActionListener() { - private int count = 5; - - @Override - 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 && info.getLatestVersion() != null && - !current.equals(info.getLatestVersion()) && - !last.equals(info.getLatestVersion())) { - - UpdateInfoDialog infoDialog = new UpdateInfoDialog(info); - infoDialog.setVisible(true); - if (infoDialog.isReminderSelected()) { - Prefs.putString(Prefs.LAST_UPDATE, ""); - } else { - Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion()); - } - } - } - count--; - if (count <= 0) - timer.stop(); - } - }; - timer.addActionListener(listener); - timer.start(); - } - - - /** - * Handles arguments passed from the command line. This may be used either - * when starting the first instance of OpenRocket or later when OpenRocket is - * executed again while running. - * - * @param args the command-line arguments. - * @return whether a new frame was opened or similar user desired action was - * performed as a result. - */ - public static boolean handleCommandLine(String[] args) { - - // Check command-line for files - boolean opened = false; - for (String file : args) { - if (BasicFrame.open(new File(file), null)) { - opened = true; - } - } - return opened; - } - - /** - * Check that the JRE is not running headless. + * Initializes the loggins system. */ - private static void checkHead() { - - log.info("Checking for graphics head"); - - if (GraphicsEnvironment.isHeadless()) { - log.error("Application is headless."); - System.err.println(); - System.err.println("OpenRocket cannot currently be run without the graphical " + - "user interface."); - System.err.println(); - System.exit(1); - } - - } - - - /////////// Logging /////////// - private static void initializeLogging() { DelegatorLogger delegator = new DelegatorLogger(); @@ -387,7 +104,7 @@ public class Startup { // Initialize the log for this class log = Application.getLogger(); - log.info("Logging subsystem initialized for OpenRocket " + Prefs.getVersion()); + log.info("Logging subsystem initialized"); String str = "Console logging output:"; for (LogLevel l : LogLevel.values()) { PrintStream ps = printer.getOutput(l); @@ -420,50 +137,64 @@ public class Startup { } - /////////// Helper methods ////////// - + + /** - * Presents an error message to the user and exits the application. - * - * @param message an array of messages to present. + * Initializes the localization system. */ - static void error(String[] message) { + private static void initializeL10n() { - 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(); + // Check for locale propery + String langcode = System.getProperty("openrocket.locale"); - - if (!GraphicsEnvironment.isHeadless()) { + if (langcode != null) { - JOptionPane.showMessageDialog(null, message, "Error starting OpenRocket", - JOptionPane.ERROR_MESSAGE); + Locale l = L10N.toLocale(langcode); + log.info("Setting custom locale " + l); + Locale.setDefault(l); + + } else { + + // Check user-configured locale + Locale l = getUserLocale(); + if (l != null) { + log.info("Setting user-selected locale " + l); + Locale.setDefault(l); + } else { + log.info("Using default locale " + Locale.getDefault()); + } } - System.exit(1); + // Setup the translator + Translator t; + t = new ResourceBundleTranslator("l10n.messages"); + if (Locale.getDefault().getLanguage().equals("xx")) { + t = new DebugTranslator(t); + } + + log.info("Set up translation for locale " + Locale.getDefault() + + ", debug.currentFile=" + t.get("debug.currentFile")); + + Application.setBaseTranslator(t); } - /** - * 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. - */ - 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); - } + + + private static Locale getUserLocale() { + /* + * This method MUST NOT use the Prefs class, since is causes a multitude + * of classes to be initialized. Therefore this duplicates the functionality + * of the Prefs class locally. + */ + + if (System.getProperty("openrocket.debug.prefs") != null) { + return null; } + + return L10N.toLocale(Preferences.userRoot().node("OpenRocket").get("locale", null)); } + } diff --git a/src/net/sf/openrocket/startup/Startup2.java b/src/net/sf/openrocket/startup/Startup2.java new file mode 100644 index 00000000..4371fc3e --- /dev/null +++ b/src/net/sf/openrocket/startup/Startup2.java @@ -0,0 +1,291 @@ +package net.sf.openrocket.startup; + +import java.awt.GraphicsEnvironment; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.ToolTipManager; + +import net.sf.openrocket.communication.UpdateInfo; +import net.sf.openrocket.communication.UpdateInfoRetriever; +import net.sf.openrocket.database.Databases; +import net.sf.openrocket.database.ThrustCurveMotorSet; +import net.sf.openrocket.database.ThrustCurveMotorSetDatabase; +import net.sf.openrocket.file.iterator.DirectoryIterator; +import net.sf.openrocket.file.iterator.FileIterator; +import net.sf.openrocket.file.motor.MotorLoaderHelper; +import net.sf.openrocket.gui.dialogs.UpdateInfoDialog; +import net.sf.openrocket.gui.main.BasicFrame; +import net.sf.openrocket.gui.main.ExceptionHandler; +import net.sf.openrocket.gui.main.Splash; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.motor.Motor; +import net.sf.openrocket.motor.ThrustCurveMotor; +import net.sf.openrocket.util.GUIUtil; +import net.sf.openrocket.util.Prefs; +import net.sf.openrocket.util.SimpleFileFilter; + +/** + * The second class in the OpenRocket startup sequence. This class can assume the + * Application class to be properly set up, and can use any classes safely. + * + * @author Sampo Niskanen + */ +public class Startup2 { + private static final LogHelper log = Application.getLogger(); + + + private static final String THRUSTCURVE_DIRECTORY = "datafiles/thrustcurves/"; + + /** Block motor loading for this many milliseconds */ + private static AtomicInteger blockLoading = new AtomicInteger(Integer.MAX_VALUE); + + + + /** + * Run when starting up OpenRocket after Application has been set up. + * + * @param args command line arguments + */ + static void runMain(final String[] args) throws Exception { + + log.info("Starting up OpenRocket version " + Prefs.getVersion()); + + // Check that we're not running headless + log.info("Checking for graphics head"); + checkHead(); + + // Check that we're running a good version of a JRE + log.info("Checking JRE compatibility"); + VersionHelper.checkVersion(); + VersionHelper.checkOpenJDK(); + + // Run the actual startup method in the EDT since it can use progress dialogs etc. + log.info("Moving startup to EDT"); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + runInEDT(args); + } + }); + + log.info("Startup complete"); + } + + + /** + * Run in the EDT when starting up OpenRocket. + * + * @param args command line arguments + */ + private static void runInEDT(String[] args) { + + // Initialize the splash screen with version info + log.info("Initializing the splash screen"); + Splash.init(); + + // Setup the uncaught exception handler + log.info("Registering exception handler"); + ExceptionHandler.registerExceptionHandler(); + + // Start update info fetching + final UpdateInfoRetriever updateInfo; + if (Prefs.getCheckUpdates()) { + log.info("Starting update check"); + updateInfo = new UpdateInfoRetriever(); + updateInfo.start(); + } else { + log.info("Update check disabled"); + updateInfo = null; + } + + // Set the best available look-and-feel + log.info("Setting best LAF"); + GUIUtil.setBestLAF(); + + // Set tooltip delay time. Tooltips are used in MotorChooserDialog extensively. + ToolTipManager.sharedInstance().setDismissDelay(30000); + + // Load defaults + Prefs.loadDefaultUnits(); + + // Load motors etc. + log.info("Loading databases"); + loadMotor(); + Databases.fakeMethod(); + + // Starting action (load files or open new document) + log.info("Opening main application window"); + if (!handleCommandLine(args)) { + BasicFrame.newAction(); + } + + // Check whether update info has been fetched or whether it needs more time + log.info("Checking update status"); + checkUpdateStatus(updateInfo); + + // Block motor loading for 1.5 seconds to allow window painting to be faster + blockLoading.set(1500); + } + + + /** + * Check that the JRE is not running headless. + */ + private static void checkHead() { + + if (GraphicsEnvironment.isHeadless()) { + log.error("Application is headless."); + System.err.println(); + System.err.println("OpenRocket cannot currently be run without the graphical " + + "user interface."); + System.err.println(); + System.exit(1); + } + + } + + + private static void loadMotor() { + + log.info("Starting motor loading from " + THRUSTCURVE_DIRECTORY + " in background thread."); + ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(true) { + + @Override + protected void loadMotors() { + + // Block loading until timeout occurs or database is taken into use + log.info("Blocking motor loading while starting up"); + while (!inUse && blockLoading.addAndGet(-100) > 0) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + log.info("Blocking ended, inUse=" + inUse + " blockLoading=" + blockLoading.get()); + + // Start loading + log.info("Loading motors from " + THRUSTCURVE_DIRECTORY); + long t0 = System.currentTimeMillis(); + int fileCount; + int thrustCurveCount; + + // Load the packaged thrust curves + List list; + FileIterator iterator = DirectoryIterator.findDirectory(THRUSTCURVE_DIRECTORY, + new SimpleFileFilter("", false, "eng", "rse")); + if (iterator == null) { + throw new IllegalStateException("Thrust curve directory " + THRUSTCURVE_DIRECTORY + + "not found, distribution built wrong"); + } + list = MotorLoaderHelper.load(iterator); + for (Motor m : list) { + this.addMotor((ThrustCurveMotor) m); + } + fileCount = iterator.getFileCount(); + + thrustCurveCount = list.size(); + + // Load the user-defined thrust curves + for (File file : Prefs.getUserThrustCurveFiles()) { + log.info("Loading motors from " + file); + list = MotorLoaderHelper.load(file); + for (Motor m : list) { + this.addMotor((ThrustCurveMotor) m); + } + fileCount++; + thrustCurveCount += list.size(); + } + + long t1 = System.currentTimeMillis(); + + // Count statistics + int distinctMotorCount = 0; + int distinctThrustCurveCount = 0; + distinctMotorCount = motorSets.size(); + for (ThrustCurveMotorSet set : motorSets) { + distinctThrustCurveCount += set.getMotorCount(); + } + log.info("Motor loading done, took " + (t1 - t0) + " ms to load " + + fileCount + " files/directories containing " + + thrustCurveCount + " thrust curves which contained " + + distinctMotorCount + " distinct motors with " + + distinctThrustCurveCount + " distinct thrust curves."); + } + + }; + db.startLoading(); + Application.setMotorSetDatabase(db); + } + + private static void checkUpdateStatus(final UpdateInfoRetriever updateInfo) { + if (updateInfo == null) + return; + + int delay = 1000; + if (!updateInfo.isRunning()) + delay = 100; + + final Timer timer = new Timer(delay, null); + + ActionListener listener = new ActionListener() { + private int count = 5; + + @Override + 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 && info.getLatestVersion() != null && + !current.equals(info.getLatestVersion()) && + !last.equals(info.getLatestVersion())) { + + UpdateInfoDialog infoDialog = new UpdateInfoDialog(info); + infoDialog.setVisible(true); + if (infoDialog.isReminderSelected()) { + Prefs.putString(Prefs.LAST_UPDATE, ""); + } else { + Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion()); + } + } + } + count--; + if (count <= 0) + timer.stop(); + } + }; + timer.addActionListener(listener); + timer.start(); + } + + /** + * Handles arguments passed from the command line. This may be used either + * when starting the first instance of OpenRocket or later when OpenRocket is + * executed again while running. + * + * @param args the command-line arguments. + * @return whether a new frame was opened or similar user desired action was + * performed as a result. + */ + private static boolean handleCommandLine(String[] args) { + + // Check command-line for files + boolean opened = false; + for (String file : args) { + if (BasicFrame.open(new File(file), null)) { + opened = true; + } + } + return opened; + } + +} diff --git a/src/net/sf/openrocket/startup/VersionHelper.java b/src/net/sf/openrocket/startup/VersionHelper.java index 3d90d3e9..097f1dc4 100644 --- a/src/net/sf/openrocket/startup/VersionHelper.java +++ b/src/net/sf/openrocket/startup/VersionHelper.java @@ -1,5 +1,9 @@ package net.sf.openrocket.startup; +import java.awt.GraphicsEnvironment; + +import javax.swing.JOptionPane; + import net.sf.openrocket.logging.LogHelper; public class VersionHelper { @@ -34,14 +38,14 @@ public class VersionHelper { if (major < REQUIRED_MAJOR_VERSION || (major == REQUIRED_MAJOR_VERSION && minor < REQUIRED_MINOR_VERSION)) { - Startup.error(new String[] { "Java SE version 6 is required to run OpenRocket.", + error(new String[] { "Java SE version 6 is required to run OpenRocket.", "You are currently running " + jreName + " version " + jreVersion + " by " + jreVendor }); } } catch (RuntimeException e) { - Startup.confirm(new String[] { "The Java version in use could not be detected.", + confirm(new String[] { "The Java version in use could not be detected.", "OpenRocket requires at least Java SE 6.", "Continue anyway?" }); @@ -64,7 +68,7 @@ public class VersionHelper { if (jreVersion.matches(BAD_OPENJDK_VERSION)) { - Startup.confirm(new String[] { "Old versions of OpenJDK are known to have problems " + + confirm(new String[] { "Old versions of OpenJDK are known to have problems " + "running OpenRocket.", " ", "You are currently running " + jreName + " version " + @@ -74,4 +78,51 @@ public class VersionHelper { } } + + + /////////// Helper methods ////////// + + /** + * 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/util/LineStyle.java b/src/net/sf/openrocket/util/LineStyle.java index 73df2b73..2bb3af6d 100644 --- a/src/net/sf/openrocket/util/LineStyle.java +++ b/src/net/sf/openrocket/util/LineStyle.java @@ -14,6 +14,7 @@ import net.sf.openrocket.startup.Application; public enum LineStyle { + //// Solid SOLID("LineStyle.Solid", new float[] { 10f, 0f }), //// Dashed @@ -24,6 +25,10 @@ public enum LineStyle { DASHDOT("LineStyle.Dash-dotted", new float[] { 8f, 3f, 2f, 3f }); private static final Translator trans = Application.getTranslator(); + static { + System.out.println("*** LineStyle initialized trans:" + trans + " ***"); + System.err.println("*** LineStyle initialized ***"); + } private final String name; private final float[] dashes;