From b8b1e6576e81251bac26ff31b0e51d83f1e81bb2 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Wed, 3 Jun 2015 15:48:13 -0400 Subject: [PATCH] [GUI Options Implemented] Implemented GUI elements to change the position of external components. External Components are pods and parallel stages. Slightly different UI options have been implemented for each. --- core/resources/l10n/messages.properties | 8 +++ .../rocketcomponent/ExternalComponent.java | 11 +-- .../rocketcomponent/OutsideComponent.java | 4 +- .../sf/openrocket/rocketcomponent/Stage.java | 20 ++++-- .../configdialog/RocketComponentConfig.java | 72 +++++++++++++++++++ .../gui/configdialog/StageConfig.java | 66 ++++++++++++++++- 6 files changed, 168 insertions(+), 13 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 72f5c27ab..f1ac5016f 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -823,6 +823,14 @@ RocketCompCfg.lbl.Componentname = Component name: RocketCompCfg.ttip.Thecomponentname = The component name. RocketCompCfg.tab.Override = Override RocketCompCfg.tab.MassandCGoverride = Mass and CG override options +RocketCompCfg.tab.Pod = Pod +RocketCompCfg.tab.PodComment = Options for locating ExteriorComponents outside the Rocket +RocketCompCfg.tab.Parallel = Parallel +RocketCompCfg.tab.ParallelComment = Options for locating Stages parallel to other stages +RocketCompCfg.parallel.inline = Make this Stage Parallel +RocketCompCfg.parallel.radius = Radial Distance (meters) +RocketCompCfg.parallel.angle = Angle (Radians) +RocketCompCfg.parallel.rotation = Rotation (Radians) RocketCompCfg.tab.Figure = Figure RocketCompCfg.tab.Figstyleopt = Figure style options RocketCompCfg.tab.Comment = Comment diff --git a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java index 48c3e2228..622302737 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java @@ -131,15 +131,18 @@ public abstract class ExternalComponent extends RocketComponent implements Outsi fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); } - - @Override public boolean isInline() { return this.axial; } @Override - public void setInline(final boolean inline) { - this.axial = inline; + public boolean getParallel() { + return !this.axial; + } + + @Override + public void setParallel(final boolean parallel) { + this.axial = !parallel; } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/OutsideComponent.java b/core/src/net/sf/openrocket/rocketcomponent/OutsideComponent.java index 23da91663..808c57145 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/OutsideComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/OutsideComponent.java @@ -9,14 +9,14 @@ public interface OutsideComponent { * @return True This component is aligned with its parent * False This component is offset from its parent -- like an external pod, or strap-on stage */ - public boolean isInline(); + public boolean getParallel(); /** * Change whether this component is located inside or outside of the rest of the rocket. (Specifically, inside or outside its parent.) * * @param inline True indicates that this component axially aligned with its parent. False indicates an off-center component. */ - public void setInline(final boolean inline); + public void setParallel(final boolean inline); /** * Get the position of this component in polar coordinates diff --git a/core/src/net/sf/openrocket/rocketcomponent/Stage.java b/core/src/net/sf/openrocket/rocketcomponent/Stage.java index 9eefdeb48..be87bcce2 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Stage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Stage.java @@ -14,6 +14,8 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon private double position_radial_m = 0; private double rotation_rad = 0; + // ParallelStagingConfiguration parallelConfiguration = null; + public Stage() { this.separationConfigurations = new FlightConfigurationImpl(this, ComponentChangeEvent.EVENT_CHANGE, new StageSeparationConfiguration()); } @@ -29,7 +31,9 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon return separationConfigurations; } - + // public ParallelStagingConfiguration getParallelStageConfiguration() { + // return parallelConfiguration; + // } @Override @@ -66,13 +70,17 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon } @Override - public boolean isInline() { + public boolean getParallel() { + return !this.axial; + } + + public boolean getInline() { return this.axial; } @Override - public void setInline(final boolean inline) { - this.axial = inline; + public void setParallel(final boolean parallel) { + this.axial = !parallel; } @Override @@ -84,8 +92,8 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon } @Override - public void setAngularPosition(final double phi) { - this.position_angular_rad = phi; + public void setAngularPosition(final double angle_rad) { + this.position_angular_rad = angle_rad; } @Override diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 30142f4cc..45d222d0f 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -1,6 +1,8 @@ package net.sf.openrocket.gui.configdialog; +import java.awt.Component; +import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; @@ -17,10 +19,14 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JSeparator; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.database.ComponentPresetDatabase; @@ -41,6 +47,8 @@ import net.sf.openrocket.material.Material; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.ExternalComponent; +import net.sf.openrocket.rocketcomponent.OutsideComponent; +import net.sf.openrocket.rocketcomponent.Stage; import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish; import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.RocketComponent; @@ -65,6 +73,9 @@ public class RocketComponentConfig extends JPanel { protected JTextArea commentTextArea; private final TextFieldListener textFieldListener; + private BooleanModel podsEnabledModel = null; + private JPanel podsEnabledPanel = null; + private JPanel buttonPanel; private JLabel infoLabel; @@ -115,6 +126,8 @@ public class RocketComponentConfig extends JPanel { tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(), trans.get("RocketCompCfg.tab.Specifyacomment")); + + addButtons(); updateFields(); @@ -146,6 +159,10 @@ public class RocketComponentConfig extends JPanel { }); buttonPanel.add(closeButton, "right, gap 30lp"); + if( component instanceof ExternalComponent ){ + tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Pod"), null, podTab( (ExternalComponent) component ), trans.get("RocketCompCfg.tab.PodComment"), 2); + } + updateFields(); this.add(buttonPanel, "spanx, growx"); @@ -268,6 +285,53 @@ public class RocketComponentConfig extends JPanel { return subPanel; } + private JPanel podTab( final ExternalComponent pod ){ + // enable parallel staging + JPanel motherPanel = new JPanel( new MigLayout("fill")); + podsEnabledModel = new BooleanModel( component, "Parallel"); + podsEnabledModel.setValue(false); + JCheckBox parallelEnabled = new JCheckBox( podsEnabledModel); + parallelEnabled.setText(trans.get("RocketCompCfg.parallel.inline")); + motherPanel.add(parallelEnabled, "wrap"); + + JPanel enabledPanel = new JPanel( new MigLayout("fill")); + this.podsEnabledPanel = enabledPanel; + + enabledPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "growx,wrap"); + + // set radial distance + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.radius")), "align left"); + DoubleModel radiusModel = new DoubleModel( pod, "RadialPosition", 0.); + JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel()); + radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner )); + enabledPanel.add(radiusSpinner , "growx, wrap, align right"); + + // set angle around the primary stage + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.angle")), "align left"); + DoubleModel angleModel = new DoubleModel( pod, "AngularPosition", 0., Math.PI*2); + JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel()); + angleSpinner.setEditor(new SpinnerEditor(angleSpinner)); + enabledPanel.add(angleSpinner, "growx, wrap"); + + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.rotation")), "align left"); + DoubleModel rotationModel = new DoubleModel( pod, "Rotation", 0.0, Math.PI*2); + JSpinner rotationSpinner = new JSpinner(rotationModel.getSpinnerModel()); + rotationSpinner.setEditor(new SpinnerEditor(rotationSpinner)); + enabledPanel.add(rotationSpinner, "growx, wrap"); + + setDeepEnabled( enabledPanel, podsEnabledModel.getValue()); + parallelEnabled.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + setDeepEnabled( podsEnabledPanel, podsEnabledModel.getValue()); + } + }); + + motherPanel.add( enabledPanel , "growx, wrap"); + + return motherPanel; + } + private JPanel overrideTab() { JPanel panel = new JPanel(new MigLayout("align 50% 20%, fillx, gap rel unrel", @@ -569,4 +633,12 @@ public class RocketComponentConfig extends JPanel { } + protected static void setDeepEnabled(Component component, boolean enabled) { + component.setEnabled(enabled); + if (component instanceof Container) { + for (Component c : ((Container) component).getComponents()) { + setDeepEnabled(c, enabled); + } + } + } } \ No newline at end of file diff --git a/swing/src/net/sf/openrocket/gui/configdialog/StageConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/StageConfig.java index 70ce149b2..db6f6bd94 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/StageConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/StageConfig.java @@ -1,18 +1,28 @@ package net.sf.openrocket.gui.configdialog; +import java.awt.Component; +import java.awt.Container; + +import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JSeparator; import javax.swing.JSpinner; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; +import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.rocketcomponent.OutsideComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.Stage; import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration; @@ -21,6 +31,9 @@ import net.sf.openrocket.startup.Application; public class StageConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); + private BooleanModel parallelEnabledModel = null; + private JPanel parallelEnabledPanel = null; + public StageConfig(OpenRocketDocument document, RocketComponent component) { super(document, component); @@ -30,9 +43,59 @@ public class StageConfig extends RocketComponentConfig { tabbedPane.insertTab(trans.get("tab.Separation"), null, tab, trans.get("tab.Separation.ttip"), 1); } - + + // all stage instances should qualify here... + if( component instanceof OutsideComponent ){ + tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (Stage) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 2); + } } + private JPanel parallelTab( final Stage stage ){ + // enable parallel staging + JPanel motherPanel = new JPanel( new MigLayout("fill")); + parallelEnabledModel = new BooleanModel( component, "Parallel"); + parallelEnabledModel.setValue(false); + JCheckBox parallelEnabled = new JCheckBox( parallelEnabledModel); + parallelEnabled.setText(trans.get("RocketCompCfg.parallel.inline")); + motherPanel.add(parallelEnabled, "wrap"); + + JPanel enabledPanel = new JPanel( new MigLayout("fill")); + this.parallelEnabledPanel = enabledPanel; + + enabledPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "growx,wrap"); + + // set radial distance + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.radius")), "align left"); + DoubleModel radiusModel = new DoubleModel( stage, "RadialPosition", 0.0); + JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel()); + radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner )); + enabledPanel.add(radiusSpinner , "growx, wrap, align right"); + + // set angle around the primary stage + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.angle")), "align left"); + DoubleModel angleModel = new DoubleModel( stage, "AngularPosition", 0.0, Math.PI*2); + JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel()); + angleSpinner.setEditor(new SpinnerEditor(angleSpinner)); + enabledPanel.add(angleSpinner, "growx, wrap"); + + enabledPanel.add(new JLabel(trans.get("RocketCompCfg.parallel.rotation")), "align left"); + DoubleModel rotationModel = new DoubleModel( stage, "Rotation", 0.0, Math.PI*2); + JSpinner rotationSpinner = new JSpinner(rotationModel.getSpinnerModel()); + rotationSpinner.setEditor(new SpinnerEditor(rotationSpinner)); + enabledPanel.add(rotationSpinner, "growx, wrap"); + + setDeepEnabled( enabledPanel, parallelEnabledModel.getValue()); + parallelEnabled.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + setDeepEnabled( parallelEnabledPanel, parallelEnabledModel.getValue()); + } + }); + + motherPanel.add( enabledPanel , "growx, wrap"); + + return motherPanel; + } private JPanel separationTab(Stage stage) { JPanel panel = new JPanel(new MigLayout("fill")); @@ -59,5 +122,6 @@ public class StageConfig extends RocketComponentConfig { return panel; } + }