From 05e9758f36609c7a636b146f82a9fef0282a444a Mon Sep 17 00:00:00 2001 From: "neil.weinstock@gmail.com" Date: Sun, 10 Dec 2023 20:48:28 -0500 Subject: [PATCH 1/4] texture select combobox: show 20 items, change "From file..." to "Select file..." --- core/resources/l10n/messages.properties | 2 +- core/resources/l10n/messages_uk_UA.properties | 2 +- .../src/net/sf/openrocket/gui/configdialog/AppearancePanel.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 7da3ad017..1088b6678 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -2393,7 +2393,7 @@ 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 +DecalModel.lbl.choose = Select file\u2026 ! Export Decal Dialog ExportDecalDialog.title = Export Decal diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index e2c53e030..f39035f58 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -1799,7 +1799,7 @@ PresetModel.lbl.custompreset = Custom PresetModel.lbl.partsLib = Parts Library DecalModel.lbl.select = -DecalModel.lbl.choose = From file... +DecalModel.lbl.choose = Select file... ! Export Decal Dialog ExportDecalDialog.title = Export Decal diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 823efb2dc..7efa38176 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -505,6 +505,7 @@ public class AppearancePanel extends JPanel { DecalModel decalModel = new DecalModel(panel, document, builder); JComboBox textureDropDown = new JComboBox(decalModel); + textureDropDown.setMaximumRowCount(20); // We need to add this action listener that triggers a decalModel update when the same item is selected, because // for multi-comp edits, the listeners' decals may not be updated otherwise From ba7da7c4ee83025c4a018e8cb47852fe8ec13996 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Tue, 26 Dec 2023 19:57:39 +0100 Subject: [PATCH 2/4] Add snapshot version to OpenRocket versioning system --- core/resources/build.properties | 2 +- .../communication/UpdateInfoRetriever.java | 34 ++++++++++++++++--- .../communication/UpdateInfoTest.java | 24 +++++++++++++ .../communication/WelcomeInfoTest.java | 13 ++++--- 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/core/resources/build.properties b/core/resources/build.properties index 16395f062..af4f46bbd 100644 --- a/core/resources/build.properties +++ b/core/resources/build.properties @@ -1,6 +1,6 @@ # The OpenRocket build version -build.version=23.09 +build.version=23.09.SNAPSHOT # The copyright year for the build. Displayed in the about dialog. # Will show as Copyright 2013-${build.copyright} diff --git a/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java b/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java index 96ede4c05..41eb4ec1b 100644 --- a/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java +++ b/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java @@ -39,6 +39,8 @@ public class UpdateInfoRetriever { { "RC", 3 }, // Release Candidate }).collect(Collectors.toMap(c -> (String) c[0], c -> (Integer) c[1])); + public static final String snapshotTag = "SNAPSHOT"; + /* Enum for the current build version. Values: OLDER: current build version is older than the latest official release LATEST: current build is the latest official release @@ -280,7 +282,7 @@ public class UpdateInfoRetriever { public static List filterOfficialRelease(List names) { if (names == null) return null; return names.stream().filter(c -> Arrays.stream(devTags.keySet().toArray(new String[0])) - .noneMatch(c::contains)).collect(Collectors.toList()); + .noneMatch(c::contains) && !c.contains(snapshotTag)).collect(Collectors.toList()); } /** @@ -358,8 +360,8 @@ public class UpdateInfoRetriever { // If the loop is still going until this condition, you have the situation where tag1 is e.g. // '15.03' and tag2 '15.03.01', so tag is in that case the more recent version. if (i >= tag1Split.length) { - // Tag 1 is e.g. '15.03' and tag2 '15.03.01', so tag2 is the more recent version - if (tag2Split[i].matches("\\d+")) { + // Tag 1 is e.g. '15.03' and tag2 '15.03.01' or '15.03.SNAPSHOT', so tag2 is the more recent version + if (tag2Split[i].matches("\\d+") || snapshotTag.equals(tag2Split[i])) { return ReleaseStatus.OLDER; } // Tag 1 is e.g. '15.03' and tag2 '15.03.beta.01', so tag1 is the more recent version (it's an official release) @@ -392,6 +394,30 @@ public class UpdateInfoRetriever { continue; } + // Handle snapshots + if (snapshotTag.equals(tag1Split[i]) || snapshotTag.equals(tag2Split[i])) { + // In case when e.g. tag1 is '23.09.SNAPSHOT.02' and tag2 '23.09.SNAPSHOT.01', go to the next loop to compare '01' and '02' + if (snapshotTag.equals(tag1Split[i]) && snapshotTag.equals(tag2Split[i])) { + continue; + } + // In case when e.g. tag1 is '23.09.SNAPSHOT' and tag2 '23.09', tag1 is newer + else if (snapshotTag.equals(tag1Split[i])) { + // E.g. tag1 is '23.09.SNAPSHOT', tag2 is '23.09.01' + if (tag2Split[i].matches("\\d+")) { + return ReleaseStatus.OLDER; + } else { + return ReleaseStatus.NEWER; + } + } else { + // E.g. tag1 is '23.09.01', tag2 is '23.09.SNAPSHOT' + if (tag1Split[i].matches("\\d+")) { + return ReleaseStatus.NEWER; + } else { + return ReleaseStatus.OLDER; + } + } + } + // In case tag1 is e.g. '20.alpha.01', but tag2 is already an official release with a number instead of // a text, e.g. '20.01' if (tag2Split[i].matches("\\d+")) { @@ -445,7 +471,7 @@ public class UpdateInfoRetriever { log.warn(message); throw new UpdateCheckerException(message); } - if (!devTags.containsKey(tagSplit[i])) { + if (!devTags.containsKey(tagSplit[i]) && !snapshotTag.equals(tagSplit[i])) { String message = String.format("Malformed release tag: '%s'", String.join(".", tagSplit)); log.warn(message); throw new UpdateCheckerException(message); diff --git a/core/test/net/sf/openrocket/communication/UpdateInfoTest.java b/core/test/net/sf/openrocket/communication/UpdateInfoTest.java index e6b03316d..8ee7671e1 100644 --- a/core/test/net/sf/openrocket/communication/UpdateInfoTest.java +++ b/core/test/net/sf/openrocket/communication/UpdateInfoTest.java @@ -215,6 +215,30 @@ public class UpdateInfoTest extends BaseTestCase { assertEquals(UpdateInfoRetriever.ReleaseStatus.OLDER, UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("22.02.RC.01", "22.02.02")); + // Test snapshots + assertEquals(UpdateInfoRetriever.ReleaseStatus.OLDER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09", "23.09.SNAPSHOT")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.LATEST, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT", "23.09.SNAPSHOT")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.NEWER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT", "23.09")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.NEWER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("24.01", "23.09.SNAPSHOT")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.OLDER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT", "24.01")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.NEWER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("24.01.SNAPSHOT", "23.09")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.OLDER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT.01", "23.09.SNAPSHOT.02")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.LATEST, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT.02", "23.09.SNAPSHOT.02")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.NEWER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT.02", "23.09.SNAPSHOT.01")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.NEWER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.01", "23.09.SNAPSHOT")); + assertEquals(UpdateInfoRetriever.ReleaseStatus.OLDER, + UpdateInfoRetriever.UpdateInfoFetcher.compareLatest("23.09.SNAPSHOT", "23.09.01")); + // Test bogus releases assertExceptionCompareLatest("22.02.gamma.01", "22.02"); diff --git a/core/test/net/sf/openrocket/communication/WelcomeInfoTest.java b/core/test/net/sf/openrocket/communication/WelcomeInfoTest.java index aeb4f75d7..e7cb6d324 100644 --- a/core/test/net/sf/openrocket/communication/WelcomeInfoTest.java +++ b/core/test/net/sf/openrocket/communication/WelcomeInfoTest.java @@ -1,8 +1,10 @@ package net.sf.openrocket.communication; import net.sf.openrocket.util.BaseTestCase.BaseTestCase; +import net.sf.openrocket.util.BuildProperties; import org.junit.Test; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -12,12 +14,15 @@ public class WelcomeInfoTest extends BaseTestCase { @Test public void testWelcomeInfo() throws Exception { // Test the welcome info for the current build version - String welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo(); - assertNotNull("Current release version not present in release notes", welcomeInfo); - assertTrue("Body of release notes is empty", welcomeInfo.length() > 0); + String version = BuildProperties.getVersion(); + if (!version.contains(UpdateInfoRetriever.snapshotTag)) { // Ignore snapshot releases; they don't need release notes + String welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo(); + assertNotNull("Current release version not present in release notes", welcomeInfo); + assertFalse("Body of release notes is empty", welcomeInfo.isEmpty()); + } // Test the release info for a bogus release version - welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo("bogus release"); + String welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo("bogus release"); assertNull(welcomeInfo); } } From 2f81d26216eb29c088108398e83958af4b449b3a Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 27 Dec 2023 19:54:25 +0100 Subject: [PATCH 3/4] Set RockSim parachute length to radius --- .../net/sf/openrocket/file/rocksim/importt/ParachuteHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/ParachuteHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/ParachuteHandler.java index 8a8006a35..1485612a9 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/ParachuteHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/ParachuteHandler.java @@ -81,6 +81,7 @@ class ParachuteHandler extends RecoveryDeviceHandler { packed = chute.getDiameter() * 0.025; } chute.setRadius(packed); + chute.setLength(packed); } if (RockSimCommonConstants.SHROUD_LINE_COUNT.equals(element)) { chute.setLineCount(Math.max(0, Integer.parseInt(content))); From f66788e618953cf4002986e6d4dd26de2b211f31 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 27 Dec 2023 23:58:58 +0100 Subject: [PATCH 4/4] Fix parachute length resizing when loading preset parachute --- .../importt/ComponentParameterHandler.java | 13 ++++++ .../importt/ComponentPresetSetter.java | 12 +++++- .../openrocket/importt/DocumentConfig.java | 3 ++ .../openrocket/rocketcomponent/Parachute.java | 38 ++++++++++++----- .../rocketcomponent/RocketComponent.java | 41 +++++++++++++------ 5 files changed, 83 insertions(+), 24 deletions(-) diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java index 34bbee014..3486eb610 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java @@ -14,6 +14,7 @@ import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.AxialStage; +import org.xml.sax.SAXException; /** * A handler that populates the parameters of a previously constructed rocket component. @@ -27,6 +28,10 @@ class ComponentParameterHandler extends AbstractElementHandler { public ComponentParameterHandler(RocketComponent c, DocumentLoadingContext context) { this.component = c; this.context = context; + + // Sometimes setting certain component parameters will clear the preset. We don't want that to happen, so + // ignore preset clearing. + this.component.setIgnorePresetClearing(true); } @Override @@ -124,4 +129,12 @@ class ComponentParameterHandler extends AbstractElementHandler { + component.getComponentName() + ", ignoring.")); } } + + @Override + public void endHandler(String element, HashMap attributes, String content, WarningSet warnings) throws SAXException { + super.endHandler(element, attributes, content, warnings); + + // Restore the preset clearing behavior + this.component.setIgnorePresetClearing(false); + } } \ No newline at end of file diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentPresetSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentPresetSetter.java index 097338116..82b2233ca 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentPresetSetter.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentPresetSetter.java @@ -13,10 +13,16 @@ import net.sf.openrocket.util.Reflection; ////ComponentPresetSetter - sets a ComponentPreset value class ComponentPresetSetter implements Setter { private final Reflection.Method setMethod; + private Object[] extraParameters = null; public ComponentPresetSetter(Reflection.Method set) { this.setMethod = set; } + + public ComponentPresetSetter(Reflection.Method set, Object... parameters) { + this.setMethod = set; + this.extraParameters = parameters; + } @Override public void set(RocketComponent c, String name, HashMap attributes, @@ -71,7 +77,11 @@ class ComponentPresetSetter implements Setter { // The preset loader can override the component name, so first store it and then apply it again String componentName = c.getName(); - setMethod.invoke(c, matchingPreset); + if (extraParameters != null) { + setMethod.invoke(c, matchingPreset, extraParameters); + } else { + setMethod.invoke(c, matchingPreset); + } c.setName(componentName); } } diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java index 24b3655df..489fec875 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java @@ -452,6 +452,9 @@ class DocumentConfig { setters.put("Parachute:linematerial", new MaterialSetter( Reflection.findMethod(Parachute.class, "setLineMaterial", Material.class), Material.Type.LINE)); + setters.put("Parachute:preset", new ComponentPresetSetter( + Reflection.findMethod(Parachute.class, "loadPreset", ComponentPreset.class, Object[].class), + false)); // PodSet setters.put("PodSet:instancecount", new IntSetter( diff --git a/core/src/net/sf/openrocket/rocketcomponent/Parachute.java b/core/src/net/sf/openrocket/rocketcomponent/Parachute.java index 5111b13af..6becd0636 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Parachute.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Parachute.java @@ -153,8 +153,18 @@ public class Parachute extends RecoveryDevice { return false; } + /** + * Load the component from a preset. + * @param preset the preset to load from + * @param params extra parameters to be used in the preset loading + * params[0] = boolean allowAutoRadius: true = allow auto radius to be set during preset loading, false = do not allow auto radius + */ @Override - protected void loadFromPreset(ComponentPreset preset) { + protected void loadFromPreset(ComponentPreset preset, Object...params) { + boolean allowAutoRadius = true; + if (params != null && params.length > 0) { + allowAutoRadius = (boolean) params[0]; + } // SUBSTITUTE preset parachute values for existing component values // // Set preset parachute description @@ -176,13 +186,13 @@ public class Parachute extends RecoveryDevice { this.diameter = DEFAULT_DIAMETER; } // // Set preset parachute drag coefficient - if ((preset.has(ComponentPreset.CD)) && preset.get(ComponentPreset.CD) > 0){ - cdAutomatic = false; - cd = preset.get(ComponentPreset.CD); - } else { - cdAutomatic = true; - cd = Parachute.DEFAULT_CD; - } + if ((preset.has(ComponentPreset.CD)) && preset.get(ComponentPreset.CD) > 0){ + cdAutomatic = false; + cd = preset.get(ComponentPreset.CD); + } else { + cdAutomatic = true; + cd = Parachute.DEFAULT_CD; + } // // Set preset parachute line count if ((preset.has(ComponentPreset.LINE_COUNT)) && preset.get(ComponentPreset.LINE_COUNT) > 0) { this.lineCount = preset.get(ComponentPreset.LINE_COUNT); @@ -196,7 +206,7 @@ public class Parachute extends RecoveryDevice { this.lineLength = DEFAULT_LINE_LENGTH; } // // Set preset parachute line material - // NEED a better way to set preset if field is empty ---- + // NEED a better way to set preset if field is empty ---- if ((preset.has(ComponentPreset.LINE_MATERIAL))) { String lineMaterialEmpty = preset.get(ComponentPreset.LINE_MATERIAL).toString(); int count = lineMaterialEmpty.length(); @@ -219,7 +229,8 @@ public class Parachute extends RecoveryDevice { } // // Size parachute packed diameter within parent inner diameter if (preset.has(ComponentPreset.PACKED_LENGTH) && (getLength() > 0) && - preset.has(ComponentPreset.PACKED_DIAMETER) && (getRadius() > 0)) { + preset.has(ComponentPreset.PACKED_DIAMETER) && (getRadius() > 0) && + allowAutoRadius) { setRadiusAutomatic(true); } @@ -232,7 +243,12 @@ public class Parachute extends RecoveryDevice { massOverridden = false; } - super.loadFromPreset(preset); + super.loadFromPreset(preset, params); + } + + @Override + protected void loadFromPreset(ComponentPreset preset) { + loadFromPreset(preset, true); } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 5f42d1c75..d366a73f4 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -136,6 +136,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab // Preset component this component is based upon private ComponentPreset presetComponent = null; + + // If set to true, presets will not be cleared + private boolean ignorePresetClearing = false; // The realistic appearance of this component private Appearance appearance = null; @@ -1176,10 +1179,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * preset values. * * @param preset the preset component to load, or null to clear the preset. + * @param params extra parameters to be used in the preset loading */ - public final void loadPreset(ComponentPreset preset) { + public final void loadPreset(ComponentPreset preset, Object...params) { for (RocketComponent listener : configListeners) { - listener.loadPreset(preset); + listener.loadPreset(preset, params); } if (presetComponent == preset) { @@ -1211,8 +1215,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab if (rocket != null) { rocket.freeze(); } - - loadFromPreset(preset); + + if (params == null || params.length == 0) + loadFromPreset(preset); + else + loadFromPreset(preset, params); this.presetComponent = preset; @@ -1224,8 +1231,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } - - + + public final void loadPreset(ComponentPreset preset) { + loadPreset(preset, (Object[]) null); + } + /** * Load component properties from the specified preset. The preset is guaranteed * to be of the correct type. @@ -1235,14 +1245,19 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab *

* This method must FIRST perform the preset loading and THEN call super.loadFromPreset(). * This is because mass setting requires the dimensions to be set beforehand. - * + * * @param preset the preset to load from + * @param params extra parameters to be used in the preset loading */ - protected void loadFromPreset(ComponentPreset preset) { + protected void loadFromPreset(ComponentPreset preset, Object...params) { if (preset.has(ComponentPreset.LENGTH)) { this.length = preset.get(ComponentPreset.LENGTH); } } + + protected void loadFromPreset(ComponentPreset preset) { + loadFromPreset(preset, (Object[]) null); + } /** @@ -1254,14 +1269,16 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab listener.clearPreset(); } - if (presetComponent == null) + if (presetComponent == null || ignorePresetClearing) return; presetComponent = null; fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } - - - + + public void setIgnorePresetClearing(boolean ignorePresetClearing) { + this.ignorePresetClearing = ignorePresetClearing; + } + /** * Returns the unique ID of the component. *