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) {