From ccffffa1867e7b5e0719a66c2c7f6334260d3e25 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 24 Aug 2023 23:22:44 +0200 Subject: [PATCH 1/7] [#2204] Big rewrite of motor config substitutor to make it general + add cases --- .../MotorConfigurationSubstitutor.java | 409 ++++++++++-------- 1 file changed, 221 insertions(+), 188 deletions(-) diff --git a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java index 864a0ea8a..71f1ae751 100644 --- a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java +++ b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java @@ -12,11 +12,11 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.Chars; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -26,8 +26,8 @@ import java.util.regex.Pattern; * General substitutor for motor configurations. This currently includes substitutions for * - {motors} - the motor designation (e.g. "M1350-0") * - {manufacturers} - the motor manufacturer (e.g. "AeroTech") - * - a combination of motors and manufacturers, e.g. {motors | manufacturers} -> "M1350-0 | AeroTech" - * You can choose which comes first and what the separator is. E.g. {manufacturers, motors} -> "AeroTech, M1350-0". + * - a combination of motors and manufacturers, e.g. {motors manufacturers} -> "M1350-0 AeroTech" + * You can choose which comes first is. E.g. {manufacturers motors} -> "AeroTech M1350-0". * *

* This substitutor is added through injection. All substitutors with the "@Plugin" tag in the formatting package will @@ -35,217 +35,250 @@ import java.util.regex.Pattern; */ @Plugin public class MotorConfigurationSubstitutor implements RocketSubstitutor { - public static final String SUBSTITUTION_START = "{"; - public static final String SUBSTITUTION_END = "}"; - public static final String SUBSTITUTION_MOTORS = "motors"; - public static final String SUBSTITUTION_MANUFACTURERS = "manufacturers"; + // Substitution start and end + public static final String SUB_START = "{"; + public static final String SUB_END = "}"; - // Substitutions for combinations of motors and manufacturers - private static final String SUBSTITUTION_PATTERN = "\\" + SUBSTITUTION_START + - "(" + SUBSTITUTION_MOTORS + "|" + SUBSTITUTION_MANUFACTURERS + ")" + - "(.*?)" + - "(" + SUBSTITUTION_MOTORS + "|" + SUBSTITUTION_MANUFACTURERS + ")" + - "\\" + SUBSTITUTION_END; + // Map containing substitution words and their corresponding replacement strings. + private static final Map SUBSTITUTIONS = new HashMap<>(); + + static { + SUBSTITUTIONS.put("motors", new MotorSubstitutor()); + SUBSTITUTIONS.put("manufacturers", new ManufacturerSubstitutor()); + SUBSTITUTIONS.put("cases", new CaseSubstitutor()); + } @Inject private Translator trans; @Override public boolean containsSubstitution(String input) { - return getSubstitutionContent(input) != null; + Pattern pattern = Pattern.compile("\\" + SUB_START + "(.*?[^\\s])\\" + SUB_END); // ensures non-whitespace content + Matcher matcher = pattern.matcher(input); + + while (matcher.find()) { + String tagContent = matcher.group(1).trim(); + for (String key : SUBSTITUTIONS.keySet()) { + if (tagContent.contains(key)) { + return true; + } + } + } + return false; } @Override public String substitute(String input, Rocket rocket, FlightConfigurationId configId) { - String description = getConfigurationSubstitution(input, rocket, configId); - String substitutionString = getSubstiutionString(input); - if (substitutionString != null) { - return input.replace(substitutionString, description); + Pattern pattern = Pattern.compile("\\" + SUB_START + "(.*?)\\" + SUB_END); + Matcher matcher = pattern.matcher(input); + StringBuilder resultBuffer = new StringBuilder(); + + while (matcher.find()) { + String tagContent = matcher.group(1).trim(); + String[] keys = tagContent.split("\\s"); + + List>> stageSubstitutes = new ArrayList<>(); + for (String key : keys) { + if (SUBSTITUTIONS.containsKey(key)) { + Map> sub = SUBSTITUTIONS.get(key).substitute(rocket, configId); + stageSubstitutes.add(sub); + } + } + + FlightConfiguration config = rocket.getFlightConfiguration(configId); + List combinations = combineSubstitutesForStages(rocket, config, stageSubstitutes, " "); + + String combined = String.join("; ", combinations); + matcher.appendReplacement(resultBuffer, Matcher.quoteReplacement(combined)); } - return input; + + matcher.appendTail(resultBuffer); + + return resultBuffer.toString(); } + private List combineSubstitutesForStages(Rocket rocket, FlightConfiguration config, + List>> stageSubstitutes, String separator) { + List combinations = new ArrayList<>(); + + // Parse through all the stages to get the final configuration string + for (AxialStage stage : rocket.getStageList()) { + if (!config.isStageActive(stage.getStageNumber())) { + combinations.add(""); + continue; + } + + StringBuilder sbStageSub = new StringBuilder(); + // Parse through all the substitutes (motors, manufacturers, etc.) for each stage to build a combined stage substitution + for (Map> substituteMap : stageSubstitutes) { + List substitutes = substituteMap.get(stage); + if (substitutes == null || substitutes.isEmpty()) { + continue; + } + + // If this is not the first substitute, add a separator between the different substitutes (motor, manufacturer, etc.) + if (!sbStageSub.isEmpty()) { + sbStageSub.append(separator); + } + + // Create a final substitute for this sub tag from the list of substitutes + String finalSubstitute = getFinalSubstitute(substitutes, sbStageSub); + sbStageSub.append(finalSubstitute); + } + + if (sbStageSub.isEmpty()) { + sbStageSub.append(trans.get("Rocket.motorCount.noStageMotors")); + } + combinations.add(sbStageSub.toString()); + } + + // Check if all the stages are empty + boolean onlyEmpty = true; + for (String s : combinations) { + if (!s.isEmpty() && !s.equals(trans.get("Rocket.motorCount.noStageMotors"))) { + onlyEmpty = false; + break; + } + } + + // If all the stages are empty, return a single "No motors" string + if (combinations.isEmpty() || onlyEmpty) { + return Collections.singletonList(trans.get("Rocket.motorCount.Nomotor")); + } + + return combinations; + } + + private static String getFinalSubstitute(List substitutes, StringBuilder sbStageSub) { + if (substitutes.size() == 1 || !sbStageSub.isEmpty()) { + return substitutes.get(0); + } + + // Change multiple occurrences of a configuration to 'n x configuration' + String stageName = ""; + String previous = null; + int count = 0; + + Collections.sort(substitutes); + for (String current : substitutes) { + if (current.isEmpty()) { + continue; + } + if (current.equals(previous)) { + count++; + } else { + if (previous != null) { + String s = count > 1 ? count + Chars.TIMES + previous : previous; + stageName = stageName.isEmpty() ? s : stageName + "," + s; + } + + previous = current; + count = 1; + } + } + + if (previous != null) { + String s = count > 1 ? "" + count + Chars.TIMES + previous : previous; + stageName = stageName.isEmpty() ? s : stageName + "," + s; + } + + return stageName; + } + + @Override public Map getDescriptions() { return null; } - public String getConfigurationSubstitution(String input, Rocket rocket, FlightConfigurationId fcid) { - StringBuilder configurations = new StringBuilder(); - int motorCount = 0; + private interface Substitutor { + /** + * Generates a string to substitute a certain substitutor word with. + * @param rocket The used rocket + * @param fcid The flight configuration id + * @return A list of strings to substitute the substitutor word with for each stage + */ + Map> substitute(Rocket rocket, FlightConfigurationId fcid); + } - // Iterate over each stage and store the manufacturer of each motor - List> list = new ArrayList<>(); - List currentList = new ArrayList<>(); + public abstract static class BaseSubstitutor implements Substitutor { - String[] content = getSubstitutionContent(input); - if (content == null) { + protected abstract String getData(Motor motor, MotorConfiguration motorConfig); + + @Override + public Map> substitute(Rocket rocket, FlightConfigurationId fcid) { + List dataList; // Data for one stage. Is a list because multiple motors per stage are possible + Map> stageMap = new HashMap<>(); // Data for all stages + + FlightConfiguration config = rocket.getFlightConfiguration(fcid); + + for (AxialStage stage : rocket.getStageList()) { + if (config.isStageActive(stage.getStageNumber())) { + dataList = new ArrayList<>(); + stageMap.put(stage, dataList); + } else { + stageMap.put(stage, null); + continue; + } + + for (RocketComponent child : stage.getAllChildren()) { + // If the child is nested inside another stage (e.g. booster), skip it + // Plus other conditions :) But I'm not gonna bore you with those details. The goal + // of code documentation is to not waste a programmers time by making them read too + // much text when you can word something in a more concise way. I think I've done that + // here. I think I have succeeded. Yes. Anyway, have a good day reader! + if (child.getStage() != stage || !(child instanceof MotorMount mount) || !mount.isMotorMount()) { + continue; + } + + MotorConfiguration inst = mount.getMotorConfig(fcid); + Motor motor = inst.getMotor(); + + // Mount has no motor + if (motor == null) { + dataList.add(""); + continue; + } + + // Get the data for this substitutor word + String data = getData(motor, inst); + + // Add the data for each motor instance + for (int i = 0; i < mount.getMotorCount(); i++) { + dataList.add(data); + } + } + } + + return stageMap; + } + } + + private static class MotorSubstitutor extends BaseSubstitutor { + @Override + protected String getData(Motor motor, MotorConfiguration motorConfig) { + return motor.getMotorName(motorConfig.getEjectionDelay()); + } + } + + private static class ManufacturerSubstitutor extends BaseSubstitutor { + @Override + protected String getData(Motor motor, MotorConfiguration motorConfig) { + if (motor instanceof ThrustCurveMotor) { + return ((ThrustCurveMotor) motor).getManufacturer().getDisplayName(); + } return ""; } - - FlightConfiguration config = rocket.getFlightConfiguration(fcid); - for (RocketComponent c : rocket) { - if (c instanceof AxialStage) { - currentList = new ArrayList<>(); - list.add(currentList); - } else if (c instanceof MotorMount) { - MotorMount mount = (MotorMount) c; - MotorConfiguration inst = mount.getMotorConfig(fcid); - Motor motor = inst.getMotor(); - - if (mount.isMotorMount() && config.isComponentActive(mount) && (motor != null)) { - String motorDesignation = motor.getMotorName(inst.getEjectionDelay()); - String manufacturer = ""; - if (motor instanceof ThrustCurveMotor) { - manufacturer = ((ThrustCurveMotor) motor).getManufacturer().getDisplayName(); - } - - for (int i = 0; i < mount.getMotorCount(); i++) { - if (content.length == 2) { - if (SUBSTITUTION_MOTORS.equals(content[1])) { - currentList.add(motorDesignation); - } else if (SUBSTITUTION_MANUFACTURERS.equals(content[1])) { - currentList.add(manufacturer); - } else { - continue; - } - } else if (content.length == 4) { - String configString; - if (content[1].equals(SUBSTITUTION_MOTORS)) { - configString = motorDesignation; - } else if (content[1].equals(SUBSTITUTION_MANUFACTURERS)) { - configString = manufacturer; - } else { - continue; - } - configString += content[2]; - if (content[3].equals(SUBSTITUTION_MOTORS)) { - configString += motorDesignation; - } else if (content[3].equals(SUBSTITUTION_MANUFACTURERS)) { - configString += manufacturer; - } else { - continue; - } - currentList.add(configString); - } else { - continue; - } - motorCount++; - } - } - } - } - - if (motorCount == 0) { - return trans.get("Rocket.motorCount.Nomotor"); - } - - // Change multiple occurrences of a motor to n x motor - List stages = new ArrayList<>(); - for (List stage : list) { - String stageName = ""; - String previous = null; - int count = 0; - - Collections.sort(stage); - for (String current : stage) { - if (current.equals(previous)) { - count++; - } else { - if (previous != null) { - String s = count > 1 ? count + Chars.TIMES + previous : previous; - stageName = stageName.equals("") ? s : stageName + "," + s; - } - - previous = current; - count = 1; - } - } - - if (previous != null) { - String s = count > 1 ? "" + count + Chars.TIMES + previous : previous; - stageName = stageName.equals("") ? s : stageName + "," + s; - } - - stages.add(stageName); - } - - for (int i = 0; i < stages.size(); i++) { - String s = stages.get(i); - if (s.equals("") && config.isStageActive(i)) { - s = trans.get("Rocket.motorCount.noStageMotors"); - } - - configurations.append(i == 0 ? s : "; " + s); - } - - return configurations.toString(); } - /** - * Returns which string in input should be replaced, or null if no text needs to be replaced. - * @param input The input string - * @return The string to replace, or null if no text needs to be replaced. - */ - private static String getSubstiutionString(String input) { - String[] content = getSubstitutionContent(input); - if (content != null) { - return content[0]; - } - return null; - } - - /** - * Fills in the content of the substitution tag and the separator. - * If there are both a motor and a manufacturer substitution tag, the array will contain the following: - * [0] = The full tag, including substitution start and end - * [1] = The motor/manufacturer substitution tag, depending on which one was found first. - * if there are two substitution tags, the array will also contain the following: - * ([2] = The separator) - * ([3] = The motor/manufacturer substitution tag, depending on which one was found first.) - * @param input The input string - * @return The content of the substitution tag and the separator, or null if no text needs to be replaced. - */ - private static String[] getSubstitutionContent(String input) { - // First try with only the motors tag - String pattern = "\\" + SUBSTITUTION_START + "(" + SUBSTITUTION_MOTORS + ")" + "\\" + SUBSTITUTION_END; - Pattern regexPattern = Pattern.compile(pattern); - Matcher matcher = regexPattern.matcher(input); - if (matcher.find()) { - String[] content = new String[2]; - content[0] = matcher.group(0); - content[1] = matcher.group(1); - return content; - } - // First try with only the manufacturers tag - pattern = "\\" + SUBSTITUTION_START + "(" + SUBSTITUTION_MANUFACTURERS + ")" + "\\" + SUBSTITUTION_END; - regexPattern = Pattern.compile(pattern); - matcher = regexPattern.matcher(input); - if (matcher.find()) { - String[] content = new String[2]; - content[0] = matcher.group(0); - content[1] = matcher.group(1); - return content; - } - - // Then try combined patterns - pattern = SUBSTITUTION_PATTERN; - regexPattern = Pattern.compile(pattern); - matcher = regexPattern.matcher(input); - if (matcher.find()) { - String[] content = new String[4]; - content[0] = matcher.group(0); - content[1] = matcher.group(1); - if (matcher.groupCount() >= 3) { - content[2] = matcher.group(2); - content[3] = matcher.group(3); - for (int i = 4; i < matcher.groupCount(); i++) { - content[3] += matcher.group(i); - } + private static class CaseSubstitutor extends BaseSubstitutor { + @Override + protected String getData(Motor motor, MotorConfiguration motorConfig) { + if (motor instanceof ThrustCurveMotor) { + return ((ThrustCurveMotor) motor).getCaseInfo(); } - return content; + return ""; } - return null; } } From e72870c3065fced994ab2b608acbfb84d12afadb Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 00:00:14 +0200 Subject: [PATCH 2/7] Eujj, add custom separator support :)) --- .../MotorConfigurationSubstitutor.java | 38 +++++++++++++++---- .../FlightConfigurationTest.java | 22 ++++++----- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java index 71f1ae751..7b152be7a 100644 --- a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java +++ b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java @@ -26,8 +26,9 @@ import java.util.regex.Pattern; * General substitutor for motor configurations. This currently includes substitutions for * - {motors} - the motor designation (e.g. "M1350-0") * - {manufacturers} - the motor manufacturer (e.g. "AeroTech") - * - a combination of motors and manufacturers, e.g. {motors manufacturers} -> "M1350-0 AeroTech" - * You can choose which comes first is. E.g. {manufacturers motors} -> "AeroTech M1350-0". + * - {cases} - the motor case (e.g. "SU 18.0x70.0") + * - a combination of motors and manufacturers, e.g. {motors | manufacturers} -> "M1350-0 | AeroTech" + * You can choose which comes first and what the separator is. E.g. {manufacturers, motors} -> "AeroTech, M1350-0". * *

* This substitutor is added through injection. All substitutors with the "@Plugin" tag in the formatting package will @@ -75,10 +76,27 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { while (matcher.find()) { String tagContent = matcher.group(1).trim(); - String[] keys = tagContent.split("\\s"); + // Step 1: Find the keys + List foundKeys = new ArrayList<>(); + Matcher keyMatcher = Pattern.compile("\\b(" + String.join("|", SUBSTITUTIONS.keySet()) + ")\\b").matcher(tagContent); + while (keyMatcher.find()) { + foundKeys.add(keyMatcher.group()); + } + + // Step 2: Extracting the separators + List separators = new ArrayList<>(); + int lastEnd = 0; + for (int i = 0; i < foundKeys.size() - 1; i++) { + int startOfNextKey = tagContent.indexOf(foundKeys.get(i + 1), lastEnd); + String separator = tagContent.substring(lastEnd + foundKeys.get(i).length(), startOfNextKey); + separators.add(separator); + lastEnd = startOfNextKey + foundKeys.get(i + 1).length(); + } + + // Continue with the original function List>> stageSubstitutes = new ArrayList<>(); - for (String key : keys) { + for (String key : foundKeys) { if (SUBSTITUTIONS.containsKey(key)) { Map> sub = SUBSTITUTIONS.get(key).substitute(rocket, configId); stageSubstitutes.add(sub); @@ -86,7 +104,8 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { } FlightConfiguration config = rocket.getFlightConfiguration(configId); - List combinations = combineSubstitutesForStages(rocket, config, stageSubstitutes, " "); + // Use the extracted separators instead of a single space + List combinations = combineSubstitutesForStages(rocket, config, stageSubstitutes, separators); String combined = String.join("; ", combinations); matcher.appendReplacement(resultBuffer, Matcher.quoteReplacement(combined)); @@ -98,7 +117,7 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { } private List combineSubstitutesForStages(Rocket rocket, FlightConfiguration config, - List>> stageSubstitutes, String separator) { + List>> stageSubstitutes, List separators) { List combinations = new ArrayList<>(); // Parse through all the stages to get the final configuration string @@ -110,6 +129,7 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { StringBuilder sbStageSub = new StringBuilder(); // Parse through all the substitutes (motors, manufacturers, etc.) for each stage to build a combined stage substitution + int idx = 0; for (Map> substituteMap : stageSubstitutes) { List substitutes = substituteMap.get(stage); if (substitutes == null || substitutes.isEmpty()) { @@ -117,13 +137,15 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { } // If this is not the first substitute, add a separator between the different substitutes (motor, manufacturer, etc.) - if (!sbStageSub.isEmpty()) { - sbStageSub.append(separator); + if (!sbStageSub.isEmpty() && idx > 0) { + sbStageSub.append(separators.get(idx - 1)); } // Create a final substitute for this sub tag from the list of substitutes String finalSubstitute = getFinalSubstitute(substitutes, sbStageSub); sbStageSub.append(finalSubstitute); + + idx++; } if (sbStageSub.isEmpty()) { diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index 372d3f2de..09e38984b 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -651,36 +651,38 @@ public class FlightConfigurationTest extends BaseTestCase { assertEquals("{}", selected.getName()); // Test invalid tags (1) - selected.setName("{motorsm}"); + selected.setName("{motorms}"); selected.setAllStages(); - assertEquals("{motorsm}", selected.getName()); + assertEquals("{motorms}", selected.getName()); selected.setOnlyStage(0); - assertEquals("{motorsm}", selected.getName()); + assertEquals("{motorms}", selected.getName()); selected.setOnlyStage(1); - assertEquals("{motorsm}", selected.getName()); + assertEquals("{motorms}", selected.getName()); + + selected.setName("{motor}"); selected.setAllStages(); selected._setStageActive(0, false); - assertEquals("{motorsm}", selected.getName()); + assertEquals("{motor}", selected.getName()); // Test invalid tags (2) - selected.setName("{motors manufacturers '}"); + selected.setName("{mot'ors manuf'acturers '}"); selected.setAllStages(); - assertEquals("{motors manufacturers '}", selected.getName()); + assertEquals("{mot'ors manuf'acturers '}", selected.getName()); selected.setOnlyStage(0); - assertEquals("{motors manufacturers '}", selected.getName()); + assertEquals("{mot'ors manuf'acturers '}", selected.getName()); selected.setOnlyStage(1); - assertEquals("{motors manufacturers '}", selected.getName()); + assertEquals("{mot'ors manuf'acturers '}", selected.getName()); selected.setAllStages(); selected._setStageActive(0, false); - assertEquals("{motors manufacturers '}", selected.getName()); + assertEquals("{mot'ors manuf'acturers '}", selected.getName()); } @Test From 2c750498bb0dcf9a02e39fbb3d5c80701021b439 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 00:04:06 +0200 Subject: [PATCH 3/7] Update rename dialog to include cases info --- core/resources/l10n/messages.properties | 3 ++- .../flightconfiguration/RenameConfigDialog.java | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index e8dc1d512..254420bb9 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -240,7 +240,8 @@ RenameConfigDialog.lbl.name = Name for flight configuration: RenameConfigDialog.but.reset = Reset to default RenameConfigDialog.lbl.infoMotors = The text '{motors}' will be replaced with the motor designation(s).

\te.g. '{motors} \u2192 'M1350-0'
RenameConfigDialog.lbl.infoManufacturers = The text '{manufacturers}' will be replaced with the motor manufacturer(s).
\te.g. '{manufacturers}' \u2192 'AeroTech'
-RenameConfigDialog.lbl.infoCombination = A combination of the above can be used.
\te.g. '{manufacturers motors}' \u2192 'AeroTech M1350-0'
+RenameConfigDialog.lbl.infoCases = The text '{cases}' will be replaced with the motor case(s).
\te.g. '{cases}' \u2192 'SU 18.0x70.0'
+RenameConfigDialog.lbl.infoCombination = A combination of the above can be used (you may choose the separator).
\te.g. '{manufacturers motors}' \u2192 'AeroTech M1350-0'
! Example design dialog diff --git a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java index 88222ec54..7cb232a0b 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java @@ -46,17 +46,17 @@ public class RenameConfigDialog extends JDialog { RenameConfigDialog.this.setVisible(false); } }); - panel.add(okButton, "growx"); + panel.add(okButton); - JButton renameToDefaultButton = new SelectColorButton(trans.get("RenameConfigDialog.but.reset")); - renameToDefaultButton.addActionListener(new ActionListener() { + JButton resetToDefaultButton = new SelectColorButton(trans.get("RenameConfigDialog.but.reset")); + resetToDefaultButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { rocket.getFlightConfiguration(fcid).setName(null); RenameConfigDialog.this.setVisible(false); } }); - panel.add(renameToDefaultButton, "growx"); + panel.add(resetToDefaultButton); JButton cancel = new SelectColorButton(trans.get("button.cancel")); cancel.addActionListener(new ActionListener() { @@ -65,11 +65,12 @@ public class RenameConfigDialog extends JDialog { RenameConfigDialog.this.setVisible(false); } }); - panel.add(cancel, "growx, wrap para"); + panel.add(cancel, "wrap para"); // {motors} & {manufacturers} info String text = "" + CommonStrings.dagger + " " + trans.get("RenameConfigDialog.lbl.infoMotors") + trans.get("RenameConfigDialog.lbl.infoManufacturers") + + trans.get("RenameConfigDialog.lbl.infoCases") + trans.get("RenameConfigDialog.lbl.infoCombination"); StyledLabel info = new StyledLabel(text, -2); info.setFontColor(GUIUtil.getUITheme().getDimTextColor()); From 41b6c8755034717d10c391fb136ca6a969c25e2e Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 00:38:45 +0200 Subject: [PATCH 4/7] Add case info to test motors --- core/src/net/sf/openrocket/util/TestRockets.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java index f0012a0d5..29f9b6a47 100644 --- a/core/src/net/sf/openrocket/util/TestRockets.java +++ b/core/src/net/sf/openrocket/util/TestRockets.java @@ -106,6 +106,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("A")) .setDesignation("F12X") .setDescription("Desc") + .setCaseInfo("info") .setMotorType(Motor.Type.UNKNOWN) .setStandardDelays(new double[] {}) .setDiameter(0.024) @@ -123,6 +124,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("Estes")) .setDesignation("A8") .setDescription(" SU Black Powder") + .setCaseInfo("SU 18.0x70.0") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {0,3,5}) .setDiameter(0.018) @@ -141,6 +143,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("Estes")) .setDesignation("B4") .setDescription(" SU Black Powder") + .setCaseInfo("SU 18.0x70.0") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {0,3,5}) .setDiameter(0.018) @@ -159,6 +162,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("Estes")) .setDesignation("C6") .setDescription(" SU Black Powder") + .setCaseInfo("SU 18.0x70.0") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {0,3,5,7}) .setDiameter(0.018) @@ -177,6 +181,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("AeroTech")) .setDesignation("D21") .setDescription("Desc") + .setCaseInfo("SU 18.0x70.0") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {}) .setDiameter(0.018) @@ -195,6 +200,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("AeroTech")) .setDesignation("M1350") .setDescription("Desc") + .setCaseInfo("SU 75/512") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {}) .setDiameter(0.075) @@ -213,6 +219,7 @@ public class TestRockets { .setManufacturer(Manufacturer.getManufacturer("AeroTech")) .setDesignation("G77") .setDescription("Desc") + .setCaseInfo("SU 29/180") .setMotorType(Motor.Type.SINGLE) .setStandardDelays(new double[] {4,7,10}) .setDiameter(0.029) From eb549ceb19ea4f2d7ec8b6ec153355aa42edcf65 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 00:39:04 +0200 Subject: [PATCH 5/7] Add extra unit tests for case flight config sub --- .../FlightConfigurationTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index 09e38984b..a0810549d 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -585,6 +585,24 @@ public class FlightConfigurationTest extends BaseTestCase { Rocket rocket = TestRockets.makeFalcon9Heavy(); FlightConfiguration selected = rocket.getSelectedConfiguration(); + // Test only motors + selected.setName("[{motors}]"); + + selected.setAllStages(); + assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0; 4\u00D7G77-0]", selected.getName()); + + // Test only manufacturers + selected.setName("[{manufacturers}]"); + + selected.setAllStages(); + assertEquals("[[Rocket.motorCount.noStageMotors]; AeroTech; 4\u00D7AeroTech]", selected.getName()); + + // Test only cases + selected.setName("[{cases}]"); + + selected.setAllStages(); + assertEquals("[[Rocket.motorCount.noStageMotors]; SU 75/512; 4×SU 29/180]", selected.getName()); + // Test only motors or only manufacturers selected.setName("[{motors}] - [{manufacturers}]"); @@ -634,6 +652,12 @@ public class FlightConfigurationTest extends BaseTestCase { selected._setStageActive(0, false); assertEquals("[; AeroTech | M1350-0; 4\u00D7AeroTech | G77-0]", selected.getName()); + // Test combination of motors, manufacturers and cases + selected.setName("[{motors manufacturers | cases}]"); + + selected.setAllStages(); + assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0 AeroTech | SU 75/512; 4×G77-0 AeroTech | SU 29/180]", selected.getName()); + // Test empty tags selected.setName("{}"); From db61dec547f70888b01cd0f25f290acea0eb6936 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 00:39:11 +0200 Subject: [PATCH 6/7] Fix bug --- .../formatting/MotorConfigurationSubstitutor.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java index 7b152be7a..9accb30d0 100644 --- a/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java +++ b/core/src/net/sf/openrocket/formatting/MotorConfigurationSubstitutor.java @@ -88,10 +88,12 @@ public class MotorConfigurationSubstitutor implements RocketSubstitutor { List separators = new ArrayList<>(); int lastEnd = 0; for (int i = 0; i < foundKeys.size() - 1; i++) { - int startOfNextKey = tagContent.indexOf(foundKeys.get(i + 1), lastEnd); - String separator = tagContent.substring(lastEnd + foundKeys.get(i).length(), startOfNextKey); + int startOfThisKey = tagContent.indexOf(foundKeys.get(i), lastEnd); + int endOfThisKey = startOfThisKey + foundKeys.get(i).length(); + int startOfNextKey = tagContent.indexOf(foundKeys.get(i + 1), endOfThisKey); + String separator = tagContent.substring(endOfThisKey, startOfNextKey); separators.add(separator); - lastEnd = startOfNextKey + foundKeys.get(i + 1).length(); + lastEnd = startOfNextKey; } // Continue with the original function From 93e0ae1dcbec05e8e250cbee5acf068eedc3ab82 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 25 Aug 2023 01:00:23 +0200 Subject: [PATCH 7/7] GRRRR, ASCII.... --- .../openrocket/rocketcomponent/FlightConfigurationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index a0810549d..0a7858e80 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -601,7 +601,7 @@ public class FlightConfigurationTest extends BaseTestCase { selected.setName("[{cases}]"); selected.setAllStages(); - assertEquals("[[Rocket.motorCount.noStageMotors]; SU 75/512; 4×SU 29/180]", selected.getName()); + assertEquals("[[Rocket.motorCount.noStageMotors]; SU 75/512; 4\u00D7SU 29/180]", selected.getName()); // Test only motors or only manufacturers selected.setName("[{motors}] - [{manufacturers}]"); @@ -656,7 +656,7 @@ public class FlightConfigurationTest extends BaseTestCase { selected.setName("[{motors manufacturers | cases}]"); selected.setAllStages(); - assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0 AeroTech | SU 75/512; 4×G77-0 AeroTech | SU 29/180]", selected.getName()); + assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0 AeroTech | SU 75/512; 4\u00D7G77-0 AeroTech | SU 29/180]", selected.getName()); // Test empty tags selected.setName("{}");