diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 038159462..650a40db7 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -826,6 +826,7 @@ AppearanceCfg.but.edit = Edit
AppearanceCfg.but.savedefault = Save as default appearance
AppearanceCfg.lbl.Texture = Texture:
AppearanceCfg.lbl.shine = Shine:
+AppearanceCfg.lbl.opacity = Opacity:
AppearanceCfg.lbl.color.Color = Color:
AppearanceCfg.lbl.color.diffuse = Diffuse Color:
AppearanceCfg.lbl.color.ambient = Ambient Color:
diff --git a/core/src/net/sf/openrocket/appearance/AppearanceBuilder.java b/core/src/net/sf/openrocket/appearance/AppearanceBuilder.java
index f7becf700..08bdd6724 100644
--- a/core/src/net/sf/openrocket/appearance/AppearanceBuilder.java
+++ b/core/src/net/sf/openrocket/appearance/AppearanceBuilder.java
@@ -161,6 +161,34 @@ public class AppearanceBuilder extends AbstractChangeSource {
this.shine = shine;
fireChangeEvent();
}
+
+ /**
+ * Returns the opacity of the paint color, expressed in percentages, where 0 is fully transparent and 1 is fully opaque
+ * @return opacity value of the pain color, expressed in a percentage
+ */
+ public double getOpacity() {
+ if (this.paint == null) {
+ return 100;
+ }
+ return (double) this.paint.getAlpha() / 255;
+ }
+
+ /**
+ * Sets the opacity/alpha of the paint color.
+ *
+ * @param opacity new opacity value expressed in a percentage, where 0 is fully transparent and 1 is fully opaque
+ */
+ public void setOpacity(double opacity) {
+ if (this.paint == null) {
+ return;
+ }
+
+ // Clamp opacity between 0 and 1
+ opacity = Math.max(0, Math.min(1, opacity));
+
+ this.paint.setAlpha((int) (opacity * 255));
+ fireChangeEvent();
+ }
/**
* gets the current offset axis U used
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
index c4c37c13a..182612544 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
@@ -111,7 +111,9 @@ public class RocketComponentSaver {
if (c instanceof FinSet || c instanceof TubeFinSet) {
elements.add("" + angleOffset + "");
}
- else if (!(c instanceof RailButton) && !(c instanceof PodSet)) {
+ else if (!(c instanceof ParallelStage) &&
+ !(c instanceof PodSet) &&
+ !(c instanceof RailButton)) {
elements.add("" + angleOffset + "");
}
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
index d2630b6c7..fb03fe8ee 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
@@ -55,7 +55,7 @@ public class RocketSaver extends RocketComponentSaver {
}
if (flightConfig.isNameOverridden()){
- str += ">" + net.sf.openrocket.util.TextUtil.escapeXML(flightConfig.getName())
+ str += ">" + net.sf.openrocket.util.TextUtil.escapeXML(flightConfig.getNameRaw())
+ "";
} else {
str += "/>";
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
index 49377e579..2ec435327 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java
@@ -34,7 +34,8 @@ public class FlightConfiguration implements FlightConfigurableParameter combo = new JComboBox(new EnumModel(builder,
- "EdgeMode", list));
- mDefault.addEnableComponent(combo, false);
- panel.add(combo);
+ // Opacity
+ panel.add(new JLabel(trans.get("AppearanceCfg.lbl.opacity")));
+ DoubleModel opacityModel = new DoubleModel(builder, "Opacity",
+ UnitGroup.UNITS_RELATIVE);
+ JSpinner spinOpacity = new JSpinner(opacityModel.getSpinnerModel());
+ spinOpacity.setEditor(new SpinnerEditor(spinOpacity));
+ JSlider slideOpacity = new JSlider(opacityModel.getSliderModel(0, 1));
+ UnitSelector unitOpacity = new UnitSelector(opacityModel);
+
+ mDefault.addEnableComponent(slideOpacity, false);
+ mDefault.addEnableComponent(spinOpacity, false);
+ mDefault.addEnableComponent(unitOpacity, false);
+
+ panel.add(spinOpacity, "split 3, w 50");
+ panel.add(unitOpacity);
+ panel.add(slideOpacity, "w 50");
// Rotation
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.rotation")));
@@ -603,5 +610,15 @@ public class AppearancePanel extends JPanel {
-Math.PI, Math.PI));
mDefault.addEnableComponent(bs, false);
panel.add(bs, "w 50, wrap");
+
+ // Repeat
+ panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.repeat")), "skip 2");
+ EdgeMode[] list = new EdgeMode[EdgeMode.values().length];
+ System.arraycopy(EdgeMode.values(), 0, list, 0,
+ EdgeMode.values().length);
+ JComboBox combo = new JComboBox(new EnumModel(builder,
+ "EdgeMode", list));
+ mDefault.addEnableComponent(combo, false);
+ panel.add(combo, "wrap");
}
}
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java
index daed8e7af..55b4dce42 100644
--- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java
+++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java
@@ -149,7 +149,7 @@ public class RocketComponentConfig extends JPanel {
updateFields();
- this.add(buttonPanel, "newline, spanx, growx, height 32!");
+ this.add(buttonPanel, "newline, spanx, growx");
}
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
index 75d6d5744..b768b81b6 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
@@ -30,7 +30,7 @@ public class RenameConfigDialog extends JDialog {
panel.add(new JLabel(trans.get("RenameConfigDialog.lbl.name")), "span, wrap rel");
- final JTextField textbox = new JTextField(rocket.getFlightConfiguration(fcid).getName());
+ final JTextField textbox = new JTextField(rocket.getFlightConfiguration(fcid).getNameRaw());
panel.add(textbox, "span, w 200lp, growx, wrap para");
panel.add(new JPanel(), "growx");
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/motor/MotorChooserDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/motor/MotorChooserDialog.java
index ada3cb748..0148738f9 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/motor/MotorChooserDialog.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/motor/MotorChooserDialog.java
@@ -6,6 +6,8 @@ import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
@@ -73,7 +75,13 @@ public class MotorChooserDialog extends JDialog implements CloseableDialog {
this.setModal(true);
this.pack();
this.setLocationByPlatform(true);
- GUIUtil.installEscapeCloseOperation(this);
+ Action closeAction = new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ close(false);
+ }
+ };
+ GUIUtil.installEscapeCloseOperation(this, closeAction);
JComponent focus = selectionPanel.getDefaultFocus();
if (focus != null) {
@@ -107,9 +115,13 @@ public class MotorChooserDialog extends JDialog implements CloseableDialog {
public double getSelectedDelay() {
return selectionPanel.getSelectedDelay();
}
-
-
-
+
+ public void open() {
+ // Update the motor selection based on the motor table value that was already selected in a previous session.
+ selectionPanel.selectMotorFromTable();
+ setVisible(true);
+ }
+
@Override
public void close(boolean ok) {
okClicked = ok;
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/ThrustCurveMotorSelectionPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/ThrustCurveMotorSelectionPanel.java
index 8605ace7b..9bf036f25 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/ThrustCurveMotorSelectionPanel.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/ThrustCurveMotorSelectionPanel.java
@@ -112,14 +112,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
setMotorMountAndConfig( fcid, mount );
}
-
- /**
- * Sole constructor.
- *
- * @param current the currently selected ThrustCurveMotor, or null for none.
- * @param delay the currently selected ejection charge delay.
- * @param diameter the diameter of the motor mount.
- */
+
public ThrustCurveMotorSelectionPanel() {
super(new MigLayout("fill", "[grow][]"));
@@ -264,17 +257,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
- int row = table.getSelectedRow();
- if (row >= 0) {
- row = table.convertRowIndexToModel(row);
- ThrustCurveMotorSet motorSet = model.getMotorSet(row);
- log.info(Markers.USER_MARKER, "Selected table row " + row + ": " + motorSet);
- if (motorSet != selectedMotorSet) {
- select(selectMotor(motorSet));
- }
- } else {
- log.info(Markers.USER_MARKER, "Selected table row " + row + ", nothing selected");
- }
+ selectMotorFromTable();
}
});
table.addMouseListener(new MouseAdapter() {
@@ -608,6 +591,23 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
return list.get(0);
}
+ /**
+ * Selects a new motor based on the selection in the motor table
+ */
+ public void selectMotorFromTable() {
+ int row = table.getSelectedRow();
+ if (row >= 0) {
+ row = table.convertRowIndexToModel(row);
+ ThrustCurveMotorSet motorSet = model.getMotorSet(row);
+ log.info(Markers.USER_MARKER, "Selected table row " + row + ": " + motorSet);
+ if (motorSet != selectedMotorSet) {
+ select(selectMotor(motorSet));
+ }
+ } else {
+ log.info(Markers.USER_MARKER, "Selected table row " + row + ", nothing selected");
+ }
+ }
+
/**
* Set the values in the delay combo box. If reset is true
diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurationPanel.java
index ce1a3115e..59d75641b 100644
--- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurationPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurationPanel.java
@@ -220,7 +220,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
if (fcIds == null) return;
FlightConfigurationId initFcId = fcIds.get(0);
new RenameConfigDialog(SwingUtilities.getWindowAncestor(this), rocket, initFcId).setVisible(true);
- String newName = rocket.getFlightConfiguration(initFcId).getName();
+ String newName = rocket.getFlightConfiguration(initFcId).getNameRaw();
for (int i = 1; i < fcIds.size(); i++) {
rocket.getFlightConfiguration(fcIds.get(i)).setName(newName);
}
diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java
index b96d05cd3..ad3c0f40b 100644
--- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/MotorConfigurationPanel.java
@@ -288,7 +288,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel
double initDelay = initMount.getMotorConfig(initFcId).getEjectionDelay();
motorChooserDialog.setMotorMountAndConfig(initFcId, initMount);
- motorChooserDialog.setVisible(true);
+ motorChooserDialog.open();
Motor mtr = motorChooserDialog.getSelectedMotor();
double d = motorChooserDialog.getSelectedDelay();
diff --git a/swing/src/net/sf/openrocket/gui/util/GUIUtil.java b/swing/src/net/sf/openrocket/gui/util/GUIUtil.java
index ba657497f..24234a846 100644
--- a/swing/src/net/sf/openrocket/gui/util/GUIUtil.java
+++ b/swing/src/net/sf/openrocket/gui/util/GUIUtil.java
@@ -157,9 +157,22 @@ public class GUIUtil {
* @param dialog the dialog for which to install the action.
*/
public static void installEscapeCloseOperation(final JDialog dialog) {
+ installEscapeCloseOperation(dialog, null);
+ }
+
+ /**
+ * Add the correct action to close a JDialog when the ESC key is pressed.
+ * The dialog is closed by sending it a WINDOW_CLOSING event.
+ *
+ * An additional action can be passed which will be executed upon the close action key.
+ *
+ * @param dialog the dialog for which to install the action.
+ * @param action action to execute upon the close action
+ */
+ public static void installEscapeCloseOperation(final JDialog dialog, Action action) {
Action dispatchClosing = new AbstractAction() {
/**
- *
+ *
*/
private static final long serialVersionUID = 9196153713666242274L;
@@ -172,6 +185,9 @@ public class GUIUtil {
JRootPane root = dialog.getRootPane();
root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ESCAPE, CLOSE_ACTION_KEY);
root.getActionMap().put(CLOSE_ACTION_KEY, dispatchClosing);
+ if (action != null) {
+ root.getActionMap().put(CLOSE_ACTION_KEY, action);
+ }
}