Merge branch 'unstable' into issue-1147
This commit is contained in:
commit
6b64f8e7f5
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
31
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Help us make OpenRocket better
|
|
||||||
title: '[Bug] <insert your title>'
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**ORK File**
|
|
||||||
If the problem is triggered by a particular ORK file, please zip it and attach it to this issue.
|
|
||||||
|
|
||||||
**Platform**
|
|
||||||
- OS: [e.g. Windows10]
|
|
||||||
- OpenRocket version (e.g. 22-02)
|
|
||||||
- Graphics card (if a graphics or display-related problem)
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
70
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
70
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Help us make OpenRocket better
|
||||||
|
title: '[Bug] <insert your title>'
|
||||||
|
labels: bug
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: "Thanks for taking the time to fill out this bug report!"
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: What happened? Also tell us what you've expect to happen.
|
||||||
|
placeholder: Describe your bug in detail.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: repro
|
||||||
|
attributes:
|
||||||
|
label: To Reproduce
|
||||||
|
description: "Steps to reproduce the behavior:"
|
||||||
|
value: |
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: files
|
||||||
|
attributes:
|
||||||
|
label: Screenshots / .ork file
|
||||||
|
description: Provide screenshots for clarification and/or the .ork file that caused the issue.
|
||||||
|
value: |
|
||||||
|
#### Screenshot(s):
|
||||||
|
*(drag-and-drop the screenshot(s) here)*
|
||||||
|
|
||||||
|
|
||||||
|
#### .ork file:
|
||||||
|
*(drag-and-drop the file here as a .zip file)*
|
||||||
|
|
||||||
|
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: version-openrocket
|
||||||
|
attributes:
|
||||||
|
label: OpenRocket version
|
||||||
|
description: In what version(s) of OpenRocket does this bug happen?
|
||||||
|
placeholder: 22.02, unstable...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: platform
|
||||||
|
attributes:
|
||||||
|
label: What platform are you running on?
|
||||||
|
options:
|
||||||
|
- Windows
|
||||||
|
- macOS
|
||||||
|
- Linux
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem here.
|
||||||
|
placeholder:
|
||||||
|
validations:
|
||||||
|
required: false
|
@ -324,6 +324,8 @@ pref.dlg.checkbox.AlwaysOpenLeftmost = Always open leftmost tab when opening a c
|
|||||||
pref.dlg.checkbox.AlwaysOpenLeftmost.ttip = <html>If checked, a component edit dialog will always pop up with the first tab selected.<br>If unchecked, the previous selected tab will be used.</html>
|
pref.dlg.checkbox.AlwaysOpenLeftmost.ttip = <html>If checked, a component edit dialog will always pop up with the first tab selected.<br>If unchecked, the previous selected tab will be used.</html>
|
||||||
pref.dlg.checkbox.ShowDiscardConfirmation = Show confirmation dialog for discarding component changes
|
pref.dlg.checkbox.ShowDiscardConfirmation = Show confirmation dialog for discarding component changes
|
||||||
pref.dlg.checkbox.ShowDiscardConfirmation.ttip = If checked, you will be asked if you want really want to discard component configuration configuration changes.
|
pref.dlg.checkbox.ShowDiscardConfirmation.ttip = If checked, you will be asked if you want really want to discard component configuration configuration changes.
|
||||||
|
pref.dlg.checkbox.ShowDiscardSimulationConfirmation = Show confirmation dialog for discarding simulation changes
|
||||||
|
pref.dlg.checkbox.ShowDiscardSimulationConfirmation.ttip = If checked, you will be asked if you want really want to discard simulation configuration configuration changes.
|
||||||
pref.dlg.lbl.User-definedthrust = User-defined thrust curves:
|
pref.dlg.lbl.User-definedthrust = User-defined thrust curves:
|
||||||
pref.dlg.lbl.Windspeed = Wind speed
|
pref.dlg.lbl.Windspeed = Wind speed
|
||||||
pref.dlg.Allthrustcurvefiles = All thrust curve files (*.eng; *.rse; *.zip; directories)
|
pref.dlg.Allthrustcurvefiles = All thrust curve files (*.eng; *.rse; *.zip; directories)
|
||||||
@ -413,6 +415,8 @@ simedtdlg.but.savedefault = Save as default
|
|||||||
simedtdlg.but.add = Add
|
simedtdlg.but.add = Add
|
||||||
simedtdlg.but.delete = Delete
|
simedtdlg.but.delete = Delete
|
||||||
simedtdlg.title.Editsim = Edit simulation
|
simedtdlg.title.Editsim = Edit simulation
|
||||||
|
simedtdlg.title.MultiSimEdit = Multi-simulation edit
|
||||||
|
simedtdlg.title.MultiSimEdit.ttip = <html>You are editing the following simulations:<br>
|
||||||
simedtdlg.lbl.Simname = Simulation name:
|
simedtdlg.lbl.Simname = Simulation name:
|
||||||
simedtdlg.tab.Launchcond = Launch conditions
|
simedtdlg.tab.Launchcond = Launch conditions
|
||||||
simedtdlg.tab.Simopt = Simulation options
|
simedtdlg.tab.Simopt = Simulation options
|
||||||
@ -522,6 +526,12 @@ SimulationEditDialog.btn.export = Export
|
|||||||
SimulationEditDialog.btn.edit = Edit
|
SimulationEditDialog.btn.edit = Edit
|
||||||
SimulationEditDialog.btn.simulate = Simulate
|
SimulationEditDialog.btn.simulate = Simulate
|
||||||
SimulationEditDialog.btn.simulateAndPlot = Simulate & Plot
|
SimulationEditDialog.btn.simulateAndPlot = Simulate & Plot
|
||||||
|
SimulationEditDialog.btn.OK.ttip = Keep changes and close the dialog
|
||||||
|
SimulationEditDialog.btn.Cancel.ttip = Discard changes and close the dialog
|
||||||
|
SimulationEditDialog.CancelOperation.msg.discardChanges = <html>Are you sure you want to <b>discard</b> your <b>changes</b> to this simulation?</html>
|
||||||
|
SimulationEditDialog.CancelOperation.msg.undoAdd = <html>Are you sure you want to <b>undo adding</b> this simulation?</html>
|
||||||
|
SimulationEditDialog.CancelOperation.title = Cancel operation
|
||||||
|
SimulationEditDialog.CancelOperation.checkbox.dontAskAgain = Don't ask me again
|
||||||
|
|
||||||
GeodeticComputationStrategy.flat.name = Flat Earth
|
GeodeticComputationStrategy.flat.name = Flat Earth
|
||||||
GeodeticComputationStrategy.flat.desc = Perform computations with a flat Earth approximation. Sufficient for low-altitude flights.
|
GeodeticComputationStrategy.flat.desc = Perform computations with a flat Earth approximation. Sufficient for low-altitude flights.
|
||||||
@ -2344,6 +2354,7 @@ PhotoSettingsConfig.lbl.lightAz = Light Azimuth
|
|||||||
PhotoSettingsConfig.lbl.lightAlt = Light Altitude
|
PhotoSettingsConfig.lbl.lightAlt = Light Altitude
|
||||||
PhotoSettingsConfig.lbl.sky = Sky
|
PhotoSettingsConfig.lbl.sky = Sky
|
||||||
PhotoSettingsConfig.lbl.skyColor = Sky Color
|
PhotoSettingsConfig.lbl.skyColor = Sky Color
|
||||||
|
PhotoSettingsConfig.lbl.skyColorOpacity = Sky Color Opacity
|
||||||
PhotoSettingsConfig.lbl.skyImage = Sky Image
|
PhotoSettingsConfig.lbl.skyImage = Sky Image
|
||||||
PhotoSettingsConfig.lbl.skyCredit = Image Credit
|
PhotoSettingsConfig.lbl.skyCredit = Image Credit
|
||||||
|
|
||||||
|
@ -234,9 +234,9 @@ public class FinSetCalc extends RocketComponentCalc {
|
|||||||
finArea = component.getPlanformArea();
|
finArea = component.getPlanformArea();
|
||||||
ar = 2 * pow2(span) / finArea;
|
ar = 2 * pow2(span) / finArea;
|
||||||
|
|
||||||
|
// Check geometry; don't consider points along fin root for this
|
||||||
|
// (doing so will cause spurious jagged fin warnings)
|
||||||
Coordinate[] points = component.getFinPoints();
|
Coordinate[] points = component.getFinPoints();
|
||||||
|
|
||||||
// Check geometry
|
|
||||||
geometryWarnings.clear();
|
geometryWarnings.clear();
|
||||||
boolean down = false;
|
boolean down = false;
|
||||||
for (int i = 1; i < points.length; i++) {
|
for (int i = 1; i < points.length; i++) {
|
||||||
@ -258,8 +258,9 @@ public class FinSetCalc extends RocketComponentCalc {
|
|||||||
geometryWarnings.add(Warning.THICK_FIN, component.toString());
|
geometryWarnings.add(Warning.THICK_FIN, component.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the chord lead and trail positions and length
|
// Calculate the chord lead and trail positions and length. We do need the points
|
||||||
|
// along the root for this
|
||||||
|
points = component.getFinPointsWithRoot();
|
||||||
Arrays.fill(chordLead, Double.POSITIVE_INFINITY);
|
Arrays.fill(chordLead, Double.POSITIVE_INFINITY);
|
||||||
Arrays.fill(chordTrail, Double.NEGATIVE_INFINITY);
|
Arrays.fill(chordTrail, Double.NEGATIVE_INFINITY);
|
||||||
Arrays.fill(chordLength, 0);
|
Arrays.fill(chordLength, 0);
|
||||||
|
@ -268,6 +268,18 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
mutex.verify();
|
mutex.verify();
|
||||||
return simulationExtensions;
|
return simulationExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the simulation extensions to the simulation.
|
||||||
|
* @param extensions the simulation extensions to apply.
|
||||||
|
*/
|
||||||
|
public void copyExtensionsFrom(List<SimulationExtension> extensions) {
|
||||||
|
if (extensions == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.simulationExtensions.clear();
|
||||||
|
this.simulationExtensions.addAll(extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,6 +361,7 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
*/
|
*/
|
||||||
public void syncModID() {
|
public void syncModID() {
|
||||||
this.simulatedConfigurationID = getActiveConfiguration().getModID();
|
this.simulatedConfigurationID = getActiveConfiguration().getModID();
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -522,6 +535,67 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
mutex.unlock("copy");
|
mutex.unlock("copy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Simulation clone() {
|
||||||
|
mutex.lock("clone");
|
||||||
|
try {
|
||||||
|
Simulation clone = (Simulation) super.clone();
|
||||||
|
|
||||||
|
clone.mutex = SafetyMutex.newInstance();
|
||||||
|
clone.name = this.name;
|
||||||
|
clone.configId = this.configId;
|
||||||
|
clone.simulatedConfigurationDescription = this.simulatedConfigurationDescription;
|
||||||
|
clone.simulatedConfigurationID = this.simulatedConfigurationID;
|
||||||
|
clone.options = this.options.clone();
|
||||||
|
clone.listeners = new ArrayList<>();
|
||||||
|
if (this.simulatedConditions != null) {
|
||||||
|
clone.simulatedConditions = this.simulatedConditions.clone();
|
||||||
|
} else {
|
||||||
|
clone.simulatedConditions = null;
|
||||||
|
}
|
||||||
|
clone.simulationExtensions = new ArrayList<>();
|
||||||
|
for (SimulationExtension c : this.simulationExtensions) {
|
||||||
|
clone.simulationExtensions.add(c.clone());
|
||||||
|
}
|
||||||
|
clone.status = this.status;
|
||||||
|
clone.simulatedData = this.simulatedData != null ? this.simulatedData.clone() : this.simulatedData;
|
||||||
|
clone.simulationStepperClass = this.simulationStepperClass;
|
||||||
|
clone.aerodynamicCalculatorClass = this.aerodynamicCalculatorClass;
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new BugException("Clone not supported, BUG", e);
|
||||||
|
} finally {
|
||||||
|
mutex.unlock("clone");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the data from the specified simulation into this simulation.
|
||||||
|
* @param simulation the simulation to load from.
|
||||||
|
*/
|
||||||
|
public void loadFrom(Simulation simulation) {
|
||||||
|
mutex.lock("loadFrom");
|
||||||
|
try {
|
||||||
|
this.name = simulation.name;
|
||||||
|
this.configId = simulation.configId;
|
||||||
|
this.simulatedConfigurationDescription = simulation.simulatedConfigurationDescription;
|
||||||
|
this.simulatedConfigurationID = simulation.simulatedConfigurationID;
|
||||||
|
this.options.copyConditionsFrom(simulation.options);
|
||||||
|
if (simulation.simulatedConditions == null) {
|
||||||
|
this.simulatedConditions = null;
|
||||||
|
} else {
|
||||||
|
this.simulatedConditions.copyConditionsFrom(simulation.simulatedConditions);
|
||||||
|
}
|
||||||
|
copyExtensionsFrom(simulation.getSimulationExtensions());
|
||||||
|
this.status = simulation.status;
|
||||||
|
this.simulatedData = simulation.simulatedData;
|
||||||
|
this.simulationStepperClass = simulation.simulationStepperClass;
|
||||||
|
this.aerodynamicCalculatorClass = simulation.aerodynamicCalculatorClass;
|
||||||
|
} finally {
|
||||||
|
mutex.unlock("loadFrom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -541,7 +615,7 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
final Simulation newSim = new Simulation(this.document, newRocket);
|
final Simulation newSim = new Simulation(this.document, newRocket);
|
||||||
newSim.name = this.name;
|
newSim.name = this.name;
|
||||||
newSim.configId = this.configId;
|
newSim.configId = this.configId;
|
||||||
newSim.options.copyFrom(this.options);
|
newSim.options.copyConditionsFrom(this.options);
|
||||||
newSim.simulatedConfigurationDescription = this.simulatedConfigurationDescription;
|
newSim.simulatedConfigurationDescription = this.simulatedConfigurationDescription;
|
||||||
for (SimulationExtension c : this.simulationExtensions) {
|
for (SimulationExtension c : this.simulationExtensions) {
|
||||||
newSim.simulationExtensions.add(c.clone());
|
newSim.simulationExtensions.add(c.clone());
|
||||||
@ -584,15 +658,9 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
|
|
||||||
|
|
||||||
private class ConditionListener implements StateChangeListener {
|
private class ConditionListener implements StateChangeListener {
|
||||||
|
|
||||||
private Status oldStatus = null;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(EventObject e) {
|
public void stateChanged(EventObject e) {
|
||||||
if (getStatus() != oldStatus) {
|
fireChangeEvent();
|
||||||
oldStatus = getStatus();
|
|
||||||
fireChangeEvent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +490,6 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
for (int i = 0; i < types.length; i++) {
|
for (int i = 0; i < types.length; i++) {
|
||||||
data.add(branch.get(types[i]));
|
data.add(branch.get(types[i]));
|
||||||
}
|
}
|
||||||
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
|
|
||||||
|
|
||||||
// Build the <databranch> tag
|
// Build the <databranch> tag
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -273,7 +273,23 @@ public class FlightData {
|
|||||||
return mutable.isMutable();
|
return mutable.isMutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FlightData clone() {
|
||||||
|
FlightData clone = new FlightData();
|
||||||
|
clone.warnings.addAll(warnings);
|
||||||
|
for (FlightDataBranch b : branches) {
|
||||||
|
clone.branches.add(b.clone());
|
||||||
|
}
|
||||||
|
clone.maxAltitude = maxAltitude;
|
||||||
|
clone.maxVelocity = maxVelocity;
|
||||||
|
clone.maxAcceleration = maxAcceleration;
|
||||||
|
clone.maxMachNumber = maxMachNumber;
|
||||||
|
clone.timeToApogee = timeToApogee;
|
||||||
|
clone.flightTime = flightTime;
|
||||||
|
clone.groundHitVelocity = groundHitVelocity;
|
||||||
|
clone.launchRodVelocity = launchRodVelocity;
|
||||||
|
clone.deploymentVelocity = deploymentVelocity;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the maximum acceleration before apogee.
|
* Find the maximum acceleration before apogee.
|
||||||
|
@ -363,5 +363,20 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
public int getModID() {
|
public int getModID() {
|
||||||
return modID;
|
return modID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FlightDataBranch clone() {
|
||||||
|
FlightDataType[] types = getTypes();
|
||||||
|
FlightDataBranch clone = new FlightDataBranch(branchName, types);
|
||||||
|
for (FlightDataType type : values.keySet()) {
|
||||||
|
clone.values.put(type, values.get(type).clone());
|
||||||
|
}
|
||||||
|
clone.minValues.putAll(minValues);
|
||||||
|
clone.maxValues.putAll(maxValues);
|
||||||
|
clone.events.addAll(events);
|
||||||
|
clone.timeToOptimumAltitude = timeToOptimumAltitude;
|
||||||
|
clone.optimumAltitude = optimumAltitude;
|
||||||
|
clone.modID = modID;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
if (MathUtil.equals(this.launchRodLength, launchRodLength))
|
if (MathUtil.equals(this.launchRodLength, launchRodLength))
|
||||||
return;
|
return;
|
||||||
this.launchRodLength = launchRodLength;
|
this.launchRodLength = launchRodLength;
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -104,7 +105,10 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setLaunchIntoWind(boolean i) {
|
public void setLaunchIntoWind(boolean i) {
|
||||||
|
if (launchIntoWind == i)
|
||||||
|
return;
|
||||||
launchIntoWind = i;
|
launchIntoWind = i;
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getLaunchRodAngle() {
|
public double getLaunchRodAngle() {
|
||||||
@ -404,28 +408,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void copyFrom(SimulationOptions src) {
|
|
||||||
|
|
||||||
this.launchAltitude = src.launchAltitude;
|
|
||||||
this.launchLatitude = src.launchLatitude;
|
|
||||||
this.launchLongitude = src.launchLongitude;
|
|
||||||
this.launchPressure = src.launchPressure;
|
|
||||||
this.launchRodAngle = src.launchRodAngle;
|
|
||||||
this.launchRodDirection = src.launchRodDirection;
|
|
||||||
this.launchRodLength = src.launchRodLength;
|
|
||||||
this.launchTemperature = src.launchTemperature;
|
|
||||||
this.maximumAngle = src.maximumAngle;
|
|
||||||
this.timeStep = src.timeStep;
|
|
||||||
this.windAverage = src.windAverage;
|
|
||||||
this.windTurbulence = src.windTurbulence;
|
|
||||||
this.windDirection = src.windDirection;
|
|
||||||
this.calculateExtras = src.calculateExtras;
|
|
||||||
this.randomSeed = src.randomSeed;
|
|
||||||
|
|
||||||
fireChangeEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void copyConditionsFrom(SimulationOptions src) {
|
public void copyConditionsFrom(SimulationOptions src) {
|
||||||
// Be a little smart about triggering the change event.
|
// Be a little smart about triggering the change event.
|
||||||
// only do it if one of the "important" (user specified) parameters has really changed.
|
// only do it if one of the "important" (user specified) parameters has really changed.
|
||||||
@ -442,10 +424,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.launchLongitude = src.launchLongitude;
|
this.launchLongitude = src.launchLongitude;
|
||||||
}
|
}
|
||||||
if (this.launchPressure != src.launchPressure) {
|
|
||||||
isChanged = true;
|
|
||||||
this.launchPressure = src.launchPressure;
|
|
||||||
}
|
|
||||||
if (this.launchRodAngle != src.launchRodAngle) {
|
if (this.launchRodAngle != src.launchRodAngle) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.launchRodAngle = src.launchRodAngle;
|
this.launchRodAngle = src.launchRodAngle;
|
||||||
@ -458,19 +436,26 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.launchRodLength = src.launchRodLength;
|
this.launchRodLength = src.launchRodLength;
|
||||||
}
|
}
|
||||||
|
if (this.launchIntoWind != src.launchIntoWind) {
|
||||||
|
isChanged = true;
|
||||||
|
this.launchIntoWind = src.launchIntoWind;
|
||||||
|
}
|
||||||
|
if (this.useISA != src.useISA) {
|
||||||
|
isChanged = true;
|
||||||
|
this.useISA = src.useISA;
|
||||||
|
}
|
||||||
if (this.launchTemperature != src.launchTemperature) {
|
if (this.launchTemperature != src.launchTemperature) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.launchTemperature = src.launchTemperature;
|
this.launchTemperature = src.launchTemperature;
|
||||||
}
|
}
|
||||||
|
if (this.launchPressure != src.launchPressure) {
|
||||||
|
isChanged = true;
|
||||||
|
this.launchPressure = src.launchPressure;
|
||||||
|
}
|
||||||
if (this.maximumAngle != src.maximumAngle) {
|
if (this.maximumAngle != src.maximumAngle) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.maximumAngle = src.maximumAngle;
|
this.maximumAngle = src.maximumAngle;
|
||||||
}
|
}
|
||||||
this.maximumAngle = src.maximumAngle;
|
|
||||||
if (this.timeStep != src.timeStep) {
|
|
||||||
isChanged = true;
|
|
||||||
this.timeStep = src.timeStep;
|
|
||||||
}
|
|
||||||
if (this.windAverage != src.windAverage) {
|
if (this.windAverage != src.windAverage) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.windAverage = src.windAverage;
|
this.windAverage = src.windAverage;
|
||||||
@ -487,6 +472,14 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
isChanged = true;
|
isChanged = true;
|
||||||
this.calculateExtras = src.calculateExtras;
|
this.calculateExtras = src.calculateExtras;
|
||||||
}
|
}
|
||||||
|
if (this.timeStep != src.timeStep) {
|
||||||
|
isChanged = true;
|
||||||
|
this.timeStep = src.timeStep;
|
||||||
|
}
|
||||||
|
if (this.geodeticComputation != src.geodeticComputation) {
|
||||||
|
isChanged = true;
|
||||||
|
this.geodeticComputation = src.geodeticComputation;
|
||||||
|
}
|
||||||
|
|
||||||
if (isChanged) {
|
if (isChanged) {
|
||||||
// Only copy the randomSeed if something else has changed.
|
// Only copy the randomSeed if something else has changed.
|
||||||
@ -539,6 +532,10 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
public void removeChangeListener(StateChangeListener listener) {
|
public void removeChangeListener(StateChangeListener listener) {
|
||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<EventListener> getChangeListeners() {
|
||||||
|
return listeners;
|
||||||
|
}
|
||||||
|
|
||||||
private final EventObject event = new EventObject(this);
|
private final EventObject event = new EventObject(this);
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN";
|
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 OPEN_LEFTMOST_DESIGN_TAB = "OPEN_LEFTMOST_DESIGN_TAB";
|
||||||
private static final String SHOW_DISCARD_CONFIRMATION = "IgnoreDiscardEditingWarning";
|
private static final String SHOW_DISCARD_CONFIRMATION = "IgnoreDiscardEditingWarning";
|
||||||
|
private static final String SHOW_DISCARD_SIMULATION_CONFIRMATION = "IgnoreDiscardSimulationEditingWarning";
|
||||||
public static final String MARKER_STYLE_ICON = "MARKER_STYLE_ICON";
|
public static final String MARKER_STYLE_ICON = "MARKER_STYLE_ICON";
|
||||||
private static final String SHOW_MARKERS = "SHOW_MARKERS";
|
private static final String SHOW_MARKERS = "SHOW_MARKERS";
|
||||||
private static final String SHOW_RASAERO_FORMAT_WARNING = "SHOW_RASAERO_FORMAT_WARNING";
|
private static final String SHOW_RASAERO_FORMAT_WARNING = "SHOW_RASAERO_FORMAT_WARNING";
|
||||||
@ -546,6 +547,22 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
this.putBoolean(SHOW_DISCARD_CONFIRMATION, enabled);
|
this.putBoolean(SHOW_DISCARD_CONFIRMATION, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer if a confirmation dialog should be shown when canceling a simulation config operation.
|
||||||
|
*
|
||||||
|
* @return true if the confirmation dialog should be shown.
|
||||||
|
*/
|
||||||
|
public final boolean isShowDiscardSimulationConfirmation() {
|
||||||
|
return this.getBoolean(SHOW_DISCARD_SIMULATION_CONFIRMATION, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/Disable showing a confirmation warning when canceling a simulation config operation.
|
||||||
|
*/
|
||||||
|
public final void setShowDiscardSimulationConfirmation(boolean enabled) {
|
||||||
|
this.putBoolean(SHOW_DISCARD_SIMULATION_CONFIRMATION, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Answer if the always open leftmost tab is enabled.
|
* Answer if the always open leftmost tab is enabled.
|
||||||
*
|
*
|
||||||
|
@ -1557,4 +1557,49 @@ public class FreeformFinSetTest extends BaseTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that fins on transitions don't get NaN MAClength
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFinsOnTransitions() {
|
||||||
|
// Rocket consisting of just a transition and a freeform fin set
|
||||||
|
final Rocket rocket = new Rocket();
|
||||||
|
|
||||||
|
final AxialStage stage = new AxialStage();
|
||||||
|
rocket.addChild(stage);
|
||||||
|
|
||||||
|
Transition trans = new Transition();
|
||||||
|
stage.addChild(trans);
|
||||||
|
|
||||||
|
FreeformFinSet fins = new FreeformFinSet();
|
||||||
|
trans.addChild(fins);
|
||||||
|
|
||||||
|
// set the finset at the beginning of the transition
|
||||||
|
fins.setAxialMethod(AxialMethod.TOP);
|
||||||
|
fins.setAxialOffset(0.0);
|
||||||
|
|
||||||
|
// Test 1: transition getting smaller
|
||||||
|
trans.setForeRadius(trans.getForeRadius()*2.0);
|
||||||
|
fins.setPoints(new Coordinate[] {
|
||||||
|
new Coordinate(0, 0),
|
||||||
|
new Coordinate(trans.getLength(), 0),
|
||||||
|
new Coordinate(trans.getLength(), trans.getAftRadius() - trans.getForeRadius())
|
||||||
|
});
|
||||||
|
FinSetCalc calc = new FinSetCalc(fins);
|
||||||
|
|
||||||
|
assertEquals(0.075, calc.getMACLength(), EPSILON);
|
||||||
|
|
||||||
|
// Test 2: transition getting larger
|
||||||
|
trans.setForeRadius(trans.getAftRadius());
|
||||||
|
trans.setAftRadius(trans.getAftRadius()*2.0);
|
||||||
|
fins.setPoints(new Coordinate[] {
|
||||||
|
new Coordinate(0, 0),
|
||||||
|
new Coordinate(0, trans.getAftRadius() - trans.getForeRadius()),
|
||||||
|
new Coordinate(trans.getLength(), trans.getAftRadius() - trans.getForeRadius())
|
||||||
|
});
|
||||||
|
calc = new FinSetCalc(fins);
|
||||||
|
|
||||||
|
assertEquals(0.05053191489361704, calc.getMACLength(), EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,7 @@ public class BulkheadConfig extends RingComponentConfig {
|
|||||||
|
|
||||||
JPanel tab;
|
JPanel tab;
|
||||||
|
|
||||||
tab = generalTab(trans.get("BulkheadCfg.tab.Diameter"), null, null,
|
tab = generalTab(trans.get("BulkheadCfg.tab.Thickness"), trans.get("BulkheadCfg.tab.Diameter"), null, null);
|
||||||
trans.get("BulkheadCfg.tab.Thickness"));
|
|
||||||
//// General and General properties
|
//// General and General properties
|
||||||
tabbedPane.insertTab(trans.get("BulkheadCfg.tab.General"), null, tab,
|
tabbedPane.insertTab(trans.get("BulkheadCfg.tab.General"), null, tab,
|
||||||
trans.get("BulkheadCfg.tab.Generalproperties"), 0);
|
trans.get("BulkheadCfg.tab.Generalproperties"), 0);
|
||||||
|
@ -22,9 +22,8 @@ public class CenteringRingConfig extends RingComponentConfig {
|
|||||||
JPanel tab;
|
JPanel tab;
|
||||||
|
|
||||||
//// Outer diameter: and Inner diameter: and Thickness:
|
//// Outer diameter: and Inner diameter: and Thickness:
|
||||||
tab = generalTab(trans.get("CenteringRingCfg.tab.Outerdiam"),
|
tab = generalTab(trans.get("CenteringRingCfg.tab.Thickness"), trans.get("CenteringRingCfg.tab.Outerdiam"),
|
||||||
trans.get("CenteringRingCfg.tab.Innerdiam"), null,
|
trans.get("CenteringRingCfg.tab.Innerdiam"), null);
|
||||||
trans.get("CenteringRingCfg.tab.Thickness"));
|
|
||||||
//// General and General properties
|
//// General and General properties
|
||||||
tabbedPane.insertTab(trans.get("CenteringRingCfg.tab.General"), null, tab,
|
tabbedPane.insertTab(trans.get("CenteringRingCfg.tab.General"), null, tab,
|
||||||
trans.get("CenteringRingCfg.tab.Generalproperties"), 0);
|
trans.get("CenteringRingCfg.tab.Generalproperties"), 0);
|
||||||
|
@ -71,6 +71,19 @@ public class InnerTubeConfig extends RocketComponentConfig {
|
|||||||
|
|
||||||
//// ---------------------------- Attributes ----------------------------
|
//// ---------------------------- Attributes ----------------------------
|
||||||
|
|
||||||
|
//// Length
|
||||||
|
panel.add(new JLabel(trans.get("ThicknessRingCompCfg.tab.Length")));
|
||||||
|
m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
focusElement = spin;
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
order.add(((SpinnerEditor) spin.getEditor()).getTextField());
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap");
|
||||||
|
|
||||||
//// Outer diameter
|
//// Outer diameter
|
||||||
panel.add(new JLabel(trans.get("ThicknessRingCompCfg.tab.Outerdiam")));
|
panel.add(new JLabel(trans.get("ThicknessRingCompCfg.tab.Outerdiam")));
|
||||||
|
|
||||||
@ -128,22 +141,6 @@ public class InnerTubeConfig extends RocketComponentConfig {
|
|||||||
panel.add(new UnitSelector(m), "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)), "w 100lp, wrap");
|
||||||
|
|
||||||
|
|
||||||
//// Inner tube length
|
|
||||||
panel.add(new JLabel(trans.get("ThicknessRingCompCfg.tab.Length")));
|
|
||||||
|
|
||||||
//// Length
|
|
||||||
m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
|
|
||||||
|
|
||||||
spin = new JSpinner(m.getSpinnerModel());
|
|
||||||
spin.setEditor(new SpinnerEditor(spin));
|
|
||||||
focusElement = spin;
|
|
||||||
panel.add(spin, "growx");
|
|
||||||
order.add(((SpinnerEditor) spin.getEditor()).getTextField());
|
|
||||||
|
|
||||||
panel.add(new UnitSelector(m), "growx");
|
|
||||||
panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap");
|
|
||||||
|
|
||||||
mainPanel.add(panel, "aligny 0, gapright 40lp");
|
mainPanel.add(panel, "aligny 0, gapright 40lp");
|
||||||
|
|
||||||
//// Right side of panel ----
|
//// Right side of panel ----
|
||||||
|
@ -29,7 +29,7 @@ public class RingComponentConfig extends RocketComponentConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected JPanel generalTab(String outer, String inner, String thickness, String length) {
|
protected JPanel generalTab(String length, String outer, String inner, String thickness) {
|
||||||
JPanel primary = new JPanel(new MigLayout());
|
JPanel primary = new JPanel(new MigLayout());
|
||||||
|
|
||||||
JPanel panel = new JPanel(new MigLayout("gap rel unrel, ins 0", "[][65lp::][30lp::]", ""));
|
JPanel panel = new JPanel(new MigLayout("gap rel unrel, ins 0", "[][65lp::][30lp::]", ""));
|
||||||
@ -39,6 +39,24 @@ public class RingComponentConfig extends RocketComponentConfig {
|
|||||||
|
|
||||||
//// Attributes ----
|
//// Attributes ----
|
||||||
|
|
||||||
|
//// Length
|
||||||
|
if (length != null) {
|
||||||
|
panel.add(new JLabel(length));
|
||||||
|
|
||||||
|
m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
if (component instanceof ThicknessRingComponent) {
|
||||||
|
focusElement = spin;
|
||||||
|
}
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
order.add(((SpinnerEditor) spin.getEditor()).getTextField());
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap");
|
||||||
|
}
|
||||||
|
|
||||||
//// Outer diameter
|
//// Outer diameter
|
||||||
if (outer != null) {
|
if (outer != null) {
|
||||||
panel.add(new JLabel(outer));
|
panel.add(new JLabel(outer));
|
||||||
@ -110,26 +128,6 @@ public class RingComponentConfig extends RocketComponentConfig {
|
|||||||
panel.add(new UnitSelector(m), "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)), "w 100lp, wrap");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Inner tube length
|
|
||||||
if (length != null) {
|
|
||||||
panel.add(new JLabel(length));
|
|
||||||
|
|
||||||
//// Length
|
|
||||||
m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
|
|
||||||
|
|
||||||
spin = new JSpinner(m.getSpinnerModel());
|
|
||||||
spin.setEditor(new SpinnerEditor(spin));
|
|
||||||
if (component instanceof ThicknessRingComponent) {
|
|
||||||
focusElement = spin;
|
|
||||||
}
|
|
||||||
panel.add(spin, "growx");
|
|
||||||
order.add(((SpinnerEditor) spin.getEditor()).getTextField());
|
|
||||||
|
|
||||||
panel.add(new UnitSelector(m), "growx");
|
|
||||||
panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap");
|
|
||||||
}
|
|
||||||
|
|
||||||
primary.add(panel, "grow, gapright 40lp");
|
primary.add(panel, "grow, gapright 40lp");
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ public class SleeveConfig extends RingComponentConfig {
|
|||||||
//// Inner diameter:
|
//// Inner diameter:
|
||||||
//// Wall thickness:
|
//// Wall thickness:
|
||||||
//// Length:
|
//// Length:
|
||||||
tab = generalTab(trans.get("SleeveCfg.tab.Outerdiam"), trans.get("SleeveCfg.tab.Innerdiam"),
|
tab = generalTab(trans.get("SleeveCfg.tab.Length"), trans.get("SleeveCfg.tab.Outerdiam"),
|
||||||
trans.get("SleeveCfg.tab.Wallthickness"), trans.get("SleeveCfg.tab.Length"));
|
trans.get("SleeveCfg.tab.Innerdiam"), trans.get("SleeveCfg.tab.Wallthickness"));
|
||||||
//// General and General properties
|
//// General and General properties
|
||||||
tabbedPane.insertTab(trans.get("SleeveCfg.tab.General"), null, tab,
|
tabbedPane.insertTab(trans.get("SleeveCfg.tab.General"), null, tab,
|
||||||
trans.get("SleeveCfg.tab.Generalproperties"), 0);
|
trans.get("SleeveCfg.tab.Generalproperties"), 0);
|
||||||
|
@ -19,14 +19,14 @@ public class ThicknessRingComponentConfig extends RingComponentConfig {
|
|||||||
super(d, c, parent);
|
super(d, c, parent);
|
||||||
|
|
||||||
JPanel tab;
|
JPanel tab;
|
||||||
|
|
||||||
|
//// Length:
|
||||||
//// Outer diameter:
|
//// Outer diameter:
|
||||||
//// Inner diameter:
|
//// Inner diameter:
|
||||||
//// Wall thickness:
|
//// Wall thickness:
|
||||||
//// Length:
|
tab = generalTab(trans.get("ThicknessRingCompCfg.tab.Length"), trans.get("ThicknessRingCompCfg.tab.Outerdiam"),
|
||||||
tab = generalTab(trans.get("ThicknessRingCompCfg.tab.Outerdiam"),
|
|
||||||
trans.get("ThicknessRingCompCfg.tab.Innerdiam"),
|
trans.get("ThicknessRingCompCfg.tab.Innerdiam"),
|
||||||
trans.get("ThicknessRingCompCfg.tab.Wallthickness"), trans.get("ThicknessRingCompCfg.tab.Length"));
|
trans.get("ThicknessRingCompCfg.tab.Wallthickness"));
|
||||||
//// General and General properties
|
//// General and General properties
|
||||||
tabbedPane.insertTab(trans.get("ThicknessRingCompCfg.tab.General"), null, tab,
|
tabbedPane.insertTab(trans.get("ThicknessRingCompCfg.tab.General"), null, tab,
|
||||||
trans.get("ThicknessRingCompCfg.tab.Generalprop"), 0);
|
trans.get("ThicknessRingCompCfg.tab.Generalprop"), 0);
|
||||||
|
@ -25,6 +25,8 @@ public class MotorMountConfigurationPanel extends JPanel {
|
|||||||
table.setShowVerticalLines(false);
|
table.setShowVerticalLines(false);
|
||||||
table.setRowSelectionAllowed(false);
|
table.setRowSelectionAllowed(false);
|
||||||
table.setColumnSelectionAllowed(false);
|
table.setColumnSelectionAllowed(false);
|
||||||
|
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||||
|
table.setAutoCreateColumnsFromModel(false);
|
||||||
|
|
||||||
TableColumnModel columnModel = table.getColumnModel();
|
TableColumnModel columnModel = table.getColumnModel();
|
||||||
TableColumn col0 = columnModel.getColumn(0);
|
TableColumn col0 = columnModel.getColumn(0);
|
||||||
|
@ -24,7 +24,7 @@ class MotorMountTableModel extends AbstractTableModel implements ComponentChange
|
|||||||
private final Rocket rocket;
|
private final Rocket rocket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param motorConfigurationPanel
|
* @param rocket the rocket to select motor mounts from
|
||||||
*/
|
*/
|
||||||
MotorMountTableModel( Rocket rocket) {
|
MotorMountTableModel( Rocket rocket) {
|
||||||
this.rocket = rocket;
|
this.rocket = rocket;
|
||||||
|
@ -115,6 +115,19 @@ public class DesignPreferencesPanel extends PreferencesPanel {
|
|||||||
});
|
});
|
||||||
this.add(showDiscardConfirmation, "wrap, growx, spanx");
|
this.add(showDiscardConfirmation, "wrap, growx, spanx");
|
||||||
|
|
||||||
|
// // Show confirmation dialog for discarding simulation configuration changes
|
||||||
|
final JCheckBox showDiscardSimulationConfirmation = new JCheckBox(
|
||||||
|
trans.get("pref.dlg.checkbox.ShowDiscardSimulationConfirmation"));
|
||||||
|
showDiscardSimulationConfirmation.setSelected(preferences.isShowDiscardSimulationConfirmation());
|
||||||
|
showDiscardSimulationConfirmation.setToolTipText(trans.get("pref.dlg.checkbox.ShowDiscardSimulationConfirmation.ttip"));
|
||||||
|
showDiscardSimulationConfirmation.addItemListener(new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
preferences.setShowDiscardSimulationConfirmation(e.getStateChange() == ItemEvent.SELECTED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add(showDiscardSimulationConfirmation, "wrap, growx, spanx");
|
||||||
|
|
||||||
// // Update flight estimates in the design window
|
// // Update flight estimates in the design window
|
||||||
final JCheckBox updateEstimates = new JCheckBox(
|
final JCheckBox updateEstimates = new JCheckBox(
|
||||||
trans.get("pref.dlg.checkbox.Updateestimates"));
|
trans.get("pref.dlg.checkbox.Updateestimates"));
|
||||||
|
@ -97,6 +97,7 @@ public class PreferencesDialog extends JDialog {
|
|||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.getRocketPanel().updateExtras();
|
parent.getRocketPanel().updateExtras();
|
||||||
parent.getRocketPanel().updateFigures();
|
parent.getRocketPanel().updateFigures();
|
||||||
|
parent.getRocketPanel().updateRulers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -156,6 +156,7 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
final GLProfile glp = GLProfile.get(GLProfile.GL2);
|
final GLProfile glp = GLProfile.get(GLProfile.GL2);
|
||||||
|
|
||||||
final GLCapabilities caps = new GLCapabilities(glp);
|
final GLCapabilities caps = new GLCapabilities(glp);
|
||||||
|
caps.setBackgroundOpaque(false);
|
||||||
|
|
||||||
if (Application.getPreferences().getBoolean(
|
if (Application.getPreferences().getBoolean(
|
||||||
Preferences.OPENGL_ENABLE_AA, true)) {
|
Preferences.OPENGL_ENABLE_AA, true)) {
|
||||||
@ -169,10 +170,12 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
Preferences.OPENGL_USE_FBO, false)) {
|
Preferences.OPENGL_USE_FBO, false)) {
|
||||||
log.trace("GL - Creating GLJPanel");
|
log.trace("GL - Creating GLJPanel");
|
||||||
canvas = new GLJPanel(caps);
|
canvas = new GLJPanel(caps);
|
||||||
|
((GLJPanel) canvas).setOpaque(false);
|
||||||
} else {
|
} else {
|
||||||
log.trace("GL - Creating GLCanvas");
|
log.trace("GL - Creating GLCanvas");
|
||||||
canvas = new GLCanvas(caps);
|
canvas = new GLCanvas(caps);
|
||||||
}
|
}
|
||||||
|
canvas.setBackground(new java.awt.Color(0, 0, 0, 0));
|
||||||
|
|
||||||
((GLAutoDrawable) canvas).addGLEventListener(this);
|
((GLAutoDrawable) canvas).addGLEventListener(this);
|
||||||
this.add(canvas, BorderLayout.CENTER);
|
this.add(canvas, BorderLayout.CENTER);
|
||||||
@ -277,7 +280,7 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
|
|
||||||
if (!imageCallbacks.isEmpty()) {
|
if (!imageCallbacks.isEmpty()) {
|
||||||
BufferedImage i = (new AWTGLReadBufferUtil(
|
BufferedImage i = (new AWTGLReadBufferUtil(
|
||||||
GLProfile.get(GLProfile.GL2), false))
|
GLProfile.get(GLProfile.GL2), true)) // Set the second parameter to true
|
||||||
.readPixelsToBufferedImage(drawable.getGL(), 0, 0,
|
.readPixelsToBufferedImage(drawable.getGL(), 0, 0,
|
||||||
drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), true);
|
drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), true);
|
||||||
final Vector<ImageCallback> cbs = new Vector<PhotoPanel.ImageCallback>(
|
final Vector<ImageCallback> cbs = new Vector<PhotoPanel.ImageCallback>(
|
||||||
@ -298,18 +301,41 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
out[0] = 1;
|
out[0] = 1;
|
||||||
out[1] = 1;
|
out[1] = 1;
|
||||||
out[2] = 0;
|
out[2] = 0;
|
||||||
|
out[3] = 1;
|
||||||
} else {
|
} else {
|
||||||
out[0] = (float) color.getRed() / 255f;
|
out[0] = (float) color.getRed() / 255f;
|
||||||
out[1] = (float) color.getGreen() / 255f;
|
out[1] = (float) color.getGreen() / 255f;
|
||||||
out[2] = (float) color.getBlue() / 255f;
|
out[2] = (float) color.getBlue() / 255f;
|
||||||
|
out[3] = (float) color.getAlpha() / 255f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blend two colors
|
||||||
|
* @param color1 first color to blend
|
||||||
|
* @param color2 second color to blend
|
||||||
|
* @param ratio blend ratio. 0 = full color 1, 0.5 = mid-blend, 1 = full color 2
|
||||||
|
* @return blended color
|
||||||
|
*/
|
||||||
|
private static Color blendColors(Color color1, Color color2, double ratio) {
|
||||||
|
if (ratio < 0 || ratio > 1) {
|
||||||
|
throw new IllegalArgumentException("Blend ratio must be between 0 and 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
double inverseRatio = 1 - ratio;
|
||||||
|
|
||||||
|
int r = (int) ((color1.getRed() * inverseRatio) + (color2.getRed() * ratio));
|
||||||
|
int g = (int) ((color1.getGreen() * inverseRatio) + (color2.getGreen() * ratio));
|
||||||
|
int b = (int) ((color1.getBlue() * inverseRatio) + (color2.getBlue() * ratio));
|
||||||
|
|
||||||
|
return new Color(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
private void draw(final GLAutoDrawable drawable, float dx) {
|
private void draw(final GLAutoDrawable drawable, float dx) {
|
||||||
GL2 gl = drawable.getGL().getGL2();
|
GL2 gl = drawable.getGL().getGL2();
|
||||||
GLU glu = new GLU();
|
GLU glu = new GLU();
|
||||||
|
|
||||||
float[] color = new float[3];
|
float[] color = new float[4];
|
||||||
|
|
||||||
gl.glEnable(GL.GL_MULTISAMPLE);
|
gl.glEnable(GL.GL_MULTISAMPLE);
|
||||||
|
|
||||||
@ -333,8 +359,16 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
new float[] { spc * color[0], spc * color[1], spc * color[2], 1 },
|
new float[] { spc * color[0], spc * color[1], spc * color[2], 1 },
|
||||||
0);
|
0);
|
||||||
|
|
||||||
convertColor(p.getSkyColor(), color);
|
// Machines that don't use off-screen rendering can't render transparent background, so we create it
|
||||||
gl.glClearColor(color[0], color[1], color[2], 1);
|
// artificially by blending the sky color with white (= color that is rendered as transparent background)
|
||||||
|
if (!Application.getPreferences().getBoolean(
|
||||||
|
Preferences.OPENGL_USE_FBO, false)) {
|
||||||
|
convertColor(blendColors(p.getSkyColor(), new Color(255, 255, 255), 1-p.getSkyColorOpacity()),
|
||||||
|
color);
|
||||||
|
} else {
|
||||||
|
convertColor(p.getSkyColor(), color);
|
||||||
|
}
|
||||||
|
gl.glClearColor(color[0], color[1], color[2], color[3]);
|
||||||
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
|
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
||||||
|
@ -24,6 +24,7 @@ public class PhotoSettings extends AbstractChangeSource implements FlameSettings
|
|||||||
private double ambiance = .3f;
|
private double ambiance = .3f;
|
||||||
|
|
||||||
private Color skyColor = new Color(55, 95, 155);
|
private Color skyColor = new Color(55, 95, 155);
|
||||||
|
private double skyColorOpacity = 1.0;
|
||||||
|
|
||||||
|
|
||||||
private boolean motionBlurred = false;
|
private boolean motionBlurred = false;
|
||||||
@ -186,9 +187,20 @@ public class PhotoSettings extends AbstractChangeSource implements FlameSettings
|
|||||||
|
|
||||||
public void setSkyColor(Color skyColor) {
|
public void setSkyColor(Color skyColor) {
|
||||||
this.skyColor = skyColor;
|
this.skyColor = skyColor;
|
||||||
|
this.skyColorOpacity = skyColor.getAlpha() / 255f;
|
||||||
fireChangeEvent();
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getSkyColorOpacity() {
|
||||||
|
return skyColorOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkyColorOpacity(double skyColorOpacity) {
|
||||||
|
this.skyColorOpacity = skyColorOpacity;
|
||||||
|
skyColor.setAlpha((int) (skyColorOpacity * 255));
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
|
|
||||||
public Color getFlameColor() {
|
public Color getFlameColor() {
|
||||||
return flameColor;
|
return flameColor;
|
||||||
}
|
}
|
||||||
|
@ -256,10 +256,10 @@ public class PhotoSettingsConfig extends JTabbedPane {
|
|||||||
|
|
||||||
/// Light altitude
|
/// Light altitude
|
||||||
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAlt")));
|
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAlt")));
|
||||||
DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE, -Math.PI / 2, Math.PI / 2);
|
DoubleModel lightAltModel = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE, -Math.PI / 2, Math.PI / 2);
|
||||||
add(new EditableSpinner(lightAltModle.getSpinnerModel()), "growx, split 2");
|
add(new EditableSpinner(lightAltModel.getSpinnerModel()), "growx, split 2");
|
||||||
add(new UnitSelector(lightAltModle));
|
add(new UnitSelector(lightAltModel));
|
||||||
add(new BasicSlider(lightAltModle.getSliderModel(-Math.PI / 2, Math.PI / 2)), "wrap");
|
add(new BasicSlider(lightAltModel.getSliderModel(-Math.PI / 2, Math.PI / 2)), "wrap");
|
||||||
|
|
||||||
// Sky
|
// Sky
|
||||||
add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.sky"), Style.BOLD), "split, span, gapright para");
|
add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.sky"), Style.BOLD), "split, span, gapright para");
|
||||||
@ -269,6 +269,17 @@ public class PhotoSettingsConfig extends JTabbedPane {
|
|||||||
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.skyColor")));
|
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.skyColor")));
|
||||||
add(skyColorButton, "wrap");
|
add(skyColorButton, "wrap");
|
||||||
|
|
||||||
|
/// Sky color opacity
|
||||||
|
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.skyColorOpacity")));
|
||||||
|
DoubleModel skyColorOpacityModel = new DoubleModel(p, "SkyColorOpacity", UnitGroup.UNITS_RELATIVE, 0, 1);
|
||||||
|
EditableSpinner skyColorOpacitySpinner = new EditableSpinner(skyColorOpacityModel.getSpinnerModel());
|
||||||
|
add(skyColorOpacitySpinner, "growx, split 2");
|
||||||
|
UnitSelector skyColorOpacityUnitSelector = new UnitSelector(skyColorOpacityModel);
|
||||||
|
add(skyColorOpacityUnitSelector);
|
||||||
|
BasicSlider skyColorOpacitySlider = new BasicSlider(skyColorOpacityModel.getSliderModel());
|
||||||
|
add(skyColorOpacitySlider, "wrap");
|
||||||
|
p.addChangeListener(skyColorOpacityModel);
|
||||||
|
|
||||||
/// Sky image
|
/// Sky image
|
||||||
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.skyImage")));
|
add(new JLabel(trans.get("PhotoSettingsConfig.lbl.skyImage")));
|
||||||
|
|
||||||
@ -293,9 +304,15 @@ public class PhotoSettingsConfig extends JTabbedPane {
|
|||||||
if (s instanceof Sky && s != noSky) {
|
if (s instanceof Sky && s != noSky) {
|
||||||
p.setSky((Sky) s);
|
p.setSky((Sky) s);
|
||||||
skyColorButton.setEnabled(false);
|
skyColorButton.setEnabled(false);
|
||||||
|
skyColorOpacitySpinner.setEnabled(false);
|
||||||
|
skyColorOpacityUnitSelector.setEnabled(false);
|
||||||
|
skyColorOpacitySlider.setEnabled(false);
|
||||||
} else if (s == noSky) {
|
} else if (s == noSky) {
|
||||||
p.setSky(null);
|
p.setSky(null);
|
||||||
skyColorButton.setEnabled(true);
|
skyColorButton.setEnabled(true);
|
||||||
|
skyColorOpacitySpinner.setEnabled(true);
|
||||||
|
skyColorOpacityUnitSelector.setEnabled(true);
|
||||||
|
skyColorOpacitySlider.setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -515,12 +515,12 @@ public class BasicFrame extends JFrame {
|
|||||||
fileMenu.add(item);
|
fileMenu.add(item);
|
||||||
|
|
||||||
//// Edit
|
//// Edit
|
||||||
fileMenu = new JMenu(trans.get("main.menu.edit"));
|
JMenu editMenu = new JMenu(trans.get("main.menu.edit"));
|
||||||
fileMenu.setMnemonic(KeyEvent.VK_E);
|
editMenu.setMnemonic(KeyEvent.VK_E);
|
||||||
|
|
||||||
//// Rocket editing
|
//// Rocket editing
|
||||||
fileMenu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.desc"));
|
editMenu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.desc"));
|
||||||
menubar.add(fileMenu);
|
menubar.add(editMenu);
|
||||||
|
|
||||||
Action action = UndoRedoAction.newUndoAction(document);
|
Action action = UndoRedoAction.newUndoAction(document);
|
||||||
item = new JMenuItem(action);
|
item = new JMenuItem(action);
|
||||||
@ -530,7 +530,7 @@ public class BasicFrame extends JFrame {
|
|||||||
//// Undo the previous operation
|
//// Undo the previous operation
|
||||||
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.undo.desc"));
|
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.undo.desc"));
|
||||||
|
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
action = UndoRedoAction.newRedoAction(document);
|
action = UndoRedoAction.newRedoAction(document);
|
||||||
item = new JMenuItem(action);
|
item = new JMenuItem(action);
|
||||||
@ -539,42 +539,42 @@ public class BasicFrame extends JFrame {
|
|||||||
|
|
||||||
//// Redo the previously undone operation
|
//// Redo the previously undone operation
|
||||||
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.redo.desc"));
|
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.redo.desc"));
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
fileMenu.addSeparator();
|
editMenu.addSeparator();
|
||||||
|
|
||||||
|
|
||||||
item = new JMenuItem(actions.getEditAction());
|
item = new JMenuItem(actions.getEditAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(actions.getCutAction());
|
item = new JMenuItem(actions.getCutAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(actions.getCopyAction());
|
item = new JMenuItem(actions.getCopyAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(actions.getPasteAction());
|
item = new JMenuItem(actions.getPasteAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(actions.getDuplicateAction());
|
item = new JMenuItem(actions.getDuplicateAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(actions.getDeleteAction());
|
item = new JMenuItem(actions.getDeleteAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
fileMenu.addSeparator();
|
editMenu.addSeparator();
|
||||||
|
|
||||||
JMenu subMenu = new JMenu(trans.get("RocketActions.Select"));
|
JMenu subMenu = new JMenu(trans.get("RocketActions.Select"));
|
||||||
fileMenu.add(subMenu);
|
editMenu.add(subMenu);
|
||||||
item = new JMenuItem(actions.getSelectSameColorAction());
|
item = new JMenuItem(actions.getSelectSameColorAction());
|
||||||
subMenu.add(item);
|
subMenu.add(item);
|
||||||
item = new JMenuItem(actions.getDeselectAllAction());
|
item = new JMenuItem(actions.getDeselectAllAction());
|
||||||
subMenu.add(item);
|
subMenu.add(item);
|
||||||
|
|
||||||
fileMenu.addSeparator();
|
editMenu.addSeparator();
|
||||||
|
|
||||||
item = new JMenuItem(actions.getScaleAction());
|
item = new JMenuItem(actions.getScaleAction());
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
|
|
||||||
//// Preferences
|
//// Preferences
|
||||||
@ -590,7 +590,7 @@ public class BasicFrame extends JFrame {
|
|||||||
PreferencesDialog.showPreferences(BasicFrame.this);
|
PreferencesDialog.showPreferences(BasicFrame.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
|
|
||||||
//// Edit Component Preset File
|
//// Edit Component Preset File
|
||||||
if (System.getProperty("openrocket.preseteditor.fileMenu") != null) {
|
if (System.getProperty("openrocket.preseteditor.fileMenu") != null) {
|
||||||
@ -605,13 +605,13 @@ public class BasicFrame extends JFrame {
|
|||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
editMenu.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
fileMenu = new JMenu(trans.get("main.menu.tools"));
|
JMenu toolsMenu = new JMenu(trans.get("main.menu.tools"));
|
||||||
menubar.add(fileMenu);
|
menubar.add(toolsMenu);
|
||||||
|
|
||||||
//// Component analysis
|
//// Component analysis
|
||||||
item = new JMenuItem(trans.get("main.menu.tools.componentAnalysis"), KeyEvent.VK_C);
|
item = new JMenuItem(trans.get("main.menu.tools.componentAnalysis"), KeyEvent.VK_C);
|
||||||
@ -625,7 +625,7 @@ public class BasicFrame extends JFrame {
|
|||||||
ComponentAnalysisDialog.showDialog(rocketpanel);
|
ComponentAnalysisDialog.showDialog(rocketpanel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
toolsMenu.add(item);
|
||||||
|
|
||||||
//// Optimize
|
//// Optimize
|
||||||
item = new JMenuItem(trans.get("main.menu.tools.optimization"), KeyEvent.VK_O);
|
item = new JMenuItem(trans.get("main.menu.tools.optimization"), KeyEvent.VK_O);
|
||||||
@ -641,7 +641,7 @@ public class BasicFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
toolsMenu.add(item);
|
||||||
|
|
||||||
//// Custom expressions
|
//// Custom expressions
|
||||||
item = new JMenuItem(trans.get("main.menu.tools.customExpressions"), KeyEvent.VK_E);
|
item = new JMenuItem(trans.get("main.menu.tools.customExpressions"), KeyEvent.VK_E);
|
||||||
@ -653,7 +653,7 @@ public class BasicFrame extends JFrame {
|
|||||||
new CustomExpressionDialog(document, BasicFrame.this).setVisible(true);
|
new CustomExpressionDialog(document, BasicFrame.this).setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
toolsMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem(trans.get("PhotoFrame.title"), KeyEvent.VK_P);
|
item = new JMenuItem(trans.get("PhotoFrame.title"), KeyEvent.VK_P);
|
||||||
item.getAccessibleContext().setAccessibleDescription(trans.get("PhotoFrame.desc"));
|
item.getAccessibleContext().setAccessibleDescription(trans.get("PhotoFrame.desc"));
|
||||||
@ -665,7 +665,7 @@ public class BasicFrame extends JFrame {
|
|||||||
pa.setVisible(true);
|
pa.setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
toolsMenu.add(item);
|
||||||
|
|
||||||
//// Debug
|
//// Debug
|
||||||
// // (shown if openrocket.debug.fileMenu is defined)
|
// // (shown if openrocket.debug.fileMenu is defined)
|
||||||
@ -1284,34 +1284,24 @@ public class BasicFrame extends JFrame {
|
|||||||
//// Handle the document
|
//// Handle the document
|
||||||
OpenRocketDocument doc = null;
|
OpenRocketDocument doc = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
doc = worker.get();
|
doc = worker.get();
|
||||||
|
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
|
|
||||||
Throwable cause = e.getCause();
|
Throwable cause = e.getCause();
|
||||||
|
|
||||||
if (cause instanceof FileNotFoundException) {
|
if (cause instanceof FileNotFoundException) {
|
||||||
|
|
||||||
log.warn("File not found", cause);
|
log.warn("File not found", cause);
|
||||||
JOptionPane.showMessageDialog(parent,
|
JOptionPane.showMessageDialog(parent,
|
||||||
"File not found: " + displayName,
|
"File not found: " + displayName,
|
||||||
"Error opening file", JOptionPane.ERROR_MESSAGE);
|
"Error opening file", JOptionPane.ERROR_MESSAGE);
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
} else if (cause instanceof RocketLoadException) {
|
} else if (cause instanceof RocketLoadException) {
|
||||||
|
|
||||||
log.warn("Error loading the file", cause);
|
log.warn("Error loading the file", cause);
|
||||||
JOptionPane.showMessageDialog(parent,
|
JOptionPane.showMessageDialog(parent,
|
||||||
"Unable to open file '" + displayName + "': "
|
"Unable to open file '" + displayName + "': "
|
||||||
+ cause.getMessage(),
|
+ cause.getMessage(),
|
||||||
"Error opening file", JOptionPane.ERROR_MESSAGE);
|
"Error opening file", JOptionPane.ERROR_MESSAGE);
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
throw new BugException("Unknown error when opening file", e);
|
throw new BugException("Unknown error when opening file", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -1322,7 +1312,6 @@ public class BasicFrame extends JFrame {
|
|||||||
throw new BugException("Document loader returned null");
|
throw new BugException("Document loader returned null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Show warnings
|
//// Show warnings
|
||||||
WarningSet warnings = worker.getRocketLoader().getWarnings();
|
WarningSet warnings = worker.getRocketLoader().getWarnings();
|
||||||
if (!warnings.isEmpty()) {
|
if (!warnings.isEmpty()) {
|
||||||
|
@ -107,7 +107,7 @@ public final class ExampleDesignFileAction extends JMenu {
|
|||||||
/**
|
/**
|
||||||
* When a user clicks on one of the recently used design files, open it.
|
* When a user clicks on one of the recently used design files, open it.
|
||||||
*
|
*
|
||||||
* @param file the design file name (absolute path)
|
* @param example the design file name (absolute path)
|
||||||
*
|
*
|
||||||
* @return the action to open a design file
|
* @return the action to open a design file
|
||||||
*/
|
*/
|
||||||
|
@ -297,7 +297,7 @@ public class SimulationPanel extends JPanel {
|
|||||||
simulationTable.addRowSelectionInterval(n, n);
|
simulationTable.addRowSelectionInterval(n, n);
|
||||||
updatePreviousSelection();
|
updatePreviousSelection();
|
||||||
|
|
||||||
openDialog(false, sim);
|
openDialog(false, true, sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plotSimulation() {
|
private void plotSimulation() {
|
||||||
@ -595,8 +595,8 @@ public class SimulationPanel extends JPanel {
|
|||||||
return simulationTable.getSelectionModel();
|
return simulationTable.getSelectionModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openDialog(boolean plotMode, final Simulation... sims) {
|
private void openDialog(boolean plotMode, boolean isNewSimulation, final Simulation... sims) {
|
||||||
SimulationEditDialog d = new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, sims);
|
SimulationEditDialog d = new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, isNewSimulation, sims);
|
||||||
if (plotMode) {
|
if (plotMode) {
|
||||||
d.setPlotMode();
|
d.setPlotMode();
|
||||||
}
|
}
|
||||||
@ -605,6 +605,10 @@ public class SimulationPanel extends JPanel {
|
|||||||
takeTheSpotlight();
|
takeTheSpotlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openDialog(boolean plotMode, final Simulation... sims) {
|
||||||
|
openDialog(plotMode, false, sims);
|
||||||
|
}
|
||||||
|
|
||||||
private void openDialog(final Simulation sim) {
|
private void openDialog(final Simulation sim) {
|
||||||
boolean plotMode = false;
|
boolean plotMode = false;
|
||||||
if (sim.hasSimulationData() && Simulation.isStatusUpToDate(sim.getStatus())) {
|
if (sim.hasSimulationData() && Simulation.isStatusUpToDate(sim.getStatus())) {
|
||||||
@ -662,7 +666,7 @@ public class SimulationPanel extends JPanel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateEnabledState() {
|
public void updateEnabledState() {
|
||||||
setEnabled(simulationTable.getSelectedRowCount() == 1);
|
setEnabled(simulationTable.getSelectedRowCount() > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
|||||||
BorderFactory.createEtchedBorder(),
|
BorderFactory.createEtchedBorder(),
|
||||||
"<html><b>" + trans.get("lbl.motorMounts") + "</b></html>"));
|
"<html><b>" + trans.get("lbl.motorMounts") + "</b></html>"));
|
||||||
|
|
||||||
MotorMountConfigurationPanel mountConfigPanel = new MotorMountConfigurationPanel(this, rocket);
|
MotorMountConfigurationPanel mountConfigPanel = new MotorMountConfigurationPanel(subpanel, rocket);
|
||||||
subpanel.add(mountConfigPanel, "grow, pushy");
|
subpanel.add(mountConfigPanel, "grow, pushy");
|
||||||
this.add(subpanel, "split, growy, pushy");
|
this.add(subpanel, "split, growy, pushy");
|
||||||
}
|
}
|
||||||
|
@ -271,6 +271,15 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
figure3d.updateFigure();
|
figure3d.updateFigure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the rulers of the rocket panel to the currently selected default unit.
|
||||||
|
*/
|
||||||
|
public void updateRulers() {
|
||||||
|
scrollPane.updateRulerUnit();
|
||||||
|
scrollPane.revalidate();
|
||||||
|
scrollPane.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
private void go3D() {
|
private void go3D() {
|
||||||
if (is3d)
|
if (is3d)
|
||||||
return;
|
return;
|
||||||
|
@ -15,6 +15,7 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.event.MouseMotionListener;
|
import java.awt.event.MouseMotionListener;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@ -56,6 +57,7 @@ public class ScaleScrollPane extends JScrollPane
|
|||||||
private final AbstractScaleFigure figure;
|
private final AbstractScaleFigure figure;
|
||||||
|
|
||||||
private DoubleModel rulerUnit;
|
private DoubleModel rulerUnit;
|
||||||
|
private UnitSelector unitSelector;
|
||||||
private Ruler horizontalRuler;
|
private Ruler horizontalRuler;
|
||||||
private Ruler verticalRuler;
|
private Ruler verticalRuler;
|
||||||
|
|
||||||
@ -83,7 +85,7 @@ public class ScaleScrollPane extends JScrollPane
|
|||||||
|
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.figure = (AbstractScaleFigure) component;
|
this.figure = (AbstractScaleFigure) component;
|
||||||
|
|
||||||
rulerUnit = new DoubleModel(0.0, UnitGroup.UNITS_LENGTH);
|
rulerUnit = new DoubleModel(0.0, UnitGroup.UNITS_LENGTH);
|
||||||
rulerUnit.addChangeListener(new ChangeListener() {
|
rulerUnit.addChangeListener(new ChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -95,10 +97,10 @@ public class ScaleScrollPane extends JScrollPane
|
|||||||
verticalRuler = new Ruler(Ruler.VERTICAL);
|
verticalRuler = new Ruler(Ruler.VERTICAL);
|
||||||
this.setColumnHeaderView(horizontalRuler);
|
this.setColumnHeaderView(horizontalRuler);
|
||||||
this.setRowHeaderView(verticalRuler);
|
this.setRowHeaderView(verticalRuler);
|
||||||
|
|
||||||
UnitSelector selector = new UnitSelector(rulerUnit);
|
unitSelector = new UnitSelector(rulerUnit);
|
||||||
selector.setFont(new Font("SansSerif", Font.PLAIN, 8));
|
unitSelector.setFont(new Font("SansSerif", Font.PLAIN, 8));
|
||||||
this.setCorner(JScrollPane.UPPER_LEFT_CORNER, selector);
|
this.setCorner(JScrollPane.UPPER_LEFT_CORNER, unitSelector);
|
||||||
|
|
||||||
this.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
this.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
|
||||||
@ -176,6 +178,14 @@ public class ScaleScrollPane extends JScrollPane
|
|||||||
public Unit getCurrentUnit() {
|
public Unit getCurrentUnit() {
|
||||||
return rulerUnit.getCurrentUnit();
|
return rulerUnit.getCurrentUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the units of the ruler to the default units of the current unit group.
|
||||||
|
*/
|
||||||
|
public void updateRulerUnit() {
|
||||||
|
rulerUnit.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
|
||||||
|
unitSelector.stateChanged(new EventObject(this));
|
||||||
|
}
|
||||||
|
|
||||||
public String toViewportString(){
|
public String toViewportString(){
|
||||||
Rectangle view = this.getViewport().getViewRect();
|
Rectangle view = this.getViewport().getViewRect();
|
||||||
|
@ -2,14 +2,22 @@ package net.sf.openrocket.gui.simulation;
|
|||||||
|
|
||||||
|
|
||||||
import java.awt.CardLayout;
|
import java.awt.CardLayout;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.awt.event.WindowListener;
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
@ -21,7 +29,9 @@ import javax.swing.event.DocumentListener;
|
|||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.document.Simulation;
|
import net.sf.openrocket.document.Simulation;
|
||||||
|
import net.sf.openrocket.document.events.DocumentChangeEvent;
|
||||||
import net.sf.openrocket.gui.components.ConfigurationComboBox;
|
import net.sf.openrocket.gui.components.ConfigurationComboBox;
|
||||||
|
import net.sf.openrocket.gui.components.StyledLabel;
|
||||||
import net.sf.openrocket.gui.util.GUIUtil;
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.gui.widgets.SelectColorButton;
|
import net.sf.openrocket.gui.widgets.SelectColorButton;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
@ -30,6 +40,8 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
|||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.simulation.extension.SimulationExtension;
|
import net.sf.openrocket.simulation.extension.SimulationExtension;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.startup.Preferences;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
|
||||||
public class SimulationEditDialog extends JDialog {
|
public class SimulationEditDialog extends JDialog {
|
||||||
@ -38,17 +50,37 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
private final Simulation[] simulationList;
|
private final Simulation[] simulationList;
|
||||||
private final OpenRocketDocument document;
|
private final OpenRocketDocument document;
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
private static final Preferences preferences = Application.getPreferences();
|
||||||
|
|
||||||
JPanel cards;
|
JPanel cards;
|
||||||
private final static String EDITMODE = "EDIT";
|
private final static String EDITMODE = "EDIT";
|
||||||
private final static String PLOTMODE = "PLOT";
|
private final static String PLOTMODE = "PLOT";
|
||||||
|
|
||||||
|
private final WindowListener applyChangesToSimsListener;
|
||||||
|
private final Simulation initialSim; // A copy of the first selected simulation before it was modified
|
||||||
|
private final boolean initialIsSaved; // Whether the document was saved before the dialog was opened
|
||||||
|
private boolean isModified = false; // Whether the simulation has been modified
|
||||||
|
private final boolean isNewSimulation; // Whether you are editing a new simulation, or an existing one
|
||||||
|
|
||||||
public SimulationEditDialog(Window parent, final OpenRocketDocument document, Simulation... sims) {
|
public SimulationEditDialog(Window parent, final OpenRocketDocument document, boolean isNewSimulation, Simulation... sims) {
|
||||||
//// Edit simulation
|
//// Edit simulation
|
||||||
super(parent, trans.get("simedtdlg.title.Editsim"), JDialog.ModalityType.DOCUMENT_MODAL);
|
super(parent, sims.length == 1 ? trans.get("simedtdlg.title.Editsim") : trans.get("simedtdlg.title.MultiSimEdit"),
|
||||||
|
JDialog.ModalityType.DOCUMENT_MODAL);
|
||||||
this.document = document;
|
this.document = document;
|
||||||
this.parentWindow = parent;
|
this.parentWindow = parent;
|
||||||
this.simulationList = sims;
|
this.simulationList = sims;
|
||||||
|
this.initialSim = simulationList[0].clone();
|
||||||
|
this.initialIsSaved = document.isSaved();
|
||||||
|
this.isNewSimulation = isNewSimulation;
|
||||||
|
|
||||||
|
simulationList[0].addChangeListener(new StateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(EventObject e) {
|
||||||
|
isModified = true;
|
||||||
|
setTitle("* " + getTitle()); // Add component changed indicator to the title
|
||||||
|
simulationList[0].removeChangeListener(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.cards = new JPanel(new CardLayout());
|
this.cards = new JPanel(new CardLayout());
|
||||||
this.add(cards);
|
this.add(cards);
|
||||||
@ -59,6 +91,14 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
this.pack();
|
this.pack();
|
||||||
|
|
||||||
this.setLocationByPlatform(true);
|
this.setLocationByPlatform(true);
|
||||||
|
|
||||||
|
this.applyChangesToSimsListener = new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosed(WindowEvent e) {
|
||||||
|
copyChangesToAllSims();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.addWindowListener(applyChangesToSimsListener);
|
||||||
|
|
||||||
GUIUtil.setDisposableDialogOptions(this, null);
|
GUIUtil.setDisposableDialogOptions(this, null);
|
||||||
}
|
}
|
||||||
@ -72,16 +112,21 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setEditMode() {
|
public void setEditMode() {
|
||||||
|
String baseTitle = simulationList.length == 1 ?
|
||||||
|
trans.get("simedtdlg.title.Editsim") : trans.get("simedtdlg.title.MultiSimEdit");
|
||||||
|
setTitle((isModified ? "* " : "") + baseTitle);
|
||||||
CardLayout cl = (CardLayout) (cards.getLayout());
|
CardLayout cl = (CardLayout) (cards.getLayout());
|
||||||
cl.show(cards, EDITMODE);
|
cl.show(cards, EDITMODE);
|
||||||
cards.validate();
|
cards.validate();
|
||||||
|
this.addWindowListener(applyChangesToSimsListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlotMode() {
|
public void setPlotMode() {
|
||||||
if (!allowsPlotMode()) {
|
if (!allowsPlotMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setTitle(trans.get("simplotpanel.title.Plotsim"));
|
this.removeWindowListener(applyChangesToSimsListener);
|
||||||
|
setTitle((isModified ? "* " : "") + trans.get("simplotpanel.title.Plotsim"));
|
||||||
CardLayout cl = (CardLayout) (cards.getLayout());
|
CardLayout cl = (CardLayout) (cards.getLayout());
|
||||||
cl.show(cards, PLOTMODE);
|
cl.show(cards, PLOTMODE);
|
||||||
cards.validate();
|
cards.validate();
|
||||||
@ -107,7 +152,7 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void buildEditCard() {
|
private void buildEditCard() {
|
||||||
JPanel simEditPanel = new JPanel(new MigLayout("fill"));
|
JPanel simEditPanel = new JPanel(new MigLayout("fill, hidemode 1"));
|
||||||
|
|
||||||
if (isSingleEdit()) {
|
if (isSingleEdit()) {
|
||||||
JPanel panel = new JPanel(new MigLayout("fill, ins 0"));
|
JPanel panel = new JPanel(new MigLayout("fill, ins 0"));
|
||||||
@ -135,7 +180,6 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
String name = field.getText();
|
String name = field.getText();
|
||||||
if (name == null || name.equals(""))
|
if (name == null || name.equals(""))
|
||||||
return;
|
return;
|
||||||
//System.out.println("Setting name:" + name);
|
|
||||||
simulationList[0].setName(name);
|
simulationList[0].setName(name);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -193,12 +237,29 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
simEditPanel.add(button, "spanx, split 3, align left");
|
simEditPanel.add(button, "spanx, split 5, align left");
|
||||||
if (allowsPlotMode()) {
|
if (allowsPlotMode()) {
|
||||||
button.setVisible(true);
|
button.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
button.setVisible(false);
|
button.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//// Multi-simulation edit
|
||||||
|
if (simulationList.length > 1) {
|
||||||
|
StyledLabel multiSimEditLabel = new StyledLabel("", -1, StyledLabel.Style.BOLD);
|
||||||
|
multiSimEditLabel.setFontColor(new Color(170, 0, 100));
|
||||||
|
multiSimEditLabel.setText(trans.get("simedtdlg.title.MultiSimEdit"));
|
||||||
|
StringBuilder components = new StringBuilder(trans.get("simedtdlg.title.MultiSimEdit.ttip"));
|
||||||
|
for (int i = 0; i < simulationList.length; i++) {
|
||||||
|
if (i < simulationList.length - 1) {
|
||||||
|
components.append(simulationList[i].getName()).append(", ");
|
||||||
|
} else {
|
||||||
|
components.append(simulationList[i].getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multiSimEditLabel.setToolTipText(components.toString());
|
||||||
|
simEditPanel.add(multiSimEditLabel, "align left");
|
||||||
|
}
|
||||||
|
|
||||||
//// Run simulation button
|
//// Run simulation button
|
||||||
button = new SelectColorButton(trans.get("SimulationEditDialog.btn.simulateAndPlot"));
|
button = new SelectColorButton(trans.get("SimulationEditDialog.btn.simulateAndPlot"));
|
||||||
@ -216,18 +277,49 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
simEditPanel.add(button, " align right, tag ok");
|
simEditPanel.add(button, "align right, gapright 10lp, tag ok");
|
||||||
|
|
||||||
//// Close button
|
//// Cancel button
|
||||||
JButton close = new SelectColorButton(trans.get("dlg.but.close"));
|
JButton cancelButton = new SelectColorButton(trans.get("dlg.but.cancel"));
|
||||||
close.addActionListener(new ActionListener() {
|
cancelButton.setToolTipText(trans.get("SimulationEditDialog.btn.Cancel.ttip"));
|
||||||
|
cancelButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
// Don't do anything on cancel if you are editing an existing simulation, and it is not modified
|
||||||
|
if (!isNewSimulation && !isModified) {
|
||||||
|
SimulationEditDialog.this.removeWindowListener(applyChangesToSimsListener);
|
||||||
|
SimulationEditDialog.this.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the cancel operation if set to auto discard in preferences
|
||||||
|
if (!preferences.isShowDiscardSimulationConfirmation()) {
|
||||||
|
discardChanges();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yes/No dialog: Are you sure you want to discard your changes?
|
||||||
|
JPanel msg = createCancelOperationContent();
|
||||||
|
int resultYesNo = JOptionPane.showConfirmDialog(SimulationEditDialog.this, msg,
|
||||||
|
trans.get("SimulationEditDialog.CancelOperation.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||||
|
if (resultYesNo == JOptionPane.YES_OPTION) {
|
||||||
|
discardChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
simEditPanel.add(cancelButton, "tag ok");
|
||||||
|
|
||||||
|
//// Ok button
|
||||||
|
JButton okButton = new SelectColorButton(trans.get("dlg.but.ok"));
|
||||||
|
okButton.setToolTipText(trans.get("SimulationEditDialog.btn.OK.ttip"));
|
||||||
|
okButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
copyChangesToAllSims();
|
copyChangesToAllSims();
|
||||||
SimulationEditDialog.this.dispose();
|
SimulationEditDialog.this.dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
simEditPanel.add(close, "tag ok");
|
simEditPanel.add(okButton, "tag ok");
|
||||||
|
|
||||||
cards.add(simEditPanel, EDITMODE);
|
cards.add(simEditPanel, EDITMODE);
|
||||||
}
|
}
|
||||||
@ -322,4 +414,47 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JPanel createCancelOperationContent() {
|
||||||
|
JPanel panel = new JPanel(new MigLayout());
|
||||||
|
String msg = isNewSimulation ? trans.get("SimulationEditDialog.CancelOperation.msg.undoAdd") :
|
||||||
|
trans.get("SimulationEditDialog.CancelOperation.msg.discardChanges");
|
||||||
|
JLabel msgLabel = new JLabel(msg);
|
||||||
|
JCheckBox dontAskAgain = new JCheckBox(trans.get("SimulationEditDialog.CancelOperation.checkbox.dontAskAgain"));
|
||||||
|
dontAskAgain.setSelected(false);
|
||||||
|
dontAskAgain.addItemListener(new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
preferences.setShowDiscardSimulationConfirmation(false);
|
||||||
|
}
|
||||||
|
// Unselected state should be not be possible and thus not be handled
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.add(msgLabel, "left, wrap");
|
||||||
|
panel.add(dontAskAgain, "left, gaptop para");
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void discardChanges() {
|
||||||
|
if (isNewSimulation) {
|
||||||
|
document.removeSimulation(simulationList[0]);
|
||||||
|
} else {
|
||||||
|
undoSimulationChanges();
|
||||||
|
}
|
||||||
|
document.setSaved(this.initialIsSaved); // Restore the saved state of the document
|
||||||
|
document.fireDocumentChangeEvent(new DocumentChangeEvent(this));
|
||||||
|
|
||||||
|
SimulationEditDialog.this.removeWindowListener(applyChangesToSimsListener);
|
||||||
|
SimulationEditDialog.this.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void undoSimulationChanges() {
|
||||||
|
if (simulationList == null || simulationList.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
simulationList[0].loadFrom(initialSim);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user