diff --git a/build.xml b/build.xml
index b568e33ea..dd726a6eb 100644
--- a/build.xml
+++ b/build.xml
@@ -44,15 +44,26 @@
+
+
+
+
+
+
+
-
+
+
+
+
+
diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index b1719fd2f..4b1c2b4b8 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -64,6 +64,8 @@ RocketPanel.lbl.Stability = Stability:
RocketPanel.checkbox.ShowCGCP = Show CG/CP
RocketPanel.checkbox.ShowCGCP.ttip = Disabling this checkbox hides the CG and CP markings in the rocket view.
RocketPanel.lbl.Stages = Stages:
+RocketPanel.btn.Stages.Toggle.ttip = Toggle this button to activate or deactivate the corresponding stage in your design.
+RocketPanel.btn.Stages.NoChildren.ttip = This stages does not have any child components and is therefore marked as inactive.
Add components to the stage to activate it.
RocketPanel.ttip.Rotation = Change the rocket's roll rotation (only affects the rocket view)
! BasicFrame
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
index b2cf9ce61..10c302735 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
@@ -242,8 +242,10 @@ public class FlightConfiguration implements FlightConfigurableParameter 0 &&
+ stages.get(stageNumber) != null && stages.get(stageNumber).active;
}
public Collection getAllComponents() {
@@ -380,7 +382,7 @@ public class FlightConfiguration implements FlightConfigurableParameter activeStages = new ArrayList<>();
for (StageFlags flags : this.stages.values()) {
- if (flags.active) {
+ if (isStageActive(flags.stageNumber)) {
AxialStage stage = rocket.getStage(flags.stageId);
if (stage == null) {
continue;
@@ -393,13 +395,7 @@ public class FlightConfiguration implements FlightConfigurableParameter buttons = new ArrayList();
@@ -61,9 +64,16 @@ public class StageSelector extends JPanel implements StateChangeListener {
private class StageAction extends AbstractAction {
private final AxialStage stage;
-
+
public StageAction(final AxialStage stage) {
this.stage = stage;
+ if (this.stage.getChildCount() == 0) {
+ putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.NoChildren.ttip"));
+ setEnabled(false);
+ } else {
+ putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip"));
+ }
+ updateUI();
}
@Override
@@ -77,6 +87,15 @@ public class StageSelector extends JPanel implements StateChangeListener {
@Override
public void actionPerformed(ActionEvent e) {
+ // Don't toggle the state if the stage has no children (and is therefore inactive)
+ if (stage.getChildCount() == 0) {
+ putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.NoChildren.ttip"));
+ setEnabled(false);
+ return;
+ } else {
+ setEnabled(true);
+ putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip"));
+ }
rocket.getSelectedConfiguration().toggleStage(stage.getStageNumber());
rocket.fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE | ComponentChangeEvent.MOTOR_CHANGE );
}
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorFilterPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorFilterPanel.java
index 8dc619ac8..49674d686 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorFilterPanel.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorFilterPanel.java
@@ -38,6 +38,7 @@ import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.gui.widgets.SelectColorButton;
@@ -64,8 +65,18 @@ public abstract class MotorFilterPanel extends JPanel {
* updates: motorDiameters, diameterLabels
*/
private static void scaleDiameterLabels(){
+ Unit unit = UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit();
for( int i = 0; i < motorDiameters.length; i++ ) {
- diameterLabels.put( i, new JLabel(UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit().toString(motorDiameters[i])));
+ // Round the labels, because for imperial units, the labels can otherwise overlap
+ double diam = unit.toUnit(motorDiameters[i]);
+ double diamRounded = unit.round(diam * 10) / 10; // 10 multiplication for 2-decimal precision
+ diam = unit.fromUnit(diamRounded);
+ String formatted = unit.toString(diam);
+ // Remove the leading zero for numbers between 0 and 1
+ if (diamRounded > 0 && diamRounded < 1) {
+ formatted = formatted.substring(1);
+ }
+ diameterLabels.put( i, new JLabel(formatted));
}
diameterLabels.get( motorDiameters.length-1).setText("+");
}
@@ -96,6 +107,7 @@ public abstract class MotorFilterPanel extends JPanel {
final JSpinner maxLengthSpinner;
final UnitSelector maxLengthUnitSelect;
private boolean limitDiameter = false;
+ boolean limitByLength = false;
private Double mountDiameter = null;
@@ -113,7 +125,7 @@ public abstract class MotorFilterPanel extends JPanel {
List unselectedManusFromPreferences = ((SwingPreferences) Application.getPreferences()).getExcludedMotorManufacturers();
filter.setExcludedManufacturers(unselectedManusFromPreferences);
- boolean limitByLengthPref = ((SwingPreferences) Application.getPreferences()).getBoolean("motorFilterLimitLength", false);
+ limitByLength = ((SwingPreferences) Application.getPreferences()).getBoolean("motorFilterLimitLength", false);
limitDiameter = ((SwingPreferences) Application.getPreferences()).getBoolean("motorFilterLimitDiameter", false);
//// Hide used motor files
@@ -239,9 +251,10 @@ public abstract class MotorFilterPanel extends JPanel {
// Motor Dimension selection
{
sub.add( new JLabel(trans.get("TCMotorSelPan.Diameter")), "split 2, wrap");
- limitDiameterCheckBox = new JCheckBox( trans.get("TCMotorSelPan.checkbox.limitdiameter"));
+ final BooleanModel limitByDiameterModel = new BooleanModel(limitDiameter);
+ limitDiameterCheckBox = new JCheckBox(limitByDiameterModel);
+ limitDiameterCheckBox.setText(trans.get("TCMotorSelPan.checkbox.limitdiameter"));
GUIUtil.changeFontSize(limitDiameterCheckBox, -1);
- limitDiameterCheckBox.setSelected(limitDiameter);
limitDiameterCheckBox.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
@@ -273,12 +286,13 @@ public abstract class MotorFilterPanel extends JPanel {
}
});
sub.add( diameterSlider, "growx, wrap");
+ limitByDiameterModel.addEnableComponent(diameterSlider, false);
}
{ // length selection
sub.add( new JLabel(trans.get("TCMotorSelPan.Length")), "split 2, wrap");
- final BooleanModel limitByLengthModel = new BooleanModel(limitByLengthPref);
+ final BooleanModel limitByLengthModel = new BooleanModel(limitByLength);
limitByLengthCheckBox = new JCheckBox( limitByLengthModel );
limitByLengthCheckBox.setText( trans.get("TCMotorSelPan.checkbox.limitlength"));
GUIUtil.changeFontSize(limitByLengthCheckBox, -1);
@@ -286,7 +300,7 @@ public abstract class MotorFilterPanel extends JPanel {
limitByLengthCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- //boolean limitByLength = limitByLengthCheckBox.isSelected();
+ limitByLength = limitByLengthCheckBox.isSelected();
MotorFilterPanel.this.setLimitLength();
onSelectionChanged();
}
@@ -326,9 +340,6 @@ public abstract class MotorFilterPanel extends JPanel {
lengthSlider = new MultiSlider(MultiSlider.HORIZONTAL,0, 1000, 0, 1000);
lengthSlider.setBounded(true); // thumbs cannot cross
- lengthSlider.setMajorTickSpacing(100);
- lengthSlider.setPaintTicks(true);
- lengthSlider.setLabelTable(diameterLabels);
lengthSlider.addChangeListener( new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@@ -371,7 +382,6 @@ public abstract class MotorFilterPanel extends JPanel {
minLengthUnitSelect.setSelectedUnit(UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit());
maxLengthUnitSelect.setSelectedUnit(UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit());
- boolean limitByLength = limitByLengthCheckBox.isSelected();
((SwingPreferences) Application.getPreferences()).putBoolean("motorFilterLimitLength", limitByLength);
if ( mountLength != null & limitByLength ) {
lengthSlider.setValueAt(1, (int) Math.min(1000,Math.round(1000*mountLength)));
diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
index 5d8cd2e53..423f23d25 100644
--- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
@@ -1006,7 +1006,7 @@ public class SimulationPanel extends JPanel {
*/
public void takeTheSpotlight() {
simulationTable.requestFocusInWindow();
- if (simulationTable.getSelectedRows().length > 0) {
+ if (simulationTable.getRowCount() == 0 || simulationTable.getSelectedRows().length > 0) {
return;
}
if (previousSelection == null || previousSelection.length == 0) {