diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 20cbc4bac..f84c5e7b3 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1066,6 +1066,11 @@ ShockCordCfg.lbl.Posrelativeto = Position relative to: ShockCordCfg.lbl.plus = plus ShockCordCfg.lbl.Packedlength = Packed length: ShockCordCfg.lbl.Packeddiam = Packed diameter: +ShockCordCfg.tab.Radialpos = Radial position +ShockCordCfg.tab.ttip.Radialpos = Radial position configuration +ShockCordCfg.lbl.Radialdistance = Radial distance: +ShockCordCfg.lbl.Radialdirection = Radial direction: +ShockCordCfg.but.Reset = Reset ShockCordCfg.tab.General = General ShockCordCfg.tab.ttip.General = General properties diff --git a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java index 442deb00d..92ef86e72 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java +++ b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java @@ -21,7 +21,7 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, B private double radius; private double thickness; - private double angleOffsetRadians = 0; + private double angleOffsetRadians = Math.PI; private double radialOffset = 0; private int instanceCount = 1; diff --git a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java index 10241780f..5ce537034 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java @@ -56,7 +56,7 @@ public class RailButton extends ExternalComponent implements AnglePositionable, private double radialDistance_m=0; protected static final AngleMethod angleMethod = AngleMethod.RELATIVE; - private double angle_rad = 0; + private double angle_rad = Math.PI; private int instanceCount = 1; private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0]; diff --git a/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java index 79dd28f05..36c3d90bb 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java @@ -22,7 +22,7 @@ public class LaunchLugTest extends BaseTestCase { lug.setInstanceCount(2); double expX = 0.111 + body.getLocations()[0].x; - double expR = body.getOuterRadius()+lug.getOuterRadius(); + double expR = -(body.getOuterRadius()+lug.getOuterRadius()); Coordinate expPos = new Coordinate( expX, expR, 0, 0); Coordinate actPos[] = lug.getLocations(); assertEquals(" LaunchLug has the wrong x value: ", expPos.x, actPos[0].x, EPSILON); diff --git a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java index e75146eca..2cbe37116 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java @@ -89,7 +89,7 @@ public class RocketTest extends BaseTestCase { } LaunchLug lugs = (LaunchLug)body.getChild(1); - expLoc = new Coordinate(0.181, 0.015, 0); + expLoc = new Coordinate(0.181, -0.015, 0); assertThat(lugs.getName()+" have incorrect count: ", lugs.getInstanceCount(), equalTo(1)); actLocs = lugs.getComponentLocations(); { // singular instance: diff --git a/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java b/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java new file mode 100644 index 000000000..462ba97d8 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java @@ -0,0 +1,28 @@ +package net.sf.openrocket.gui.components; + +import javax.swing.JSpinner; +import javax.swing.SpinnerModel; + +import net.sf.openrocket.gui.SpinnerEditor; + +/** + * A JSpinner that allows edits. + * + * @author Billy Olsen + */ +public class EditableSpinner extends JSpinner { + + private static final long serialVersionUID = 1L; + + + /** + * Creates a new EditableSpinner for the SpinnerModel + * + * @param model + */ + public EditableSpinner(SpinnerModel model) { + super(model); + this.setEditor(new SpinnerEditor(this)); + } + +} diff --git a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java index 0711c72e6..7402580ea 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java @@ -20,6 +20,9 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + @SuppressWarnings("serial") public class LaunchLugConfig extends RocketComponentConfig { @@ -108,28 +111,33 @@ public class LaunchLugConfig extends RocketComponentConfig { // create a new panel for the right column panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); - + //// Position relative to: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"))); EnumModel positionModel = new EnumModel(component, "AxialMethod", AxialMethod.axialOffsetMethods ); JComboBox positionCombo = new JComboBox( positionModel ); - panel.add( positionCombo, "spanx, growx, wrap"); + panel.add(positionCombo, "spanx, growx, wrap"); //// plus + final DoubleModel mAxOff = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.plus")), "right"); - - m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); - spin = new JSpinner(m.getSpinnerModel()); + spin = new JSpinner(mAxOff.getSpinnerModel()); // Plus quantity input spin.setEditor(new SpinnerEditor(spin)); panel.add(spin, "growx"); - panel.add(new UnitSelector(m), "growx"); - panel.add(new BasicSlider(m.getSliderModel( + panel.add(new UnitSelector(mAxOff), "growx"); // Unity selection + panel.add(new BasicSlider(mAxOff.getSliderModel( // Plus quantity slider new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap para"); - - + + // Add an action listener to update the plus quantity, based on the selected reference point + positionCombo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mAxOff.stateChanged(e); + } + }); //// Material panel.add(materialPanel( Material.Type.BULK), "span, wrap"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java index 113381cdc..0edf5e687 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java @@ -1,10 +1,7 @@ package net.sf.openrocket.gui.configdialog; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; +import javax.swing.*; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -15,11 +12,16 @@ import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; +import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + @SuppressWarnings("serial") public class ShockCordConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); @@ -114,11 +116,56 @@ public class ShockCordConfig extends RocketComponentConfig { //// 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(trans.get("ShockCordCfg.tab.General"), null, panel, + trans.get("ShockCordCfg.tab.ttip.General"), 0); + //// Radial position and Radial position configuration + tabbedPane.insertTab(trans.get("ShockCordCfg.tab.Radialpos"), null, positionTab(), + trans.get("ShockCordCfg.tab.ttip.Radialpos"), 1); tabbedPane.setSelectedIndex(0); } - + // TODO: LOW: there is a lot of duplicate code here with other mass components... (e.g. in MassComponentConfig or ParachuteConfig) + protected JPanel positionTab() { + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); + + //// Radial position + //// Radial distance: + panel.add(new JLabel(trans.get("ShockCordCfg.lbl.Radialdistance"))); + + 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"); + + + //// Radial direction: + panel.add(new JLabel(trans.get("ShockCordCfg.lbl.Radialdirection"))); + + m = new DoubleModel(component, "RadialDirection", UnitGroup.UNITS_ANGLE); + + 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"); + + + //// Reset button + JButton button = new JButton(trans.get("ShockCordCfg.but.Reset")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ((ShockCord) component).setRadialDirection(0.0); + ((ShockCord) component).setRadialPosition(0.0); + } + }); + panel.add(button, "spanx, right"); + + return panel; + } } diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java index 58a3c1d93..c51e5da32 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java @@ -124,12 +124,20 @@ final class MassObjectRenderer { private MassObjectRenderer() { } - + + /** + * Draw the mass object as a 3D figure. + * + * @param gl OpenGL object + * @param o mass object to draw (e.g. Parachute or Mass Component) + * @param slices number of slices for the 3D object (kind of like subdivision surface) + * @param stacks number of stacks for the 3D object (kind of like subdivision surface) + */ static final void drawMassObject(final GL2 gl, final MassObject o, final int slices, final int stacks) { - - double da, r, dz; - double x, y, z; + + double da, r, dz; // Axial length per slice, radius & length per stack + double x, y, z; // X-, y- and z-position int i, j; da = 2.0f * PI / slices; @@ -156,20 +164,24 @@ final class MassObjectRenderer { x = sin((i * da)); y = cos((i * da)); } - + + // Add radial offset + double xOffset = o.getRadialPosition() * sin(o.getRadialDirection()); + double yOffset = o.getRadialPosition() * cos(o.getRadialDirection()); + if (r == 0) normal3d(gl, 0, 0, 1); else normal3d(gl, x, y, z); TXTR_COORD(gl, s, t); - glVertex3d(gl, (x * r), (y * r), z); + glVertex3d(gl, (x * r) + xOffset, (y * r) + yOffset, z); if (rNext == 0) normal3d(gl, 0, 0, -1); else normal3d(gl, x, y, z); TXTR_COORD(gl, s, t + dt); - glVertex3d(gl, (x * rNext), (y * rNext), (z + dz)); + glVertex3d(gl, (x * rNext) + xOffset, (y * rNext) + yOffset, (z + dz)); s += ds; } // for slices diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java index dac63d28c..c8b7d1faa 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java @@ -16,15 +16,18 @@ import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSeparator; -import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.SwingConstants; +import javax.swing.colorchooser.ColorSelectionModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.components.ColorIcon; +import net.sf.openrocket.gui.components.EditableSpinner; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.gui.components.UnitSelector; @@ -57,28 +60,61 @@ public class PhotoSettingsConfig extends JTabbedPane { this.o = o; } + /** + Changes the color of the selected component to + @param color: color to change the component to + */ + private void changeComponentColor(Color color) { + try { + final Method setMethod = o.getClass().getMethod("set" + valueName, net.sf.openrocket.util.Color.class); + if (color == null) + return; + try { + setMethod.invoke(o, ColorConversion.fromAwtColor(color)); + } catch (Throwable e1) { + Application.getExceptionHandler().handleErrorCondition(e1); + } + } catch (Throwable e1) { + Application.getExceptionHandler().handleErrorCondition(e1); + } + + } + + @Override public void actionPerformed(ActionEvent colorClickEvent) { try { final Method getMethod = o.getClass().getMethod("get" + valueName); - final Method setMethod = o.getClass().getMethod("set" + valueName, net.sf.openrocket.util.Color.class); net.sf.openrocket.util.Color c = (net.sf.openrocket.util.Color) getMethod.invoke(o); Color awtColor = ColorConversion.toAwtColor(c); colorChooser.setColor(awtColor); + + // Bind a change of color selection to a change in the components color + ColorSelectionModel model = colorChooser.getSelectionModel(); + ChangeListener changeListener = new ChangeListener() { + public void stateChanged(ChangeEvent changeEvent) { + Color selected = colorChooser.getColor(); + changeComponentColor(selected); + } + }; + model.addChangeListener(changeListener); + JDialog d = JColorChooser.createDialog(PhotoSettingsConfig.this, trans.get("PhotoSettingsConfig.colorChooser.title"), true, colorChooser, new ActionListener() { @Override public void actionPerformed(ActionEvent okEvent) { - Color selected = colorChooser.getColor(); - if (selected == null) - return; - try { - setMethod.invoke(o, ColorConversion.fromAwtColor(selected)); - } catch (Throwable e1) { - Application.getExceptionHandler().handleErrorCondition(e1); - } + changeComponentColor(colorChooser.getColor()); + // Unbind listener to avoid the current component's appearance to change with other components + model.removeChangeListener(changeListener); } - }, null); + }, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + changeComponentColor(awtColor); + // Unbind listener to avoid the current component's appearance to change with other components + model.removeChangeListener(changeListener); + } + }); d.setVisible(true); } catch (Throwable e1) { Application.getExceptionHandler().handleErrorCondition(e1); @@ -128,22 +164,22 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.pitch"))); DoubleModel pitchModel = new DoubleModel(p, "Pitch", UnitGroup.UNITS_ANGLE); - add(new JSpinner(pitchModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(pitchModel.getSpinnerModel()), "w 40"); add(new UnitSelector(pitchModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.yaw"))); DoubleModel yawModel = new DoubleModel(p, "Yaw", UnitGroup.UNITS_ANGLE); - add(new JSpinner(yawModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(yawModel.getSpinnerModel()), "w 40"); add(new UnitSelector(yawModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.roll"))); DoubleModel rollModel = new DoubleModel(p, "Roll", UnitGroup.UNITS_ANGLE); - add(new JSpinner(rollModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(rollModel.getSpinnerModel()), "w 40"); add(new UnitSelector(rollModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.advance"))); DoubleModel advanceModel = new DoubleModel(p, "Advance", UnitGroup.UNITS_LENGTH); - add(new JSpinner(advanceModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(advanceModel.getSpinnerModel()), "w 40"); add(new UnitSelector(advanceModel), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.camera"), Style.BOLD)); @@ -151,22 +187,22 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAz"))); DoubleModel viewAzModel = new DoubleModel(p, "ViewAz", UnitGroup.UNITS_ANGLE); - add(new JSpinner(viewAzModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewAzModel.getSpinnerModel()), "w 40"); add(new UnitSelector(viewAzModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAlt"))); DoubleModel viewAltModle = new DoubleModel(p, "ViewAlt", UnitGroup.UNITS_ANGLE); - add(new JSpinner(viewAltModle.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewAltModle.getSpinnerModel()), "w 40"); add(new UnitSelector(viewAltModle), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vDist"))); DoubleModel viewDistanceModel = new DoubleModel(p, "ViewDistance", UnitGroup.UNITS_LENGTH); - add(new JSpinner(viewDistanceModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewDistanceModel.getSpinnerModel()), "w 40"); add(new UnitSelector(viewDistanceModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.fov"))); DoubleModel fovModel = new DoubleModel(p, "Fov", UnitGroup.UNITS_ANGLE); - add(new JSpinner(fovModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(fovModel.getSpinnerModel()), "w 40"); add(new UnitSelector(fovModel), "wrap"); } }); @@ -181,16 +217,16 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.amb"))); DoubleModel ambianceModel = new DoubleModel(p, "Ambiance", 100, UnitGroup.UNITS_NONE, 0, 100); - add(new JSpinner(ambianceModel.getSpinnerModel()), "wrap"); + add(new EditableSpinner(ambianceModel.getSpinnerModel()), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAz"))); DoubleModel lightAzModel = new DoubleModel(p, "LightAz", UnitGroup.UNITS_ANGLE); - add(new JSpinner(lightAzModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(lightAzModel.getSpinnerModel()), "w 40"); add(new UnitSelector(lightAzModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAlt"))); DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE); - add(new JSpinner(lightAltModle.getSpinnerModel()), "wrap"); + add(new EditableSpinner(lightAltModle.getSpinnerModel()), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.sky"), Style.BOLD)); add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx"); @@ -265,7 +301,7 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.smokeOpacity"))); DoubleModel smokeAlphaModel = new DoubleModel(p, "SmokeAlpha", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner opacitySpinner = new JSpinner(smokeAlphaModel.getSpinnerModel()); + EditableSpinner opacitySpinner = new EditableSpinner(smokeAlphaModel.getSpinnerModel()); add(opacitySpinner, "wrap"); smokeModel.addEnableComponent(opacitySpinner); @@ -279,7 +315,7 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.flameAspect"))); DoubleModel flameAspectModel = new DoubleModel(p, "FlameAspectRatio", 100, UnitGroup.UNITS_NONE, 25, 250); - JSpinner flameAspectSpinner = new JSpinner(flameAspectModel.getSpinnerModel()); + EditableSpinner flameAspectSpinner = new EditableSpinner(flameAspectModel.getSpinnerModel()); add(flameAspectSpinner, "wrap"); fireModel.addEnableComponent(flameAspectSpinner); @@ -292,19 +328,19 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkConcentration"))); DoubleModel sparkConcentrationModel = new DoubleModel(p, "SparkConcentration", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner sparkConcentrationSpinner = new JSpinner(sparkConcentrationModel.getSpinnerModel()); + EditableSpinner sparkConcentrationSpinner = new EditableSpinner(sparkConcentrationModel.getSpinnerModel()); add(sparkConcentrationSpinner, "wrap"); sparksModel.addEnableComponent(sparkConcentrationSpinner); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkWeight"))); DoubleModel sparkWeightModel = new DoubleModel(p, "SparkWeight", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner sparkWeightSpinner = new JSpinner(sparkWeightModel.getSpinnerModel()); + EditableSpinner sparkWeightSpinner = new EditableSpinner(sparkWeightModel.getSpinnerModel()); add(sparkWeightSpinner, "wrap"); sparksModel.addEnableComponent(sparkWeightSpinner); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.exhaustScale"))); DoubleModel exhaustScaleModel = new DoubleModel(p, "ExhaustScale", 100, UnitGroup.UNITS_NONE, 0, 1000); - add(new JSpinner(exhaustScaleModel.getSpinnerModel()), "wrap"); + add(new EditableSpinner(exhaustScaleModel.getSpinnerModel()), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.effects"), Style.BOLD)); add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx"); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java index 92962bf24..0ff5dbccf 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java @@ -1,6 +1,9 @@ package net.sf.openrocket.gui.rocketfigure; +import net.sf.openrocket.rocketcomponent.MassComponent; +import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; @@ -13,33 +16,41 @@ import java.awt.geom.RoundRectangle2D; public class ShockCordShapes extends RocketComponentShape { public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { - - - net.sf.openrocket.rocketcomponent.MassObject massObj = (net.sf.openrocket.rocketcomponent.MassObject)component; + final ShockCord massObj = (ShockCord)component; double length = massObj.getLength(); double radius = massObj.getRadius(); double arc = Math.min(length, 2*radius) * 0.7; - - Coordinate start = transformation.transform(Coordinate.ZERO); + final double radialDistance = massObj.getRadialPosition(); + final double radialAngleRadians = massObj.getRadialDirection(); + + final Coordinate localPosition = new Coordinate(0, + radialDistance * Math.cos(radialAngleRadians), + radialDistance * Math.sin(radialAngleRadians)); + final Coordinate renderPosition = transformation.transform(localPosition); Shape[] s = new Shape[1]; - s[0] = new RoundRectangle2D.Double(start.x,(start.y-radius), + s[0] = new RoundRectangle2D.Double(renderPosition.x,(renderPosition.y-radius), length,2*radius,arc,arc); - return RocketComponentShape.toArray( addSymbol(s), component); + return RocketComponentShape.toArray(addSymbol(s), component); } public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { - - net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; + final ShockCord massObj = (ShockCord)component; - double or = tube.getRadius(); + double or = massObj.getRadius(); + final double radialDistance = massObj.getRadialPosition(); + final double radialAngleRadians = massObj.getRadialDirection(); + + final Coordinate localPosition = new Coordinate(0, + radialDistance * Math.cos(radialAngleRadians), + radialDistance * Math.sin(radialAngleRadians)); + final Coordinate renderPosition = transformation.transform(localPosition); Shape[] s = new Shape[1]; - Coordinate start = transformation.transform(Coordinate.ZERO); - s[0] = new Ellipse2D.Double((start.z-or),(start.y-or),2*or,2*or); + s[0] = new Ellipse2D.Double((renderPosition.z-or),(renderPosition.y-or),2*or,2*or); // Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset)); //