diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 2e2e983e8..f12e187bd 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -766,6 +766,9 @@ BodyTubecfg.tab.Generalproperties = General properties BodyTubecfg.tab.Motor = Motor BodyTubecfg.tab.Motormountconf = Motor mount configuration BodyTubecfg.checkbox.Automatic = Automatic +BodyTubecfg.checkbox.ttip.Automatic = Use the diameter of the previous/next component +BodyTubecfg.checkbox.ttip.Automatic_noReferenceComponent = There is no previous/next component to take the diameter of +BodyTubecfg.checkbox.ttip.Automatic_alreadyAuto = The previous/next component already has its auto setting turned on BodyTubecfg.checkbox.Filled = Filled ! FinSetConfig @@ -1035,6 +1038,9 @@ NoseConeCfg.lbl.Shapeparam = Shape parameter: NoseConeCfg.lbl.Noseconelength = Nose cone length: NoseConeCfg.lbl.Basediam = Base diameter: NoseConeCfg.checkbox.Automatic = Automatic +NoseConeCfg.checkbox.ttip.Automatic = Use the diameter of the next component +NoseConeCfg.checkbox.ttip.Automatic_noReferenceComponent = There is no next component to take the diameter of +NoseConeCfg.checkbox.ttip.Automatic_alreadyAuto = The next component already has its auto setting turned on NoseConeCfg.lbl.Wallthickness = Wall thickness: NoseConeCfg.checkbox.Filled = Filled NoseConeCfg.tab.General = General @@ -1136,6 +1142,9 @@ TransitionCfg.lbl.Shapeparam = Shape parameter: TransitionCfg.lbl.Transitionlength = Transition length: TransitionCfg.lbl.Forediam = Fore diameter: TransitionCfg.checkbox.Automatic = Automatic +TransitionCfg.checkbox.ttip.Automatic = Use the diameter of the previous/next component +TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent = There is no previous/next component to take the diameter of +TransitionCfg.checkbox.ttip.Automatic_alreadyAuto = The previous/next component already has its auto setting turned on TransitionCfg.lbl.Aftdiam = Aft diameter: TransitionCfg.lbl.Wallthickness = Wall thickness: TransitionCfg.checkbox.Filled = Filled diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java index 03b979543..684279ca5 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java @@ -1,10 +1,7 @@ package net.sf.openrocket.rocketcomponent; -import java.util.EventObject; import java.util.Iterator; -import net.sf.openrocket.appearance.Appearance; -import net.sf.openrocket.appearance.Decal; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; @@ -25,6 +22,8 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou private double outerRadius = 0; private boolean autoRadius = false; // Radius chosen automatically based on parent component + + private SymmetricComponent refComp = null; // Reference component that is used for the autoRadius // When changing the inner radius, thickness is modified private double overhang = 0; @@ -79,13 +78,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou // Return auto radius from front or rear double r = -1; SymmetricComponent c = this.getPreviousSymmetricComponent(); - if (c != null) { + // Don't use the radius of a component who already has its auto diameter enabled + if (c != null && !c.usesNextCompAutomatic()) { r = c.getFrontAutoRadius(); + refComp = c; } if (r < 0) { c = this.getNextSymmetricComponent(); - if (c != null) { + // Don't use the radius of a component who already has its auto diameter enabled + if (c != null && !c.usesPreviousCompAutomatic()) { r = c.getRearAutoRadius(); + refComp = c; } } if (r < 0) @@ -136,8 +139,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); clearPreset(); } - - + + @Override + public boolean usesPreviousCompAutomatic() { + return isOuterRadiusAutomatic() && refComp == getPreviousSymmetricComponent(); + } + + @Override + public boolean usesNextCompAutomatic() { + return isOuterRadiusAutomatic() && refComp == getNextSymmetricComponent(); + } + @Override protected void loadFromPreset(ComponentPreset preset) { this.autoRadius = false; diff --git a/core/src/net/sf/openrocket/rocketcomponent/NoseCone.java b/core/src/net/sf/openrocket/rocketcomponent/NoseCone.java index a7316fdb3..851dfd2d5 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/NoseCone.java +++ b/core/src/net/sf/openrocket/rocketcomponent/NoseCone.java @@ -69,7 +69,12 @@ public class NoseCone extends Transition implements InsideColorComponent { public void setForeRadiusAutomatic(boolean b) { // No-op } - + + @Override + public boolean usesPreviousCompAutomatic() { + return false; + } + @Override public double getForeShoulderLength() { return 0; diff --git a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java index b5d704496..aa61cd979 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java @@ -644,5 +644,15 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou } return null; } - + + /** + * Checks whether the component uses the previous symmetric component for its auto diameter. + */ + public abstract boolean usesPreviousCompAutomatic(); + + /** + * Checks whether the component uses the next symmetric component for its auto diameter. + */ + public abstract boolean usesNextCompAutomatic(); + } diff --git a/core/src/net/sf/openrocket/rocketcomponent/Transition.java b/core/src/net/sf/openrocket/rocketcomponent/Transition.java index 304750066..188a01f40 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Transition.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Transition.java @@ -192,7 +192,15 @@ public class Transition extends SymmetricComponent implements InsideColorCompone return getForeRadius(); } + @Override + public boolean usesPreviousCompAutomatic() { + return isForeRadiusAutomatic(); + } + @Override + public boolean usesNextCompAutomatic() { + return isAftRadiusAutomatic(); + } //////// Type & shape ///////// diff --git a/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java index 677e5778b..163c1002f 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java @@ -5,8 +5,6 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -19,8 +17,8 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.MotorMount; -import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; @@ -28,6 +26,7 @@ import net.sf.openrocket.unit.UnitGroup; public class BodyTubeConfig extends RocketComponentConfig { private DoubleModel maxLength; + private final JCheckBox checkAutoOuterRadius; private static final Translator trans = Application.getTranslator(); public BodyTubeConfig(OpenRocketDocument d, RocketComponent c) { @@ -62,24 +61,10 @@ public class BodyTubeConfig extends RocketComponentConfig { //// Automatic javax.swing.Action outerAutoAction = od.getAutomaticAction(); - JCheckBox checkAuto = new JCheckBox(outerAutoAction); - checkAuto.setText(trans.get("BodyTubecfg.checkbox.Automatic")); - panel.add(checkAuto, "skip, span 2, wrap"); - // Disable check button if there is no component to get the diameter from - checkAuto.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (!(c instanceof BodyTube)) return; - if (((BodyTube) c).getPreviousSymmetricComponent() != null) { - checkAuto.setEnabled(true); - } - else { - checkAuto.setEnabled(false); - ((BodyTube) c).setOuterRadiusAutomatic(false); - } - } - }); - checkAuto.getChangeListeners()[0].stateChanged(null); + checkAutoOuterRadius = new JCheckBox(outerAutoAction); + checkAutoOuterRadius.setText(trans.get("BodyTubecfg.checkbox.Automatic")); + panel.add(checkAutoOuterRadius, "skip, span 2, wrap"); + updateCheckboxAutoAftRadius(); //// Inner diameter panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Innerdiameter"))); @@ -132,4 +117,33 @@ public class BodyTubeConfig extends RocketComponentConfig { super.updateFields(); } + /** + * Sets the checkAutoOuterRadius checkbox's enabled state and tooltip text, based on the state of its previous + * component. If there is no next and previous symmetric component, the checkAutoOuterRadius checkbox is disabled. + * If there is still a next or previous component which does not have its auto state enabled, meaning it can still + * serve as a reference component for this component, the auto checkbox is enabled. + */ + private void updateCheckboxAutoAftRadius() { + if (component == null || checkAutoOuterRadius == null) return; + + // Disable check button if there is no component to get the diameter from + SymmetricComponent prevComp = ((BodyTube) component).getPreviousSymmetricComponent(); + SymmetricComponent nextComp = ((BodyTube) component).getNextSymmetricComponent(); + if (prevComp == null && nextComp == null) { + checkAutoOuterRadius.setEnabled(false); + ((BodyTube) component).setOuterRadiusAutomatic(false); + checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic_noReferenceComponent")); + return; + } + if (!(prevComp != null && nextComp == null && prevComp.usesNextCompAutomatic()) && + !(nextComp != null && prevComp == null && nextComp.usesPreviousCompAutomatic()) && + !(nextComp != null && prevComp != null && prevComp.usesNextCompAutomatic() && nextComp.usesPreviousCompAutomatic())) { + checkAutoOuterRadius.setEnabled(true); + checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic")); + } else { + checkAutoOuterRadius.setEnabled(false); + ((BodyTube) component).setOuterRadiusAutomatic(false); + checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic_alreadyAuto")); + } + } } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java index d8f8332a7..6be83867e 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/NoseConeConfig.java @@ -10,8 +10,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.JSpinner; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -25,6 +23,7 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; @@ -38,6 +37,7 @@ public class NoseConeConfig extends RocketComponentConfig { private JLabel shapeLabel; private JSpinner shapeSpinner; private JSlider shapeSlider; + private final JCheckBox checkAutoAftRadius; private static final Translator trans = Application.getTranslator(); // Prepended to the description from NoseCone.DESCRIPTIONS @@ -111,25 +111,11 @@ public class NoseConeConfig extends RocketComponentConfig { panel.add(new UnitSelector(aftRadiusModel), "growx"); panel.add(new BasicSlider(aftRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - JCheckBox check = new JCheckBox(aftRadiusModel.getAutomaticAction()); + checkAutoAftRadius = new JCheckBox(aftRadiusModel.getAutomaticAction()); //// Automatic - check.setText(trans.get("NoseConeCfg.checkbox.Automatic")); - panel.add(check, "skip, span 2, wrap"); - // Disable check button if there is no component to get the diameter from - check.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (!(c instanceof NoseCone)) return; - if (((NoseCone) c).getNextSymmetricComponent() != null) { - check.setEnabled(true); - } - else { - check.setEnabled(false); - ((NoseCone) c).setAftRadiusAutomatic(false); - } - } - }); - check.getChangeListeners()[0].stateChanged(null); + checkAutoAftRadius.setText(trans.get("NoseConeCfg.checkbox.Automatic")); + panel.add(checkAutoAftRadius, "skip, span 2, wrap"); + updateCheckboxAutoAftRadius(); } {//// Wall thickness: @@ -182,6 +168,30 @@ public class NoseConeConfig extends RocketComponentConfig { shapeSpinner.setEnabled(e); shapeSlider.setEnabled(e); } - + /** + * Sets the checkAutoAftRadius checkbox's enabled state and tooltip text, based on the state of its next component. + * If there is no next symmetric component or if that component already has its auto checkbox checked, the + * checkAutoAftRadius checkbox is disabled. + */ + private void updateCheckboxAutoAftRadius() { + if (component == null || checkAutoAftRadius == null) return; + + // Disable check button if there is no component to get the diameter from + SymmetricComponent nextComp = ((NoseCone) component).getNextSymmetricComponent(); + if (nextComp == null) { + checkAutoAftRadius.setEnabled(false); + ((NoseCone) component).setAftRadiusAutomatic(false); + checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic_noReferenceComponent")); + return; + } + if (!nextComp.usesPreviousCompAutomatic()) { + checkAutoAftRadius.setEnabled(true); + checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic")); + } else { + checkAutoAftRadius.setEnabled(false); + ((NoseCone) component).setAftRadiusAutomatic(false); + checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic_alreadyAuto")); + } + } } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java index 90178611f..8bd0b2181 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/TransitionConfig.java @@ -9,8 +9,6 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -22,9 +20,8 @@ import net.sf.openrocket.gui.components.DescriptionArea; import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; -import net.sf.openrocket.rocketcomponent.BodyTube; -import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; @@ -39,6 +36,8 @@ public class TransitionConfig extends RocketComponentConfig { private JLabel shapeLabel; private JSpinner shapeSpinner; private BasicSlider shapeSlider; + private final JCheckBox checkAutoAftRadius; + private final JCheckBox checkAutoForeRadius; private DescriptionArea description; @@ -124,25 +123,11 @@ public class TransitionConfig extends RocketComponentConfig { panel.add(new UnitSelector(foreRadiusModel), "growx"); panel.add(new BasicSlider(foreRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - final JCheckBox checkbox = new JCheckBox(foreRadiusModel.getAutomaticAction()); + checkAutoForeRadius = new JCheckBox(foreRadiusModel.getAutomaticAction()); //// Automatic - checkbox.setText(trans.get("TransitionCfg.checkbox.Automatic")); - panel.add(checkbox, "skip, span 2, wrap"); - // Disable check button if there is no component to get the diameter from - checkbox.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (!(c instanceof Transition)) return; - if (((Transition) c).getPreviousSymmetricComponent() != null) { - checkbox.setEnabled(true); - } - else { - checkbox.setEnabled(false); - ((Transition) c).setForeRadiusAutomatic(false); - } - } - }); - checkbox.getChangeListeners()[0].stateChanged(null); + checkAutoForeRadius.setText(trans.get("TransitionCfg.checkbox.Automatic")); + panel.add(checkAutoForeRadius, "skip, span 2, wrap"); + updateCheckboxAutoForeRadius(); } { //// Aft diameter: @@ -158,25 +143,11 @@ public class TransitionConfig extends RocketComponentConfig { panel.add(new UnitSelector(aftRadiusModel), "growx"); panel.add(new BasicSlider(aftRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px"); - final JCheckBox aftRadiusCheckbox = new JCheckBox(aftRadiusModel.getAutomaticAction()); + checkAutoAftRadius = new JCheckBox(aftRadiusModel.getAutomaticAction()); //// Automatic - aftRadiusCheckbox.setText(trans.get("TransitionCfg.checkbox.Automatic")); - panel.add(aftRadiusCheckbox, "skip, span 2, wrap"); - // Disable check button if there is no component to get the diameter from - aftRadiusCheckbox.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (!(c instanceof Transition)) return; - if (((Transition) c).getNextSymmetricComponent() != null) { - aftRadiusCheckbox.setEnabled(true); - } - else { - aftRadiusCheckbox.setEnabled(false); - ((Transition) c).setAftRadiusAutomatic(false); - } - } - }); - aftRadiusCheckbox.getChangeListeners()[0].stateChanged(null); + checkAutoAftRadius.setText(trans.get("TransitionCfg.checkbox.Automatic")); + panel.add(checkAutoAftRadius, "skip, span 2, wrap"); + updateCheckboxAutoAftRadius(); } { /// Wall thickness: @@ -228,5 +199,57 @@ public class TransitionConfig extends RocketComponentConfig { shapeSpinner.setEnabled(e); shapeSlider.setEnabled(e); } + + /** + * Sets the checkAutoAftRadius checkbox's enabled state and tooltip text, based on the state of its next component. + * If there is no next symmetric component or if that component already has its auto checkbox checked, the + * checkAutoAftRadius checkbox is disabled. + */ + private void updateCheckboxAutoAftRadius() { + if (component == null || checkAutoAftRadius == null) return; + + // Disable check button if there is no component to get the diameter from + SymmetricComponent nextComp = ((Transition) component).getNextSymmetricComponent(); + if (nextComp == null) { + checkAutoAftRadius.setEnabled(false); + ((Transition) component).setAftRadiusAutomatic(false); + checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent")); + return; + } + if (!nextComp.usesPreviousCompAutomatic()) { + checkAutoAftRadius.setEnabled(true); + checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic")); + } else { + checkAutoAftRadius.setEnabled(false); + ((Transition) component).setAftRadiusAutomatic(false); + checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_alreadyAuto")); + } + } + + /** + * Sets the checkAutoForeRadius checkbox's enabled state and tooltip text, based on the state of its next component. + * If there is no next symmetric component or if that component already has its auto checkbox checked, the + * checkAutoForeRadius checkbox is disabled. + */ + private void updateCheckboxAutoForeRadius() { + if (component == null || checkAutoForeRadius == null) return; + + // Disable check button if there is no component to get the diameter from + SymmetricComponent prevComp = ((Transition) component).getPreviousSymmetricComponent(); + if (prevComp == null) { + checkAutoForeRadius.setEnabled(false); + ((Transition) component).setForeRadiusAutomatic(false); + checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent")); + return; + } + if (!prevComp.usesNextCompAutomatic()) { + checkAutoForeRadius.setEnabled(true); + checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic")); + } else { + checkAutoForeRadius.setEnabled(false); + ((Transition) component).setForeRadiusAutomatic(false); + checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_alreadyAuto")); + } + } }