+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
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.
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;
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);
}
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;
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;
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;
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);
}
//// 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();
}
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) {
try {
configclass = Class.forName(configclassname);
c = (Constructor<? extends RocketComponentConfig>)
- configclass.getConstructor(RocketComponent.class);
+ configclass.getConstructor(OpenRocketDocument.class, RocketComponent.class);
return c;
} catch (Exception ignore) {
}
}
- /**
- * 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.
*/
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;
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
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<RocketComponent.Position>(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<FinSet.CrossSection>(component,"CrossSection"));
- panel.add(combo,"growx, wrap unrel");
+ new EnumModel<FinSet.CrossSection>(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);
}
-
+
}
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;
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<FinSet.TabRelativePosition> em =
- new EnumModel<FinSet.TabRelativePosition>(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<RocketComponent> children = parent.getChildren();
- List<CenteringRing> rings = new ArrayList<CenteringRing>();
-
- 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:
- * <p/>
- * 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<CenteringRing> rings, Double finPositionFromTop, Double finLength, DoubleModel mts) {
- List<SortableRing> positionsFromTop = new ArrayList<SortableRing>();
-
- //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<CenteringRing>() {
- @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<FinSet.TabRelativePosition> em =
+ new EnumModel<FinSet.TabRelativePosition>(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<RocketComponent> children = parent.getChildren();
+ List<CenteringRing> rings = new ArrayList<CenteringRing>();
+
+ 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:
+ * <p/>
+ * 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<CenteringRing> rings, Double finPositionFromTop, Double finLength, DoubleModel mts) {
+ List<SortableRing> positionsFromTop = new ArrayList<SortableRing>();
+
+ //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<CenteringRing>() {
+ @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;
+ }
+ }
}
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;
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
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;
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);
if (tube.getClusterCount() <= 1)
return;
- ComponentConfigDialog.addUndoPosition("Split cluster");
+ document.addUndoPosition("Split cluster");
Coordinate[] coords = { Coordinate.NUL };
coords = component.shiftCoordinates(coords);
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;
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<RocketComponent.Position>(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);
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
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;
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<RocketComponent.Position>(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() {
((MassComponent) component).setRadialPosition(0.0);
}
});
- panel.add(button,"spanx, right");
+ panel.add(button, "spanx, right");
return panel;
}
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;
import net.sf.openrocket.unit.UnitGroup;
public class NoseConeConfig extends RocketComponentConfig {
-
+
private JComboBox typeBox;
private DescriptionArea description;
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 = "<html>";
- 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);
}
-
+
}
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;
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
//// <html>Drag coefficient C<sub>D</sub>:
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<RocketComponent.Position>(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<IgnitionEvent>(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() {
((MassObject) component).setRadialPosition(0.0);
}
});
- panel.add(button,"spanx, right");
+ panel.add(button, "spanx, right");
return panel;
}
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<JComponent> altitudeComponents = new ArrayList<JComponent>();
- public RecoveryDeviceConfig(RocketComponent component) {
- super(component);
+ public RecoveryDeviceConfig(OpenRocketDocument d, RocketComponent component) {
+ super(d, component);
}
-
+
@Override
public void updateFields() {
super.updateFields();
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);
}
}
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;
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);
}
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;
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;
private static final Translator trans = Application.getTranslator();
+ protected final OpenRocketDocument document;
protected final RocketComponent component;
protected final JTabbedPane tabbedPane;
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:
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();
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() + ")";
}
}
@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<RocketComponent> iter = rocket.iterator();
+ Iterator<RocketComponent> 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();
}
}
});
//// <html>The overridden mass does not include motors.<br>
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");
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
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;
private final Rocket rocket;
- public RocketConfig(RocketComponent c) {
- super(c);
+ public RocketConfig(OpenRocketDocument d, RocketComponent c) {
+ super(d, c);
rocket = (Rocket) c;
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;
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
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
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<RocketComponent.Position>(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);
}
-
+
}
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;
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);
}
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;
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());
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;
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;
//// 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);
}
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;
import net.sf.openrocket.unit.UnitGroup;
public class TransitionConfig extends RocketComponentConfig {
-
+
private static final Translator trans = Application.getTranslator();
private JComboBox typeBox;
//private JLabel description;
private static final String PREDESC = "<html>";
- 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);
}
-
+
}
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;
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;
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"));
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"));
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
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<FinSet.CrossSection>(component,"CrossSection"));
- panel.add(combo,"span, growx, wrap");
+ new EnumModel<FinSet.CrossSection>(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<RocketComponent.Position>(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);
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;
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.
+ * <p>
+ * 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 <sampo.niskanen@iki.fi>
*/
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
// 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");
}
- /**
- * 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<Motor> 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();
// 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);
}
- /////////// 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));
}
+
}
--- /dev/null
+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 <sampo.niskanen@iki.fi>
+ */
+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<Motor> 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;
+ }
+
+}
package net.sf.openrocket.startup;
+import java.awt.GraphicsEnvironment;
+
+import javax.swing.JOptionPane;
+
import net.sf.openrocket.logging.LogHelper;
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?" });
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 " +
}
}
+
+
+ /////////// 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);
+ }
+ }
+ }
}
public enum LineStyle {
+
//// Solid
SOLID("LineStyle.Solid", new float[] { 10f, 0f }),
//// Dashed
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;