presets;
+
+ public BodyTubePresetModel(RocketComponent component) {
+ presets = Application.getDaos().getBodyTubePresetDao().listAll();
+ this.component = component;
+ }
+
+ public static class BodyTubePresetAdapter {
+ private ComponentPreset bt;
+ private BodyTubePresetAdapter( ComponentPreset bt ) {
+ this.bt = bt;
+ }
+ @Override
+ public String toString() {
+ return bt.getManufacturer() + " " + bt.getPartNo();
+ }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((bt == null) ? 0 : bt.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BodyTubePresetAdapter other = (BodyTubePresetAdapter) obj;
+ if (bt == null) {
+ if (other.bt != null)
+ return false;
+ } else if (!bt.equals(other.bt))
+ return false;
+ return true;
+ }
+ }
+
+ @Override
+ public int getSize() {
+ return presets.size();
+ }
+
+ @Override
+ public Object getElementAt(int index) {
+ return new BodyTubePresetAdapter(presets.get(index));
+ }
+
+ @Override
+ public void addListDataListener(ListDataListener l) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void removeListDataListener(ListDataListener l) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void componentChanged(ComponentChangeEvent e) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setSelectedItem(Object anItem) {
+ BodyTubePresetAdapter selected = (BodyTubePresetAdapter) anItem;
+ component.loadPreset(selected.bt);
+ }
+
+ @Override
+ public Object getSelectedItem() {
+ ComponentPreset preset = (ComponentPreset) component.getPresetComponent();
+ if ( preset == null ) {
+ return null;
+ } else {
+ return new BodyTubePresetAdapter(preset);
+ }
+ }
+
+}
diff --git a/core/src/net/sf/openrocket/gui/adaptors/DoubleModel.java b/core/src/net/sf/openrocket/gui/adaptors/DoubleModel.java
index 820a54a66..cd7066f85 100644
--- a/core/src/net/sf/openrocket/gui/adaptors/DoubleModel.java
+++ b/core/src/net/sf/openrocket/gui/adaptors/DoubleModel.java
@@ -157,7 +157,8 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* Use linear scale value = linear1 * x + linear0 when x < linearPosition
* Use quadratic scale value = quad2 * x^2 + quad1 * x + quad0 otherwise
*/
-
+ private final boolean islinear;
+
// Linear in range x <= linearPosition
private final double linearPosition;
@@ -169,11 +170,10 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
//private final double linear0;
// Non-linear multiplier, exponent and constant
- private final double quad2, quad1, quad0;
-
-
+ private double quad2, quad1, quad0;
public ValueSliderModel(DoubleModel min, DoubleModel max) {
+ this.islinear = true;
linearPosition = 1.0;
this.min = min;
@@ -192,6 +192,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* Generate a linear model from min to max.
*/
public ValueSliderModel(double min, double max) {
+ this.islinear = true;
linearPosition = 1.0;
this.min = new DoubleModel(min);
@@ -205,6 +206,10 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
this(min, 0.5, mid, max);
}
+ public ValueSliderModel(double min, double mid, DoubleModel max) {
+ this(min, 0.5, mid, max);
+ }
+
/*
* v(x) = mul * x^exp + add
*
@@ -212,33 +217,46 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* v(1) = mul + add = max
* v'(pos) = mul*exp * pos^(exp-1) = linearMul
*/
- public ValueSliderModel(double min, double pos, double mid, double max) {
+ public ValueSliderModel(double min, double pos, double mid, double max ) {
+ this(min, pos, mid, new DoubleModel(max));
+ }
+ public ValueSliderModel(double min, double pos, double mid, DoubleModel max) {
this.min = new DoubleModel(min);
this.mid = new DoubleModel(mid);
- this.max = new DoubleModel(max);
-
+ this.max = max;
+ this.islinear = false;
+
+ max.addChangeListener(this);
+
linearPosition = pos;
//linear0 = min;
//linear1 = (mid-min)/pos;
- if (!(min < mid && mid <= max && 0 < pos && pos < 1)) {
+ if (!(min < mid && mid <= max.getValue() && 0 < pos && pos < 1)) {
throw new IllegalArgumentException("Bad arguments for ValueSliderModel " +
"min=" + min + " mid=" + mid + " max=" + max + " pos=" + pos);
}
+ updateExponentialParameters();
+
+ }
+
+ private void updateExponentialParameters() {
+ double pos = this.linearPosition;
+ double minValue = this.min.getValue();
+ double midValue = this.mid.getValue();
+ double maxValue = this.max.getValue();
/*
* quad2..0 are calculated such that
* f(pos) = mid - continuity
* f(1) = max - end point
* f'(pos) = linear1 - continuity of derivative
*/
-
- double delta = (mid - min) / pos;
- quad2 = (max - mid - delta + delta * pos) / pow2(pos - 1);
- quad1 = (delta + 2 * (mid - max) * pos - delta * pos * pos) / pow2(pos - 1);
- quad0 = (mid - (2 * mid + delta) * pos + (max + delta) * pos * pos) / pow2(pos - 1);
-
+ double delta = (midValue - minValue) / pos;
+ quad2 = (maxValue - midValue - delta + delta * pos) / pow2(pos - 1);
+ quad1 = (delta + 2 * (midValue - maxValue) * pos - delta * pos * pos) / pow2(pos - 1);
+ quad0 = (midValue - (2 * midValue + delta) * pos + (maxValue + delta) * pos * pos) / pow2(pos - 1);
}
private double pow2(double x) {
@@ -366,6 +384,11 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
@Override
public void stateChanged(EventObject e) {
// Min or max range has changed.
+ if ( !islinear ) {
+ double midValue = (max.getValue() - min.getValue()) /3.0;
+ mid.setValue(midValue);
+ updateExponentialParameters();
+ }
// Fire if not already firing
if (firing == 0)
fireStateChanged();
@@ -385,6 +408,10 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
return new ValueSliderModel(min, mid, max);
}
+ public BoundedRangeModel getSliderModel(double min, double mid, DoubleModel max) {
+ return new ValueSliderModel(min, mid, max);
+ }
+
public BoundedRangeModel getSliderModel(double min, double pos, double mid, double max) {
return new ValueSliderModel(min, pos, mid, max);
}
@@ -516,7 +543,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
private Unit currentUnit;
private final double minValue;
- private final double maxValue;
+ private double maxValue;
private String toString = null;
@@ -725,7 +752,6 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
}
}
-
/**
* Returns whether setting the value automatically is available.
*/
diff --git a/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java
index af272a0d8..ffed6e738 100644
--- a/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java
+++ b/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java
@@ -2,6 +2,7 @@ package net.sf.openrocket.gui.configdialog;
import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
@@ -9,6 +10,7 @@ import javax.swing.JSpinner;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.BodyTubePresetModel;
import net.sf.openrocket.gui.adaptors.BooleanModel;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.components.BasicSlider;
@@ -16,12 +18,15 @@ import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
+import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
public class BodyTubeConfig extends RocketComponentConfig {
+ private ComponentChangeListener listener;
private MotorConfig motorConfigPane = null;
private static final Translator trans = Application.getTranslator();
@@ -30,17 +35,25 @@ public class BodyTubeConfig extends RocketComponentConfig {
JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", ""));
+ //// Body tube template
+ panel.add( new JLabel(trans.get("BodyTubecfg.lbl.Bodytubepreset")) );
+ {
+ JComboBox combo = new JComboBox(new BodyTubePresetModel(component));
+ panel.add(combo, "wrap");
+ }
+
//// Body tube length
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Bodytubelength")));
- DoubleModel m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
+ final DoubleModel maxLength = new DoubleModel(2.0);
+ DoubleModel length = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
- JSpinner spin = new JSpinner(m.getSpinnerModel());
+ JSpinner spin = new JSpinner(length.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
- panel.add(new UnitSelector(m), "growx");
- panel.add(new BasicSlider(m.getSliderModel(0, 0.5, 2.0)), "w 100lp, wrap");
+ panel.add(new UnitSelector(length), "growx");
+ panel.add(new BasicSlider(length.getSliderModel(0, 0.5, maxLength)), "w 100lp, wrap");
//// Body tube diameter
@@ -66,7 +79,7 @@ public class BodyTubeConfig extends RocketComponentConfig {
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Innerdiameter")));
// Diameter = 2*Radius
- m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0);
+ DoubleModel m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0);
spin = new JSpinner(m.getSpinnerModel());
@@ -107,6 +120,29 @@ public class BodyTubeConfig extends RocketComponentConfig {
tabbedPane.insertTab(trans.get("BodyTubecfg.tab.Motor"), null, motorConfigPane,
trans.get("BodyTubecfg.tab.Motormountconf"), 1);
tabbedPane.setSelectedIndex(0);
+
+ // need to work in the max length for body tubes based on presets...
+ BodyTube bt = (BodyTube) component;
+ if ( bt.getPresetComponent() != null ) {
+ BodyTube btPreset = (BodyTube) bt.getPresetComponent().getPrototype();
+ maxLength.setValue( btPreset.getLength() );
+ }
+
+ listener = new ComponentChangeListener() {
+
+ @Override
+ public void componentChanged(ComponentChangeEvent e) {
+ BodyTube bt = (BodyTube) component;
+ if ( bt.getPresetComponent() != null ) {
+ BodyTube btPreset = (BodyTube) bt.getPresetComponent().getPrototype();
+ maxLength.setValue(btPreset.getLength());
+ }
+
+ }
+
+ };
+ component.addChangeListener(listener);
+
}
@Override
@@ -115,5 +151,11 @@ public class BodyTubeConfig extends RocketComponentConfig {
if (motorConfigPane != null)
motorConfigPane.updateFields();
}
+
+ @Override
+ public void invalidateModels() {
+ super.invalidateModels();
+ component.removeChangeListener(listener);
+ }
}
diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java
index 87343e935..cf24bb1bd 100644
--- a/core/src/net/sf/openrocket/preset/ComponentPreset.java
+++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java
@@ -1,8 +1,8 @@
package net.sf.openrocket.preset;
-import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.rocketcomponent.RocketComponent;
+
/**
* A model for a preset component.
*
@@ -11,63 +11,63 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
*
* @author Sampo Niskanen
*/
-public abstract class ComponentPreset {
-
- private final Manufacturer manufacturer;
+public class ComponentPreset {
+
+
+ private final String manufacturer;
private final String partNo;
private final String partDescription;
private final RocketComponent prototype;
-
-
- public ComponentPreset(Manufacturer manufacturer, String partNo, String partDescription,
- RocketComponent prototype) {
+
+
+ public ComponentPreset(String manufacturer, String partNo, String partDescription, RocketComponent prototype) {
this.manufacturer = manufacturer;
this.partNo = partNo;
this.partDescription = partDescription;
this.prototype = prototype.copy();
-
+
if (prototype.getParent() != null) {
throw new IllegalArgumentException("Prototype component cannot have a parent");
}
if (prototype.getChildCount() > 0) {
throw new IllegalArgumentException("Prototype component cannot have children");
}
+
}
-
-
+
/**
* Return the component class that this preset defines.
*/
public Class extends RocketComponent> getComponentClass() {
return prototype.getClass();
}
-
+
/**
* Return the manufacturer of this preset component.
*/
- public Manufacturer getManufacturer() {
+ public String getManufacturer() {
return manufacturer;
}
-
+
/**
* Return the part number. This is the part identifier (e.g. "BT-50").
*/
public String getPartNo() {
return partNo;
}
-
+
/**
* Return the part description. This is a longer description of the component.
*/
public String getPartDescription() {
return partDescription;
}
-
+
/**
* Return a prototype component. This component may be modified freely.
*/
public RocketComponent getPrototype() {
return prototype.copy();
}
-
+
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
index 64c1b4a99..fe8571eb9 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
@@ -135,13 +135,16 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
@Override
protected void loadFromPreset(RocketComponent preset) {
- BodyTube c = (BodyTube) preset;
- this.setOuterRadius(c.getOuterRadius());
-
super.loadFromPreset(preset);
+ BodyTube bt = (BodyTube) preset;
+ this.autoRadius = false;
+ this.outerRadius = bt.getOuterRadius();
+ this.thickness = (bt.getOuterRadius() - bt.getInnerRadius());
+ this.length = bt.getLength();
+
+ fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
+
}
-
-
@Override
public double getAftRadius() {
return getOuterRadius();
diff --git a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java
index 8d958da6d..85bc39f19 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java
@@ -17,7 +17,7 @@ import net.sf.openrocket.unit.UnitGroup;
*/
public abstract class ExternalComponent extends RocketComponent {
-
+
public enum Finish {
//// Rough
ROUGH("ExternalComponent.Rough", 500e-6),
@@ -29,35 +29,35 @@ public abstract class ExternalComponent extends RocketComponent {
SMOOTH("ExternalComponent.Smoothpaint", 20e-6),
//// Polished
POLISHED("ExternalComponent.Polished", 2e-6);
-
+
private static final Translator trans = Application.getTranslator();
private final String name;
private final double roughnessSize;
-
+
Finish(String name, double roughness) {
this.name = name;
this.roughnessSize = roughness;
}
-
+
public double getRoughnessSize() {
return roughnessSize;
}
-
+
@Override
public String toString() {
return trans.get(name) + " (" + UnitGroup.UNITS_ROUGHNESS.toStringUnit(roughnessSize) + ")";
}
}
-
-
+
+
/**
* The material of the component.
*/
protected Material material = null;
-
+
protected Finish finish = Finish.NORMAL;
-
-
+
+
/**
* Constructor that sets the relative position of the component.
@@ -66,13 +66,13 @@ public abstract class ExternalComponent extends RocketComponent {
super(relativePosition);
this.material = Application.getPreferences().getDefaultComponentMaterial(this.getClass(), Material.Type.BULK);
}
-
+
/**
* Returns the volume of the component. This value is used in calculating the mass
* of the object.
*/
public abstract double getComponentVolume();
-
+
/**
* Calculates the mass of the component as the product of the volume and interior density.
*/
@@ -80,7 +80,7 @@ public abstract class ExternalComponent extends RocketComponent {
public double getComponentMass() {
return material.getDensity() * getComponentVolume();
}
-
+
/**
* ExternalComponent has aerodynamic effect, so return true.
*/
@@ -88,7 +88,7 @@ public abstract class ExternalComponent extends RocketComponent {
public boolean isAerodynamic() {
return true;
}
-
+
/**
* ExternalComponent has effect on the mass, so return true.
*/
@@ -96,18 +96,18 @@ public abstract class ExternalComponent extends RocketComponent {
public boolean isMassive() {
return true;
}
-
-
+
+
public Material getMaterial() {
return material;
}
-
+
public void setMaterial(Material mat) {
if (mat.getType() != Material.Type.BULK) {
throw new IllegalArgumentException("ExternalComponent requires a bulk material" +
" type=" + mat.getType());
}
-
+
if (material.equals(mat))
return;
material = mat;
@@ -115,29 +115,31 @@ public abstract class ExternalComponent extends RocketComponent {
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
clearPreset();
}
-
+
public Finish getFinish() {
return finish;
}
-
+
public void setFinish(Finish finish) {
if (this.finish == finish)
return;
this.finish = finish;
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
-
-
+
+
@Override
protected void loadFromPreset(RocketComponent preset) {
super.loadFromPreset(preset);
-
+
// Surface finish is left unchanged
-
+
ExternalComponent c = (ExternalComponent) preset;
-
+
Material mat = c.getMaterial();
- if (c.isMassOverridden()) {
+ if ( mat != null ) {
+ setMaterial(mat);
+ } else if (c.isMassOverridden()) {
double mass = c.getOverrideMass();
double volume = getComponentVolume();
double density;
@@ -147,12 +149,11 @@ public abstract class ExternalComponent extends RocketComponent {
density = 1000;
}
mat = Material.newMaterial(Type.BULK, mat.getName(), density, true);
+ setMaterial(mat);
}
-
- setMaterial(mat);
}
-
-
+
+
@Override
protected List copyFrom(RocketComponent c) {
ExternalComponent src = (ExternalComponent) c;
@@ -160,5 +161,5 @@ public abstract class ExternalComponent extends RocketComponent {
this.material = src.material;
return super.copyFrom(c);
}
-
+
}
diff --git a/core/src/net/sf/openrocket/startup/Application.java b/core/src/net/sf/openrocket/startup/Application.java
index 7718b67ec..9f0f4321f 100644
--- a/core/src/net/sf/openrocket/startup/Application.java
+++ b/core/src/net/sf/openrocket/startup/Application.java
@@ -1,5 +1,6 @@
package net.sf.openrocket.startup;
+import net.sf.openrocket.database.Daos;
import net.sf.openrocket.database.MotorDatabase;
import net.sf.openrocket.l10n.ClassBasedTranslator;
import net.sf.openrocket.l10n.DebugTranslator;
@@ -23,6 +24,8 @@ public final class Application {
private static Translator baseTranslator = new DebugTranslator(null);
private static MotorDatabase motorSetDatabase;
+
+ private static Daos daos;
private static Preferences preferences;
@@ -159,6 +162,14 @@ public final class Application {
public static void setMotorSetDatabase(MotorDatabase motorSetDatabase) {
Application.motorSetDatabase = motorSetDatabase;
}
+
+ public static Daos getDaos() {
+ return daos;
+ }
+
+ public static void setDaos(Daos daos) {
+ Application.daos = daos;
+ }
}
diff --git a/core/src/net/sf/openrocket/startup/Startup.java b/core/src/net/sf/openrocket/startup/Startup.java
index d288ea76f..95b03c528 100644
--- a/core/src/net/sf/openrocket/startup/Startup.java
+++ b/core/src/net/sf/openrocket/startup/Startup.java
@@ -4,6 +4,7 @@ import java.io.PrintStream;
import java.util.Locale;
import java.util.prefs.Preferences;
+import net.sf.openrocket.database.DaosImpl;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.L10N;
@@ -52,6 +53,8 @@ public class Startup {
Application.setPreferences( new SwingPreferences() );
+ Application.setDaos( new DaosImpl() );
+
// Setup the translations
initializeL10n();