From 0b7b4d7bc7c1696e56223d60b4f116d0619da62c Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 24 Jun 2022 00:46:15 +0200 Subject: [PATCH 01/47] [#1470] Move component config dialog to center if outside parent's monitor --- .../configdialog/ComponentConfigDialog.java | 6 ++ .../gui/util/WindowLocationUtil.java | 74 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 swing/src/net/sf/openrocket/gui/util/WindowLocationUtil.java diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java index 7defaca26..efd9cc02a 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java @@ -1,11 +1,15 @@ package net.sf.openrocket.gui.configdialog; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import java.util.List; import javax.swing.JDialog; @@ -13,6 +17,7 @@ import javax.swing.JDialog; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; +import net.sf.openrocket.gui.util.WindowLocationUtil; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; @@ -256,6 +261,7 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis dialog = new ComponentConfigDialog(parent, document, component); dialog.setVisible(true); + WindowLocationUtil.moveIfOutsideOfParentMonitor(dialog, parent); ////Modify if (component.getConfigListeners().size() == 0) { diff --git a/swing/src/net/sf/openrocket/gui/util/WindowLocationUtil.java b/swing/src/net/sf/openrocket/gui/util/WindowLocationUtil.java new file mode 100644 index 000000000..d4443954c --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/util/WindowLocationUtil.java @@ -0,0 +1,74 @@ +package net.sf.openrocket.gui.util; + +import java.awt.GraphicsDevice; +import java.awt.Window; + +/** + * Helper class for setting the location of a Swing window. E.g. to check when the window is outside the screen and + * recenter it if so. + * + * @author Sibo Van Gool + */ +public abstract class WindowLocationUtil { + /** + * Sets the location of the window, but don't go outside the screen. + * @param window the window to move + * @param x the target x position on the screen + * @param y the target y position on the screen + */ + public static void setLocationWithinScreen(Window window, int x, int y) { + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + java.awt.Dimension windowSize = window.getSize(); + int screenWidth = screenSize.width; + int screenHeight = screenSize.height; + int windowWidth = windowSize.width; + int windowHeight = windowSize.height; + int xPos = x; + int yPos = y; + if (xPos + windowWidth > screenWidth) { + xPos = screenWidth - windowWidth; + } + if (yPos + windowHeight > screenHeight) { + yPos = screenHeight - windowHeight; + } + window.setLocation(xPos, yPos); + } + + /** + * Moves the window to the center of the screen if its location is outside the boundary of the screen. + * @param window window to move + */ + public static void moveIfOutsideOfMonitor(Window window) { + GraphicsDevice currentDevice = window.getGraphicsConfiguration().getDevice(); + if (currentDevice != null && window.isVisible() && + !currentDevice.getDefaultConfiguration().getBounds().contains(window.getLocationOnScreen())) { + int width = currentDevice.getDefaultConfiguration().getBounds().width; + int height = currentDevice.getDefaultConfiguration().getBounds().height; + window.setLocation( + ((width / 2) - (window.getSize().width / 2)) + currentDevice.getDefaultConfiguration().getBounds().x, + ((height / 2) - (window.getSize().height / 2)) + currentDevice.getDefaultConfiguration().getBounds().y + ); + } + } + + /** + * Moves the window to the center of the screen if it is on another monitor as the parent window, or if its location + * is outside the boundary of the parent's monitor screen. + * @param window window to move + * @param parent parent window + */ + public static void moveIfOutsideOfParentMonitor(Window window, Window parent) { + GraphicsDevice parentDevice = parent.getGraphicsConfiguration().getDevice(); + GraphicsDevice currentDevice = window.getGraphicsConfiguration().getDevice(); + if (parentDevice != null && (currentDevice == null || currentDevice != parentDevice || + (window.isVisible() && !parentDevice.getDefaultConfiguration().getBounds().contains( + window.getLocationOnScreen())))) { + int width = parentDevice.getDefaultConfiguration().getBounds().width; + int height = parentDevice.getDefaultConfiguration().getBounds().height; + window.setLocation( + ((width / 2) - (window.getSize().width / 2)) + parentDevice.getDefaultConfiguration().getBounds().x, + ((height / 2) - (window.getSize().height / 2)) + parentDevice.getDefaultConfiguration().getBounds().y + ); + } + } +} From 4a79581244c56f9f69831c2efd0513408de95603 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 24 Jun 2022 02:13:01 +0200 Subject: [PATCH 02/47] [#1477] Don't include inactive stages in calculateForceAnalysis --- .../net/sf/openrocket/aerodynamics/BarrowmanCalculator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index b1d2f3bfc..034e9cc02 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -4,6 +4,7 @@ import static net.sf.openrocket.util.MathUtil.pow2; import java.util.*; +import net.sf.openrocket.rocketcomponent.AxialStage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -152,6 +153,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { } for( RocketComponent child : comp.getChildren()) { + // Ignore inactive stages + if (child instanceof AxialStage && + !child.getRocket().getSelectedConfiguration().isStageActive(child.getStageNumber())) { + continue; + } // forces particular to each component AerodynamicForces childForces = calculateForceAnalysis(conds, child, instances, eachForces, assemblyForces, warnings); From 77bad60155ac49a5cda416f106e34e68fc0543b3 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 24 Jun 2022 05:37:30 +0200 Subject: [PATCH 03/47] Don't include inactive stages in Cp calculations --- .../aerodynamics/BarrowmanCalculator.java | 20 ++++++++++++++++--- .../rocketcomponent/AxialStage.java | 17 ++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 034e9cc02..0b7b3674d 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -155,7 +155,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { for( RocketComponent child : comp.getChildren()) { // Ignore inactive stages if (child instanceof AxialStage && - !child.getRocket().getSelectedConfiguration().isStageActive(child.getStageNumber())) { + !((AxialStage) child).isStageActive()) { continue; } // forces particular to each component @@ -278,14 +278,28 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { private boolean testIsContinuous( final RocketComponent treeRoot ){ Queue queue = new LinkedList<>(); - queue.addAll(treeRoot.getChildren()); + for (RocketComponent child : treeRoot.getChildren()) { + // Ignore inactive stages + if (child instanceof AxialStage && + !((AxialStage) child).isStageActive()) { + continue; + } + queue.add(child); + } boolean isContinuous = true; SymmetricComponent prevComp = null; while((isContinuous)&&( null != queue.peek())){ RocketComponent comp = queue.poll(); if( comp instanceof SymmetricComponent ){ - queue.addAll( comp.getChildren()); + for (RocketComponent child : comp.getChildren()) { + // Ignore inactive stages + if (child instanceof AxialStage && + !((AxialStage) child).isStageActive()) { + continue; + } + queue.add(child); + } SymmetricComponent sym = (SymmetricComponent) comp; if( null == prevComp){ diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index 20f3a13f5..289f98c2d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -67,6 +67,23 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC public boolean isCompatible(Class type) { return BodyComponent.class.isAssignableFrom(type); } + + /** + * Returns whether the current stage is active in the currently selected configuration. + * @return true if the stage is active, false if not + */ + public boolean isStageActive() { + return getRocket().getSelectedConfiguration().isStageActive(getStageNumber()); + } + + /** + * Returns whether the current stage is active in the flight configuration. + * @param fc the flight configuration to check + * @return true if the stage is active, false if not + */ + public boolean isStageActive(FlightConfiguration fc) { + return fc.isStageActive(getStageNumber()); + } @Override public void copyFlightConfiguration(FlightConfigurationId oldConfigId, FlightConfigurationId newConfigId) { From 027ed2eaa699429c7a010f3a24d4ed53c2aa9c51 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 25 Jun 2022 00:44:54 +0200 Subject: [PATCH 04/47] [#1460] Exclude inactive stages in tbe simulation calculations --- .../aerodynamics/AerodynamicCalculator.java | 2 +- .../aerodynamics/BarrowmanCalculator.java | 28 ++++++------ .../openrocket/masscalc/MassCalculator.java | 2 +- .../sf/openrocket/motor/IgnitionEvent.java | 17 ++++---- .../rocketcomponent/AxialStage.java | 7 +-- .../rocketcomponent/FlightConfiguration.java | 18 ++++++-- .../sf/openrocket/rocketcomponent/Rocket.java | 43 ++++++++++++------- .../BasicEventSimulationEngine.java | 15 ++++--- .../sf/openrocket/simulation/FlightEvent.java | 2 +- .../simulation/MotorClusterState.java | 10 ++--- .../aerodynamics/BarrowmanCalculatorTest.java | 12 ++++-- .../FlightConfigurationTest.java | 4 +- 12 files changed, 95 insertions(+), 65 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/AerodynamicCalculator.java b/core/src/net/sf/openrocket/aerodynamics/AerodynamicCalculator.java index d51448699..fbdac87e4 100644 --- a/core/src/net/sf/openrocket/aerodynamics/AerodynamicCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/AerodynamicCalculator.java @@ -68,5 +68,5 @@ public interface AerodynamicCalculator extends Monitorable { */ public AerodynamicCalculator newInstance(); - public boolean isContinuous( final Rocket rkt); + public boolean isContinuous(FlightConfiguration configuration, final Rocket rkt); } diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 0b7b3674d..9335b4b64 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -81,7 +81,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { Map assemblyMap = new LinkedHashMap<>(); // Calculate non-axial force data - calculateForceAnalysis(conditions, configuration.getRocket(), instMap, eachMap, assemblyMap, warnings); + calculateForceAnalysis(configuration, conditions, configuration.getRocket(), instMap, eachMap, assemblyMap, warnings); // Calculate drag coefficient data AerodynamicForces rocketForces = assemblyMap.get(configuration.getRocket()); @@ -126,7 +126,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { return finalMap; } - private AerodynamicForces calculateForceAnalysis( FlightConditions conds, + private AerodynamicForces calculateForceAnalysis( FlightConfiguration configuration, + FlightConditions conds, RocketComponent comp, InstanceMap instances, Map eachForces, @@ -154,12 +155,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { for( RocketComponent child : comp.getChildren()) { // Ignore inactive stages - if (child instanceof AxialStage && - !((AxialStage) child).isStageActive()) { + if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) { continue; } // forces particular to each component - AerodynamicForces childForces = calculateForceAnalysis(conds, child, instances, eachForces, assemblyForces, warnings); + AerodynamicForces childForces = calculateForceAnalysis(configuration, conds, child, instances, eachForces, assemblyForces, warnings); if(null != childForces) { aggregateForces.merge(childForces); @@ -246,7 +246,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { if (calcMap == null) buildCalcMap(configuration); - if( ! isContinuous( configuration.getRocket() ) ){ + if (!isContinuous(configuration, configuration.getRocket())){ warnings.add( Warning.DIAMETER_DISCONTINUITY); } @@ -272,16 +272,15 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { } @Override - public boolean isContinuous( final Rocket rkt){ - return testIsContinuous( rkt); + public boolean isContinuous(FlightConfiguration configuration, final Rocket rkt){ + return testIsContinuous(configuration, rkt); } - private boolean testIsContinuous( final RocketComponent treeRoot ){ + private boolean testIsContinuous(FlightConfiguration configuration, final RocketComponent treeRoot ){ Queue queue = new LinkedList<>(); for (RocketComponent child : treeRoot.getChildren()) { // Ignore inactive stages - if (child instanceof AxialStage && - !((AxialStage) child).isStageActive()) { + if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) { continue; } queue.add(child); @@ -294,8 +293,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { if( comp instanceof SymmetricComponent ){ for (RocketComponent child : comp.getChildren()) { // Ignore inactive stages - if (child instanceof AxialStage && - !((AxialStage) child).isStageActive()) { + if (child instanceof AxialStage && !configuration.isStageActive(child.getStageNumber())) { continue; } queue.add(child); @@ -323,7 +321,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { prevComp = sym; }else if( comp instanceof ComponentAssembly ){ - isContinuous &= testIsContinuous( comp ); + isContinuous &= testIsContinuous(configuration, comp); } } @@ -339,7 +337,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { * @param configuration Rocket configuration * @param conditions Flight conditions taken into account * @param map ? - * @param set Set to handle + * @param warningSet Set to handle warnings * @return friction drag for entire rocket */ private double calculateFrictionCD(FlightConfiguration configuration, FlightConditions conditions, diff --git a/core/src/net/sf/openrocket/masscalc/MassCalculator.java b/core/src/net/sf/openrocket/masscalc/MassCalculator.java index 463ed7f4b..4b36d03dc 100644 --- a/core/src/net/sf/openrocket/masscalc/MassCalculator.java +++ b/core/src/net/sf/openrocket/masscalc/MassCalculator.java @@ -104,7 +104,7 @@ public class MassCalculator implements Monitorable { public static RigidBody calculate( final MassCalculation.Type _type, final SimulationStatus status ){ final FlightConfiguration config = status.getConfiguration(); final double time = status.getSimulationTime(); - final Collection activeMotorList = status.getMotors(); + final Collection activeMotorList = status.getActiveMotors(); MassCalculation calculation= new MassCalculation( _type, config, time, activeMotorList, config.getRocket(), Transformation.IDENTITY, null); calculation.calculateAssembly(); diff --git a/core/src/net/sf/openrocket/motor/IgnitionEvent.java b/core/src/net/sf/openrocket/motor/IgnitionEvent.java index 60a2bf2ea..619642167 100644 --- a/core/src/net/sf/openrocket/motor/IgnitionEvent.java +++ b/core/src/net/sf/openrocket/motor/IgnitionEvent.java @@ -4,6 +4,7 @@ import java.util.Locale; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.AxialStage; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.startup.Application; @@ -13,25 +14,25 @@ public enum IgnitionEvent { //// Automatic (launch or ejection charge) AUTOMATIC( "AUTOMATIC", "MotorMount.IgnitionEvent.AUTOMATIC"){ @Override - public boolean isActivationEvent(FlightEvent testEvent, RocketComponent targetComponent) { + public boolean isActivationEvent(FlightConfiguration config, FlightEvent testEvent, RocketComponent targetComponent) { AxialStage targetStage = targetComponent.getStage(); - if ( targetStage.isLaunchStage() ){ - return LAUNCH.isActivationEvent(testEvent, targetComponent); + if (targetStage.isLaunchStage(config)) { + return LAUNCH.isActivationEvent(config, testEvent, targetComponent); } else { - return EJECTION_CHARGE.isActivationEvent(testEvent, targetComponent); + return EJECTION_CHARGE.isActivationEvent(config, testEvent, targetComponent); } } }, LAUNCH ( "LAUNCH", "MotorMount.IgnitionEvent.LAUNCH"){ @Override - public boolean isActivationEvent( FlightEvent fe, RocketComponent source){ + public boolean isActivationEvent(FlightConfiguration config, FlightEvent fe, RocketComponent source){ return (fe.getType() == FlightEvent.Type.LAUNCH); } }, EJECTION_CHARGE ("EJECTION_CHARGE", "MotorMount.IgnitionEvent.EJECTION_CHARGE"){ @Override - public boolean isActivationEvent( FlightEvent testEvent, RocketComponent targetComponent){ + public boolean isActivationEvent(FlightConfiguration config, FlightEvent testEvent, RocketComponent targetComponent){ if (testEvent.getType() != FlightEvent.Type.EJECTION_CHARGE){ return false; } @@ -44,7 +45,7 @@ public enum IgnitionEvent { }, BURNOUT ("BURNOUT", "MotorMount.IgnitionEvent.BURNOUT"){ @Override - public boolean isActivationEvent( FlightEvent testEvent, RocketComponent targetComponent){ + public boolean isActivationEvent(FlightConfiguration config, FlightEvent testEvent, RocketComponent targetComponent){ if (testEvent.getType() != FlightEvent.Type.BURNOUT) return false; @@ -64,7 +65,7 @@ public enum IgnitionEvent { //public static final IgnitionEvent[] events = {AUTOMATIC, LAUNCH, EJECTION_CHARGE, BURNOUT, NEVER}; - public boolean isActivationEvent( FlightEvent fe, RocketComponent source){ + public boolean isActivationEvent(FlightConfiguration config, FlightEvent fe, RocketComponent source){ // default behavior. Also for the NEVER case. return false; } diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index 289f98c2d..e4ff3bb7c 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -130,11 +130,12 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC /** * returns if the object is a launch stage + * @param config the flight configuration which will check which stages are active * @return if the object is a launch stage */ - public boolean isLaunchStage(){ - return ( this instanceof ParallelStage ) - ||( getRocket().getBottomCoreStage().equals(this)); + public boolean isLaunchStage(FlightConfiguration config) { + return ((this instanceof ParallelStage && config.isStageActive(this.stageNumber)) + ||( getRocket().getBottomCoreStage(config).equals(this))); } /** diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index 2ae0211fa..09c090f11 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -60,8 +60,8 @@ public class FlightConfiguration implements FlightConfigurableParameter stages = new HashMap(); - final protected HashMap motors = new HashMap(); + final protected Map stages = new HashMap(); + final protected Map motors = new HashMap(); final private Collection activeMotors = new ArrayList(); final private InstanceMap activeInstances = new InstanceMap(); @@ -190,7 +190,7 @@ public class FlightConfiguration implements FlightConfigurableParameterfalse) or active (true) */ - private void _setStageActive(final int stageNumber, final boolean _active ) { + public void _setStageActive(final int stageNumber, final boolean _active ) { if ((0 <= stageNumber) && (stages.containsKey(stageNumber))) { stages.get(stageNumber).active = _active; fireChangeEvent(); @@ -338,6 +338,18 @@ public class FlightConfiguration implements FlightConfigurableParameter getAllStages() { + List stages = new ArrayList<>(); + for (StageFlags flags : this.stages.values()) { + stages.add( rocket.getStage(flags.stageNumber)); + } + return stages; + } public List getActiveStages() { List activeStages = new ArrayList<>(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 7a3f1780a..3855db54c 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -197,24 +197,37 @@ public class Rocket extends ComponentAssembly { public AxialStage getStage( final int stageNumber ) { return this.stageMap.get( stageNumber); } - - /* - * Returns the stage at the top of the central stack - * - * @Return a reference to the topmost stage + + /** + * Get the topmost stage, only taking into account active stages from the flight configuration. + * @param config flight configuration dictating which stages are active + * @return the topmost active stage, or null if there are no active stages. */ - public AxialStage getTopmostStage(){ - return (AxialStage) getChild(0); + public AxialStage getTopmostStage(FlightConfiguration config) { + if (config == null) return null; + + for (int i = 0; i < getChildCount(); i++) { + if (getChild(i) instanceof AxialStage && config.isStageActive(getChild(i).getStageNumber())) { + return (AxialStage) getChild(i); + } + } + return null; } - - /* - * Returns the stage at the top of the central stack - * - * @Return a reference to the topmost stage + + /** + * Get the bottommost stage, only taking into account active stages from the flight configuration. + * @param config flight configuration dictating which stages are active + * @return the bottommost active stage, or null if there are no active stages. */ - /*package-local*/ AxialStage getBottomCoreStage(){ - // get last stage that's a direct child of the rocket. - return (AxialStage) children.get( children.size()-1 ); + public AxialStage getBottomCoreStage(FlightConfiguration config) { + if (config == null) return null; + + for (int i = getChildCount() - 1; i >= 0; i--) { + if (getChild(i) instanceof AxialStage && config.isStageActive(getChild(i).getStageNumber())) { + return (AxialStage) getChild(i); + } + } + return null; } @Override diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index 8fdae800a..1d5b62e76 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -45,7 +45,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { private final static double AOA_TUMBLE_CONDITION = Math.PI / 9.0; // The thrust must be below this value for the transition to tumbling. - // TODO: this is an arbitrary value + // TODO HIGH: this is an arbitrary value private final static double THRUST_TUMBLE_CONDITION = 0.01; private SimulationStepper currentStepper; @@ -65,7 +65,9 @@ public class BasicEventSimulationEngine implements SimulationEngine { // Set up rocket configuration this.fcid = simulationConditions.getFlightConfigurationID(); - FlightConfiguration simulationConfig = simulationConditions.getRocket().getFlightConfiguration( this.fcid).clone(); + FlightConfiguration origConfig = simulationConditions.getRocket().getFlightConfiguration(this.fcid); + FlightConfiguration simulationConfig = origConfig.clone(); + simulationConfig.copyStages(origConfig); // Clone the stage activation configuration if ( ! simulationConfig.hasMotors() ) { throw new MotorIgnitionException(trans.get("BasicEventSimulationEngine.error.noMotorsDefined")); } @@ -74,7 +76,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { currentStatus.getEventQueue().add(new FlightEvent(FlightEvent.Type.LAUNCH, 0, simulationConditions.getRocket())); { // main simulation branch - final String branchName = simulationConfig.getRocket().getTopmostStage().getName(); + final String branchName = simulationConfig.getRocket().getTopmostStage(currentStatus.getConfiguration()).getName(); currentStatus.setFlightData(new FlightDataBranch( branchName, FlightDataType.TYPE_TIME)); } toSimulate.push(currentStatus); @@ -273,9 +275,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { // Check for motor ignition events, add ignition events to queue for (MotorClusterState state : currentStatus.getActiveMotors() ){ - if( state.testForIgnition(event )){ - final double simulationTime = currentStatus.getSimulationTime() ; - + if (state.testForIgnition(currentStatus.getConfiguration(), event)) { MotorClusterState sourceState = (MotorClusterState) event.getData(); double ignitionDelay = 0; if (event.getType() == FlightEvent.Type.BURNOUT) @@ -543,7 +543,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { } - // TODO : FUTURE : do not hard code the 1200 (maybe even make it configurable by the user) + // TODO FUTURE : do not hard code the 1200 (maybe even make it configurable by the user) if( 1200 < currentStatus.getSimulationTime() ){ ret = false; log.error("Simulation hit max time (1200s): aborting."); @@ -553,6 +553,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { // If no motor has ignited, abort if (!currentStatus.isMotorIgnited()) { + // TODO MEDIUM: display this as a warning to the user (e.g. highlight the cell in the simulation panel in red and a hover: 'make sure the motor ignition is correct' or something) throw new MotorIgnitionException(trans.get("BasicEventSimulationEngine.error.noIgnition")); } diff --git a/core/src/net/sf/openrocket/simulation/FlightEvent.java b/core/src/net/sf/openrocket/simulation/FlightEvent.java index 55ceaab36..b78ad1f3b 100644 --- a/core/src/net/sf/openrocket/simulation/FlightEvent.java +++ b/core/src/net/sf/openrocket/simulation/FlightEvent.java @@ -172,7 +172,7 @@ public class FlightEvent implements Comparable { * @return */ public void validate(){ - if( this.time == Double.NaN ){ + if(Double.isNaN(this.time)){ throw new IllegalStateException(type.name()+" event has a NaN time!"); } switch( this.type ){ diff --git a/core/src/net/sf/openrocket/simulation/MotorClusterState.java b/core/src/net/sf/openrocket/simulation/MotorClusterState.java index 43c73f9c3..728287c96 100644 --- a/core/src/net/sf/openrocket/simulation/MotorClusterState.java +++ b/core/src/net/sf/openrocket/simulation/MotorClusterState.java @@ -4,6 +4,7 @@ import net.sf.openrocket.motor.IgnitionEvent; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.motor.MotorConfigurationId; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RocketComponent; @@ -121,8 +122,8 @@ public class MotorClusterState { /** * Compute the average thrust over an interval. * - * @param simulationTime - * @param cond + * @param startSimulationTime start time of the averaging interval + * @param endSimulationTime end time of the averaging interval * @return */ public double getAverageThrust( final double startSimulationTime, final double endSimulationTime) { @@ -141,7 +142,6 @@ public class MotorClusterState { * Compute the average thrust over an interval. * * @param simulationTime - * @param cond * @return */ public double getThrust( final double simulationTime){ @@ -182,9 +182,9 @@ public class MotorClusterState { currentState = ThrustState.ARMED; } - public boolean testForIgnition( final FlightEvent _event ){ + public boolean testForIgnition(FlightConfiguration flightConfiguration, final FlightEvent _event ){ RocketComponent mount = (RocketComponent) this.getMount(); - return getIgnitionEvent().isActivationEvent( _event, mount); + return getIgnitionEvent().isActivationEvent(flightConfiguration, _event, mount); } public String toDescription(){ diff --git a/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java b/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java index 9f285a709..828a49447 100644 --- a/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java +++ b/core/test/net/sf/openrocket/aerodynamics/BarrowmanCalculatorTest.java @@ -267,22 +267,25 @@ public class BarrowmanCalculatorTest { public void testContinuousRocket() { Rocket rocket = TestRockets.makeEstesAlphaIII(); AerodynamicCalculator calc = new BarrowmanCalculator(); + FlightConfiguration configuration = rocket.getSelectedConfiguration(); - assertTrue("Estes Alpha III should be continous: ", calc.isContinuous( rocket)); + assertTrue("Estes Alpha III should be continous: ", calc.isContinuous(configuration, rocket)); } @Test public void testContinuousRocketWithStrapOns() { Rocket rocket = TestRockets.makeFalcon9Heavy(); AerodynamicCalculator calc = new BarrowmanCalculator(); + FlightConfiguration configuration = rocket.getSelectedConfiguration(); - assertTrue("F9H should be continuous: ", calc.isContinuous( rocket)); + assertTrue("F9H should be continuous: ", calc.isContinuous(configuration, rocket)); } @Test public void testRadialDiscontinuousRocket() { Rocket rocket = TestRockets.makeEstesAlphaIII(); AerodynamicCalculator calc = new BarrowmanCalculator(); + FlightConfiguration configuration = rocket.getSelectedConfiguration(); NoseCone nose = (NoseCone)rocket.getChild(0).getChild(0); BodyTube body = (BodyTube)rocket.getChild(0).getChild(1); @@ -291,13 +294,14 @@ public class BarrowmanCalculatorTest { body.setOuterRadius( 0.012 ); body.setName( body.getName()+" << discontinuous"); - assertFalse(" Estes Alpha III has an undetected discontinuity:", calc.isContinuous( rocket)); + assertFalse(" Estes Alpha III has an undetected discontinuity:", calc.isContinuous(configuration, rocket)); } @Test public void testRadialDiscontinuityWithStrapOns() { Rocket rocket = TestRockets.makeFalcon9Heavy(); AerodynamicCalculator calc = new BarrowmanCalculator(); + FlightConfiguration configuration = rocket.getSelectedConfiguration(); final AxialStage coreStage = (AxialStage)rocket.getChild(1); final ParallelStage booster = (ParallelStage)coreStage.getChild(0).getChild(0); @@ -309,7 +313,7 @@ public class BarrowmanCalculatorTest { body.setOuterRadius( 0.012 ); body.setName( body.getName()+" << discontinuous"); - assertFalse(" Missed discontinuity in Falcon 9 Heavy:", calc.isContinuous( rocket)); + assertFalse(" Missed discontinuity in Falcon 9 Heavy:", calc.isContinuous(configuration, rocket)); } @Test diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index c4ad802af..31907369f 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -295,8 +295,8 @@ public class FlightConfigurationTest extends BaseTestCase { config.toggleStage(0); assertThat(" toggle stage #0: ", config.isStageActive(0), equalTo(false)); - AxialStage sustainer = rkt.getTopmostStage(); - AxialStage booster = rkt.getBottomCoreStage(); + AxialStage sustainer = rkt.getTopmostStage(config); + AxialStage booster = rkt.getBottomCoreStage(config); assertThat(" sustainer stage is stage #0: ", sustainer.getStageNumber(), equalTo(0)); assertThat(" booster stage is stage #1: ", booster.getStageNumber(), equalTo(1)); From d8a1de26526af14dd962e38a2b3c738180f0fc3e Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 25 Jun 2022 01:03:09 +0200 Subject: [PATCH 05/47] Include non-active booster condition --- core/src/net/sf/openrocket/rocketcomponent/AxialStage.java | 3 +-- core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index e4ff3bb7c..8e0f533c5 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -134,8 +134,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC * @return if the object is a launch stage */ public boolean isLaunchStage(FlightConfiguration config) { - return ((this instanceof ParallelStage && config.isStageActive(this.stageNumber)) - ||( getRocket().getBottomCoreStage(config).equals(this))); + return (getRocket().getBottomCoreStage(config).equals(this)); } /** diff --git a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java index 8f74ee6fa..d09b71f54 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java @@ -111,8 +111,8 @@ public class ParallelStage extends AxialStage implements FlightConfigurableCompo } @Override - public boolean isLaunchStage(){ - return true; + public boolean isLaunchStage(FlightConfiguration config) { + return config.isStageActive(this.stageNumber); } @Override From 88e343a30ce64665151f44a6a093fc2071a24685 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 25 Jun 2022 01:26:05 +0200 Subject: [PATCH 06/47] Update unit tests --- .../rocketcomponent/FlightConfigurationTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index 31907369f..8a69a1ff4 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -294,9 +294,22 @@ public class FlightConfigurationTest extends BaseTestCase { config.toggleStage(0); assertThat(" toggle stage #0: ", config.isStageActive(0), equalTo(false)); - + AxialStage sustainer = rkt.getTopmostStage(config); AxialStage booster = rkt.getBottomCoreStage(config); + assertThat(" sustainer stage is stage #1: ", sustainer.getStageNumber(), equalTo(1)); + assertThat(" booster stage is stage #1: ", booster.getStageNumber(), equalTo(1)); + + config.setAllStages(); + config._setStageActive(1, false); + sustainer = rkt.getTopmostStage(config); + booster = rkt.getBottomCoreStage(config); + assertThat(" sustainer stage is stage #1: ", sustainer.getStageNumber(), equalTo(0)); + assertThat(" booster stage is stage #1: ", booster.getStageNumber(), equalTo(0)); + + config.setAllStages(); + sustainer = rkt.getTopmostStage(config); + booster = rkt.getBottomCoreStage(config); assertThat(" sustainer stage is stage #0: ", sustainer.getStageNumber(), equalTo(0)); assertThat(" booster stage is stage #1: ", booster.getStageNumber(), equalTo(1)); From 4d1e6165a841a04f2a2c60f2555ea543c29641f3 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 25 Jun 2022 13:59:57 +0200 Subject: [PATCH 07/47] Disable stage when parent stage is inactive --- .../rocketcomponent/FlightConfiguration.java | 8 ++++++++ .../rocketcomponent/RocketComponent.java | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index 09c090f11..308ec86c2 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -193,6 +193,10 @@ public class FlightConfiguration implements FlightConfigurableParameter getSubStages() { + List result = new LinkedList<>(); + Iterator it = iterator(false); + while (it.hasNext()) { + RocketComponent c = it.next(); + if (c instanceof AxialStage) + result.add((AxialStage) c); + } + return result; + } /** * Return the first component assembly component that this component belongs to. From 9191d9df51af4cd683936356692b958fd4167768 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 25 Jun 2022 16:32:49 +0200 Subject: [PATCH 08/47] Remove sub-stage from removed component Fixes a bug where if you delete the parent component of a booster set, it would throw a NullPointerException in BarrowmanCalculator.java:861 --- .../openrocket/rocketcomponent/FlightConfiguration.java | 2 +- core/src/net/sf/openrocket/rocketcomponent/Rocket.java | 8 ++++++++ .../sf/openrocket/rocketcomponent/RocketComponent.java | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index 308ec86c2..f94a34325 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -60,7 +60,7 @@ public class FlightConfiguration implements FlightConfigurableParameter stages = new HashMap(); + final protected Map stages = new HashMap(); // Map of stage number to StageFlags of the corresponding stage final protected Map motors = new HashMap(); final private Collection activeMotors = new ArrayList(); final private InstanceMap activeInstances = new InstanceMap(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 3855db54c..5411440f7 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -748,6 +748,14 @@ public class Rocket extends ComponentAssembly { fireComponentChangeEvent(ComponentChangeEvent.TREE_CHANGE); return nextConfig.getFlightConfigurationID(); } + + /** + * Return all the flight configurations of this rocket. + * @return all the flight configurations of this rocket. + */ + public FlightConfigurableParameterSet getFlightConfigurations() { + return this.configSet; + } /** diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index ff43f79ed..23a954e70 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -1545,6 +1545,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab AxialStage stage = (AxialStage) component; this.getRocket().forgetStage(stage); } + + // Remove sub-stages of the removed component + for (AxialStage stage : component.getSubStages()) { + this.getRocket().forgetStage(stage); + } this.checkComponentStructure(); component.checkComponentStructure(); From 6b23576c340ea03bc87c0da5a2181db484e048de Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 26 Jun 2022 00:00:44 +0200 Subject: [PATCH 09/47] Fix unit tests Because of the new behavior 'disable sub-stages when parent stage is disabled', some unit tests needed to be rewritten --- .../rocketcomponent/FlightConfiguration.java | 29 ++++++++++++++----- .../FlightConfigurationTest.java | 1 - 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index f94a34325..7bb3cfae3 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -179,23 +179,26 @@ public class FlightConfiguration implements FlightConfigurableParameterfalse) or active (true) + * @param activateSubStages whether the sub-stages of the specified stage should be activated as well. */ - public void _setStageActive(final int stageNumber, final boolean _active ) { + public void _setStageActive(final int stageNumber, final boolean _active, final boolean activateSubStages) { if ((0 <= stageNumber) && (stages.containsKey(stageNumber))) { stages.get(stageNumber).active = _active; - // Set the active state of all the sub-stages as well. - for (AxialStage stage : rocket.getStage(stageNumber).getSubStages()) { - stages.get(stage.getStageNumber()).active = _active; + if (activateSubStages) { + // Set the active state of all the sub-stages as well. + for (AxialStage stage : rocket.getStage(stageNumber).getSubStages()) { + stages.get(stage.getStageNumber()).active = _active; + } } fireChangeEvent(); return; @@ -203,6 +206,16 @@ public class FlightConfiguration implements FlightConfigurableParameterfalse) or active (true) + */ + public void _setStageActive(final int stageNumber, final boolean _active ) { + _setStageActive(stageNumber, _active, true); + } + public void toggleStage(final int stageNumber) { if ((0 <= stageNumber) && (stages.containsKey(stageNumber))) { diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index 8a69a1ff4..51db91e7d 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -364,7 +364,6 @@ public class FlightConfigurationTest extends BaseTestCase { selected.clearAllStages(); selected.toggleStage(1); - selected.toggleStage(2); // vvvv Test Target vvvv InstanceMap instances = selected.getActiveInstances(); From 33b0f77c804b18bb34ef970db29fccf366fd780e Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 26 Jun 2022 01:13:51 +0200 Subject: [PATCH 10/47] Fix minor issue --- .../net/sf/openrocket/aerodynamics/BarrowmanCalculator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 9335b4b64..add6b3b7b 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -629,7 +629,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { double radius = 0; final SymmetricComponent prevComponent = s.getPreviousSymmetricComponent(); - if (prevComponent != null) + if (prevComponent != null && configuration.isComponentActive(prevComponent)) radius = prevComponent.getAftRadius(); if (radius < s.getForeRadius()) { @@ -690,7 +690,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { // its aft CD double radius = 0; final SymmetricComponent prevComponent = s.getPreviousSymmetricComponent(); - if (prevComponent != null) { + if (prevComponent != null && configuration.isComponentActive(prevComponent)) { radius = prevComponent.getAftRadius(); } From 42a49a0aac54a555672ed2577441fc814ce40888 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 26 Jun 2022 01:14:27 +0200 Subject: [PATCH 11/47] Add unit tests for disabling stages --- .../simulation/DisableStageTest.java | 305 ++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 core/test/net/sf/openrocket/simulation/DisableStageTest.java diff --git a/core/test/net/sf/openrocket/simulation/DisableStageTest.java b/core/test/net/sf/openrocket/simulation/DisableStageTest.java new file mode 100644 index 000000000..9b4b0f7df --- /dev/null +++ b/core/test/net/sf/openrocket/simulation/DisableStageTest.java @@ -0,0 +1,305 @@ +package net.sf.openrocket.simulation; + +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.FlightConfigurationId; +import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.simulation.exception.MotorIgnitionException; +import net.sf.openrocket.simulation.exception.SimulationException; +import net.sf.openrocket.simulation.listeners.AbstractSimulationListener; +import net.sf.openrocket.simulation.listeners.SimulationListener; +import net.sf.openrocket.util.BaseTestCase.BaseTestCase; +import net.sf.openrocket.util.TestRockets; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test class that tests the effect on the simulation results of activating/deactivating stages. + * + * @author Sibo Van Gool + */ +public class DisableStageTest extends BaseTestCase { + /** + * Tests that the simulation results are correct when a single stage is deactivated and re-activated. + */ + @Test + public void testSingleStage() throws SimulationException { + //// Test disabling the stage + Rocket rocket = TestRockets.makeEstesAlphaIII(); + + Simulation simDisabled = new Simulation(rocket); + simDisabled.setFlightConfigurationId(TestRockets.TEST_FCID_0); + simDisabled.getActiveConfiguration()._setStageActive(0, false); + simDisabled.getOptions().setISAAtmosphere(true); + simDisabled.getOptions().setTimeStep(0.05); + + SimulationListener simulationListener = new AbstractSimulationListener(); + + // Since there are no stages, the simulation should throw an exception. + try { + simDisabled.simulate(simulationListener); + } catch (SimulationException e) { + if (!(e instanceof MotorIgnitionException)) { + Assert.fail("Simulation should have thrown a MotorIgnitionException"); + } + } + + //// Test re-enableing the stage. + Rocket rocketOriginal = TestRockets.makeEstesAlphaIII(); + + Simulation simOriginal = new Simulation(rocketOriginal); + simOriginal.setFlightConfigurationId(TestRockets.TEST_FCID_0); + simOriginal.getOptions().setISAAtmosphere(true); + simOriginal.getOptions().setTimeStep(0.05); + + simDisabled.getActiveConfiguration().setAllStages(); // Re-enable all stages. + + double delta = 0.05; // 5 % error margin (simulations are not exact) + compareSims(simOriginal, simDisabled, simulationListener, delta); + } + + /** + * Tests that the simulation results are correct when the last stage of a multi-stage rocket is deactivated and re-activated. + */ + @Test + public void testMultiStageLastDisabled() { + //// Test disabling the stage + Rocket rocketRemoved = TestRockets.makeBeta(); // Rocket with the last stage removed + Rocket rocketDisabled = TestRockets.makeBeta(); // Rocket with the last stage disabled + + int stageNr = rocketRemoved.getChildCount() - 1; + rocketRemoved.removeChild(stageNr); + FlightConfiguration fc = rocketDisabled.getFlightConfiguration(TestRockets.TEST_FCID_1); + fc._setStageActive(stageNr, false); + + Simulation simRemoved = new Simulation(rocketRemoved); + simRemoved.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simRemoved.getOptions().setISAAtmosphere(true); + simRemoved.getOptions().setTimeStep(0.05); + + Simulation simDisabled = new Simulation(rocketDisabled); + simDisabled.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simDisabled.getOptions().setISAAtmosphere(true); + simDisabled.getOptions().setTimeStep(0.05); + + SimulationListener simulationListener = new AbstractSimulationListener(); + + double delta = 0.05; // 5 % error margin (simulations are not exact) + compareSims(simRemoved, simDisabled, simulationListener, delta); + + //// Test re-enableing the stage. + Rocket rocketOriginal = TestRockets.makeBeta(); + Simulation simOriginal = new Simulation(rocketOriginal); + simOriginal.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simOriginal.getOptions().setISAAtmosphere(true); + simOriginal.getOptions().setTimeStep(0.05); + + simDisabled.getActiveConfiguration().setAllStages(); + + compareSims(simOriginal, simDisabled, simulationListener, delta); + } + + /** + * Tests that the simulation results are correct when the first stage of a multi-stage rocket is deactivated and re-activated. + */ + // Don't even know if this test was useful, but simulation results vary wildly because the first stage is disabled, + // so I'm just gonna ignore this test. + /*@Test + public void testMultiStageFirstDisabled() { + //// Test disabling the stage + Rocket rocketRemoved = TestRockets.makeBeta(); // Rocket with the last stage removed + Rocket rocketDisabled = TestRockets.makeBeta(); // Rocket with the last stage disabled + + // You need to disable the second stage body tube going into automatic radius mode, otherwise the + // removed and disabled rocket will have different results (removed rocket will have a different diameter) + BodyTube bodyTube = (BodyTube) rocketRemoved.getChild(1).getChild(0); + bodyTube.setOuterRadiusAutomatic(false); + + + int stageNr = 0; + rocketRemoved.removeChild(stageNr); + FlightConfiguration fc = rocketDisabled.getFlightConfiguration(TestRockets.TEST_FCID_1); + fc._setStageActive(stageNr, false); + + Simulation simRemoved = new Simulation(rocketRemoved); + simRemoved.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simRemoved.getOptions().setISAAtmosphere(true); + simRemoved.getOptions().setTimeStep(0.05); + + Simulation simDisabled = new Simulation(rocketDisabled); + simDisabled.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simDisabled.getOptions().setISAAtmosphere(true); + simDisabled.getOptions().setTimeStep(0.05); + + SimulationListener simulationListener = new AbstractSimulationListener(); + + double delta = 0.1; // 10 % error margin (simulations are very unstable and not exact when the first stage is disabled...) + compareSims(simRemoved, simDisabled, simulationListener, delta); + + //// Test re-enableing the stage. + Rocket rocketOriginal = TestRockets.makeBeta(); + Simulation simOriginal = new Simulation(rocketOriginal); + simOriginal.setFlightConfigurationId(TestRockets.TEST_FCID_1); + simOriginal.getOptions().setISAAtmosphere(true); + simOriginal.getOptions().setTimeStep(0.05); + + simDisabled.getActiveConfiguration().setAllStages(); + + compareSims(simOriginal, simDisabled, simulationListener, delta); + }*/ + + /** + * Tests that the simulation results are correct when a booster stage is deactivated and re-activated. + */ + @Test + public void testBooster1() { + //// Test disabling the stage + Rocket rocketRemoved = TestRockets.makeFalcon9Heavy(); // Rocket with the last stage removed + Rocket rocketDisabled = TestRockets.makeFalcon9Heavy(); // Rocket with the last stage disabled + + FlightConfigurationId fcid = new FlightConfigurationId(TestRockets.FALCON_9H_FCID_1); + int stageNr = 2; // Stage 2 is the Parallel Booster Stage + rocketRemoved.getChild(1).getChild(0).removeChild(0); // Remove the Parallel Booster Stage + FlightConfiguration fc = rocketDisabled.getFlightConfiguration(fcid); + fc._setStageActive(stageNr, false); + + Simulation simRemoved = new Simulation(rocketRemoved); + simRemoved.setFlightConfigurationId(fcid); + simRemoved.getOptions().setISAAtmosphere(true); + simRemoved.getOptions().setTimeStep(0.05); + + Simulation simDisabled = new Simulation(rocketDisabled); + simDisabled.setFlightConfigurationId(fcid); + simDisabled.getOptions().setISAAtmosphere(true); + simDisabled.getOptions().setTimeStep(0.05); + + SimulationListener simulationListener = new AbstractSimulationListener(); + + double delta = 0.05; // 5 % error margin (simulations are not exact) + compareSims(simRemoved, simDisabled, simulationListener, delta); + + //// Test re-enableing the stage. + Rocket rocketOriginal = TestRockets.makeFalcon9Heavy(); + Simulation simOriginal = new Simulation(rocketOriginal); + simOriginal.setFlightConfigurationId(fcid); + simOriginal.getOptions().setISAAtmosphere(true); + simOriginal.getOptions().setTimeStep(0.05); + + simDisabled.getActiveConfiguration().setAllStages(); + + compareSims(simOriginal, simDisabled, simulationListener, delta); + } + + /** + * Tests that the simulation results are correct when the parent stage of a booster stage is deactivated and re-activated. + */ + @Test + public void testBooster2() { + //// Test disabling the stage + Rocket rocketRemoved = TestRockets.makeFalcon9Heavy(); // Rocket with the last stage removed + Rocket rocketDisabled = TestRockets.makeFalcon9Heavy(); // Rocket with the last stage disabled + + FlightConfigurationId fid = new FlightConfigurationId(TestRockets.FALCON_9H_FCID_1); + int stageNr = 1; // Stage 1 is the Parallel Booster Stage's parent stage + rocketRemoved.getChild(1).removeChild(0); // Remove the Parallel Booster Stage's parent stage + FlightConfiguration fc = rocketDisabled.getFlightConfiguration(fid); + fc._setStageActive(stageNr, false); + + Simulation simRemoved = new Simulation(rocketRemoved); + simRemoved.setFlightConfigurationId(fid); + simRemoved.getOptions().setISAAtmosphere(true); + simRemoved.getOptions().setTimeStep(0.05); + + Simulation simDisabled = new Simulation(rocketDisabled); + simDisabled.setFlightConfigurationId(fid); + simDisabled.getOptions().setISAAtmosphere(true); + simDisabled.getOptions().setTimeStep(0.05); + + SimulationListener simulationListener = new AbstractSimulationListener(); + + // There should be no motors left at this point, so a no motors exception should be thrown + try { + simRemoved.simulate(simulationListener); + } catch (SimulationException e) { + if (!(e instanceof MotorIgnitionException)) { + Assert.fail("Simulation failed: " + e); + } + } + + try { + simDisabled.simulate(simulationListener); + } catch (SimulationException e) { + if (!(e instanceof MotorIgnitionException)) { + Assert.fail("Simulation failed: " + e); + } + } + + //// Test re-enableing the stage. + Rocket rocketOriginal = TestRockets.makeFalcon9Heavy(); + Simulation simOriginal = new Simulation(rocketOriginal); + simOriginal.setFlightConfigurationId(fid); + simOriginal.getOptions().setISAAtmosphere(true); + simOriginal.getOptions().setTimeStep(0.05); + + simDisabled.getActiveConfiguration().setAllStages(); + + double delta = 0.05; // 5 % error margin (simulations are not exact) + compareSims(simOriginal, simDisabled, simulationListener, delta); + } + + /** + * Compare simActual to simExpected and fail the unit test if there was an error during simulation or + * the two don't match. + * Tested parameters: + * - maxAcceleration + * - maxAltitude + * - maxVelocity + * - maxMachNumber + * - flightTime + * - launchRodVelocity + * - deploymentVelocity + * - groundHitVelocity + * @param simExpected the expected simulation results + * @param simActual the actual simulation results + * @param simulationListener the simulation listener to use for the comparison + * @param delta the error margin for the comparison (e.g. 0.05 = 5 % error margin) + */ + private void compareSims(Simulation simExpected, Simulation simActual, + SimulationListener simulationListener, double delta) { + try { + simExpected.simulate(simulationListener); + double maxAccelerationOriginal = simExpected.getSimulatedData().getMaxAcceleration(); + double maxAltitudeOriginal = simExpected.getSimulatedData().getMaxAltitude(); + double maxVelocityOriginal = simExpected.getSimulatedData().getMaxVelocity(); + double maxMachNumberOriginal = simExpected.getSimulatedData().getMaxMachNumber(); + double flightTimeOriginal = simExpected.getSimulatedData().getFlightTime(); + double timeToApogeeOriginal = simExpected.getSimulatedData().getTimeToApogee(); + double launchRodVelocityOriginal = simExpected.getSimulatedData().getLaunchRodVelocity(); + double deploymentVelocityOriginal = simExpected.getSimulatedData().getDeploymentVelocity(); + double groundHitVelocityOriginal = simExpected.getSimulatedData().getGroundHitVelocity(); + + simActual.simulate(simulationListener); + double maxAccelerationDisabled = simActual.getSimulatedData().getMaxAcceleration(); + double maxAltitudeDisabled = simActual.getSimulatedData().getMaxAltitude(); + double maxVelocityDisabled = simActual.getSimulatedData().getMaxVelocity(); + double maxMachNumberDisabled = simActual.getSimulatedData().getMaxMachNumber(); + double flightTimeDisabled = simActual.getSimulatedData().getFlightTime(); + double timeToApogeeDisabled = simActual.getSimulatedData().getTimeToApogee(); + double launchRodVelocityDisabled = simActual.getSimulatedData().getLaunchRodVelocity(); + double deploymentVelocityDisabled = simActual.getSimulatedData().getDeploymentVelocity(); + double groundHitVelocityDisabled = simActual.getSimulatedData().getGroundHitVelocity(); + + Assert.assertEquals(maxAccelerationOriginal, maxAccelerationDisabled, maxAccelerationOriginal * delta); + Assert.assertEquals(maxAltitudeOriginal, maxAltitudeDisabled, maxAltitudeOriginal * delta); + Assert.assertEquals(maxVelocityOriginal, maxVelocityDisabled, maxVelocityOriginal * delta); + Assert.assertEquals(maxMachNumberOriginal, maxMachNumberDisabled, maxMachNumberOriginal * delta); + Assert.assertEquals(flightTimeOriginal, flightTimeDisabled, flightTimeOriginal * delta); + Assert.assertEquals(timeToApogeeOriginal, timeToApogeeDisabled, timeToApogeeOriginal * delta); + Assert.assertEquals(launchRodVelocityOriginal, launchRodVelocityDisabled, launchRodVelocityOriginal * delta); + Assert.assertEquals(deploymentVelocityOriginal, deploymentVelocityDisabled, deploymentVelocityOriginal * delta); + Assert.assertEquals(groundHitVelocityOriginal, groundHitVelocityDisabled, groundHitVelocityOriginal * delta); + } catch (SimulationException e) { + Assert.fail("Simulation failed: " + e); + } + } +} From 7ee5a17af994d159781327266982193bcf172cb6 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 27 Jun 2022 22:35:09 +0200 Subject: [PATCH 12/47] [#1490] Select recovery device/stage after config panel select --- .../RecoveryConfigurationPanel.java | 37 ++++++++++++++++++ .../SeparationConfigurationPanel.java | 38 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java index fb174692a..4e45d9a29 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java @@ -1,9 +1,12 @@ package net.sf.openrocket.gui.main.flightconfigpanel; import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; @@ -162,6 +165,30 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel devices = getSelectedComponents(); List fcIds = getSelectedConfigurationIds(); @@ -239,6 +266,16 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel components = new ArrayList<>(getSelectedComponents()); + if (components.size() == 0) return; + + flightConfigurationPanel.setSelectedComponents(components); + } + public void updateButtonState() { boolean componentSelected = getSelectedComponent() != null; selectDeploymentButton.setEnabled(componentSelected); diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java index 6ae182dcd..1c3854b45 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java @@ -1,9 +1,12 @@ package net.sf.openrocket.gui.main.flightconfigpanel; import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; @@ -27,6 +30,7 @@ import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.FlightConfigurationId; import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration; import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration.SeparationEvent; import net.sf.openrocket.startup.Application; @@ -170,6 +174,30 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel stages = getSelectedComponents(); List fcIds = getSelectedConfigurationIds(); @@ -248,6 +276,16 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel components = new ArrayList<>(getSelectedComponents()); + if (components.size() == 0) return; + + flightConfigurationPanel.setSelectedComponents(components); + } + public void updateButtonState() { boolean componentSelected = getSelectedComponent() != null; selectSeparationButton.setEnabled(componentSelected); From d82058417a80b3c895ea90e7953e1f3e33114772 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 27 Jun 2022 22:55:11 +0200 Subject: [PATCH 13/47] Fix multi-select for stages --- .../sf/openrocket/gui/main/BasicFrame.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index f83ef3fb4..b5304eba3 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -19,6 +19,7 @@ import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutionException; @@ -300,23 +301,28 @@ public class BasicFrame extends JFrame { componentSelectionModel.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { - TreePath selPath = e.getNewLeadSelectionPath(); - if (selPath == null) return; - RocketComponent c = (RocketComponent) selPath.getLastPathComponent(); + if (tree == null || tree.getSelectionPaths() == null || tree.getSelectionPaths().length == 0 + || rocketpanel == null) return; - if (c instanceof AxialStage || c instanceof Rocket || c instanceof PodSet) { - if (rocketpanel == null) return; - - List children = new LinkedList<>(); - for (RocketComponent child : c) { - children.add(child); + // Get all the components that need to be selected = currently selected components + children of stages/boosters/podsets + List children = new ArrayList<>(Arrays.asList(rocketpanel.getFigure().getSelection())); + for (TreePath p : tree.getSelectionPaths()) { + if (p != null) { + RocketComponent c = (RocketComponent) p.getLastPathComponent(); + if (c instanceof AxialStage || c instanceof Rocket || c instanceof PodSet) { + Iterator iter = c.iterator(false); + while (iter.hasNext()) { + RocketComponent child = iter.next(); + children.add(child); + } + } } + } - // Select all the child components - if (rocketpanel.getFigure() != null && rocketpanel.getFigure3d() != null) { - rocketpanel.getFigure().setSelection(children.toArray(new RocketComponent[0])); - rocketpanel.getFigure3d().setSelection(children.toArray(new RocketComponent[0])); - } + // Select all the child components + if (rocketpanel.getFigure() != null && rocketpanel.getFigure3d() != null) { + rocketpanel.getFigure().setSelection(children.toArray(new RocketComponent[0])); + rocketpanel.getFigure3d().setSelection(children.toArray(new RocketComponent[0])); } } }); From 00e77dd37b9565fed74fcf09dc1f5abcbe573afc Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 28 Jun 2022 00:46:43 +0200 Subject: [PATCH 14/47] Update selectedConfiguration of Rocket after loadFromRocket --- core/src/net/sf/openrocket/rocketcomponent/Rocket.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 7a3f1780a..0e349e3fb 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -390,10 +390,12 @@ public class Rocket extends ComponentAssembly { this.stageMap = r.stageMap; // these flight configurations need to reference the _this_ Rocket: + this.configSet.reset(); this.configSet.setDefault(new FlightConfiguration(this)); for (FlightConfigurationId key : r.configSet.map.keySet()) { this.configSet.set(key, new FlightConfiguration(this, key)); } + this.selectedConfiguration = this.configSet.get(r.getSelectedConfiguration().getId()); this.perfectFinish = r.perfectFinish; From 4660cc90453c8fe3b5d30472b964f85865c88176 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 28 Jun 2022 00:47:19 +0200 Subject: [PATCH 15/47] Update stabilityUnits after configuration change --- swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index 28bce901e..d3876b181 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -41,7 +41,7 @@ public class RocketInfo implements FigureElement { private final Caret cpCaret = new CPCaret(0,0); private final Caret cgCaret = new CGCaret(0,0); - private final UnitGroup stabilityUnits; + private UnitGroup stabilityUnits; private FlightConfiguration configuration; private double cg = 0, cp = 0; @@ -459,5 +459,6 @@ public class RocketInfo implements FigureElement { public void setCurrentConfig(FlightConfiguration newConfig) { this.configuration = newConfig; + this.stabilityUnits = UnitGroup.stabilityUnits(newConfig); } } From 186772fe3bbe76d85e25fb647c77da46a39cdec1 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 28 Jun 2022 01:00:56 +0200 Subject: [PATCH 16/47] Fix NullPointerExceptions --- .../gui/main/flightconfigpanel/RecoveryConfigurationPanel.java | 2 +- .../main/flightconfigpanel/SeparationConfigurationPanel.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java index 4e45d9a29..11c991e1f 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/RecoveryConfigurationPanel.java @@ -267,7 +267,7 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel components = new ArrayList<>(getSelectedComponents()); diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java index 1c3854b45..ccf27e1d1 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/SeparationConfigurationPanel.java @@ -277,7 +277,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel components = new ArrayList<>(getSelectedComponents()); From 4cf6b98f0341be0e5a2faad256b4b29c5bcdc835 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 28 Jun 2022 01:14:23 +0200 Subject: [PATCH 17/47] Fix unit test The unit test was actually a bit deceptive, always using the same flight configuration, even though it changes because of the undo action --- swing/test/net/sf/openrocket/IntegrationTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/swing/test/net/sf/openrocket/IntegrationTest.java b/swing/test/net/sf/openrocket/IntegrationTest.java index 24cb6178e..e0a280f09 100644 --- a/swing/test/net/sf/openrocket/IntegrationTest.java +++ b/swing/test/net/sf/openrocket/IntegrationTest.java @@ -71,7 +71,7 @@ public class IntegrationTest { private Action undoAction, redoAction; private AerodynamicCalculator aeroCalc = new BarrowmanCalculator(); - private FlightConfiguration config; + private FlightConfigurationId fcid; private FlightConditions conditions; private String massComponentID = null; @@ -112,14 +112,12 @@ public class IntegrationTest { undoAction = UndoRedoAction.newUndoAction(document); redoAction = UndoRedoAction.newRedoAction(document); - FlightConfigurationId fcid = document.getSimulation(0).getFlightConfigurationId(); - config = document.getRocket().getFlightConfiguration(fcid); + fcid = document.getSimulation(0).getFlightConfigurationId(); + FlightConfiguration config = document.getRocket().getFlightConfiguration(fcid); conditions = new FlightConditions(config); // Test undo state checkUndoState(null, null); - - InnerTube mmt = (InnerTube)config.getRocket().getChild(0).getChild(1).getChild(2); // Compute cg+cp + altitude // double cgx, double mass, double cpx, double cna) @@ -330,6 +328,7 @@ public class IntegrationTest { } private void checkCgCp(double cgx, double mass, double cpx, double cna) { + FlightConfiguration config = document.getRocket().getFlightConfiguration(fcid); final RigidBody launchData = MassCalculator.calculateLaunch(config); final Coordinate cg = launchData.getCenterOfMass(); assertEquals(cgx, cg.x, 0.001); From 55e83bf64239d8e65566a1271b417b813fd044fe Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 28 Jun 2022 19:15:39 +0200 Subject: [PATCH 18/47] [#1481] Update preset combobox --- core/resources/l10n/messages.properties | 5 +-- core/resources/l10n/messages_cs.properties | 4 +-- core/resources/l10n/messages_de.properties | 4 +-- core/resources/l10n/messages_es.properties | 4 +-- core/resources/l10n/messages_fr.properties | 4 +-- core/resources/l10n/messages_it.properties | 4 +-- core/resources/l10n/messages_ja.properties | 4 +-- core/resources/l10n/messages_nl.properties | 4 +-- core/resources/l10n/messages_pl.properties | 4 +-- core/resources/l10n/messages_pt.properties | 4 +-- core/resources/l10n/messages_ru.properties | 4 +-- core/resources/l10n/messages_uk_UA.properties | 4 +-- core/resources/l10n/messages_zh_CN.properties | 4 +-- .../openrocket/gui/adaptors/PresetModel.java | 23 ++---------- .../configdialog/RocketComponentConfig.java | 35 ++++++++++++++++++- 15 files changed, 63 insertions(+), 48 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index aa9ae51b7..0b951c197 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -2071,8 +2071,9 @@ CustomFinImport.error.badimage = Could not deduce fin shape from image. CustomFinImport.description = The image will be converted internally to black and white image (black for the fin), so make sure you use a solid dark color for the fin, and white or a light color for the background. The fin must be touching the bottom of the image, which is the base of the fin. -PresetModel.lbl.select = Select preset -PresetModel.lbl.database = From database\u2026 +PresetModel.lbl.nopreset = No preset +PresetModel.lbl.selectpreset = Select preset +PresetModel.lbl.selectpreset.ttip = Select a preset model for this rocket component from a database of components. DecalModel.lbl.select = DecalModel.lbl.choose = From file\u2026 diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index f5b5933f7..b8e41d2fe 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -1587,8 +1587,8 @@ CustomFinImport.error.badimage = Nemohu vyvodit tvar stabiliz CustomFinImport.description = Obrázek bude zmenen na cernobílý \n(cerná pro stabilizátor), ujistete se prosím, \u017Ee jste pou\u017Eily cernou barvu na stabilizátor \na bílou nebo svetlou barvu na pozadí. Stabilizátor \nse musí dotýkat steny obrázku, která predstavuje uchycení pro stabilizátor. -PresetModel.lbl.select = Výber predvolby: -PresetModel.lbl.database = Z databáze... +PresetModel.lbl.nopreset = ?ádné predvolby +PresetModel.lbl.selectpreset = Výber predvolby ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties index 45f91eda5..baa259f3e 100644 --- a/core/resources/l10n/messages_de.properties +++ b/core/resources/l10n/messages_de.properties @@ -1645,8 +1645,8 @@ CustomFinImport.error.badimage = Konnte keine Leitwerksform aus dem Bild erzeuge CustomFinImport.description = Das Bild wird intern in ein Schwarz-Weiß-Bild konvertiert (Leitwerk: schwarz). Bitte sicherstellen, dass das Leitwerk in einer dichten, dunklen Farbe ist, während der Hintergrund weiß oder sehr hell sein sollte. Das Leitwerk muss das untere Bildende berühren, da dies die Verbindungsstelle zur Rakete wird. -PresetModel.lbl.select = Voreinstellung auswählen: -PresetModel.lbl.database = Aus Datenbank... +PresetModel.lbl.nopreset = Keine Voreinstellung +PresetModel.lbl.selectpreset = Voreinstellung auswählen ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index 255e26369..245f68472 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -737,8 +737,8 @@ PreferencesDialog.languages.default = Idioma por defecto PreferencesDialog.lbl.language = Idioma de la interfaz: PreferencesDialog.lbl.languageEffect = El idioma cambiar\u00e1 la pr\u00f3xima vez que abra OpenRocket. -PresetModel.lbl.database = Desde la Base de Datos... -PresetModel.lbl.select = Prefabricado +PresetModel.lbl.nopreset = No hay preselección +PresetModel.lbl.selectpreset = Prefabricado PrintDialog.but.previewAndPrint = Vista previa e Imprimir PrintDialog.checkbox.showByStage = Mostrar por etapas diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index d4cee80d0..dfefe8177 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -729,8 +729,8 @@ PreferencesDialog.languages.default = Valeur syst\u00E8me par d\u00E9faut PreferencesDialog.lbl.language = Langue du programme: PreferencesDialog.lbl.languageEffect = La langue sera chang\u00E9e apr\u00E8s avoir red\u00E9marr\u00E9 OpenRocket. -PresetModel.lbl.database = A partir d'une base de donn\u00E9es... -PresetModel.lbl.select = Choisir une pi\u00E8ce pr\u00E9d\u00E9finie: +PresetModel.lbl.nopreset = Aucune pr\u00E9s\u00E9lection +PresetModel.lbl.selectpreset = Choisir une pi\u00E8ce pr\u00E9d\u00E9finie: PrintDialog.but.previewAndPrint = Pr\u00E9-visualiser et imprimer PrintDialog.checkbox.showByStage = Montrer par \u00E9tage diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index f99e43eb3..06791b98b 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -1651,8 +1651,8 @@ CustomFinImport.error.badimage = Non riesco a capire la forma della pinna dall CustomFinImport.description = L'immagine sar\u00e0 convertita in bianco e nero internamente (nero per le pinne), cos\u00ec assicurati di usare un nero pieno per le pinne e bianco, o colore chiaro, per lo sfondo. La pinna ndeve toccare il fondo dell'immagine, che \u00e8 la base della pinna. -PresetModel.lbl.select = Seleziona precaricati: -PresetModel.lbl.database = Da database... +PresetModel.lbl.nopreset = Nessuna preimpostazione +PresetModel.lbl.selectpreset = Seleziona precaricati ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index 2417dd0c0..56b24fd27 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -1713,8 +1713,8 @@ CustomFinImport.error.badimage = \u753B\u50CF\u304B\u3089\u30D5\u30A3\u30F3\u5F CustomFinImport.description = \u753B\u50CF\u306F\u5185\u90E8\u3067\u767D\u80CC\u666F\u3068\u9ED2\u7DDA\u306B\u5909\u63DB\u3055\u308C\u307E\u3059\u3002\u306A\u306E\u3067\u30D5\u30A3\u30F3\u306B\u306F\u6697\u3044\u8272\u306E\u5B9F\u7DDA\u3001\u80CC\u666F\u306B\u306F\u767D\u304B\u660E\u308B\u3044\u8272\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D5\u30A3\u30F3\u306F\u753B\u50CF\u306E\u5E95\u9762\u306B\u63A5\u3057\u3066\u3044\u306A\u304F\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3001\u3053\u308C\u306F\u30D5\u30A3\u30F3\u306E\u5E95\u9762\u306B\u306A\u308A\u307E\u3059\u3002 -PresetModel.lbl.select = Select preset -PresetModel.lbl.database = From database... +PresetModel.lbl.nopreset = \u30d7\u30ea\u30bb\u30c3\u30c8\u306a\u3057 +PresetModel.lbl.selectpreset = \u30d7\u30ea\u30bb\u30c3\u30c8\u9078\u629e ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index b32a8d0a5..40f3b18f7 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -1967,8 +1967,8 @@ CustomFinImport.error.badimage = Kon de vorm van de vin niet afleiden uit het be CustomFinImport.description = De afbeelding wordt intern geconverteerd naar een zwart-wit afbeelding (zwart voor de vin), dus zorg ervoor dat je een effen donkere kleur gebruikt voor de vin, en wit of een lichte kleur voor de achtergrond. De vin moet de onderkant van het beeld raken, dat is de basis van de vin. -PresetModel.lbl.select = Selecteer preset -PresetModel.lbl.database = Uit databank... +PresetModel.lbl.nopreset = Geen preset +PresetModel.lbl.selectpreset = Selecteer preset DecalModel.lbl.select = DecalModel.lbl.choose = Van bestand... diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index 08bcaec77..84dee7a9f 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -1592,8 +1592,8 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s. CustomFinImport.description = Obraz zostanie automatycznie zamieniony na czarno-bia\u0142y (statecznik w kolorze czarnym), wi\u0119c upewnij si\u0119, \u017Ce kszta\u0142t statecznika jest wype\u0142niony ciemnym kolorem, a t\u0142o jest bia\u0142e lub jasne. Podstawa statecznika musi przylega\u0107 do dolnej kraw\u0119dzi obrazu. - PresetModel.lbl.select = Wybierz ustawienia: - PresetModel.lbl.database = Z bazy danych... + PresetModel.lbl.nopreset = Brak ustawienia + PresetModel.lbl.selectpreset = Wybierz ustawienia ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index c40699812..229032f76 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -715,8 +715,8 @@ PreferencesDialog.languages.default = Padr\u00e3o do sistema PreferencesDialog.lbl.language = Idioma da interface: PreferencesDialog.lbl.languageEffect = A linguagem vai mudar na pr\u00f3xima vez que voc\u00ea iniciar o OpenRocket. -PresetModel.lbl.database = \u00c0 partir do banco de dados... -PresetModel.lbl.select = Selecione ajustes pr\u00e9-definidos +PresetModel.lbl.nopreset = Sem pr\u00e9-definidos +PresetModel.lbl.selectpreset = Selecione ajustes pr\u00e9-definidos PrintDialog.but.previewAndPrint = Visualiza\u00e7\u00e3o e impress\u00e3o PrintDialog.checkbox.showByStage = Mostrar por est\u00e1gio diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index f7eeb8792..7a3978031 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -2075,8 +2075,8 @@ CustomFinImport.error.badimage = \u041D\u0435\u0432\u043E\u0437\u043C\u043E\u043 CustomFinImport.description = \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u0447\u0435\u0440\u043D\u043E-\u0431\u0435\u043B\u043E\u0435 (\u0433\u0434\u0435 \u0447\u0435\u0440\u043D\u044B\u0439 - \u0446\u0432\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430), \u0442\u0430\u043A \u0447\u0442\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u0447\u0435\u0440\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0434\u043B\u044F \u0440\u0438\u0441\u0443\u043D\u043A\u0430 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430 \u0438 \u0431\u0435\u043B\u044B\u0439 \u0438\u043B\u0438 \u0441\u0432\u0435\u0442\u043B\u044B\u0439 \u0446\u0432\u0435\u0442 \u0434\u043B\u044F \u0444\u043E\u043D\u0430. \u041E\u0441\u043D\u043E\u0432\u0430\u043D\u0438\u0435 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430 \u0434\u043E\u043B\u0436\u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441\u043D\u0438\u0437\u0443 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F. -PresetModel.lbl.select = \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u0430\u0433\u043E\u0442\u043E\u0432\u043A\u0443 -PresetModel.lbl.database = \u0418\u0437 \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445... +PresetModel.lbl.nopreset = \u041d\u0435\u0442\u0020\u043f\u0440\u0435\u0434\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 +PresetModel.lbl.selectpreset = \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u0430\u0433\u043E\u0442\u043E\u0432\u043A\u0443 DecalModel.lbl.select = <\u043D\u0435\u0442> DecalModel.lbl.choose = \u0418\u0437 \u0444\u0430\u0439\u043B\u0430... diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 5d7147134..10846074b 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -1812,8 +1812,8 @@ CustomFinImport.error.badimage = Could not deduce fin shape from image. CustomFinImport.description = The image will be converted internally to black and white image (black for the fin), so make sure you use a solid dark color for the fin, and white or a light color for the background. The fin must be touching the bottom of the image, which is the base of the fin. -PresetModel.lbl.select = Select preset -PresetModel.lbl.database = From database... +PresetModel.lbl.nopreset = No preset +PresetModel.lbl.selectpreset = Select preset DecalModel.lbl.select = DecalModel.lbl.choose = From file... diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 9e9cfed05..804bc7ac9 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -803,8 +803,8 @@ PreferencesDialog.languages.default = \u7CFB\u7EDF\u9ED8\u8BA4 PreferencesDialog.lbl.language = \u754C\u9762\u8BED\u8A00: PreferencesDialog.lbl.languageEffect = \u8BED\u8A00\u8BBE\u7F6E\u5C06\u5728OpenRocket\u91CD\u542F\u540E\u751F\u6548 -PresetModel.lbl.database = \u4ECE\u6570\u636E\u5E93... -PresetModel.lbl.select = \u9009\u62E9\u9884\u8BBE +PresetModel.lbl.nopreset = \u6ca1\u6709\u9884\u8bbe +PresetModel.lbl.selectpreset = \u9009\u62E9\u9884\u8BBE PrintDialog.but.previewAndPrint = \u9884\u89C8 & \u6253\u5370 PrintDialog.checkbox.showByStage = \u6309\u7EA7\u663E\u793A diff --git a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java index 5fb2355d7..59f017e03 100644 --- a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java +++ b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java @@ -29,8 +29,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com private static final Logger log = LoggerFactory.getLogger(PresetModel.class); private static final Translator trans = Application.getTranslator(); - private static final String NONE_SELECTED = trans.get("lbl.select"); - private static final String SELECT_DATABASE = trans.get("lbl.database"); + private static final String NONE_SELECTED = String.format("%s", trans.get("lbl.nopreset")); private final Component parent; private final RocketComponent component; @@ -50,7 +49,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com @Override public int getSize() { - return presets.size() + 2; + return presets.size() + 1; } @Override @@ -58,9 +57,6 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com if (index == 0) { return NONE_SELECTED; } - if (index == getSize() - 1) { - return SELECT_DATABASE; - } return presets.get(index - 1); } @@ -72,21 +68,6 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com throw new BugException("item is null"); } else if (item.equals(NONE_SELECTED)) { component.clearPreset(); - } else if (item.equals(SELECT_DATABASE)) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ((ComponentPresetDatabase) Application.getComponentPresetDao()).addDatabaseListener(PresetModel.this); - ComponentPresetChooserDialog dialog = - new ComponentPresetChooserDialog(SwingUtilities.getWindowAncestor(parent), component); - dialog.setVisible(true); - ComponentPreset preset = dialog.getSelectedComponentPreset(); - if (preset != null) { - setSelectedItem(preset); - } - ((ComponentPresetDatabase) Application.getComponentPresetDao()).removeChangeListener(PresetModel.this); - } - }); } else { document.addUndoPosition("Use Preset " + component.getComponentName()); component.loadPreset((ComponentPreset) item); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 976e2945a..e380a7303 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -22,8 +22,11 @@ import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; +import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.database.ComponentPresetDatabase; +import net.sf.openrocket.database.DatabaseListener; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; @@ -36,6 +39,7 @@ import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.dialogs.preset.ComponentPresetChooserDialog; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.widgets.SelectColorButton; import net.sf.openrocket.l10n.Translator; @@ -115,8 +119,19 @@ public class RocketComponentConfig extends JPanel { // If the component supports a preset, show the preset selection box. presetModel = new PresetModel(this, document, component); presetComboBox = new JComboBox(presetModel); + presetComboBox.setMaximumRowCount(20); presetComboBox.setEditable(false); - this.add(presetComboBox, ""); + this.add(presetComboBox); + + JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.selectpreset")); + selectPreset.setToolTipText(trans.get("PresetModel.lbl.selectpreset.ttip")); + selectPreset.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + selectPreset(); + } + }); + this.add(selectPreset); } tabbedPane = new JTabbedPane(); @@ -241,6 +256,24 @@ public class RocketComponentConfig extends JPanel { } } + private void selectPreset() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (presetComboBox == null || presetModel == null) return; + ((ComponentPresetDatabase) Application.getComponentPresetDao()).addDatabaseListener(presetModel); + ComponentPresetChooserDialog dialog = + new ComponentPresetChooserDialog(SwingUtilities.getWindowAncestor(RocketComponentConfig.this), component); + dialog.setVisible(true); + ComponentPreset preset = dialog.getSelectedComponentPreset(); + if (preset != null) { + presetComboBox.setSelectedItem(preset); + } + ((ComponentPresetDatabase) Application.getComponentPresetDao()).removeChangeListener(presetModel); + } + }); + } + public void clearConfigListeners() { if (appearancePanel != null) { appearancePanel.clearConfigListeners(); From ebc0461fd0eb5565e705a17c3e9d6e7725839a08 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 30 Jun 2022 17:02:14 +0200 Subject: [PATCH 19/47] Update presets info text --- core/resources/l10n/messages.properties | 2 +- .../sf/openrocket/gui/configdialog/RocketComponentConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 0b951c197..49976fcd2 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -2095,7 +2095,7 @@ ComponentPresetChooserDialog.menu.sortDesc = Sort Descending ComponentPresetChooserDialog.menu.units = Units ComponentPresetChooserDialog.checkbox.showAllCompatible = Show all compatible ComponentPresetChooserDialog.checkbox.showLegacyCheckBox = Show Legacy Database -ComponentPresetChooserDialog.lbl.favorites = Select to add preset to drop-down menu +ComponentPresetChooserDialog.lbl.favorites = Check to add preset to the preset drop-down menu in the component edit dialog table.column.Favorite = Favorite table.column.Legacy = Legacy table.column.Manufacturer = Manufacturer diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index e380a7303..16e659976 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -119,7 +119,7 @@ public class RocketComponentConfig extends JPanel { // If the component supports a preset, show the preset selection box. presetModel = new PresetModel(this, document, component); presetComboBox = new JComboBox(presetModel); - presetComboBox.setMaximumRowCount(20); + presetComboBox.setMaximumRowCount(25); presetComboBox.setEditable(false); this.add(presetComboBox); From b1483ae03af87bbc07a96d9ad614f50b794a1ca8 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 2 Jul 2022 12:29:12 +0200 Subject: [PATCH 20/47] [#1506] Highlight spinner text after focus gained --- .../net/sf/openrocket/gui/SpinnerEditor.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/swing/src/net/sf/openrocket/gui/SpinnerEditor.java b/swing/src/net/sf/openrocket/gui/SpinnerEditor.java index be4b79525..d02997e3d 100644 --- a/swing/src/net/sf/openrocket/gui/SpinnerEditor.java +++ b/swing/src/net/sf/openrocket/gui/SpinnerEditor.java @@ -1,8 +1,14 @@ package net.sf.openrocket.gui; import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; import javax.swing.text.DefaultFormatter; import javax.swing.text.DefaultFormatterFactory; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; /** * Editable editor for a JSpinner. Simply uses JSpinner.DefaultEditor, which has been made @@ -22,6 +28,59 @@ public class SpinnerEditor extends JSpinner.DefaultEditor { DefaultFormatterFactory dff = (DefaultFormatterFactory) getTextField().getFormatterFactory(); DefaultFormatter formatter = (DefaultFormatter) dff.getDefaultFormatter(); formatter.setOverwriteMode(false); + + + // Add listeners to select all the text when the field is focussed + { + getTextField().addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + selectAllText(); + } + + @Override + public void focusLost(FocusEvent e) { + } + }); + + getTextField().addMouseListener(new MouseListener() { + private boolean isFocussed = false; // Checks whether the text field was focussed when it was clicked upon + + @Override + public void mouseClicked(MouseEvent e) { + // If the text field was focussed when it was clicked upon instead of e.g. tab-switching to gain focus, + // then the select all action from the focus listener is ignored (it is replaced by a cursor-click event). + // So if we detect such a focus change, then redo the select all action. + if (!isFocussed) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JTextField tf = (JTextField) e.getSource(); + tf.selectAll(); + } + }); + } + } + + @Override + public void mousePressed(MouseEvent e) { + JTextField tf = (JTextField) e.getSource(); + isFocussed = tf.hasFocus(); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + }); + } } /** @@ -33,5 +92,17 @@ public class SpinnerEditor extends JSpinner.DefaultEditor { this(spinner); getTextField().setColumns(cols); } + + /** + * Highlights all the text in the text field. + */ + private void selectAllText() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + getTextField().selectAll(); + } + }); + } } From c53776c0447d1cdc8566e6eeae50a5003bca850a Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 2 Jul 2022 14:18:53 +0200 Subject: [PATCH 21/47] Change 'Coupler' to 'Tube Coupler' --- core/resources/l10n/messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index aa9ae51b7..914f3883b 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -715,7 +715,7 @@ compaddbuttons.Launchlug = Launch Lug compaddbuttons.RailButton = Rail Button compaddbuttons.InnerComponent = Inner Components compaddbuttons.Innertube = Inner Tube -compaddbuttons.Coupler = Coupler +compaddbuttons.Coupler = Tube Coupler compaddbuttons.Centeringring = Centering\nRing compaddbuttons.Bulkhead = Bulkhead compaddbuttons.Engineblock = Engine\nBlock From b79a6fb852af9f5b6328b33f2a48778c0f439969 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 2 Jul 2022 14:19:24 +0200 Subject: [PATCH 22/47] Focus most commonly edited parameter after preset selection --- .../openrocket/gui/adaptors/PresetModel.java | 2 ++ .../gui/configdialog/BodyTubeConfig.java | 9 +++++++++ .../gui/configdialog/InnerTubeConfig.java | 14 ++++++------- .../gui/configdialog/LaunchLugConfig.java | 1 + .../gui/configdialog/MassComponentConfig.java | 1 + .../gui/configdialog/ParachuteConfig.java | 1 + .../gui/configdialog/RingComponentConfig.java | 7 +++++++ .../configdialog/RocketComponentConfig.java | 20 +++++++++++++++++++ .../gui/configdialog/ShockCordConfig.java | 1 + .../gui/configdialog/StreamerConfig.java | 1 + .../gui/configdialog/TubeFinSetConfig.java | 1 + 11 files changed, 51 insertions(+), 7 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java index 5fb2355d7..e62eac2d5 100644 --- a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java +++ b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java @@ -8,6 +8,7 @@ import javax.swing.ComboBoxModel; import javax.swing.SwingUtilities; import net.sf.openrocket.database.ComponentPresetDatabase; +import net.sf.openrocket.gui.configdialog.RocketComponentConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -90,6 +91,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com } else { document.addUndoPosition("Use Preset " + component.getComponentName()); component.loadPreset((ComponentPreset) item); + ((RocketComponentConfig) parent).setFocusElement(); } } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java index 9ab43f596..39fbaa2ba 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java @@ -6,6 +6,8 @@ import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -23,6 +25,12 @@ import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Arrays; + @SuppressWarnings("serial") public class BodyTubeConfig extends RocketComponentConfig { @@ -43,6 +51,7 @@ public class BodyTubeConfig extends RocketComponentConfig { JSpinner spin = new JSpinner(length.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel.add(spin, "growx"); panel.add(new UnitSelector(length), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java index e5595286f..3e3ddb3cb 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java @@ -64,7 +64,6 @@ public class InnerTubeConfig extends RocketComponentConfig { super(d, c, parent); //// General and General properties - JPanel rightPanel = new JPanel(new MigLayout()); JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); DoubleModel m; @@ -86,7 +85,7 @@ public class InnerTubeConfig extends RocketComponentConfig { panel.add(spin, "growx"); panel.add(new UnitSelector(od), "growx"); - panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap"); + panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "wmin 100lp, growx, wrap"); if (od.isAutomaticAvailable()) { JCheckBox check = new JCheckBox(od.getAutomaticAction()); @@ -106,7 +105,7 @@ public class InnerTubeConfig extends RocketComponentConfig { panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); - panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "w 100lp, wrap"); + panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "wmin 100lp, growx, wrap"); if (m.isAutomaticAvailable()) { JCheckBox check = new JCheckBox(m.getAutomaticAction()); @@ -127,7 +126,7 @@ public class InnerTubeConfig extends RocketComponentConfig { panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); - panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "wmin 100lp, growx, wrap"); //// Inner tube length @@ -138,14 +137,15 @@ public class InnerTubeConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = 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"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "wmin 100lp, growx, wrap"); //// Material panel.add(materialPanel(Material.Type.BULK), - "spanx 3, growx, wrap 15lp"); + "spanx 4, growx, wrap 15lp"); //// Right side of panel ---- @@ -174,7 +174,7 @@ public class InnerTubeConfig extends RocketComponentConfig { panel2.add(new BasicSlider(m.getSliderModel( new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), - "w 100lp, wrap"); + "wmin 100lp, growx, wrap"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java index eedab2730..8302641bb 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java @@ -45,6 +45,7 @@ public class LaunchLugConfig extends RocketComponentConfig { JSpinner spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java index 5e7d185ec..23102e1f9 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java @@ -138,6 +138,7 @@ public class MassComponentConfig extends RocketComponentConfig { m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel2.add(spin, "growx"); panel2.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java index f63abcc16..38fdffc3b 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ParachuteConfig.java @@ -163,6 +163,7 @@ public class ParachuteConfig extends RecoveryDeviceConfig { m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java index f10ea3caa..27c2a4282 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RingComponentConfig.java @@ -20,6 +20,7 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.EngineBlock; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.ThicknessRingComponent; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; @@ -116,6 +117,9 @@ public class RingComponentConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + if (component instanceof ThicknessRingComponent) { + focusElement = spin; + } panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); @@ -139,6 +143,9 @@ public class RingComponentConfig extends RocketComponentConfig { m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + if (!(component instanceof ThicknessRingComponent)) { + focusElement = spin; + } panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 976e2945a..ebc57f128 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -22,6 +22,7 @@ import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; +import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -61,6 +62,7 @@ public class RocketComponentConfig extends JPanel { private JComboBox presetComboBox; private PresetModel presetModel; + protected Component focusElement = null; // Element that will be focused on after a preset is selected protected final JTextField componentNameField; protected JTextArea commentTextArea; @@ -702,6 +704,24 @@ public class RocketComponentConfig extends JPanel { } } } + + /** + * Requests focus for the focus element that should be active after a preset is selected. + */ + public void setFocusElement() { + if (focusElement != null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (focusElement instanceof JSpinner) { + SpinnerEditor ed = (SpinnerEditor) ((JSpinner)focusElement).getEditor(); + ed.getTextField().requestFocusInWindow(); + } else { + focusElement.requestFocusInWindow(); + } + } + }); + } + } protected void register(Invalidatable model) { diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java index 624738a95..a7a6e8a78 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java @@ -80,6 +80,7 @@ public class ShockCordConfig extends RocketComponentConfig { m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel2.add(spin, "growx"); panel2.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java index c4f6e2d65..504c6e712 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/StreamerConfig.java @@ -149,6 +149,7 @@ public class StreamerConfig extends RecoveryDeviceConfig { m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/TubeFinSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/TubeFinSetConfig.java index a005d11e2..e9de11352 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/TubeFinSetConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/TubeFinSetConfig.java @@ -54,6 +54,7 @@ public class TubeFinSetConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); + focusElement = spin; panel.add(spin, "growx"); panel.add(new UnitSelector(m), "growx"); From 16479a126d2f3c6d7c0ccfb8c491c80aa1e1f83a Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 2 Jul 2022 16:02:21 +0200 Subject: [PATCH 23/47] Add focus element for rail button Even though there aren't presets for rail buttons... --- .../src/net/sf/openrocket/gui/configdialog/RailButtonConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RailButtonConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RailButtonConfig.java index 3edfa1e89..b5e005a4a 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RailButtonConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RailButtonConfig.java @@ -92,6 +92,7 @@ public class RailButtonConfig extends RocketComponentConfig { DoubleModel offsetModel = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); JSpinner offsetSpinner = new JSpinner(offsetModel.getSpinnerModel()); offsetSpinner.setEditor(new SpinnerEditor(offsetSpinner)); + focusElement = offsetSpinner; panel.add(offsetSpinner, "growx"); panel.add(new UnitSelector(offsetModel), "growx"); panel.add(new BasicSlider(offsetModel.getSliderModel( From 2814827bcc56313ffbaca2191c9bd03affc069fd Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 4 Jul 2022 12:10:29 +0200 Subject: [PATCH 24/47] [#1509] Make InnerTube InsideColorComponent --- .../sf/openrocket/rocketcomponent/InnerTube.java | 14 +++++++++++++- .../gui/figure3d/geometry/ComponentRenderer.java | 7 +++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java index a1935c0cf..272de11ac 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java @@ -26,7 +26,7 @@ import net.sf.openrocket.util.MathUtil; * * @author Sampo Niskanen */ -public class InnerTube extends ThicknessRingComponent implements AxialPositionable, BoxBounded, Clusterable, RadialParent, MotorMount { +public class InnerTube extends ThicknessRingComponent implements AxialPositionable, BoxBounded, Clusterable, RadialParent, MotorMount, InsideColorComponent { private static final Translator trans = Application.getTranslator(); private static final Logger log = LoggerFactory.getLogger(InnerTube.class); @@ -37,6 +37,8 @@ public class InnerTube extends ThicknessRingComponent implements AxialPositionab private double overhang = 0; private boolean isActingMount; private MotorConfigurationSet motors; + + private InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this); /** * Main constructor. @@ -447,6 +449,16 @@ public class InnerTube extends ThicknessRingComponent implements AxialPositionab return this.motors.toDebug(); } + @Override + public InsideColorComponentHandler getInsideColorComponentHandler() { + return this.insideColorComponentHandler; + } + + @Override + public void setInsideColorComponentHandler(InsideColorComponentHandler handler) { + this.insideColorComponentHandler = handler; + } + @Override public boolean addConfigListener(RocketComponent listener) { boolean success = super.addConfigListener(listener); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java index b83143638..5c2d39c1e 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java @@ -7,6 +7,7 @@ import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.glu.GLUquadric; +import net.sf.openrocket.rocketcomponent.InnerTube; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,6 +99,8 @@ public class ComponentRenderer { if (c instanceof BodyTube) { renderTube(gl, (BodyTube) c, which); + } else if (c instanceof InnerTube) { + renderTube(gl, (InnerTube) c, which); } else if (c instanceof LaunchLug) { renderLug(gl, (LaunchLug) c, which); } else if ( c instanceof RailButton ){ @@ -257,6 +260,10 @@ public class ComponentRenderer { renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength()); } + private void renderTube(GL2 gl, InnerTube t, Surface which) { + renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength()); + } + private void renderRing(GL2 gl, RingComponent r) { gl.glRotated(90, 0, 1.0, 0); From f3a0c32f5503ce9113e68b86b2ec62b6cf244449 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 4 Jul 2022 12:10:47 +0200 Subject: [PATCH 25/47] Better appearance tab tooltip --- core/resources/l10n/messages.properties | 9 +++++---- core/resources/l10n/messages_cs.properties | 6 +++--- core/resources/l10n/messages_de.properties | 6 +++--- core/resources/l10n/messages_es.properties | 6 +++--- core/resources/l10n/messages_fr.properties | 6 +++--- core/resources/l10n/messages_it.properties | 6 +++--- core/resources/l10n/messages_ja.properties | 6 +++--- core/resources/l10n/messages_nl.properties | 6 +++--- core/resources/l10n/messages_pl.properties | 6 +++--- core/resources/l10n/messages_pt.properties | 6 +++--- core/resources/l10n/messages_ru.properties | 6 +++--- core/resources/l10n/messages_uk_UA.properties | 6 +++--- core/resources/l10n/messages_zh_CN.properties | 6 +++--- .../gui/configdialog/RocketComponentConfig.java | 10 +++++----- 14 files changed, 46 insertions(+), 45 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index aa9ae51b7..d214901a7 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -887,16 +887,17 @@ RocketCfg.lbl.Material = Material: ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Component name: -RocketCompCfg.ttip.Thecomponentname = The component name. +RocketCompCfg.lbl.Componentname.ttip = The component name. RocketCompCfg.tab.Override = Override -RocketCompCfg.tab.MassandCGoverride = Mass and CG override options +RocketCompCfg.tab.Override.ttip = Mass and CG override options RocketCompCfg.tab.Assembly = General RocketCompCfg.tab.AssemblyComment = Options for locating stages parallel to other stages RocketCompCfg.tab.Figure = Figure RocketCompCfg.tab.Figstyleopt = Figure style options RocketCompCfg.tab.Comment = Comment -RocketCompCfg.tab.Specifyacomment = Specify a comment for the component -RocketCompCfg.tab.Appearance = Appearance +RocketCompCfg.tab.Comment.ttip = Specify a comment for the component +RocketCompCfg.tab.Appearance = Appearance +RocketCompCfg.tab.Appearance.ttip = Component's appearance RocketCompCfg.lbl.Mass = Mass: RocketCompCfg.lbl.Componentmass = Component mass: RocketCompCfg.lbl.overriddento = (overridden to diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index f5b5933f7..627fe287f 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -621,13 +621,13 @@ ShockCordCfg.lbl.Shockcordlength = D ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Jméno komponenty: -RocketCompCfg.ttip.Thecomponentname = Jméno komponenty. +RocketCompCfg.lbl.Componentname.ttip = Jméno komponenty. RocketCompCfg.tab.Override = Prepsat -RocketCompCfg.tab.MassandCGoverride = Prepi\u0161 hmotnost a te\u017Ei\u0161te +RocketCompCfg.tab.Override.ttip = Prepi\u0161 hmotnost a te\u017Ei\u0161te RocketCompCfg.tab.Figure = Obrázek RocketCompCfg.tab.Figstyleopt = Vlastnosti obrázku RocketCompCfg.tab.Comment = Komentár -RocketCompCfg.tab.Specifyacomment = Upresnení komentáre komponenty +RocketCompCfg.tab.Comment.ttip = Upresnení komentáre komponenty RocketCompCfg.lbl.Mass = Hmotnost: RocketCompCfg.lbl.Componentmass = Hmotnost komponenty: RocketCompCfg.lbl.overriddento = (prepsáno na diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties index 45f91eda5..30b6df86c 100644 --- a/core/resources/l10n/messages_de.properties +++ b/core/resources/l10n/messages_de.properties @@ -677,13 +677,13 @@ ShockCordCfg.lbl.Shockcordlength = Gummibandl ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Komponentenname: -RocketCompCfg.ttip.Thecomponentname = Name der Komponente. +RocketCompCfg.lbl.Componentname.ttip = Name der Komponente. RocketCompCfg.tab.Override = Werte überschreiben -RocketCompCfg.tab.MassandCGoverride = Massen- und Schwerpunktsoptionen +RocketCompCfg.tab.Override.ttip = Massen- und Schwerpunktsoptionen RocketCompCfg.tab.Figure = Form RocketCompCfg.tab.Figstyleopt = Formoptionen RocketCompCfg.tab.Comment = Kommentar -RocketCompCfg.tab.Specifyacomment = Kommentar zu dieser Komponente +RocketCompCfg.tab.Comment.ttip = Kommentar zu dieser Komponente RocketCompCfg.lbl.Mass = Masse: RocketCompCfg.lbl.Componentmass = Masse der Komponente: RocketCompCfg.lbl.overriddento = (überschrieben auf diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index 255e26369..6386c101d 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -861,13 +861,13 @@ RocketCompCfg.tab.Appearance = Apariencia RocketCompCfg.tab.Comment = Comentarios RocketCompCfg.tab.Figstyleopt = Opciones de estilo de la figura RocketCompCfg.tab.Figure = Estilo -RocketCompCfg.tab.MassandCGoverride = Especificar la Masa y el CG del componente. +RocketCompCfg.tab.Override.ttip = Especificar la Masa y el CG del componente. RocketCompCfg.tab.Override = Masa y CG -RocketCompCfg.tab.Specifyacomment = Especifique un comentario para el componente +RocketCompCfg.tab.Comment.ttip = Especifique un comentario para el componente RocketCompCfg.title.Aftshoulder = Trasera del acople RocketCompCfg.title.Noseconeshoulder = Acople de la ojiva RocketCompCfg.ttip.Endcapped = Si el extremo del soporte est\u00e1 truncado. -RocketCompCfg.ttip.Thecomponentname = El nombre del componente. +RocketCompCfg.lbl.Componentname.ttip = El nombre del componente. RocketComponent.Position.ABSOLUTE = Extremo de la ojiva RocketComponent.Position.AFTER = Despu\u00e9s del componente diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index d4cee80d0..2ea355901 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -853,13 +853,13 @@ RocketCompCfg.tab.Appearance = Apparence RocketCompCfg.tab.Comment = Commentaires RocketCompCfg.tab.Figstyleopt = Options de la forme RocketCompCfg.tab.Figure = Forme -RocketCompCfg.tab.MassandCGoverride = For\u00E7age de la Masse et du CG +RocketCompCfg.tab.Override.ttip = For\u00E7age de la Masse et du CG RocketCompCfg.tab.Override = Forcer la valeur -RocketCompCfg.tab.Specifyacomment = Commentaires concernant la pi\u00E8ce +RocketCompCfg.tab.Comment.ttip = Commentaires concernant la pi\u00E8ce RocketCompCfg.title.Aftshoulder = Epaulement arri\u00E8re RocketCompCfg.title.Noseconeshoulder = Epaulement du c\u00F4ne RocketCompCfg.ttip.Endcapped = Pr\u00E9cise si l'arri\u00E8re du c\u00F4ne est clos. -RocketCompCfg.ttip.Thecomponentname = Le nom de la pi\u00E8ce. +RocketCompCfg.lbl.Componentname.ttip = Le nom de la pi\u00E8ce. RocketComponent.Position.ABSOLUTE = Pointe de l'ogive RocketComponent.Position.AFTER = Apr\u00E8s la pi\u00E8ce parente diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index f99e43eb3..6d44cadf1 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -679,13 +679,13 @@ ShockCordCfg.lbl.Shockcordlength = Lunghezza della Shock cord : ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Nome componente: -RocketCompCfg.ttip.Thecomponentname = Il nome del componente. +RocketCompCfg.lbl.Componentname.ttip = Il nome del componente. RocketCompCfg.tab.Override = Modifica -RocketCompCfg.tab.MassandCGoverride = Opzioni di sovrascrittura di massa e CG +RocketCompCfg.tab.Override.ttip = Opzioni di sovrascrittura di massa e CG RocketCompCfg.tab.Figure = Disegno RocketCompCfg.tab.Figstyleopt = Opzioni dello stile della figure RocketCompCfg.tab.Comment = Commento -RocketCompCfg.tab.Specifyacomment = Specifica un commento per il componente +RocketCompCfg.tab.Comment.ttip = Specifica un commento per il componente RocketCompCfg.lbl.Mass = Massa: RocketCompCfg.lbl.Componentmass = La massa del componente : RocketCompCfg.lbl.overriddento = (sovrascritto a diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index 2417dd0c0..44e7e9004 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -709,13 +709,13 @@ ShockCordCfg.lbl.Shockcordlength = \u30B7\u30E7\u30C3\u30AF\u30B3\u30FC\u30C9\u ! RocketComponentConfig RocketCompCfg.lbl.Componentname = \u90E8\u54C1\u540D\uFF1A -RocketCompCfg.ttip.Thecomponentname = \u90E8\u54C1\u306E\u540D\u524D +RocketCompCfg.lbl.Componentname.ttip = \u90E8\u54C1\u306E\u540D\u524D RocketCompCfg.tab.Override = \u518D\u5B9A\u7FA9 -RocketCompCfg.tab.MassandCGoverride = \u8CEA\u91CF\u3068CG\u3092\u518D\u5B9A\u7FA9\u3059\u308B\u30AA\u30D7\u30B7\u30E7\u30F3 +RocketCompCfg.tab.Override.ttip = \u8CEA\u91CF\u3068CG\u3092\u518D\u5B9A\u7FA9\u3059\u308B\u30AA\u30D7\u30B7\u30E7\u30F3 RocketCompCfg.tab.Figure = \u56F3\u793A RocketCompCfg.tab.Figstyleopt = \u56F3\u793A\u306E\u30B9\u30BF\u30A4\u30EB\u30AA\u30D7\u30B7\u30E7\u30F3 RocketCompCfg.tab.Comment = \u30B3\u30E1\u30F3\u30C8 -RocketCompCfg.tab.Specifyacomment = \u90E8\u54C1\u3078\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u8A18\u8FF0 +RocketCompCfg.tab.Comment.ttip = \u90E8\u54C1\u3078\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u8A18\u8FF0 RocketCompCfg.lbl.Mass = \u8CEA\u91CF\uFF1A RocketCompCfg.lbl.Componentmass = \u90E8\u54C1\u8CEA\u91CF\uFF1A RocketCompCfg.lbl.overriddento = (overridden to diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index b32a8d0a5..78365b1c9 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -826,15 +826,15 @@ RocketCfg.lbl.Material = Materiaal: ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Componentnaam: -RocketCompCfg.ttip.Thecomponentname = De componentnaam. +RocketCompCfg.lbl.Componentname.ttip = De componentnaam. RocketCompCfg.tab.Override = Overschrijf -RocketCompCfg.tab.MassandCGoverride = Massa en ZP overschrijvingsopties +RocketCompCfg.tab.Override.ttip = Massa en ZP overschrijvingsopties RocketCompCfg.tab.Assembly = Algemeen RocketCompCfg.tab.AssemblyComment = Opties voor het plaatsen van trappen parallel aan andere trappen RocketCompCfg.tab.Figure = Figuur RocketCompCfg.tab.Figstyleopt = Figuurstijl opties RocketCompCfg.tab.Comment = Opmerking -RocketCompCfg.tab.Specifyacomment = Geef een opmerking voor het onderdeel +RocketCompCfg.tab.Comment.ttip = Geef een opmerking voor het onderdeel RocketCompCfg.tab.Appearance = Uiterlijk RocketCompCfg.lbl.Mass = Massa: RocketCompCfg.lbl.Componentmass = Componentmassa: diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index 08bcaec77..6ed2c71de 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -623,13 +623,13 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s. ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Nazwa cz\u0119\u015Bci: - RocketCompCfg.ttip.Thecomponentname = Nazwa cz\u0119\u015Bci sk\u0142adowej rakiety. + RocketCompCfg.lbl.Componentname.ttip = Nazwa cz\u0119\u015Bci sk\u0142adowej rakiety. RocketCompCfg.tab.Override = Wymu\u015B - RocketCompCfg.tab.MassandCGoverride = Opcje wymuszenia ci\u0119\u017Caru oraz \u015Brodka ci\u0119\u017Cko\u015Bci + RocketCompCfg.tab.Override.ttip = Opcje wymuszenia ci\u0119\u017Caru oraz \u015Brodka ci\u0119\u017Cko\u015Bci RocketCompCfg.tab.Figure = Wygl\u0105d RocketCompCfg.tab.Figstyleopt = Styl kszta\u0142tu RocketCompCfg.tab.Comment = Uwagi - RocketCompCfg.tab.Specifyacomment = Dodaj uwagi do cz\u0119\u015Bci + RocketCompCfg.tab.Comment.ttip = Dodaj uwagi do cz\u0119\u015Bci RocketCompCfg.lbl.Mass = Masa: RocketCompCfg.lbl.Componentmass = Masa cz\u0119\u015Bci: RocketCompCfg.lbl.overriddento = (wymuszone do diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index c40699812..04abc97fe 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -838,13 +838,13 @@ RocketCompCfg.lbl.ttip.componentmaterialaffects = O material do componente afe RocketCompCfg.tab.Comment = Coment\u00e1rio RocketCompCfg.tab.Figstyleopt = Op\u00e7\u00f5es do estilo de figura RocketCompCfg.tab.Figure = Figura -RocketCompCfg.tab.MassandCGoverride = Op\u00e7\u00f5es de modifica\u00e7\u00e3o de massa e CG +RocketCompCfg.tab.Override.ttip = Op\u00e7\u00f5es de modifica\u00e7\u00e3o de massa e CG RocketCompCfg.tab.Override = Modificar -RocketCompCfg.tab.Specifyacomment = Especifique um coment\u00e1rio para o componente +RocketCompCfg.tab.Comment.ttip = Especifique um coment\u00e1rio para o componente RocketCompCfg.title.Aftshoulder = Ressalto traseiro RocketCompCfg.title.Noseconeshoulder = Ressalto da ogiva RocketCompCfg.ttip.Endcapped = Quando a extremidade do ressalto \u00e9 limitada. -RocketCompCfg.ttip.Thecomponentname = Nome do componente. +RocketCompCfg.lbl.Componentname.ttip = Nome do componente. RocketComponent.Position.ABSOLUTE = Dica da ogiva RocketComponent.Position.AFTER = Depois do componente pai diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index f7eeb8792..1688fc775 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -888,15 +888,15 @@ RocketCfg.lbl.Material = \u041C\u0430\u0442\u0435\u0440\u0438\u0430\u043B: ! RocketComponentConfig RocketCompCfg.lbl.Componentname = \u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430: -RocketCompCfg.ttip.Thecomponentname = \u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430. +RocketCompCfg.lbl.Componentname.ttip = \u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430. RocketCompCfg.tab.Override = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 -RocketCompCfg.tab.MassandCGoverride = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u043C\u0430\u0441\u0441\u044B \u0438 \u0426\u0422 +RocketCompCfg.tab.Override.ttip = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u043C\u0430\u0441\u0441\u044B \u0438 \u0426\u0422 RocketCompCfg.tab.Assembly = \u0421\u0431\u043E\u0440\u043A\u0430 RocketCompCfg.tab.AssemblyComment = \u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0440\u0430\u0437\u043C\u0435\u0449\u0435\u043D\u0438\u044F \u0441\u0442\u0443\u043F\u0435\u043D\u0435\u0439 \u043F\u0430\u0440\u0430\u043B\u043B\u0435\u043B\u044C\u043D\u043E \u0434\u0440\u0443\u0433\u0438\u043C \u0441\u0442\u0443\u043F\u0435\u043D\u044F\u043C RocketCompCfg.tab.Figure = \u0420\u0438\u0441\u0443\u043D\u043E\u043A RocketCompCfg.tab.Figstyleopt = \u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0441\u0442\u0438\u043B\u044F \u0440\u0438\u0441\u0443\u043D\u043A\u0430 RocketCompCfg.tab.Comment = \u041F\u0440\u0438\u043C\u0435\u0447\u0430\u043D\u0438\u0435 -RocketCompCfg.tab.Specifyacomment = \u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0440\u0438\u043C\u0435\u0447\u0430\u043D\u0438\u0435 \u043A \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0443 +RocketCompCfg.tab.Comment.ttip = \u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0440\u0438\u043C\u0435\u0447\u0430\u043D\u0438\u0435 \u043A \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0443 RocketCompCfg.tab.Appearance = \u0412\u043D\u0435\u0448\u043D\u0438\u0439 \u0432\u0438\u0434 RocketCompCfg.lbl.Mass = \u041C\u0430\u0441\u0441\u0430: RocketCompCfg.lbl.Componentmass = \u041C\u0430\u0441\u0441\u0430 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430: diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 5d7147134..c5da6e887 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -779,13 +779,13 @@ ShockCordCfg.lbl.Shockcordlength = Shock cord length: ! RocketComponentConfig RocketCompCfg.lbl.Componentname = Component name: -RocketCompCfg.ttip.Thecomponentname = The component name. +RocketCompCfg.lbl.Componentname.ttip = The component name. RocketCompCfg.tab.Override = Override -RocketCompCfg.tab.MassandCGoverride = Mass and CG override options +RocketCompCfg.tab.Override.ttip = Mass and CG override options RocketCompCfg.tab.Figure = Figure RocketCompCfg.tab.Figstyleopt = Figure style options RocketCompCfg.tab.Comment = Comment -RocketCompCfg.tab.Specifyacomment = Specify a comment for the component +RocketCompCfg.tab.Comment.ttip = Specify a comment for the component RocketCompCfg.tab.Appearance = Appearance RocketCompCfg.lbl.Mass = Mass: RocketCompCfg.lbl.Componentmass = Component mass: diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 9e9cfed05..b06908d10 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -927,13 +927,13 @@ RocketCompCfg.tab.Appearance = \u5916\u89C2 RocketCompCfg.tab.Comment = \u6CE8\u91CA RocketCompCfg.tab.Figstyleopt = \u6837\u5F0F\u9009\u9879 RocketCompCfg.tab.Figure = \u6837\u5F0F -RocketCompCfg.tab.MassandCGoverride = \u8D28\u91CF\u53CA\u91CD\u5FC3\u9009\u9879 +RocketCompCfg.tab.Override.ttip = \u8D28\u91CF\u53CA\u91CD\u5FC3\u9009\u9879 RocketCompCfg.tab.Override = \u8986\u5199 -RocketCompCfg.tab.Specifyacomment = \u7EC4\u4EF6\u6CE8\u91CA +RocketCompCfg.tab.Comment.ttip = \u7EC4\u4EF6\u6CE8\u91CA RocketCompCfg.title.Aftshoulder = \u524D\u8FDE\u63A5\u5904 RocketCompCfg.title.Noseconeshoulder = \u5934\u9525\u8FDE\u63A5\u5904 RocketCompCfg.ttip.Endcapped = \u8FDE\u63A5\u5904\u7EC8\u7AEF\u662F\u5426\u6709\u76D6. -RocketCompCfg.ttip.Thecomponentname = \u7EC4\u4EF6\u540D\u79F0. +RocketCompCfg.lbl.Componentname.ttip = \u7EC4\u4EF6\u540D\u79F0. RocketComponent.Position.ABSOLUTE = \u5934\u9525\u5C16\u7AEF RocketComponent.Position.AFTER = \u7236\u7EC4\u4EF6\u4E4B\u540E diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 976e2945a..a3b1d9e5b 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -100,7 +100,7 @@ public class RocketComponentConfig extends JPanel { //// Component name: JLabel label = new JLabel(trans.get("RocketCompCfg.lbl.Componentname")); //// The component name. - label.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname")); + label.setToolTipText(trans.get("RocketCompCfg.lbl.Componentname.ttip")); this.add(label, "spanx, height 32!, split"); componentNameField = new JTextField(15); @@ -108,7 +108,7 @@ public class RocketComponentConfig extends JPanel { componentNameField.addActionListener(textFieldListener); componentNameField.addFocusListener(textFieldListener); //// The component name. - componentNameField.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname")); + componentNameField.setToolTipText(trans.get("RocketCompCfg.lbl.Componentname.ttip")); this.add(componentNameField, "growx"); if (allSameType && component.getPresetType() != null) { @@ -124,17 +124,17 @@ public class RocketComponentConfig extends JPanel { //// Override and Mass and CG override options tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(), - trans.get("RocketCompCfg.tab.MassandCGoverride")); + trans.get("RocketCompCfg.tab.Override.ttip")); if (allMassive) { //// Appearance options appearancePanel = new AppearancePanel(document, component, parent); tabbedPane.addTab(trans.get("RocketCompCfg.tab.Appearance"), null, appearancePanel, - "Appearance Tool Tip"); + trans.get("RocketCompCfg.tab.Appearance.ttip")); } //// Comment and Specify a comment for the component tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(), - trans.get("RocketCompCfg.tab.Specifyacomment")); + trans.get("RocketCompCfg.tab.Comment.ttip")); addButtons(); From 938b9474157e018edebb10b4bcb3d6069c12b454 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 4 Jul 2022 20:51:21 +0200 Subject: [PATCH 26/47] [#1510] Don't update flight configuration from simulation edit --- .../gui/components/ConfigurationComboBox.java | 54 ++++++++++++++++--- .../gui/simulation/SimulationEditDialog.java | 2 +- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/components/ConfigurationComboBox.java b/swing/src/net/sf/openrocket/gui/components/ConfigurationComboBox.java index 4785570c2..43fc172a1 100644 --- a/swing/src/net/sf/openrocket/gui/components/ConfigurationComboBox.java +++ b/swing/src/net/sf/openrocket/gui/components/ConfigurationComboBox.java @@ -24,21 +24,49 @@ public class ConfigurationComboBox extends JComboBox implem public class ConfigurationModel implements MutableComboBoxModel { private final Rocket rkt; - - public ConfigurationModel(final Rocket _rkt) { + private FlightConfiguration selectedConfig; + private final boolean updateRocketConfig; + private final ConfigurationModel listener; + + /** + * @param _rkt the rocket to get the configurations from and to (optionally) change the rocket's selected configuration + * @param _updateRocketConfig whether to update the rocket's selected configuration based on the selected combo box item, + * or just change the combo box item without altering the rocket's configuration. + * @param listener model that should change its selected item to this model's selected item + */ + public ConfigurationModel(final Rocket _rkt, boolean _updateRocketConfig, ConfigurationModel listener) { this.rkt = _rkt; + this.updateRocketConfig = _updateRocketConfig; + this.selectedConfig = this.rkt.getSelectedConfiguration(); + this.listener = listener; + } + + public ConfigurationModel(final Rocket _rkt, boolean _updateRocketConfig) { + this(_rkt, _updateRocketConfig, null); } @Override public FlightConfiguration getSelectedItem() { - return rkt.getSelectedConfiguration(); + if (updateRocketConfig) { + return rkt.getSelectedConfiguration(); + } else { + return selectedConfig; + } } @Override public void setSelectedItem(Object nextItem) { if( nextItem instanceof FlightConfiguration ){ FlightConfigurationId selectedId = ((FlightConfiguration)nextItem).getId(); - rkt.setSelectedConfiguration(selectedId); + if (updateRocketConfig) { + rkt.setSelectedConfiguration(selectedId); + } else { + selectedConfig = rkt.getFlightConfiguration(selectedId); + } + + if (listener != null) { + listener.setSelectedItem(nextItem); + } } } @@ -79,9 +107,15 @@ public class ConfigurationComboBox extends JComboBox implem private final Rocket rkt; - public ConfigurationComboBox(Rocket _rkt) { + /** + * @param _rkt the rocket to get the configurations from and to (optionally) change the rocket's selected configuration + * @param _updateRocketConfig whether to update the rocket's selected configuration based on the selected combo box item, + * or just change the combo box item without altering the rocket's configuration. + */ + public ConfigurationComboBox(Rocket _rkt, boolean _updateRocketConfig) { rkt = _rkt; - setModel(new ConfigurationModel(rkt)); + final ConfigurationModel model = new ConfigurationModel(rkt, _updateRocketConfig); + setModel(model); rkt.addChangeListener(this); addPopupMenuListener(new PopupMenuListener() { @@ -89,12 +123,18 @@ public class ConfigurationComboBox extends JComboBox implem public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - setModel(new ConfigurationModel(rkt)); + final ConfigurationModel model2 = new ConfigurationModel(rkt, _updateRocketConfig, model); + model2.setSelectedItem(model.getSelectedItem()); + setModel(model2); } }); } + + public ConfigurationComboBox(Rocket _rkt) { + this(_rkt, true); + } @Override public void stateChanged(EventObject e) { diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java index 2bfe10afc..03b9ab944 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java @@ -151,7 +151,7 @@ public class SimulationEditDialog extends JDialog { final Rocket rkt = document.getRocket(); final FlightConfiguration config = rkt.getFlightConfiguration(simulationList[0].getFlightConfigurationId()); - final ConfigurationComboBox configComboBox = new ConfigurationComboBox(rkt); + final ConfigurationComboBox configComboBox = new ConfigurationComboBox(rkt, false); configComboBox.setSelectedItem(config); //// Select the motor configuration to use. From 62864c81909d50088b35e6a3d25f970cb07b05dd Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 4 Jul 2022 23:12:46 +0200 Subject: [PATCH 27/47] Change preset labels --- core/resources/l10n/messages.properties | 7 ++++--- core/resources/l10n/messages_cs.properties | 4 ++-- core/resources/l10n/messages_de.properties | 4 ++-- core/resources/l10n/messages_es.properties | 4 ++-- core/resources/l10n/messages_fr.properties | 4 ++-- core/resources/l10n/messages_it.properties | 4 ++-- core/resources/l10n/messages_ja.properties | 4 ++-- core/resources/l10n/messages_nl.properties | 4 ++-- core/resources/l10n/messages_pl.properties | 4 ++-- core/resources/l10n/messages_pt.properties | 4 ++-- core/resources/l10n/messages_ru.properties | 4 ++-- core/resources/l10n/messages_uk_UA.properties | 4 ++-- core/resources/l10n/messages_zh_CN.properties | 4 ++-- swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java | 5 +---- .../openrocket/gui/configdialog/RocketComponentConfig.java | 6 +++--- 15 files changed, 32 insertions(+), 34 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 49976fcd2..531b79a19 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -2071,9 +2071,10 @@ CustomFinImport.error.badimage = Could not deduce fin shape from image. CustomFinImport.description = The image will be converted internally to black and white image (black for the fin), so make sure you use a solid dark color for the fin, and white or a light color for the background. The fin must be touching the bottom of the image, which is the base of the fin. -PresetModel.lbl.nopreset = No preset -PresetModel.lbl.selectpreset = Select preset -PresetModel.lbl.selectpreset.ttip = Select a preset model for this rocket component from a database of components. +PresetModel.combo.ttip = Select a preset model from a list of favorites (selected in the component preset dialog),
or select 'Custom' when no preset is required. +PresetModel.lbl.custompreset = Custom +PresetModel.lbl.partsLib = Parts Library +PresetModel.lbl.partsLib.ttip = Select a preset model for this rocket component from a library of parts. DecalModel.lbl.select = DecalModel.lbl.choose = From file\u2026 diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index b8e41d2fe..46b652bec 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -1587,8 +1587,8 @@ CustomFinImport.error.badimage = Nemohu vyvodit tvar stabiliz CustomFinImport.description = Obrázek bude zmenen na cernobílý \n(cerná pro stabilizátor), ujistete se prosím, \u017Ee jste pou\u017Eily cernou barvu na stabilizátor \na bílou nebo svetlou barvu na pozadí. Stabilizátor \nse musí dotýkat steny obrázku, která predstavuje uchycení pro stabilizátor. -PresetModel.lbl.nopreset = ?ádné predvolby -PresetModel.lbl.selectpreset = Výber predvolby +PresetModel.lbl.custompreset = Vlastní +PresetModel.lbl.partsLib = Knihovna díl? ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties index baa259f3e..2415860ed 100644 --- a/core/resources/l10n/messages_de.properties +++ b/core/resources/l10n/messages_de.properties @@ -1645,8 +1645,8 @@ CustomFinImport.error.badimage = Konnte keine Leitwerksform aus dem Bild erzeuge CustomFinImport.description = Das Bild wird intern in ein Schwarz-Weiß-Bild konvertiert (Leitwerk: schwarz). Bitte sicherstellen, dass das Leitwerk in einer dichten, dunklen Farbe ist, während der Hintergrund weiß oder sehr hell sein sollte. Das Leitwerk muss das untere Bildende berühren, da dies die Verbindungsstelle zur Rakete wird. -PresetModel.lbl.nopreset = Keine Voreinstellung -PresetModel.lbl.selectpreset = Voreinstellung auswählen +PresetModel.lbl.custompreset = Benutzerdefiniert +PresetModel.lbl.partsLib = Teile-Bibliothek ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index 245f68472..def48e0f0 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -737,8 +737,8 @@ PreferencesDialog.languages.default = Idioma por defecto PreferencesDialog.lbl.language = Idioma de la interfaz: PreferencesDialog.lbl.languageEffect = El idioma cambiar\u00e1 la pr\u00f3xima vez que abra OpenRocket. -PresetModel.lbl.nopreset = No hay preselección -PresetModel.lbl.selectpreset = Prefabricado +PresetModel.lbl.custompreset = Personalizado +PresetModel.lbl.partsLib = Biblioteca de piezas PrintDialog.but.previewAndPrint = Vista previa e Imprimir PrintDialog.checkbox.showByStage = Mostrar por etapas diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index dfefe8177..5b1c921e8 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -729,8 +729,8 @@ PreferencesDialog.languages.default = Valeur syst\u00E8me par d\u00E9faut PreferencesDialog.lbl.language = Langue du programme: PreferencesDialog.lbl.languageEffect = La langue sera chang\u00E9e apr\u00E8s avoir red\u00E9marr\u00E9 OpenRocket. -PresetModel.lbl.nopreset = Aucune pr\u00E9s\u00E9lection -PresetModel.lbl.selectpreset = Choisir une pi\u00E8ce pr\u00E9d\u00E9finie: +PresetModel.lbl.custompreset = Personnalisé +PresetModel.lbl.partsLib = Biblioth\u00E8que de pi\u00E8ces PrintDialog.but.previewAndPrint = Pr\u00E9-visualiser et imprimer PrintDialog.checkbox.showByStage = Montrer par \u00E9tage diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index 06791b98b..a9606aeaf 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -1651,8 +1651,8 @@ CustomFinImport.error.badimage = Non riesco a capire la forma della pinna dall CustomFinImport.description = L'immagine sar\u00e0 convertita in bianco e nero internamente (nero per le pinne), cos\u00ec assicurati di usare un nero pieno per le pinne e bianco, o colore chiaro, per lo sfondo. La pinna ndeve toccare il fondo dell'immagine, che \u00e8 la base della pinna. -PresetModel.lbl.nopreset = Nessuna preimpostazione -PresetModel.lbl.selectpreset = Seleziona precaricati +PresetModel.lbl.custompreset = Personalizzato +PresetModel.lbl.partsLib = Libreria di parti ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index 56b24fd27..96be45859 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -1713,8 +1713,8 @@ CustomFinImport.error.badimage = \u753B\u50CF\u304B\u3089\u30D5\u30A3\u30F3\u5F CustomFinImport.description = \u753B\u50CF\u306F\u5185\u90E8\u3067\u767D\u80CC\u666F\u3068\u9ED2\u7DDA\u306B\u5909\u63DB\u3055\u308C\u307E\u3059\u3002\u306A\u306E\u3067\u30D5\u30A3\u30F3\u306B\u306F\u6697\u3044\u8272\u306E\u5B9F\u7DDA\u3001\u80CC\u666F\u306B\u306F\u767D\u304B\u660E\u308B\u3044\u8272\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D5\u30A3\u30F3\u306F\u753B\u50CF\u306E\u5E95\u9762\u306B\u63A5\u3057\u3066\u3044\u306A\u304F\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3001\u3053\u308C\u306F\u30D5\u30A3\u30F3\u306E\u5E95\u9762\u306B\u306A\u308A\u307E\u3059\u3002 -PresetModel.lbl.nopreset = \u30d7\u30ea\u30bb\u30c3\u30c8\u306a\u3057 -PresetModel.lbl.selectpreset = \u30d7\u30ea\u30bb\u30c3\u30c8\u9078\u629e +PresetModel.lbl.custompreset = \u30ab\u30b9\u30bf\u30e0 +PresetModel.lbl.partsLib = \u30d1\u30fc\u30c4\u30e9\u30a4\u30d6\u30e9\u30ea\u30fc ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index 40f3b18f7..9d773cfb2 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -1967,8 +1967,8 @@ CustomFinImport.error.badimage = Kon de vorm van de vin niet afleiden uit het be CustomFinImport.description = De afbeelding wordt intern geconverteerd naar een zwart-wit afbeelding (zwart voor de vin), dus zorg ervoor dat je een effen donkere kleur gebruikt voor de vin, en wit of een lichte kleur voor de achtergrond. De vin moet de onderkant van het beeld raken, dat is de basis van de vin. -PresetModel.lbl.nopreset = Geen preset -PresetModel.lbl.selectpreset = Selecteer preset +PresetModel.lbl.custompreset = Aangepast +PresetModel.lbl.partsLib = Onderdelenbibliotheek DecalModel.lbl.select = DecalModel.lbl.choose = Van bestand... diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index 84dee7a9f..90242113a 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -1592,8 +1592,8 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s. CustomFinImport.description = Obraz zostanie automatycznie zamieniony na czarno-bia\u0142y (statecznik w kolorze czarnym), wi\u0119c upewnij si\u0119, \u017Ce kszta\u0142t statecznika jest wype\u0142niony ciemnym kolorem, a t\u0142o jest bia\u0142e lub jasne. Podstawa statecznika musi przylega\u0107 do dolnej kraw\u0119dzi obrazu. - PresetModel.lbl.nopreset = Brak ustawienia - PresetModel.lbl.selectpreset = Wybierz ustawienia + PresetModel.lbl.custompreset = Niestandardowe + PresetModel.lbl.partsLib = Biblioteka cz??ci ! Component Preset Chooser Dialog diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index 229032f76..a26717bb5 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -715,8 +715,8 @@ PreferencesDialog.languages.default = Padr\u00e3o do sistema PreferencesDialog.lbl.language = Idioma da interface: PreferencesDialog.lbl.languageEffect = A linguagem vai mudar na pr\u00f3xima vez que voc\u00ea iniciar o OpenRocket. -PresetModel.lbl.nopreset = Sem pr\u00e9-definidos -PresetModel.lbl.selectpreset = Selecione ajustes pr\u00e9-definidos +PresetModel.lbl.custompreset = Personalizado +PresetModel.lbl.partsLib = Biblioteca de pe\u00e7as PrintDialog.but.previewAndPrint = Visualiza\u00e7\u00e3o e impress\u00e3o PrintDialog.checkbox.showByStage = Mostrar por est\u00e1gio diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index 7a3978031..9cc8687a2 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -2075,8 +2075,8 @@ CustomFinImport.error.badimage = \u041D\u0435\u0432\u043E\u0437\u043C\u043E\u043 CustomFinImport.description = \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u0447\u0435\u0440\u043D\u043E-\u0431\u0435\u043B\u043E\u0435 (\u0433\u0434\u0435 \u0447\u0435\u0440\u043D\u044B\u0439 - \u0446\u0432\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430), \u0442\u0430\u043A \u0447\u0442\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u0447\u0435\u0440\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0434\u043B\u044F \u0440\u0438\u0441\u0443\u043D\u043A\u0430 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430 \u0438 \u0431\u0435\u043B\u044B\u0439 \u0438\u043B\u0438 \u0441\u0432\u0435\u0442\u043B\u044B\u0439 \u0446\u0432\u0435\u0442 \u0434\u043B\u044F \u0444\u043E\u043D\u0430. \u041E\u0441\u043D\u043E\u0432\u0430\u043D\u0438\u0435 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430 \u0434\u043E\u043B\u0436\u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441\u043D\u0438\u0437\u0443 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F. -PresetModel.lbl.nopreset = \u041d\u0435\u0442\u0020\u043f\u0440\u0435\u0434\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 -PresetModel.lbl.selectpreset = \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u0430\u0433\u043E\u0442\u043E\u0432\u043A\u0443 +PresetModel.lbl.custompreset = \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0020\u0434\u0435\u0442\u0430\u043b\u0435\u0439 +PresetModel.lbl.partsLib = \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0020\u0434\u0435\u0442\u0430\u043b\u0435\u0439 DecalModel.lbl.select = <\u043D\u0435\u0442> DecalModel.lbl.choose = \u0418\u0437 \u0444\u0430\u0439\u043B\u0430... diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 10846074b..fbe608262 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -1812,8 +1812,8 @@ CustomFinImport.error.badimage = Could not deduce fin shape from image. CustomFinImport.description = The image will be converted internally to black and white image (black for the fin), so make sure you use a solid dark color for the fin, and white or a light color for the background. The fin must be touching the bottom of the image, which is the base of the fin. -PresetModel.lbl.nopreset = No preset -PresetModel.lbl.selectpreset = Select preset +PresetModel.lbl.custompreset = Custom +PresetModel.lbl.partsLib = Parts Library DecalModel.lbl.select = DecalModel.lbl.choose = From file... diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 804bc7ac9..cdd6bcd3f 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -803,8 +803,8 @@ PreferencesDialog.languages.default = \u7CFB\u7EDF\u9ED8\u8BA4 PreferencesDialog.lbl.language = \u754C\u9762\u8BED\u8A00: PreferencesDialog.lbl.languageEffect = \u8BED\u8A00\u8BBE\u7F6E\u5C06\u5728OpenRocket\u91CD\u542F\u540E\u751F\u6548 -PresetModel.lbl.nopreset = \u6ca1\u6709\u9884\u8bbe -PresetModel.lbl.selectpreset = \u9009\u62E9\u9884\u8BBE +PresetModel.lbl.custompreset = \u5b9a\u5236 +PresetModel.lbl.partsLib = \u96f6\u4ef6\u5e93 PrintDialog.but.previewAndPrint = \u9884\u89C8 & \u6253\u5370 PrintDialog.checkbox.showByStage = \u6309\u7EA7\u663E\u793A diff --git a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java index 59f017e03..f47c57b1e 100644 --- a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java +++ b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java @@ -5,16 +5,13 @@ import java.util.List; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; -import javax.swing.SwingUtilities; -import net.sf.openrocket.database.ComponentPresetDatabase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.openrocket.database.Database; import net.sf.openrocket.database.DatabaseListener; import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.gui.dialogs.preset.ComponentPresetChooserDialog; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.logging.Markers; import net.sf.openrocket.preset.ComponentPreset; @@ -29,7 +26,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com private static final Logger log = LoggerFactory.getLogger(PresetModel.class); private static final Translator trans = Application.getTranslator(); - private static final String NONE_SELECTED = String.format("%s", trans.get("lbl.nopreset")); + private static final String NONE_SELECTED = String.format("%s", trans.get("PresetModel.lbl.custompreset")); private final Component parent; private final RocketComponent component; diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 16e659976..88760b6a6 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -26,7 +26,6 @@ import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.database.ComponentPresetDatabase; -import net.sf.openrocket.database.DatabaseListener; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; @@ -121,10 +120,11 @@ public class RocketComponentConfig extends JPanel { presetComboBox = new JComboBox(presetModel); presetComboBox.setMaximumRowCount(25); presetComboBox.setEditable(false); + presetComboBox.setToolTipText(trans.get("PresetModel.combo.ttip")); this.add(presetComboBox); - JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.selectpreset")); - selectPreset.setToolTipText(trans.get("PresetModel.lbl.selectpreset.ttip")); + JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.partsLib")); + selectPreset.setToolTipText(trans.get("PresetModel.lbl.partsLib.ttip")); selectPreset.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { From b938237f0c219af47e65a30b169968df87bd2529 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 4 Jul 2022 23:31:31 +0200 Subject: [PATCH 28/47] Resolve merge conflict --- swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java index f47c57b1e..55559d7b7 100644 --- a/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java +++ b/swing/src/net/sf/openrocket/gui/adaptors/PresetModel.java @@ -9,6 +9,7 @@ import javax.swing.ComboBoxModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.sf.openrocket.gui.configdialog.RocketComponentConfig; import net.sf.openrocket.database.Database; import net.sf.openrocket.database.DatabaseListener; import net.sf.openrocket.document.OpenRocketDocument; From 08b76e0b7e82756f7d9aec39780894a9c3f37d8a Mon Sep 17 00:00:00 2001 From: thzero Date: Mon, 4 Jul 2022 16:36:57 -0500 Subject: [PATCH 29/47] XMLReaderFactory.createXMLReader Deprecation (#1493) * remove the resources\datafiles\presets folder as its is being built by the copy-orc-files build script * Refactored from new Boolean and new Integer to Boolean.valueOf and Integer.valueOf due to deprecation warnings. Value of is supported in Java 8 (https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html) * Removed non-atomic updates around deprecation * updates * sync * resolved deprecated xmlreader --- .../openrocket/file/simplesax/SimpleSAX.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/core/src/net/sf/openrocket/file/simplesax/SimpleSAX.java b/core/src/net/sf/openrocket/file/simplesax/SimpleSAX.java index 2053d42e2..cc1fc55f6 100644 --- a/core/src/net/sf/openrocket/file/simplesax/SimpleSAX.java +++ b/core/src/net/sf/openrocket/file/simplesax/SimpleSAX.java @@ -11,6 +11,9 @@ import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; /** * A "simple SAX" XML reader. This system imposes the limit that an XML element may @@ -18,27 +21,26 @@ import org.xml.sax.helpers.XMLReaderFactory; * both. This holds true for both the OpenRocket and RockSim design formats and the * RockSim engine definition format. *

- * The actual handling is performed by subclasses of {@link ElementHandler}. The + * The actual handling is performed by subclasses of {@link ElementHandler}. The * initial handler is provided to the {@link #readXML(InputSource, ElementHandler, WarningSet)} * method. - * + * * @author Sampo Niskanen */ public class SimpleSAX { - static final XMLReaderCache cache = new XMLReaderCache(10); /** * Read a simple XML file. - * + * * @param source the SAX input source. * @param initialHandler the initial content handler. * @param warnings a warning set to store warning (cannot be null). * @throws IOException if an I/O exception occurs while reading. * @throws SAXException if e.g. malformed XML is encountered. */ - public static void readXML(InputSource source, ElementHandler initialHandler, - WarningSet warnings) throws IOException, SAXException { + public static void readXML(InputSource source, ElementHandler initialHandler, WarningSet warnings) + throws IOException, SAXException { DelegatorHandler xmlhandler = new DelegatorHandler(initialHandler, warnings); @@ -55,17 +57,27 @@ public class SimpleSAX { } private static class XMLReaderCache { + private final SAXParserFactory parserFactory; private final BlockingQueue queue; + private XMLReaderCache( int maxSize ) { - this.queue = new LinkedBlockingQueue(maxSize); + parserFactory = SAXParserFactory.newInstance(); + parserFactory.setNamespaceAware(true); + queue = new LinkedBlockingQueue(maxSize); } private XMLReader createXMLReader() throws SAXException { - XMLReader reader = queue.poll(); if ( reader == null ) { + try { reader = XMLReaderFactory.createXMLReader(); + SAXParser parser = parserFactory.newSAXParser(); + reader = parser.getXMLReader(); + } + catch (ParserConfigurationException ignore) { + System.out.print(ignore); + } } return reader; } @@ -77,5 +89,4 @@ public class SimpleSAX { queue.offer( reader ); } } - } From fe4d1ea62cf8bb9033a682d33f38a0f2b89f98b9 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 5 Jul 2022 00:12:13 +0200 Subject: [PATCH 30/47] [#1513] Combine 'Add component' and 'Modify new component' undo action --- .../configdialog/ComponentConfigDialog.java | 25 +++++++++++++++---- .../gui/main/ComponentAddButtons.java | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java index 3566cf3e9..c244e4ccd 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java @@ -230,8 +230,9 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis * @param document the document to configure. * @param component the component to configure. * @param rememberPreviousTab if true, the previous tab will be remembered and used for the new dialog + * @param includeUndoModify if true, include a 'Modify component' undo action */ - public static void showDialog(Window parent, OpenRocketDocument document, RocketComponent component, boolean rememberPreviousTab) { + public static void showDialog(Window parent, OpenRocketDocument document, RocketComponent component, boolean rememberPreviousTab, boolean includeUndoModify) { if (dialog != null) { // Don't remember the previous tab for rockets or stages, because this will leave you in the override tab for // the next component, which is generally not what you want. @@ -258,13 +259,27 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis dialog.setVisible(true); ////Modify - if (component.getConfigListeners().size() == 0) { - document.addUndoPosition(trans.get("ComponentCfgDlg.Modify") + " " + component.getComponentName()); - } else { - document.addUndoPosition(trans.get("ComponentCfgDlg.ModifyComponents")); + if (includeUndoModify) { + if (component.getConfigListeners().size() == 0) { + document.addUndoPosition(trans.get("ComponentCfgDlg.Modify") + " " + component.getComponentName()); + } else { + document.addUndoPosition(trans.get("ComponentCfgDlg.ModifyComponents")); + } } } + /** + * A singleton configuration dialog. Will create and show a new dialog if one has not + * previously been used, or update the dialog and show it if a previous one exists. + * + * @param document the document to configure. + * @param component the component to configure. + * @param rememberPreviousTab if true, the previous tab will be remembered and used for the new dialog + */ + public static void showDialog(Window parent, OpenRocketDocument document, RocketComponent component, boolean rememberPreviousTab) { + ComponentConfigDialog.showDialog(parent, document, component, rememberPreviousTab, true); + } + /** * A singleton configuration dialog. Will create and show a new dialog if one has not * previously been used, or update the dialog and show it if a previous one exists. diff --git a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java index 8ed2338c9..0ff03e261 100644 --- a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java +++ b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java @@ -488,7 +488,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable { } } - ComponentConfigDialog.showDialog(parent, document, component, false); + ComponentConfigDialog.showDialog(parent, document, component, false, false); } } From 78df43569a4d76bfcee65d0ff0e6b03ae8ed6e70 Mon Sep 17 00:00:00 2001 From: thzero Date: Mon, 4 Jul 2022 17:23:03 -0500 Subject: [PATCH 31/47] refactor to remove deprecation warning for newInstance --- core/src/net/sf/openrocket/document/Simulation.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/net/sf/openrocket/document/Simulation.java b/core/src/net/sf/openrocket/document/Simulation.java index 50047e07f..3143eb83d 100644 --- a/core/src/net/sf/openrocket/document/Simulation.java +++ b/core/src/net/sf/openrocket/document/Simulation.java @@ -1,5 +1,6 @@ package net.sf.openrocket.document; +import java.lang.reflect.InvocationTargetException; import java.util.EventListener; import java.util.EventObject; import java.util.List; @@ -350,13 +351,15 @@ public class Simulation implements ChangeSource, Cloneable { SimulationEngine simulator; try { - simulator = simulationEngineClass.newInstance(); + simulator = simulationEngineClass.getConstructor().newInstance(); } catch (InstantiationException e) { throw new IllegalStateException("Cannot instantiate simulator.", e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot access simulator instance?! BUG!", e); + } catch (InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); } - + SimulationConditions simulationConditions = options.toSimulationConditions(); simulationConditions.setSimulation(this); for (SimulationListener l : additionalListeners) { From 40fa6358f408e54a9d452be05a2a2d959550b479 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 11 Jul 2022 18:07:39 +0200 Subject: [PATCH 32/47] Fix label cut off? --- .../sf/openrocket/gui/configdialog/RocketComponentConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index a5c91a1ac..216253b9a 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -122,7 +122,7 @@ public class RocketComponentConfig extends JPanel { presetComboBox.setMaximumRowCount(25); presetComboBox.setEditable(false); presetComboBox.setToolTipText(trans.get("PresetModel.combo.ttip")); - this.add(presetComboBox); + this.add(presetComboBox, "growx 110"); JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.partsLib")); selectPreset.setToolTipText(trans.get("PresetModel.lbl.partsLib.ttip")); From a4b13a7ee3a41798bd34a0a6806a4d3c5cfac256 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 01:21:48 +0200 Subject: [PATCH 33/47] Only reset edit dialog position at startup --- .../configdialog/ComponentConfigDialog.java | 5 +- .../sf/openrocket/gui/main/BasicFrame.java | 51 +++++++++++++------ .../gui/main/MRUDesignFileAction.java | 2 +- .../sf/openrocket/startup/SwingStartup.java | 5 +- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java index efd9cc02a..c8a417c34 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ComponentConfigDialog.java @@ -15,6 +15,7 @@ import java.util.List; import javax.swing.JDialog; import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.gui.main.BasicFrame; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.WindowLocationUtil; @@ -261,7 +262,9 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis dialog = new ComponentConfigDialog(parent, document, component); dialog.setVisible(true); - WindowLocationUtil.moveIfOutsideOfParentMonitor(dialog, parent); + if (parent instanceof BasicFrame && BasicFrame.getStartupFrame() == parent) { + WindowLocationUtil.moveIfOutsideOfParentMonitor(dialog, parent); + } ////Modify if (component.getConfigListeners().size() == 0) { diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index d99ba0fea..f36fcd6c1 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -116,6 +116,7 @@ public class BasicFrame extends JFrame { * it is time to exit the application. */ private static final ArrayList frames = new ArrayList(); + private static BasicFrame startupFrame = null; // the frame that was created at startup /** @@ -1200,6 +1201,19 @@ public class BasicFrame extends JFrame { return menu; } + /** + * Return the frame that was created at the application's startup. + */ + public static BasicFrame getStartupFrame() { + return startupFrame; + } + + /** + * Set the frame that is created at the application's startup. + */ + public static void setStartupFrame(BasicFrame startupFrame) { + BasicFrame.startupFrame = startupFrame; + } /** * Select the tab on the main pane. @@ -1242,7 +1256,7 @@ public class BasicFrame extends JFrame { for (File file : files) { log.info("Opening file: " + file); - if (open(file, parent)) { + if (open(file, parent) != null) { MRUDesignFile opts = MRUDesignFile.getInstance(); opts.addFile(file.getAbsolutePath()); } @@ -1272,7 +1286,7 @@ public class BasicFrame extends JFrame { for (File file : files) { log.info("Opening file: " + file); - if (open(file, this)) { + if (open(file, this) != null) { MRUDesignFile opts = MRUDesignFile.getInstance(); opts.addFile(file.getAbsolutePath()); } @@ -1342,9 +1356,9 @@ public class BasicFrame extends JFrame { * * @param file the file to open. * @param parent the parent component for which a progress dialog is opened. - * @return whether the file was successfully loaded and opened. + * @return the BasicFrame that was created, or null if not created successfully. */ - public static boolean open(File file, Window parent) { + public static BasicFrame open(File file, Window parent) { OpenFileWorker worker = new OpenFileWorker(file); return open(worker, file.getName(), parent, false); } @@ -1357,15 +1371,15 @@ public class BasicFrame extends JFrame { * @param displayName the file name to display in dialogs. * @param parent * @param openRocketConfigDialog if true, will open the configuration dialog of the rocket. This is useful for examples. - * @return + * @return the BasicFrame that was created, or null if not created successfully. */ - private static boolean open(OpenFileWorker worker, String displayName, Window parent, boolean openRocketConfigDialog) { + private static BasicFrame open(OpenFileWorker worker, String displayName, Window parent, boolean openRocketConfigDialog) { //// Open the file in a Swing worker thread log.info("Starting OpenFileWorker"); if (!SwingWorkerDialog.runWorker(parent, "Opening file", "Reading " + displayName + "...", worker)) { // // User cancelled the operation log.info("User cancelled the OpenFileWorker"); - return false; + return null; } //// Handle the document @@ -1384,7 +1398,7 @@ public class BasicFrame extends JFrame { JOptionPane.showMessageDialog(parent, "File not found: " + displayName, "Error opening file", JOptionPane.ERROR_MESSAGE); - return false; + return null; } else if (cause instanceof RocketLoadException) { @@ -1393,7 +1407,7 @@ public class BasicFrame extends JFrame { "Unable to open file '" + displayName + "': " + cause.getMessage(), "Error opening file", JOptionPane.ERROR_MESSAGE); - return false; + return null; } else { @@ -1437,7 +1451,7 @@ public class BasicFrame extends JFrame { ComponentConfigDialog.showDialog(frame, doc, doc.getRocket()); } - return true; + return frame; } @@ -1743,24 +1757,27 @@ public class BasicFrame extends JFrame { /** * Opens a new design file or the last design file, if set in the preferences. * Can be used for reopening the application or opening it the first time. + * @return the BasicFrame that was created */ - public static void reopen() { + public static BasicFrame reopen() { if (!Application.getPreferences().isAutoOpenLastDesignOnStartupEnabled()) { - BasicFrame.newAction(); + return BasicFrame.newAction(); } else { String lastFile = MRUDesignFile.getInstance().getLastEditedDesignFile(); if (lastFile != null) { log.info("Opening last design file: " + lastFile); - if (!BasicFrame.open(new File(lastFile), null)) { + BasicFrame frame = BasicFrame.open(new File(lastFile), null); + if (frame == null) { MRUDesignFile.getInstance().removeFile(lastFile); - BasicFrame.newAction(); + return BasicFrame.newAction(); } else { MRUDesignFile.getInstance().addFile(lastFile); + return frame; } } else { - BasicFrame.newAction(); + return BasicFrame.newAction(); } } } @@ -1768,8 +1785,9 @@ public class BasicFrame extends JFrame { /** * Open a new design window with a basic rocket+stage. + * @return the BasicFrame that was created */ - public static void newAction() { + public static BasicFrame newAction() { log.info("New action initiated"); OpenRocketDocument doc = OpenRocketDocumentFactory.createNewRocket(); @@ -1777,6 +1795,7 @@ public class BasicFrame extends JFrame { BasicFrame frame = new BasicFrame(doc); frame.replaceable = true; frame.setVisible(true); + return frame; } diff --git a/swing/src/net/sf/openrocket/gui/main/MRUDesignFileAction.java b/swing/src/net/sf/openrocket/gui/main/MRUDesignFileAction.java index 5582e4fca..3ff152d82 100644 --- a/swing/src/net/sf/openrocket/gui/main/MRUDesignFileAction.java +++ b/swing/src/net/sf/openrocket/gui/main/MRUDesignFileAction.java @@ -73,7 +73,7 @@ public final class MRUDesignFileAction extends JMenu { @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); - if (BasicFrame.open(new File(command), parent)) { + if (BasicFrame.open(new File(command), parent) != null) { MRUDesignFile.getInstance().addFile(command); } else { diff --git a/swing/src/net/sf/openrocket/startup/SwingStartup.java b/swing/src/net/sf/openrocket/startup/SwingStartup.java index 5d6ff3386..462549e11 100644 --- a/swing/src/net/sf/openrocket/startup/SwingStartup.java +++ b/swing/src/net/sf/openrocket/startup/SwingStartup.java @@ -223,7 +223,8 @@ public class SwingStartup { // Starting action (load files or open new document) log.info("Opening main application window"); if (!handleCommandLine(args)) { - BasicFrame.reopen(); + BasicFrame startupFrame = BasicFrame.reopen(); + BasicFrame.setStartupFrame(startupFrame); } // Check whether update info has been fetched or whether it needs more time @@ -298,7 +299,7 @@ public class SwingStartup { // Check command-line for files boolean opened = false; for (String file : args) { - if (BasicFrame.open(new File(file), null)) { + if (BasicFrame.open(new File(file), null) != null) { opened = true; } } From 452c6e222a4c51f36136b59d3e616753235d8924 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 02:24:03 +0200 Subject: [PATCH 34/47] Fix #1518 --- .../sf/openrocket/gui/configdialog/RocketComponentConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 216253b9a..59628c5ac 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -124,7 +124,7 @@ public class RocketComponentConfig extends JPanel { presetComboBox.setToolTipText(trans.get("PresetModel.combo.ttip")); this.add(presetComboBox, "growx 110"); - JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.partsLib")); + final JButton selectPreset = new SelectColorButton(trans.get("PresetModel.lbl.partsLib")); selectPreset.setToolTipText(trans.get("PresetModel.lbl.partsLib.ttip")); selectPreset.addActionListener(new ActionListener() { @Override @@ -268,7 +268,7 @@ public class RocketComponentConfig extends JPanel { dialog.setVisible(true); ComponentPreset preset = dialog.getSelectedComponentPreset(); if (preset != null) { - presetComboBox.setSelectedItem(preset); + presetModel.setSelectedItem(preset); } ((ComponentPresetDatabase) Application.getComponentPresetDao()).removeChangeListener(presetModel); } From 25342698c4c7b70d998a09c06ba3187683846a0d Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 12:32:17 +0200 Subject: [PATCH 35/47] Fix smoke opacity not updating --- .../src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java | 1 + 1 file changed, 1 insertion(+) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java index eca18a495..4d1e01288 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java @@ -278,5 +278,6 @@ public class PhotoSettings extends AbstractChangeSource implements FlameSettings public void setSmokeOpacity(double smokeOpacity) { this.smokeOpacity = smokeOpacity; + setSmokeAlpha(smokeOpacity); } } \ No newline at end of file From 8f50376797e7afca8f389db9c2de1fecf6fc10a6 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 12:33:24 +0200 Subject: [PATCH 36/47] Default spark concentration to 20% --- .../src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java index 4d1e01288..23599f7f3 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettings.java @@ -36,7 +36,7 @@ public class PhotoSettings extends AbstractChangeSource implements FlameSettings private double exhaustScale = 1.0; private double flameAspectRatio = 1.0; - private double sparkConcentration = 0; + private double sparkConcentration = 0.2; private double sparkWeight = 0; private Sky sky = Mountains.instance; From 74d21bfa3c1a0543a482282d99745e6f4e9a2066 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 13:00:09 +0200 Subject: [PATCH 37/47] [#1524] Add sliders to PhotoStudio --- .../sf/openrocket/rocketcomponent/Rocket.java | 5 + .../rocketcomponent/RocketComponent.java | 2 +- .../gui/figure3d/photo/PhotoFrame.java | 2 +- .../figure3d/photo/PhotoSettingsConfig.java | 99 +++++++++++++------ 4 files changed, 75 insertions(+), 33 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 5411440f7..81e4d8bc7 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -287,6 +287,11 @@ public class Rocket extends ComponentAssembly { refType = type; fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } + + @Override + public double getLength() { + return selectedConfiguration.getLength(); + } public double getCustomReferenceLength() { diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 23a954e70..637d01465 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -1010,7 +1010,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * If the length of a component is settable, the class must define the setter method * itself. */ - public final double getLength() { + public double getLength() { mutex.verify(); return length; } diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java index 2030dba2b..3ce2cd3cc 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java @@ -108,7 +108,7 @@ public class PhotoFrame extends JFrame { settings = new JDialog(this, trans.get("PhotoSettingsConfig.title")) { { - setContentPane(new PhotoSettingsConfig(p)); + setContentPane(new PhotoSettingsConfig(p, document)); pack(); this.setLocationByPlatform(true); GUIUtil.rememberWindowSize(this); 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 6294a6e96..ef27b0dc4 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java @@ -25,8 +25,10 @@ import javax.swing.event.ChangeListener; import com.jogamp.opengl.GL2; import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.ColorIcon; import net.sf.openrocket.gui.components.EditableSpinner; import net.sf.openrocket.gui.components.StyledLabel; @@ -125,7 +127,7 @@ public class PhotoSettingsConfig extends JTabbedPane { } } - public PhotoSettingsConfig(PhotoSettings p) { + public PhotoSettingsConfig(PhotoSettings p, OpenRocketDocument document) { super(); setPreferredSize(new Dimension(240, 320)); @@ -170,25 +172,29 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.pitch"))); DoubleModel pitchModel = new DoubleModel(p, "Pitch", UnitGroup.UNITS_ANGLE); add(new EditableSpinner(pitchModel.getSpinnerModel()), "growx"); - add(new UnitSelector(pitchModel), "pushx, left, wrap"); + add(new UnitSelector(pitchModel), "growx"); + add(new BasicSlider(pitchModel.getSliderModel(0, 2 * Math.PI)), "pushx, left, wrap"); /// Yaw add(new JLabel(trans.get("PhotoSettingsConfig.lbl.yaw"))); DoubleModel yawModel = new DoubleModel(p, "Yaw", UnitGroup.UNITS_ANGLE); add(new EditableSpinner(yawModel.getSpinnerModel()), "growx"); - add(new UnitSelector(yawModel), "wrap"); + add(new UnitSelector(yawModel), "growx"); + add(new BasicSlider(yawModel.getSliderModel(0, 2 * Math.PI)), "wrap"); /// Roll add(new JLabel(trans.get("PhotoSettingsConfig.lbl.roll"))); DoubleModel rollModel = new DoubleModel(p, "Roll", UnitGroup.UNITS_ANGLE); add(new EditableSpinner(rollModel.getSpinnerModel()), "growx"); - add(new UnitSelector(rollModel), "wrap"); + add(new UnitSelector(rollModel), "growx"); + add(new BasicSlider(rollModel.getSliderModel(0, 2 * Math.PI)), "wrap"); /// Advance add(new JLabel(trans.get("PhotoSettingsConfig.lbl.advance"))); DoubleModel advanceModel = new DoubleModel(p, "Advance", UnitGroup.UNITS_LENGTH); add(new EditableSpinner(advanceModel.getSpinnerModel()), "growx"); - add(new UnitSelector(advanceModel), "wrap"); + add(new UnitSelector(advanceModel), "growx"); + add(new BasicSlider(advanceModel.getSliderModel(-document.getRocket().getLength(), document.getRocket().getLength())), "wrap"); // Camera add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.camera"), Style.BOLD), "split, gapright para, span"); @@ -198,25 +204,29 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAz"))); DoubleModel viewAzModel = new DoubleModel(p, "ViewAz", UnitGroup.UNITS_ANGLE); add(new EditableSpinner(viewAzModel.getSpinnerModel()), "growx"); - add(new UnitSelector(viewAzModel), "wrap"); + add(new UnitSelector(viewAzModel), "growx"); + add(new BasicSlider(viewAzModel.getSliderModel(0, 2 * Math.PI)), "wrap"); /// View altitude add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAlt"))); - DoubleModel viewAltModle = new DoubleModel(p, "ViewAlt", UnitGroup.UNITS_ANGLE); + DoubleModel viewAltModle = new DoubleModel(p, "ViewAlt", UnitGroup.UNITS_ANGLE, -Math.PI / 2, Math.PI / 2); add(new EditableSpinner(viewAltModle.getSpinnerModel()), "growx"); - add(new UnitSelector(viewAltModle), "wrap"); + add(new UnitSelector(viewAltModle), "growx"); + add(new BasicSlider(viewAltModle.getSliderModel(-Math.PI / 2, Math.PI / 2)), "wrap"); /// View distance add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vDist"))); DoubleModel viewDistanceModel = new DoubleModel(p, "ViewDistance", UnitGroup.UNITS_LENGTH); add(new EditableSpinner(viewDistanceModel.getSpinnerModel()), "growx"); - add(new UnitSelector(viewDistanceModel), "wrap"); + add(new UnitSelector(viewDistanceModel), "growx"); + add(new BasicSlider(viewDistanceModel.getSliderModel(0, 2 * document.getRocket().getLength())), "wrap"); /// FoV add(new JLabel(trans.get("PhotoSettingsConfig.lbl.fov"))); - DoubleModel fovModel = new DoubleModel(p, "Fov", UnitGroup.UNITS_ANGLE); + DoubleModel fovModel = new DoubleModel(p, "Fov", UnitGroup.UNITS_ANGLE, Math.PI * 57.3/180, Math.PI * 160/180); add(new EditableSpinner(fovModel.getSpinnerModel()), "growx"); - add(new UnitSelector(fovModel), "wrap"); + add(new UnitSelector(fovModel), "growx"); + add(new BasicSlider(fovModel.getSliderModel(Math.PI * 57.3/180, Math.PI * 160/180)), "wrap"); } }); @@ -232,19 +242,24 @@ public class PhotoSettingsConfig extends JTabbedPane { /// Ambiance add(new JLabel(trans.get("PhotoSettingsConfig.lbl.amb"))); - DoubleModel ambianceModel = new DoubleModel(p, "Ambiance", 100, UnitGroup.UNITS_NONE, 0, 100); - add(new EditableSpinner(ambianceModel.getSpinnerModel()), "wrap"); + DoubleModel ambianceModel = new DoubleModel(p, "Ambiance", UnitGroup.UNITS_RELATIVE, 0, 1); + add(new EditableSpinner(ambianceModel.getSpinnerModel()), "growx, split 2"); + add(new UnitSelector(ambianceModel)); + add(new BasicSlider(ambianceModel.getSliderModel(0, 1)), "pushx, left, wrap"); /// Light azimuth add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAz"))); DoubleModel lightAzModel = new DoubleModel(p, "LightAz", UnitGroup.UNITS_ANGLE); - add(new EditableSpinner(lightAzModel.getSpinnerModel()), "split 2"); - add(new UnitSelector(lightAzModel), "pushx, left, wrap"); + add(new EditableSpinner(lightAzModel.getSpinnerModel()), "growx, split 2"); + add(new UnitSelector(lightAzModel)); + add(new BasicSlider(lightAzModel.getSliderModel(-Math.PI, Math.PI)), "wrap"); /// Light altitude add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAlt"))); - DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE); - add(new EditableSpinner(lightAltModle.getSpinnerModel()), "wrap"); + DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE, -Math.PI / 2, Math.PI / 2); + add(new EditableSpinner(lightAltModle.getSpinnerModel()), "growx, split 2"); + add(new UnitSelector(lightAltModle)); + add(new BasicSlider(lightAltModle.getSliderModel(-Math.PI / 2, Math.PI / 2)), "wrap"); // Sky add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.sky"), Style.BOLD), "split, span, gapright para"); @@ -292,7 +307,7 @@ public class PhotoSettingsConfig extends JTabbedPane { setSelectedItem(noSky); } } - }, "wrap"); + }, "spanx, wrap"); /// Image credit final JLabel creditLabel = new JLabel(trans.get("PhotoSettingsConfig.lbl.skyCredit")); @@ -304,7 +319,7 @@ public class PhotoSettingsConfig extends JTabbedPane { credit.setOpaque(false); credit.setFocusable(false); credit.setFont(creditLabel.getFont()); - add(credit); + add(credit, "spanx"); final StateChangeListener skyChange = new StateChangeListener() { @Override @@ -332,22 +347,28 @@ public class PhotoSettingsConfig extends JTabbedPane { /// Smoke add(new JLabel(trans.get("PhotoSettingsConfig.lbl.smoke"))); BooleanModel smokeModel = new BooleanModel(p, "Smoke"); - add(new JCheckBox(smokeModel), "split 2, w 15"); + add(new JCheckBox(smokeModel), "split 2, spanx"); - add(smokeColorButton, "pushx, left, wrap"); + add(smokeColorButton, "wrap"); smokeModel.addEnableComponent(smokeColorButton); /// Smoke opacity add(new JLabel(trans.get("PhotoSettingsConfig.lbl.smokeOpacity"))); - DoubleModel smokeOpacityModel = new DoubleModel(p, "SmokeOpacity", 100, UnitGroup.UNITS_NONE, 0, 100); + DoubleModel smokeOpacityModel = new DoubleModel(p, "SmokeOpacity", UnitGroup.UNITS_RELATIVE, 0, 1); EditableSpinner opacitySpinner = new EditableSpinner(smokeOpacityModel.getSpinnerModel()); - add(opacitySpinner, "wrap"); + UnitSelector opacitySelector = new UnitSelector(smokeOpacityModel); + BasicSlider opacitySlider = new BasicSlider(smokeOpacityModel.getSliderModel(0, 1)); + add(opacitySpinner, "growx"); + add(opacitySelector); + add(opacitySlider, "wrap"); smokeModel.addEnableComponent(opacitySpinner); + smokeModel.addEnableComponent(opacitySelector); + smokeModel.addEnableComponent(opacitySlider); /// Flame add(new JLabel(trans.get("PhotoSettingsConfig.lbl.flame"))); BooleanModel fireModel = new BooleanModel(p, "Flame"); - add(new JCheckBox(fireModel), "split 2, w 15"); + add(new JCheckBox(fireModel), "split 2, spanx"); add(flameColorButton, "wrap"); fireModel.addEnableComponent(flameColorButton); @@ -357,8 +378,11 @@ public class PhotoSettingsConfig extends JTabbedPane { DoubleModel flameAspectModel = new DoubleModel(p, "FlameAspectRatio", 100, UnitGroup.UNITS_NONE, 25, 250); EditableSpinner flameAspectSpinner = new EditableSpinner(flameAspectModel.getSpinnerModel()); - add(flameAspectSpinner, "wrap"); + BasicSlider flameAspectSlider = new BasicSlider(flameAspectModel.getSliderModel(25, 250)); + add(flameAspectSpinner, "growx"); + add(flameAspectSlider, "skip 1, wrap"); fireModel.addEnableComponent(flameAspectSpinner); + fireModel.addEnableComponent(flameAspectSlider); /// Sparks add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparks"))); @@ -369,23 +393,36 @@ public class PhotoSettingsConfig extends JTabbedPane { /// Sparks concentration add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkConcentration"))); - DoubleModel sparkConcentrationModel = new DoubleModel(p, "SparkConcentration", 100, - UnitGroup.UNITS_NONE, 0, 100); + DoubleModel sparkConcentrationModel = new DoubleModel(p, "SparkConcentration", + UnitGroup.UNITS_RELATIVE, 0, 1); EditableSpinner sparkConcentrationSpinner = new EditableSpinner(sparkConcentrationModel.getSpinnerModel()); - add(sparkConcentrationSpinner, "wrap"); + UnitSelector sparkConcentrationSelector = new UnitSelector(sparkConcentrationModel); + BasicSlider sparkConcentrationSlider = new BasicSlider(sparkConcentrationModel.getSliderModel(0, 1)); + add(sparkConcentrationSpinner, "growx"); + add(sparkConcentrationSelector); + add(sparkConcentrationSlider, "wrap"); sparksModel.addEnableComponent(sparkConcentrationSpinner); + sparksModel.addEnableComponent(sparkConcentrationSelector); + sparksModel.addEnableComponent(sparkConcentrationSlider); /// Spark weight add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkWeight"))); - DoubleModel sparkWeightModel = new DoubleModel(p, "SparkWeight", 100, UnitGroup.UNITS_NONE, 0, 100); + DoubleModel sparkWeightModel = new DoubleModel(p, "SparkWeight", UnitGroup.UNITS_RELATIVE, 0, 1); EditableSpinner sparkWeightSpinner = new EditableSpinner(sparkWeightModel.getSpinnerModel()); - add(sparkWeightSpinner, "wrap"); + UnitSelector sparkWeightSelector = new UnitSelector(sparkWeightModel); + BasicSlider sparkWeightSlider = new BasicSlider(sparkWeightModel.getSliderModel(0, 1)); + add(sparkWeightSpinner, "growx"); + add(sparkWeightSelector); + add(sparkWeightSlider, "wrap"); sparksModel.addEnableComponent(sparkWeightSpinner); + sparksModel.addEnableComponent(sparkWeightSelector); + sparksModel.addEnableComponent(sparkWeightSlider); /// Exhaust scale add(new JLabel(trans.get("PhotoSettingsConfig.lbl.exhaustScale"))); DoubleModel exhaustScaleModel = new DoubleModel(p, "ExhaustScale", 100, UnitGroup.UNITS_NONE, 0, 1000); - add(new EditableSpinner(exhaustScaleModel.getSpinnerModel()), "wrap"); + add(new EditableSpinner(exhaustScaleModel.getSpinnerModel()), "growx"); + add(new BasicSlider(exhaustScaleModel.getSliderModel(0, 1000)), "skip 1, wrap"); // Effects add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.effects"), Style.BOLD), "split, span, gapright para"); From b737c6f568d04c97af81f9a3d54ae0db5d944182 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 13:16:59 +0200 Subject: [PATCH 38/47] [#1520] Add check for selection options size --- swing/src/net/sf/openrocket/gui/dialogs/ScaleDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ScaleDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ScaleDialog.java index ad53576e6..3a1db6af8 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/ScaleDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/ScaleDialog.java @@ -346,7 +346,7 @@ public class ScaleDialog extends JDialog { panel.add(selectionOption, "growx, wrap para*2"); // Select the 'scale component / scale selection and all subcomponents' if a component is selected - if (selection != null && selection.size() > 0) { + if (options.size() > 1 && selection != null && selection.size() > 0) { boolean entireRocket = false; // Flag to scale entire rocket for (RocketComponent component : selection) { if (component instanceof Rocket || (component instanceof AxialStage && !(component instanceof ParallelStage))) { From 712adc6dad1cdeb853b9a14648950fc83bb5939f Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 12 Jul 2022 18:58:14 +0200 Subject: [PATCH 39/47] Include javax.json in classpath --- core/.classpath | 2 ++ swing/.classpath | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/.classpath b/core/.classpath index acc55d845..453ab552f 100644 --- a/core/.classpath +++ b/core/.classpath @@ -15,6 +15,8 @@ + + diff --git a/swing/.classpath b/swing/.classpath index 0a33deaf2..7daea48ea 100644 --- a/swing/.classpath +++ b/swing/.classpath @@ -17,6 +17,8 @@ + + From 7136df56350cffd577a158195e195b3c7b330017 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 15 Jul 2022 00:49:04 +0200 Subject: [PATCH 40/47] [#1533] Fix latency of freeform finset shape editor --- .../gui/configdialog/FreeformFinSetConfig.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java index ba6b077da..b695e5dbf 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java @@ -81,6 +81,7 @@ public class FreeformFinSetConfig extends FinSetConfig { private Point dragPoint = null; private FinPointFigure figure = null; + private ScaleScrollPane figurePane = null; private ScaleSelector selector; public FreeformFinSetConfig(OpenRocketDocument d, RocketComponent component, JDialog parent) { @@ -219,7 +220,7 @@ public class FreeformFinSetConfig extends FinSetConfig { // Create the figure figure = new FinPointFigure(finset); - ScaleScrollPane figurePane = new FinPointScrollPane( figure); + figurePane = new FinPointScrollPane( figure); // Create the table tableModel = new FinPointTableModel(); @@ -392,9 +393,10 @@ public class FreeformFinSetConfig extends FinSetConfig { } figure.updateFigure(); } - - revalidate(); - repaint(); + + if (figurePane != null) { + figurePane.revalidate(); + } } private class FinPointScrollPane extends ScaleScrollPane { @@ -408,8 +410,6 @@ public class FreeformFinSetConfig extends FinSetConfig { @Override public void mousePressed(MouseEvent event) { - int mods = event.getModifiersEx(); - final FreeformFinSet finset = (FreeformFinSet) component; final int pressIndex = getPoint(event); From 959bbfaac3f30c7d20ef7127628c878519854c55 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 16 Jul 2022 02:40:12 +0200 Subject: [PATCH 41/47] [#1146] Add 2D visualization for pod sets --- .../sf/openrocket/rocketcomponent/Rocket.java | 11 ++ .../gui/rocketfigure/EmptyShapes.java | 122 ++++++++++++++++++ .../gui/rocketfigure/PodSetShapes.java | 49 +++++++ .../rocketfigure/RocketComponentShape.java | 4 + .../gui/scalefigure/RocketFigure.java | 62 ++++++++- 5 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 swing/src/net/sf/openrocket/gui/rocketfigure/EmptyShapes.java create mode 100644 swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 5411440f7..90fa5a5a7 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -304,6 +304,17 @@ public class Rocket extends ComponentAssembly { fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } } + + @Override + public double getBoundingRadius() { + double bounding = 0; + for (RocketComponent comp : children) { + if (comp instanceof ComponentAssembly) { + bounding = Math.max(bounding, ((ComponentAssembly) comp).getBoundingRadius()); + } + } + return bounding; + } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/EmptyShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/EmptyShapes.java new file mode 100644 index 000000000..35b048551 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/EmptyShapes.java @@ -0,0 +1,122 @@ +package net.sf.openrocket.gui.rocketfigure; + +import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.Transformation; + +import java.awt.Shape; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; + +/** + * Shapes of an "empty"/virtual object, e.g. a podset without any children. + * The shape is a center square with additional lines on the north, east, south and west side of the square. + * + * @author Sibo Van Gool + */ +public class EmptyShapes extends RocketComponentShape { + /** + * Returns the empty shape in the side view. + * @param radius radius of the center square + */ + public static Shape[] getShapesSide(final Transformation transformation, final double radius) { + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + double x = instanceAbsoluteLocation.x; + double y = instanceAbsoluteLocation.y; + + double lineLength = getLineLength(radius); // Length of the line protruding the center square + + final Shape[] s = new Shape[5]; + // Center square + s[0] = new Rectangle2D.Double(x - radius, y - radius, 2 * radius, 2 * radius); + // Line North + s[1] = new Line2D.Double(x, y + radius, x, y + radius + lineLength); + // Line East + s[2] = new Line2D.Double(x + radius, y, x + radius + lineLength, y); + // Line South + s[3] = new Line2D.Double(x, y - radius, x, y - radius - lineLength); + // Line West + s[4] = new Line2D.Double(x - radius, y, x - radius - lineLength, y); + + return s; + } + + /** + * Returns the empty shape in the side view, with an additional square encompassing the shape that can be used + * for selecting the object. + * @param radius radius of the center square + */ + public static Shape[] getShapesSideWithSelectionSquare(final Transformation transformation, final double radius) { + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + double x = instanceAbsoluteLocation.x; + double y = instanceAbsoluteLocation.y; + + double lineLength = getLineLength(radius); // Length of the line protruding the center square + + Shape[] shapes = getShapesSide(transformation, radius); + + // Invisible shape for selecting the component (= a square encompassing the component) + Shape selectionShape = new Rectangle2D.Double(x - radius - lineLength, y - radius - lineLength, + lineLength * 2 + radius * 2, lineLength * 2 + radius * 2); + + Shape[] finalShapes = new Shape[shapes.length + 1]; + System.arraycopy(shapes, 0, finalShapes, 0, shapes.length); + finalShapes[finalShapes.length - 1] = selectionShape; + + return finalShapes; + } + + /** + * Returns the empty shape in the side view. + * @param radius radius of the center square + */ + public static Shape[] getShapesBack(final Transformation transformation, final double radius) { + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + double z = instanceAbsoluteLocation.z; + double y = instanceAbsoluteLocation.y; + + double lineLength = getLineLength(radius); // Length of the line protruding the center square + + final Shape[] s = new Shape[5]; + // Center square + s[0] = new Rectangle2D.Double(z - radius, y - radius, 2 * radius, 2 * radius); + // Line North + s[1] = new Line2D.Double(z, y + radius, z, y + radius + lineLength); + // Line East + s[2] = new Line2D.Double(z + radius, y, z + radius + lineLength, y); + // Line South + s[3] = new Line2D.Double(z, y - radius, z, y - radius - lineLength); + // Line West + s[4] = new Line2D.Double(z - radius, y, z - radius - lineLength, y); + + return s; + } + + /** + * Returns the empty shape in the back view, with an additional square encompassing the shape that can be used + * for selecting the object. + * @param radius radius of the center square + */ + public static Shape[] getShapesBackWithSelectionSquare(final Transformation transformation, final double radius) { + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + double z = instanceAbsoluteLocation.z; + double y = instanceAbsoluteLocation.y; + + double lineLength = getLineLength(radius); // Length of the line protruding the center square + + Shape[] shapes = getShapesBack(transformation, radius); + + // Invisible shape for selecting the component (= a square encompassing the component) + Shape selectionShape = new Rectangle2D.Double(z - radius - lineLength, y - radius - lineLength, + lineLength * 2 + radius * 2, lineLength * 2 + radius * 2); + + Shape[] finalShapes = new Shape[shapes.length + 1]; + System.arraycopy(shapes, 0, finalShapes, 0, shapes.length); + finalShapes[finalShapes.length - 1] = selectionShape; + + return finalShapes; + } + + private static double getLineLength(double radius) { + return radius * 3; + } +} diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java new file mode 100644 index 000000000..27955db60 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java @@ -0,0 +1,49 @@ +package net.sf.openrocket.gui.rocketfigure; + +import net.sf.openrocket.rocketcomponent.PodSet; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.util.Color; +import net.sf.openrocket.util.Transformation; + +import java.awt.Shape; + +public class PodSetShapes extends RocketComponentShape { + public static final Color podsetColor = new Color(160, 160, 160); // Normal color for the podset shape + public static final Color centerColor = new Color(200, 200, 200); // Color for the center shape of the podset + + public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { + PodSet podset = (PodSet)component; + double radius = getDisplayRadius(podset); + + Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(transformation, radius); + RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); + + // Set the color of the shapes + for (int i = 0; i < shapes.length - 1; i++) { + shapes[i].setColor(podsetColor); + } + shapes[shapes.length - 1].setColor(Color.INVISIBLE); + + return shapes; + } + + public static RocketComponentShape[] getShapesBack(final RocketComponent component, final Transformation transformation) { + PodSet podset = (PodSet)component; + double radius = getDisplayRadius(podset); + + Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(transformation, radius); + RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); + + // Set the color of the shapes + for (int i = 0; i < shapes.length - 1; i++) { + shapes[i].setColor(podsetColor); + } + shapes[shapes.length - 1].setColor(Color.INVISIBLE); + + return shapes; + } + + private static double getDisplayRadius(PodSet podset) { + return podset.getRocket().getBoundingRadius() * 0.03; + } +} diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java b/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java index 725713b80..c132bfd3d 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java @@ -64,6 +64,10 @@ public class RocketComponentShape { return new RocketComponentShape[0]; } + public Color getColor() { + return color; + } + public void setColor(Color color) { this.color = color; } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 3226abee2..e9b8f6de0 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -17,6 +17,8 @@ import java.awt.geom.Rectangle2D; import java.util.*; import java.util.Map.Entry; +import net.sf.openrocket.gui.rocketfigure.PodSetShapes; +import net.sf.openrocket.rocketcomponent.PodSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -385,13 +387,38 @@ public class RocketFigure extends AbstractScaleFigure { final Transformation currentTransform = this.axialRotation.applyTransformation(context.transform); allShapes = addThisShape( allShapes, this.currentViewType, comp, currentTransform); } + + // PodSets require an additional shape for the center of the podset. + if (comp instanceof PodSet) { + Transformation parentTransform = null; + for (Entry> entry2: config.getActiveInstances().entrySet()) { + final RocketComponent parent = entry2.getKey(); + if (parent == comp.getParent()) { + parentTransform = entry2.getValue().get(0).transform; // TODO: normally only the first context should be used, unless we start doing fancy stuff like adding pods to individual fins + break; + } + } + if (parentTransform == null) { + parentTransform = Transformation.IDENTITY; + } + + final Transformation compLocTransform = Transformation.getTranslationTransform(comp.getPosition()); + final Transformation componentTransform = parentTransform.applyTransformation(compLocTransform); + + final Transformation currentTransform = this.axialRotation.applyTransformation(componentTransform); + allShapes = addThisShape(allShapes, this.currentViewType, comp, currentTransform, PodSetShapes.centerColor); + } } } /** * Gets the shapes required to draw the component. - * - * @param component + * + * @param allShapes output buffer for the shapes to add to + * @param viewType the view type to draw the component in + * @param component component to draw and add to + * @param transformation transformation to apply to the component before drawing it + * @param color color to draw the component in * * @return the ArrayList containing all the shapes to draw. */ @@ -399,10 +426,11 @@ public class RocketFigure extends AbstractScaleFigure { PriorityQueue allShapes, // this is the output parameter final RocketPanel.VIEW_TYPE viewType, final RocketComponent component, - final Transformation transformation) { + final Transformation transformation, + final net.sf.openrocket.util.Color color) { Reflection.Method m; - if(( component instanceof Rocket)||( component instanceof ComponentAssembly )){ + if(( component instanceof Rocket)||( component instanceof ComponentAssembly && !(component instanceof PodSet))){ // no-op; no shapes here return allShapes; } @@ -431,9 +459,35 @@ public class RocketFigure extends AbstractScaleFigure { RocketComponentShape[] returnValue = (RocketComponentShape[]) m.invokeStatic(component, transformation); + + if (color != null) { + for (RocketComponentShape rcs : returnValue) { + if (rcs.getColor() == net.sf.openrocket.util.Color.INVISIBLE) continue; // don't change the color of invisible (often selection) components + rcs.setColor(color); + } + } + allShapes.addAll(Arrays.asList(returnValue)); return allShapes; } + + /** + * Gets the shapes required to draw the component. + * + * @param allShapes output buffer for the shapes to add to + * @param viewType the view type to draw the component in + * @param component component to draw and add to + * @param transformation transformation to apply to the component before drawing it + * + * @return the ArrayList containing all the shapes to draw. + */ + private static PriorityQueue addThisShape( + PriorityQueue allShapes, // this is the output parameter + final RocketPanel.VIEW_TYPE viewType, + final RocketComponent component, + final Transformation transformation) { + return addThisShape(allShapes, viewType, component, transformation, null); + } /** From a89f1171cccdf7ecad2058267f7971cfa4aa8973 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 16 Jul 2022 13:17:58 +0200 Subject: [PATCH 42/47] Remove podset center marker --- .../gui/rocketfigure/PodSetShapes.java | 1 - .../gui/scalefigure/RocketFigure.java | 21 ------------------- 2 files changed, 22 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java index 27955db60..ebe8641c9 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java @@ -9,7 +9,6 @@ import java.awt.Shape; public class PodSetShapes extends RocketComponentShape { public static final Color podsetColor = new Color(160, 160, 160); // Normal color for the podset shape - public static final Color centerColor = new Color(200, 200, 200); // Color for the center shape of the podset public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { PodSet podset = (PodSet)component; diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index e9b8f6de0..ed4f794b8 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -387,27 +387,6 @@ public class RocketFigure extends AbstractScaleFigure { final Transformation currentTransform = this.axialRotation.applyTransformation(context.transform); allShapes = addThisShape( allShapes, this.currentViewType, comp, currentTransform); } - - // PodSets require an additional shape for the center of the podset. - if (comp instanceof PodSet) { - Transformation parentTransform = null; - for (Entry> entry2: config.getActiveInstances().entrySet()) { - final RocketComponent parent = entry2.getKey(); - if (parent == comp.getParent()) { - parentTransform = entry2.getValue().get(0).transform; // TODO: normally only the first context should be used, unless we start doing fancy stuff like adding pods to individual fins - break; - } - } - if (parentTransform == null) { - parentTransform = Transformation.IDENTITY; - } - - final Transformation compLocTransform = Transformation.getTranslationTransform(comp.getPosition()); - final Transformation componentTransform = parentTransform.applyTransformation(compLocTransform); - - final Transformation currentTransform = this.axialRotation.applyTransformation(componentTransform); - allShapes = addThisShape(allShapes, this.currentViewType, comp, currentTransform, PodSetShapes.centerColor); - } } } From 9c5d1e9e26bc630544fbfe184b3c8fefae6b7b78 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 16 Jul 2022 13:18:10 +0200 Subject: [PATCH 43/47] Only show podset markers when selected --- .../openrocket/gui/scalefigure/RocketFigure.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index ed4f794b8..60f011d9a 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -380,6 +380,21 @@ public class RocketFigure extends AbstractScaleFigure { for(Entry> entry: config.getActiveInstances().entrySet() ) { final RocketComponent comp = entry.getKey(); + + // Only draw podsets when they are selected + if (comp instanceof PodSet) { + boolean selected = false; + + // Check if component is in the selection + for (int j = 0; j < selection.length; j++) { + if (comp == selection[j]) { + selected = true; + break; + } + } + + if (!selected) continue; + } final ArrayList contextList = entry.getValue(); From b479809b62843467e3af9836d88fded840a7f176 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 16 Jul 2022 14:41:14 +0200 Subject: [PATCH 44/47] Add 2D visualization for boosters --- .../gui/rocketfigure/ParallelStageShapes.java | 49 +++++++++++++++++++ .../gui/rocketfigure/PodSetShapes.java | 3 +- .../gui/scalefigure/RocketFigure.java | 13 +++-- 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java new file mode 100644 index 000000000..f8b1f58e4 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java @@ -0,0 +1,49 @@ +package net.sf.openrocket.gui.rocketfigure; + +import net.sf.openrocket.rocketcomponent.ParallelStage; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.util.Color; +import net.sf.openrocket.util.Transformation; + +import java.awt.Shape; + +public class ParallelStageShapes extends RocketComponentShape { + //public static final Color boosterColor = new Color(220, 185, 185); + public static final Color boosterColor = new Color(198,163,184); + + public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { + ParallelStage booster = (ParallelStage)component; + double radius = getDisplayRadius(booster); + + Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(transformation, radius); + RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); + + // Set the color of the shapes + for (int i = 0; i < shapes.length - 1; i++) { + shapes[i].setColor(boosterColor); + } + shapes[shapes.length - 1].setColor(Color.INVISIBLE); + + return shapes; + } + + public static RocketComponentShape[] getShapesBack(final RocketComponent component, final Transformation transformation) { + ParallelStage booster = (ParallelStage)component; + double radius = getDisplayRadius(booster); + + Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(transformation, radius); + RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); + + // Set the color of the shapes + for (int i = 0; i < shapes.length - 1; i++) { + shapes[i].setColor(boosterColor); + } + shapes[shapes.length - 1].setColor(Color.INVISIBLE); + + return shapes; + } + + private static double getDisplayRadius(ParallelStage booster) { + return booster.getRocket().getBoundingRadius() * 0.03; + } +} diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java index ebe8641c9..308e34929 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java @@ -8,7 +8,8 @@ import net.sf.openrocket.util.Transformation; import java.awt.Shape; public class PodSetShapes extends RocketComponentShape { - public static final Color podsetColor = new Color(160, 160, 160); // Normal color for the podset shape + //public static final Color podsetColor = new Color(180, 180, 225); + public static final Color podsetColor = new Color(160,160,215); public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { PodSet podset = (PodSet)component; diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 60f011d9a..39c18e025 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -17,7 +17,8 @@ import java.awt.geom.Rectangle2D; import java.util.*; import java.util.Map.Entry; -import net.sf.openrocket.gui.rocketfigure.PodSetShapes; +import net.sf.openrocket.rocketcomponent.AxialStage; +import net.sf.openrocket.rocketcomponent.ParallelStage; import net.sf.openrocket.rocketcomponent.PodSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,6 @@ import net.sf.openrocket.gui.util.ColorConversion; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; -import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.MotorMount; @@ -382,17 +382,16 @@ public class RocketFigure extends AbstractScaleFigure { final RocketComponent comp = entry.getKey(); // Only draw podsets when they are selected - if (comp instanceof PodSet) { + if (comp instanceof PodSet || comp instanceof ParallelStage) { boolean selected = false; // Check if component is in the selection - for (int j = 0; j < selection.length; j++) { - if (comp == selection[j]) { + for (RocketComponent component : selection) { + if (comp == component) { selected = true; break; } } - if (!selected) continue; } @@ -424,7 +423,7 @@ public class RocketFigure extends AbstractScaleFigure { final net.sf.openrocket.util.Color color) { Reflection.Method m; - if(( component instanceof Rocket)||( component instanceof ComponentAssembly && !(component instanceof PodSet))){ + if ((component instanceof Rocket) || (component instanceof AxialStage && !(component instanceof ParallelStage))){ // no-op; no shapes here return allShapes; } From 391dc37e9ba007a2f03779aca430d4498f613483 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 16 Jul 2022 14:57:58 +0200 Subject: [PATCH 45/47] Remove unwanted colors --- .../net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java | 1 - swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java | 1 - 2 files changed, 2 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java index f8b1f58e4..565a23591 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ParallelStageShapes.java @@ -8,7 +8,6 @@ import net.sf.openrocket.util.Transformation; import java.awt.Shape; public class ParallelStageShapes extends RocketComponentShape { - //public static final Color boosterColor = new Color(220, 185, 185); public static final Color boosterColor = new Color(198,163,184); public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java index 308e34929..7ef928f2d 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/PodSetShapes.java @@ -8,7 +8,6 @@ import net.sf.openrocket.util.Transformation; import java.awt.Shape; public class PodSetShapes extends RocketComponentShape { - //public static final Color podsetColor = new Color(180, 180, 225); public static final Color podsetColor = new Color(160,160,215); public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) { From d0be2e5e07449609f9c2b2e061957d8ef412bc8e Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 18 Jul 2022 00:28:05 +0200 Subject: [PATCH 46/47] Add preference for marker visibility --- core/resources/l10n/messages.properties | 2 ++ .../sf/openrocket/startup/Preferences.java | 22 ++++++++++++++++++- .../preferences/DesignPreferencesPanel.java | 22 +++++++++++++++++-- .../sf/openrocket/gui/main/BasicFrame.java | 13 ++++++++++- .../gui/scalefigure/RocketFigure.java | 3 ++- .../gui/scalefigure/RocketPanel.java | 2 +- 6 files changed, 58 insertions(+), 6 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 7d81f82eb..563738509 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -294,6 +294,8 @@ pref.dlg.lbl.PositiontoinsertStages = Position to insert new stages: pref.dlg.lbl.Confirmdeletion = Confirm deletion of simulations. pref.dlg.checkbox.Runsimulations = Run out-dated simulations when you open the simulation tab. pref.dlg.checkbox.Updateestimates = Update estimated flight parameters in design window +pref.dlg.checkbox.Markers = Only show pod set/booster markers when the pod set/booster is selected +pref.dlg.checkbox.Markers.ttip = If checked, pod set/booster markers will only be shown when the pod set/booster is selected.
If unchecked, pod set/booster markers will always be shown. pref.dlg.checkbox.AlwaysOpenLeftmost = Always open leftmost tab when opening a component edit dialog pref.dlg.checkbox.AlwaysOpenLeftmost.ttip = If checked, a component edit dialog will always pop up with the first tab selected.
If unchecked, the previous selected tab will be used. pref.dlg.lbl.User-definedthrust = User-defined thrust curves: diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 64f1de5a0..3d750c651 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -68,6 +68,7 @@ public abstract class Preferences implements ChangeSource { public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors"; private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN"; private static final String OPEN_LEFTMOST_DESIGN_TAB = "OPEN_LEFTMOST_DESIGN_TAB"; + private static final String SHOW_MARKERS = "SHOW_MARKERS"; private static final String SHOW_ROCKSIM_FORMAT_WARNING = "SHOW_ROCKSIM_FORMAT_WARNING"; //Preferences related to 3D graphics @@ -469,7 +470,26 @@ public abstract class Preferences implements ChangeSource { public final boolean isAlwaysOpenLeftmostTab() { return this.getBoolean(OPEN_LEFTMOST_DESIGN_TAB, false); } - + + /** + * Set whether pod set/booster markers should only be displayed when the pod set/booster is selected. + * @param enabled true if pod set/booster markers should only be displayed when the pod set/booster is selected, + * false if they should be displayed permanently. + */ + public final void setShowMarkers(boolean enabled) { + this.putBoolean(SHOW_MARKERS, enabled); + } + + /** + * Answer if pod set/booster markers should only be displayed when the pod set/booster is selected + * + * @return true if pod set/booster markers should only be displayed when the pod set/booster is selected, + * false if they should be displayed permanently. + */ + public final boolean isShowMarkers() { + return this.getBoolean(SHOW_MARKERS, false); + } + /** * Return the OpenRocket unique ID. * diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/DesignPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/DesignPreferencesPanel.java index 08ef4acb1..3a98bd616 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/DesignPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/DesignPreferencesPanel.java @@ -11,6 +11,7 @@ import javax.swing.JSpinner; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.main.BasicFrame; import net.sf.openrocket.startup.Preferences; import net.sf.openrocket.unit.UnitGroup; @@ -93,7 +94,6 @@ public class DesignPreferencesPanel extends PreferencesPanel { // // Always open leftmost tab when opening a component edit dialog final JCheckBox alwaysOpenLeftmostTab = new JCheckBox( trans.get("pref.dlg.checkbox.AlwaysOpenLeftmost")); - alwaysOpenLeftmostTab.setSelected(preferences.isAlwaysOpenLeftmostTab()); alwaysOpenLeftmostTab.setToolTipText(trans.get("pref.dlg.checkbox.AlwaysOpenLeftmost.ttip")); alwaysOpenLeftmostTab.addActionListener(new ActionListener() { @@ -103,7 +103,7 @@ public class DesignPreferencesPanel extends PreferencesPanel { .isSelected()); } }); - this.add(alwaysOpenLeftmostTab, "wrap, growx, span 2"); + this.add(alwaysOpenLeftmostTab, "wrap, growx, spanx"); // // Update flight estimates in the design window final JCheckBox updateEstimates = new JCheckBox( @@ -117,5 +117,23 @@ public class DesignPreferencesPanel extends PreferencesPanel { } }); this.add(updateEstimates, "wrap, growx, sg combos "); + + // // Only show pod set/booster markers when they are selected + final JCheckBox showMarkers = new JCheckBox( + trans.get("pref.dlg.checkbox.Markers")); + showMarkers.setToolTipText(trans.get("pref.dlg.checkbox.Markers.ttip")); + showMarkers.setSelected(preferences.isShowMarkers()); + showMarkers.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + preferences.setShowMarkers(showMarkers + .isSelected()); + // Update all BasicFrame rocket panel figures because it can change due to the preference change + for (BasicFrame frame : BasicFrame.getAllFrames()) { + frame.getRocketPanel().updateFigures(); + } + } + }); + this.add(showMarkers, "wrap, growx, spanx"); } } diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index 04fdf9bf3..6f76a838d 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -117,7 +117,7 @@ public class BasicFrame extends JFrame { * List of currently open frames. When the list goes empty * it is time to exit the application. */ - private static final ArrayList frames = new ArrayList(); + private static final List frames = new ArrayList(); private static BasicFrame startupFrame = null; // the frame that was created at startup @@ -490,6 +490,10 @@ public class BasicFrame extends JFrame { return result; } + public RocketPanel getRocketPanel() { + return rocketpanel; + } + /** * Creates the menu for the window. */ @@ -1890,6 +1894,13 @@ public class BasicFrame extends JFrame { return null; } + /** + * Return all BasicFrame instances + */ + public static List getAllFrames() { + return frames; + } + /** * Checks whether all the BasicFrames are closed. * @return true if all the BasicFrames are closed, false if not diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 39c18e025..6e4bf9e4b 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -54,6 +54,7 @@ import net.sf.openrocket.util.Transformation; public class RocketFigure extends AbstractScaleFigure { private final static Logger log = LoggerFactory.getLogger(FinPointFigure.class); + protected final SwingPreferences preferences = (SwingPreferences) Application.getPreferences(); private static final String ROCKET_FIGURE_PACKAGE = "net.sf.openrocket.gui.rocketfigure"; private static final String ROCKET_FIGURE_SUFFIX = "Shapes"; @@ -382,7 +383,7 @@ public class RocketFigure extends AbstractScaleFigure { final RocketComponent comp = entry.getKey(); // Only draw podsets when they are selected - if (comp instanceof PodSet || comp instanceof ParallelStage) { + if ((comp instanceof PodSet || comp instanceof ParallelStage) && preferences.isShowMarkers()) { boolean selected = false; // Check if component is in the selection diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 92df95906..9f4f309f7 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -252,7 +252,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change }); } - private void updateFigures() { + public void updateFigures() { if (!is3d) figure.updateFigure(); else From ab7915c998c95ebe769557b81577d5a855a487cc Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 19 Jul 2022 22:49:29 +0200 Subject: [PATCH 47/47] Change generate-orc-files build directory --- swing/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swing/build.xml b/swing/build.xml index dada6c98c..ce705b584 100644 --- a/swing/build.xml +++ b/swing/build.xml @@ -149,7 +149,7 @@ depends="build"> -