From: plaa Date: Fri, 8 Oct 2010 22:09:20 +0000 (+0000) Subject: bug fix + more logging X-Git-Tag: upstream/1.1.4^2~13 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=18dcece5e1a7c7a415b0ea0e9fcd72ac8b704b94;p=debian%2Fopenrocket bug fix + more logging git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@91 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/ChangeLog b/ChangeLog index 8429a3d4..0f4e934f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-10-09 Sampo Niskanen + + * [BUG] Fixed conversion to freeform fin set + * Enhanced logging + +2010-10-08 Sampo Niskanen + + * New components no longer look expandable in the component tree + 2010-10-06 Sampo Niskanen * Released version 1.1.3 diff --git a/src/net/sf/openrocket/gui/adaptors/BooleanModel.java b/src/net/sf/openrocket/gui/adaptors/BooleanModel.java index e474a9ee..2aa651c6 100644 --- a/src/net/sf/openrocket/gui/adaptors/BooleanModel.java +++ b/src/net/sf/openrocket/gui/adaptors/BooleanModel.java @@ -11,6 +11,8 @@ import javax.swing.AbstractAction; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.Reflection; @@ -33,7 +35,8 @@ import net.sf.openrocket.util.Reflection; */ public class BooleanModel extends AbstractAction implements ChangeListener { - + private static final LogHelper log = Application.getLogger(); + private final ChangeSource source; private final String valueName; @@ -44,6 +47,8 @@ public class BooleanModel extends AbstractAction implements ChangeListener { private final List components = new ArrayList(); private final List componentEnableState = new ArrayList(); + private String toString = null; + private int firing = 0; private boolean oldValue; @@ -53,34 +58,38 @@ public class BooleanModel extends AbstractAction implements ChangeListener { this.source = source; this.valueName = valueName; - Method getter=null, setter=null; - + Method getter = null, setter = null; + // Try get/is and set try { getter = source.getClass().getMethod("is" + valueName); - } catch (NoSuchMethodException ignore) { } + } catch (NoSuchMethodException ignore) { + } if (getter == null) { try { getter = source.getClass().getMethod("get" + valueName); - } catch (NoSuchMethodException ignore) { } + } catch (NoSuchMethodException ignore) { + } } try { - setter = source.getClass().getMethod("set" + valueName,boolean.class); - } catch (NoSuchMethodException ignore) { } + setter = source.getClass().getMethod("set" + valueName, boolean.class); + } catch (NoSuchMethodException ignore) { + } - if (getter==null || setter==null) { - throw new IllegalArgumentException("get/is methods for boolean '"+valueName+ - "' not present in class "+source.getClass().getCanonicalName()); + if (getter == null || setter == null) { + throw new IllegalArgumentException("get/is methods for boolean '" + valueName + + "' not present in class " + source.getClass().getCanonicalName()); } - + getMethod = getter; setMethod = setter; Method e = null; try { e = source.getClass().getMethod("is" + valueName + "Enabled"); - } catch (NoSuchMethodException ignore) { } + } catch (NoSuchMethodException ignore) { + } getEnabled = e; oldValue = getValue(); @@ -94,19 +103,20 @@ public class BooleanModel extends AbstractAction implements ChangeListener { public boolean getValue() { try { - return (Boolean)getMethod.invoke(source); + return (Boolean) getMethod.invoke(source); } catch (IllegalAccessException e) { - throw new BugException("getMethod execution error for source "+source,e); + throw new BugException("getMethod execution error for source " + source, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } } public void setValue(boolean b) { + log.debug("Setting value of " + this + " to " + b); try { - setMethod.invoke(source, new Object[] { (Boolean)b }); + setMethod.invoke(source, new Object[] { (Boolean) b }); } catch (IllegalAccessException e) { - throw new BugException("setMethod execution error for source "+source,e); + throw new BugException("setMethod execution error for source " + source, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } @@ -141,7 +151,7 @@ public class BooleanModel extends AbstractAction implements ChangeListener { private void updateEnableStatus() { boolean state = getValue(); - for (int i=0; i < components.size(); i++) { + for (int i = 0; i < components.size(); i++) { Component c = components.get(i); boolean b = componentEnableState.get(i); c.setEnabled(state == b); @@ -149,81 +159,54 @@ public class BooleanModel extends AbstractAction implements ChangeListener { } -// @Override -// public boolean isEnabled() { -// if (getEnabled == null) -// return true; -// try { -// return (Boolean)getEnabled.invoke(source); -// } catch (IllegalAccessException e) { -// throw new RuntimeException("getEnabled execution error for source "+source,e); -// } catch (InvocationTargetException e) { -// throw new RuntimeException("getEnabled execution error for source "+source,e); -// } -// } - private boolean getIsEnabled() { if (getEnabled == null) return true; try { - return (Boolean)getEnabled.invoke(source); + return (Boolean) getEnabled.invoke(source); } catch (IllegalAccessException e) { - throw new BugException("getEnabled execution error for source "+source,e); + throw new BugException("getEnabled execution error for source " + source, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } } -// @Override -// public Object getValue(String key) { -// if (key.equals(SELECTED_KEY)) { -// return getValue(); -// } -// return super.getValue(key); -// } -// -// @Override -// public void putValue(String key, Object value) { -// if (firing > 0) // Ignore if currently firing event -// return; -// if (key.equals(SELECTED_KEY) && (value instanceof Boolean)) { -// setValue((Boolean)value); -// } else { -// super.putValue(key, value); -// } -// updateEnableStatus(); -// } - - @Override public void stateChanged(ChangeEvent event) { - if (firing > 0) + if (firing > 0) { + log.debug("Ignoring stateChanged of " + this + ", currently firing events"); return; + } boolean v = getValue(); boolean e = getIsEnabled(); if (oldValue != v) { + log.debug("Value of " + this + " has changed to " + v + " oldValue=" + oldValue); oldValue = v; firing++; this.putValue(SELECTED_KEY, getValue()); -// this.firePropertyChange(SELECTED_KEY, !v, v); + // this.firePropertyChange(SELECTED_KEY, !v, v); updateEnableStatus(); firing--; } if (oldEnabled != e) { + log.debug("Enabled status of " + this + " has changed to " + e + " oldEnabled=" + oldEnabled); oldEnabled = e; setEnabled(e); } } - - + + @Override public void actionPerformed(ActionEvent e) { - if (firing > 0) + if (firing > 0) { + log.debug("Ignoring actionPerformed of " + this + ", currently firing events"); return; + } - boolean v = (Boolean)this.getValue(SELECTED_KEY); + boolean v = (Boolean) this.getValue(SELECTED_KEY); + log.user("Value of " + this + " changed to " + v + " oldValue=" + oldValue); if (v != oldValue) { firing++; setValue(v); @@ -238,6 +221,9 @@ public class BooleanModel extends AbstractAction implements ChangeListener { @Override public String toString() { - return "BooleanModel["+source.getClass().getCanonicalName()+":"+valueName+"]"; + if (toString == null) { + toString = "BooleanModel[" + source.getClass().getSimpleName() + ":" + valueName + "]"; + } + return toString; } } diff --git a/src/net/sf/openrocket/gui/adaptors/DoubleModel.java b/src/net/sf/openrocket/gui/adaptors/DoubleModel.java index 20b2ad94..a81381dc 100644 --- a/src/net/sf/openrocket/gui/adaptors/DoubleModel.java +++ b/src/net/sf/openrocket/gui/adaptors/DoubleModel.java @@ -15,6 +15,8 @@ import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.BugException; @@ -38,10 +40,11 @@ import net.sf.openrocket.util.Reflection; */ public class DoubleModel implements ChangeListener, ChangeSource { - private static final boolean DEBUG_LISTENERS = false; + private static final LogHelper log = Application.getLogger(); - public static final DoubleModel ZERO = new DoubleModel(0); + public static final DoubleModel ZERO = new DoubleModel(0); + //////////// JSpinner Model //////////// /** @@ -53,56 +56,50 @@ public class DoubleModel implements ChangeListener, ChangeSource { @Override public Object getValue() { return currentUnit.toUnit(DoubleModel.this.getValue()); -// return makeString(currentUnit.toUnit(DoubleModel.this.getValue())); } - + @Override public void setValue(Object value) { - - System.out.println("setValue("+value+") called, valueName="+valueName+ - " firing="+firing); - - if (firing > 0) // Ignore, if called when model is sending events + if (firing > 0) { + // Ignore, if called when model is sending events + log.verbose("Ignoring call to SpinnerModel setValue for " + DoubleModel.this.toString() + + " value=" + value + ", currently firing events"); return; - Number num = (Number)value; + } + Number num = (Number) value; double newValue = num.doubleValue(); - DoubleModel.this.setValue(currentUnit.fromUnit(newValue)); + double converted = currentUnit.fromUnit(newValue); + log.user("SpinnerModel setValue called for " + DoubleModel.this.toString() + " newValue=" + newValue + + " converted=" + converted); + DoubleModel.this.setValue(converted); -// try { -// double newValue = Double.parseDouble((String)value); -// DoubleModel.this.setValue(currentUnit.fromUnit(newValue)); -// } catch (NumberFormatException e) { -// DoubleModel.this.fireStateChanged(); -// }; } @Override public Object getNextValue() { double d = currentUnit.toUnit(DoubleModel.this.getValue()); double max = currentUnit.toUnit(maxValue); - if (MathUtil.equals(d,max)) + if (MathUtil.equals(d, max)) return null; d = currentUnit.getNextValue(d); if (d > max) d = max; return d; -// return makeString(d); } - + @Override public Object getPreviousValue() { double d = currentUnit.toUnit(DoubleModel.this.getValue()); double min = currentUnit.toUnit(minValue); - if (MathUtil.equals(d,min)) + if (MathUtil.equals(d, min)) return null; d = currentUnit.getPreviousValue(d); if (d < min) d = min; return d; -// return makeString(d); } - + @Override public Comparable getMinimum() { @@ -119,7 +116,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { public void addChangeListener(ChangeListener l) { DoubleModel.this.addChangeListener(l); } - + @Override public void removeChangeListener(ChangeListener l) { DoubleModel.this.removeChangeListener(l); @@ -137,9 +134,9 @@ public class DoubleModel implements ChangeListener, ChangeSource { } - - - + + + //////////// JSlider model //////////// private class ValueSliderModel implements BoundedRangeModel, ChangeListener { @@ -149,7 +146,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { * Use linear scale value = linear1 * x + linear0 when x < linearPosition * Use quadratic scale value = quad2 * x^2 + quad1 * x + quad0 otherwise */ - + // Linear in range x <= linearPosition private final double linearPosition; @@ -161,40 +158,40 @@ public class DoubleModel implements ChangeListener, ChangeSource { //private final double linear0; // Non-linear multiplier, exponent and constant - private final double quad2,quad1,quad0; - + private final double quad2, quad1, quad0; + public ValueSliderModel(DoubleModel min, DoubleModel max) { linearPosition = 1.0; - + this.min = min; - this.mid = max; // Never use exponential scale + this.mid = max; // Never use exponential scale this.max = max; min.addChangeListener(this); max.addChangeListener(this); - - quad2 = quad1 = quad0 = 0; // Not used + + quad2 = quad1 = quad0 = 0; // Not used } - + /** * Generate a linear model from min to max. */ public ValueSliderModel(double min, double max) { linearPosition = 1.0; - + this.min = new DoubleModel(min); - this.mid = new DoubleModel(max); // Never use exponential scale + this.mid = new DoubleModel(max); // Never use exponential scale this.max = new DoubleModel(max); - - quad2 = quad1 = quad0 = 0; // Not used + + quad2 = quad1 = quad0 = 0; // Not used } public ValueSliderModel(double min, double mid, double max) { - this(min,0.5,mid,max); + this(min, 0.5, mid, max); } /* @@ -208,15 +205,15 @@ public class DoubleModel implements ChangeListener, ChangeSource { this.min = new DoubleModel(min); this.mid = new DoubleModel(mid); this.max = new DoubleModel(max); - + linearPosition = pos; //linear0 = min; //linear1 = (mid-min)/pos; if (!(min < mid && mid <= max && 0 < pos && pos < 1)) { - throw new IllegalArgumentException("Bad arguments for ValueSliderModel "+ - "min="+min+" mid="+mid+" max="+max+" pos="+pos); + throw new IllegalArgumentException("Bad arguments for ValueSliderModel " + + "min=" + min + " mid=" + mid + " max=" + max + " pos=" + pos); } /* @@ -225,16 +222,16 @@ public class DoubleModel implements ChangeListener, ChangeSource { * 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 = (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); } private double pow2(double x) { - return x*x; + return x * x; } public int getValue() { @@ -250,68 +247,94 @@ public class DoubleModel implements ChangeListener, ChangeSource { //linear0 = min; //linear1 = (mid-min)/pos; - x = (value - min.getValue())*linearPosition/(mid.getValue()-min.getValue()); + x = (value - min.getValue()) * linearPosition / (mid.getValue() - min.getValue()); } else { // Use quadratic scale // Further solution of the quadratic equation // a*x^2 + b*x + c-value == 0 - x = (Math.sqrt(quad1*quad1 - 4*quad2*(quad0-value)) - quad1) / (2*quad2); + x = (Math.sqrt(quad1 * quad1 - 4 * quad2 * (quad0 - value)) - quad1) / (2 * quad2); } - return (int)(x*MAX); + return (int) (x * MAX); } - - + + public void setValue(int newValue) { - if (firing > 0) // Ignore loops + if (firing > 0) { + // Ignore loops + log.verbose("Ignoring call to SliderModel setValue for " + DoubleModel.this.toString() + + " value=" + newValue + ", currently firing events"); return; + } - double x = (double)newValue/MAX; - double value; + double x = (double) newValue / MAX; + double scaledValue; if (x <= linearPosition) { // Use linear scale //linear0 = min; //linear1 = (mid-min)/pos; - - value = (mid.getValue()-min.getValue())/linearPosition*x + min.getValue(); + + scaledValue = (mid.getValue() - min.getValue()) / linearPosition * x + min.getValue(); } else { // Use quadratic scale - value = quad2*x*x + quad1*x + quad0; + scaledValue = quad2 * x * x + quad1 * x + quad0; } - DoubleModel.this.setValue(currentUnit.fromUnit( - currentUnit.round(currentUnit.toUnit(value)))); + double converted = currentUnit.fromUnit(currentUnit.round(currentUnit.toUnit(scaledValue))); + log.user("SliderModel setValue called for " + DoubleModel.this.toString() + " newValue=" + newValue + + " scaledValue=" + scaledValue + " converted=" + converted); + DoubleModel.this.setValue(converted); } - + // Static get-methods private boolean isAdjusting; - public int getExtent() { return 0; } - public int getMaximum() { return MAX; } - public int getMinimum() { return 0; } - public boolean getValueIsAdjusting() { return isAdjusting; } + + public int getExtent() { + return 0; + } + + public int getMaximum() { + return MAX; + } + + public int getMinimum() { + return 0; + } + + public boolean getValueIsAdjusting() { + return isAdjusting; + } // Ignore set-values - public void setExtent(int newExtent) { } - public void setMaximum(int newMaximum) { } - public void setMinimum(int newMinimum) { } - public void setValueIsAdjusting(boolean b) { isAdjusting = b; } - + public void setExtent(int newExtent) { + } + + public void setMaximum(int newMaximum) { + } + + public void setMinimum(int newMinimum) { + } + + public void setValueIsAdjusting(boolean b) { + isAdjusting = b; + } + public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) { setValueIsAdjusting(adjusting); setValue(value); } - + // Pass change listeners to the underlying model public void addChangeListener(ChangeListener l) { DoubleModel.this.addChangeListener(l); } - + public void removeChangeListener(ChangeListener l) { DoubleModel.this.removeChangeListener(l); } - - + + public void stateChanged(ChangeEvent e) { // Min or max range has changed. @@ -323,24 +346,24 @@ public class DoubleModel implements ChangeListener, ChangeSource { public BoundedRangeModel getSliderModel(DoubleModel min, DoubleModel max) { - return new ValueSliderModel(min,max); + return new ValueSliderModel(min, max); } public BoundedRangeModel getSliderModel(double min, double max) { - return new ValueSliderModel(min,max); + return new ValueSliderModel(min, max); } public BoundedRangeModel getSliderModel(double min, double mid, double max) { - return new ValueSliderModel(min,mid,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); + return new ValueSliderModel(min, pos, mid, max); } - - + + //////////// Action model //////////// @@ -352,10 +375,9 @@ public class DoubleModel implements ChangeListener, ChangeSource { addChangeListener(this); } - + @Override public boolean isEnabled() { - // TODO: LOW: does not reflect if component is currently able to support automatic setting return isAutomaticAvailable(); } @@ -367,51 +389,61 @@ public class DoubleModel implements ChangeListener, ChangeSource { } return super.getValue(key); } - + @Override public void putValue(String key, Object value) { - if (firing > 0) + if (firing > 0) { + log.verbose("Ignoring call to ActionModel putValue for " + DoubleModel.this.toString() + + " key=" + key + " value=" + value + ", currently firing events"); return; + } if (key.equals(Action.SELECTED_KEY) && (value instanceof Boolean)) { - oldValue = (Boolean)value; - setAutomatic((Boolean)value); + log.user("ActionModel putValue called for " + DoubleModel.this.toString() + + " key=" + key + " value=" + value); + oldValue = (Boolean) value; + setAutomatic((Boolean) value); } else { + log.debug("Passing ActionModel putValue call to supermethod for " + DoubleModel.this.toString() + + " key=" + key + " value=" + value); super.putValue(key, value); } } - + // Implement a wrapper to the ChangeListeners - ArrayList propertyChangeListeners = - new ArrayList(); + ArrayList propertyChangeListeners = + new ArrayList(); + @Override public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeListeners.add(listener); DoubleModel.this.addChangeListener(this); } + @Override public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeListeners.remove(listener); if (propertyChangeListeners.isEmpty()) DoubleModel.this.removeChangeListener(this); } + // If the value has changed, generate an event to the listeners public void stateChanged(ChangeEvent e) { boolean newValue = isAutomatic(); if (oldValue == newValue) return; - PropertyChangeEvent event = new PropertyChangeEvent(this,Action.SELECTED_KEY, - oldValue,newValue); + PropertyChangeEvent event = new PropertyChangeEvent(this, Action.SELECTED_KEY, + oldValue, newValue); oldValue = newValue; Object[] l = propertyChangeListeners.toArray(); - for (int i=0; i0 when model itself is sending events + private String toString = null; + + private int firing = 0; // >0 when model itself is sending events + // Used to differentiate changes in valueName and other changes in the component: private double lastValue = 0; private boolean lastAutomatic = false; - + public DoubleModel(double value) { - this(value, UnitGroup.UNITS_NONE,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY); + this(value, UnitGroup.UNITS_NONE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } public DoubleModel(double value, UnitGroup unit) { - this(value,unit,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY); + this(value, unit, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } public DoubleModel(double value, UnitGroup unit, double min) { - this(value,unit,min,Double.POSITIVE_INFINITY); + this(value, unit, min, Double.POSITIVE_INFINITY); } public DoubleModel(double value, UnitGroup unit, double min, double max) { this.lastValue = value; this.minValue = min; this.maxValue = max; - + source = null; valueName = "Constant value"; multiplier = 1; @@ -488,7 +521,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { units = unit; currentUnit = units.getDefaultUnit(); } - + /** * Generates a new DoubleModel that changes the values of the specified component. @@ -505,7 +538,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { this.source = source; this.valueName = valueName; this.multiplier = multiplier; - + this.units = unit; currentUnit = units.getDefaultUnit(); @@ -515,26 +548,28 @@ public class DoubleModel implements ChangeListener, ChangeSource { try { getMethod = source.getClass().getMethod("get" + valueName); } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("get method for value '"+valueName+ - "' not present in class "+source.getClass().getCanonicalName()); + throw new IllegalArgumentException("get method for value '" + valueName + + "' not present in class " + source.getClass().getCanonicalName()); } - - Method s=null; + + Method s = null; try { - s = source.getClass().getMethod("set" + valueName,double.class); - } catch (NoSuchMethodException e1) { } // Ignore + s = source.getClass().getMethod("set" + valueName, double.class); + } catch (NoSuchMethodException e1) { + } // Ignore setMethod = s; // Automatic selection methods - Method set=null,get=null; + Method set = null, get = null; try { get = source.getClass().getMethod("is" + valueName + "Automatic"); - set = source.getClass().getMethod("set" + valueName + "Automatic",boolean.class); - } catch (NoSuchMethodException e) { } // ignore + set = source.getClass().getMethod("set" + valueName + "Automatic", boolean.class); + } catch (NoSuchMethodException e) { + } // ignore - if (set!=null && get!=null) { + if (set != null && get != null) { getAutoMethod = get; setAutoMethod = set; } else { @@ -543,57 +578,57 @@ public class DoubleModel implements ChangeListener, ChangeSource { } } - + public DoubleModel(ChangeSource source, String valueName, double multiplier, UnitGroup unit, double min) { - this(source,valueName,multiplier,unit,min,Double.POSITIVE_INFINITY); + this(source, valueName, multiplier, unit, min, Double.POSITIVE_INFINITY); } public DoubleModel(ChangeSource source, String valueName, double multiplier, UnitGroup unit) { - this(source,valueName,multiplier,unit,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY); + this(source, valueName, multiplier, unit, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } - public DoubleModel(ChangeSource source, String valueName, UnitGroup unit, + public DoubleModel(ChangeSource source, String valueName, UnitGroup unit, double min, double max) { - this(source,valueName,1.0,unit,min,max); + this(source, valueName, 1.0, unit, min, max); } public DoubleModel(ChangeSource source, String valueName, UnitGroup unit, double min) { - this(source,valueName,1.0,unit,min,Double.POSITIVE_INFINITY); + this(source, valueName, 1.0, unit, min, Double.POSITIVE_INFINITY); } public DoubleModel(ChangeSource source, String valueName, UnitGroup unit) { - this(source,valueName,1.0,unit,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY); + this(source, valueName, 1.0, unit, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } - + public DoubleModel(ChangeSource source, String valueName) { - this(source,valueName,1.0,UnitGroup.UNITS_NONE, - Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY); + this(source, valueName, 1.0, UnitGroup.UNITS_NONE, + Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } - + public DoubleModel(ChangeSource source, String valueName, double min) { - this(source,valueName,1.0,UnitGroup.UNITS_NONE,min,Double.POSITIVE_INFINITY); + this(source, valueName, 1.0, UnitGroup.UNITS_NONE, min, Double.POSITIVE_INFINITY); } public DoubleModel(ChangeSource source, String valueName, double min, double max) { - this(source,valueName,1.0,UnitGroup.UNITS_NONE,min,max); + this(source, valueName, 1.0, UnitGroup.UNITS_NONE, min, max); } - + /** * Returns the value of the variable (in SI units). */ public double getValue() { - if (getMethod==null) // Constant value + if (getMethod == null) // Constant value return lastValue; - + try { - return (Double)getMethod.invoke(source)*multiplier; + return (Double) getMethod.invoke(source) * multiplier; } catch (IllegalArgumentException e) { - throw new BugException("Unable to invoke getMethod of "+this, e); + throw new BugException("Unable to invoke getMethod of " + this, e); } catch (IllegalAccessException e) { - throw new BugException("Unable to invoke getMethod of "+this, e); + throw new BugException("Unable to invoke getMethod of " + this, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } @@ -604,27 +639,28 @@ public class DoubleModel implements ChangeListener, ChangeSource { * @param v New value for parameter in SI units. */ public void setValue(double v) { - if (setMethod==null) { + log.debug("Setting value " + v + " for " + this); + if (setMethod == null) { if (getMethod != null) { - throw new RuntimeException("setMethod not available for variable '"+valueName+ - "' in class "+source.getClass().getCanonicalName()); + throw new BugException("setMethod not available for variable '" + valueName + + "' in class " + source.getClass().getCanonicalName()); } lastValue = v; fireStateChanged(); return; } - + try { - setMethod.invoke(source, v/multiplier); + setMethod.invoke(source, v / multiplier); } catch (IllegalArgumentException e) { - throw new BugException("Unable to invoke setMethod of "+this, e); + throw new BugException("Unable to invoke setMethod of " + this, e); } catch (IllegalAccessException e) { - throw new BugException("Unable to invoke setMethod of "+this, e); + throw new BugException("Unable to invoke setMethod of " + this, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } } - + /** * Returns whether setting the value automatically is available. @@ -632,7 +668,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { public boolean isAutomaticAvailable() { return (getAutoMethod != null) && (setAutoMethod != null); } - + /** * Returns whether the value is currently being set automatically. * Returns false if automatic setting is not available at all. @@ -642,7 +678,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { return false; try { - return (Boolean)getAutoMethod.invoke(source); + return (Boolean) getAutoMethod.invoke(source); } catch (IllegalArgumentException e) { throw new BugException("Method call failed", e); } catch (IllegalAccessException e) { @@ -658,10 +694,12 @@ public class DoubleModel implements ChangeListener, ChangeSource { */ public void setAutomatic(boolean auto) { if (setAutoMethod == null) { - fireStateChanged(); // in case something is out-of-sync + log.debug("Setting automatic to " + auto + " for " + this + ", automatic not available"); + fireStateChanged(); // in case something is out-of-sync return; } + log.debug("Setting automatic to " + auto + " for " + this); lastAutomatic = auto; try { setAutoMethod.invoke(source, auto); @@ -674,7 +712,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { } } - + /** * Returns the current Unit. At the beginning it is the default unit of the UnitGroup. * @return The most recently set unit. @@ -690,6 +728,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { public void setCurrentUnit(Unit u) { if (currentUnit == u) return; + log.debug("Setting unit for " + this + " to '" + u + "'"); currentUnit = u; fireStateChanged(); } @@ -705,7 +744,7 @@ public class DoubleModel implements ChangeListener, ChangeSource { } - + /** * Add a listener to the model. Adds the model as a listener to the value source if this * is the first listener. @@ -719,12 +758,11 @@ public class DoubleModel implements ChangeListener, ChangeSource { lastAutomatic = isAutomatic(); } } - + listeners.add(l); - if (DEBUG_LISTENERS) - System.out.println(this+" adding listener (total "+listeners.size()+"): "+l); + log.verbose(this + " adding listener (total " + listeners.size() + "): " + l); } - + /** * Remove a listener from the model. Removes the model from being a listener to the Component * if this was the last listener of the model. @@ -735,10 +773,19 @@ public class DoubleModel implements ChangeListener, ChangeSource { if (listeners.isEmpty() && source != null) { source.removeChangeListener(this); } - if (DEBUG_LISTENERS) - System.out.println(this+" removing listener (total "+listeners.size()+"): "+l); + log.verbose(this + " removing listener (total " + listeners.size() + "): " + l); } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (!listeners.isEmpty()) { + log.warn(this + " being garbage-collected while having listeners " + listeners); + } + }; + + /** * Fire a ChangeEvent to all listeners. */ @@ -746,11 +793,11 @@ public class DoubleModel implements ChangeListener, ChangeSource { Object[] l = listeners.toArray(); ChangeEvent event = new ChangeEvent(this); firing++; - for (int i=0; i 0) // Ignore, if called when model is sending events + if (firing > 0) { + // Ignore, if called when model is sending events + log.verbose("Ignoring call to SpinnerModel setValue for " + IntegerModel.this.toString() + + " value=" + value + ", currently firing events"); return; - Number num = (Number)value; + + } + Number num = (Number) value; int newValue = num.intValue(); + log.user("SpinnerModel setValue called for " + IntegerModel.this.toString() + " newValue=" + newValue); IntegerModel.this.setValue(newValue); - -// try { -// int newValue = Integer.parseInt((String)value); -// IntegerModel.this.setValue(newValue); -// } catch (NumberFormatException e) { -// IntegerModel.this.fireStateChanged(); -// }; } - + @Override public Object getNextValue() { int d = IntegerModel.this.getValue(); if (d >= maxValue) return null; - return (d+1); + return (d + 1); } - + @Override public Object getPreviousValue() { int d = IntegerModel.this.getValue(); if (d <= minValue) return null; - return (d-1); + return (d - 1); } @Override public void addChangeListener(ChangeListener l) { IntegerModel.this.addChangeListener(l); } - + @Override public void removeChangeListener(ChangeListener l) { IntegerModel.this.removeChangeListener(l); @@ -82,11 +84,11 @@ public class IntegerModel implements ChangeListener { //////////// Main model ///////////// - + /* * The main model handles all values in SI units, i.e. no conversion is made within the model. */ - + private final ChangeSource source; private final String valueName; @@ -94,26 +96,27 @@ public class IntegerModel implements ChangeListener { private final Method setMethod; private final ArrayList listeners = new ArrayList(); - + private final int minValue; private final int maxValue; - - private int firing = 0; // >0 when model itself is sending events + private String toString = null; + + private int firing = 0; // >0 when model itself is sending events + // Used to differentiate changes in valueName and other changes in the source: private int lastValue = 0; - - + + /** * Generates a new DoubleModel that changes the values of the specified source. * The double value is read and written using the methods "get"/"set" + valueName. * * @param source Component whose parameter to use. - * @param valueName Name of metods used to get/set the parameter. - * @param multiplier Value shown by the model is the value from source.getXXX * multiplier + * @param valueName Name of methods used to get/set the parameter. * @param min Minimum value allowed (in SI units) * @param max Maximum value allowed (in SI units) */ @@ -126,30 +129,30 @@ public class IntegerModel implements ChangeListener { try { getMethod = source.getClass().getMethod("get" + valueName); - setMethod = source.getClass().getMethod("set" + valueName,int.class); + setMethod = source.getClass().getMethod("set" + valueName, int.class); } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("get/set methods for value '"+valueName+ - "' not present in class "+source.getClass().getCanonicalName()); + throw new IllegalArgumentException("get/set methods for value '" + valueName + + "' not present in class " + source.getClass().getCanonicalName()); } } - + public IntegerModel(ChangeSource source, String valueName, int min) { - this(source,valueName,min,Integer.MAX_VALUE); + this(source, valueName, min, Integer.MAX_VALUE); } public IntegerModel(ChangeSource source, String valueName) { - this(source,valueName,Integer.MIN_VALUE,Integer.MAX_VALUE); + this(source, valueName, Integer.MIN_VALUE, Integer.MAX_VALUE); } - - + + /** * Returns the value of the variable. */ public int getValue() { try { - return (Integer)getMethod.invoke(source); + return (Integer) getMethod.invoke(source); } catch (IllegalArgumentException e) { throw new BugException(e); } catch (IllegalAccessException e) { @@ -163,6 +166,7 @@ public class IntegerModel implements ChangeListener { * Sets the value of the variable. */ public void setValue(int v) { + log.debug("Setting value " + v + " for " + this); try { setMethod.invoke(source, v); } catch (IllegalArgumentException e) { @@ -173,7 +177,7 @@ public class IntegerModel implements ChangeListener { throw Reflection.handleWrappedException(e); } } - + /** * Add a listener to the model. Adds the model as a listener to the Component if this @@ -185,10 +189,11 @@ public class IntegerModel implements ChangeListener { source.addChangeListener(this); lastValue = getValue(); } - + listeners.add(l); + log.verbose(this + " adding listener (total " + listeners.size() + "): " + l); } - + /** * Remove a listener from the model. Removes the model from being a listener to the Component * if this was the last listener of the model. @@ -199,17 +204,28 @@ public class IntegerModel implements ChangeListener { if (listeners.isEmpty()) { source.removeChangeListener(this); } + log.verbose(this + " removing listener (total " + listeners.size() + "): " + l); } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (!listeners.isEmpty()) { + log.warn(this + " being garbage-collected while having listeners " + listeners); + } + }; + + public void fireStateChanged() { Object[] l = listeners.toArray(); ChangeEvent event = new ChangeEvent(this); firing++; - for (int i=0; i 1); + split.setEnabled(((FinSet) component).getFinCount() > 1); - if (convert==null) + if (convert == null) addButtons(split); else - addButtons(split,convert); - + addButtons(split, convert); + } - + public JPanel finTabPanel() { JPanel panel = new JPanel( new MigLayout("align 50% 20%, fillx, gap rel unrel, ins 20lp 10% 20lp 10%", - "[150lp::][65lp::][30lp::][200lp::]","")); -// JPanel panel = new JPanel(new MigLayout("fillx, align 20% 20%, gap rel unrel", -// "[40lp][80lp::][30lp::][100lp::]","")); - - panel.add(new StyledLabel("Through-the-wall fin tabs:", Style.BOLD), + "[150lp::][65lp::][30lp::][200lp::]", "")); + // JPanel panel = new JPanel(new MigLayout("fillx, align 20% 20%, gap rel unrel", + // "[40lp][80lp::][30lp::][100lp::]","")); + + panel.add(new StyledLabel("Through-the-wall fin tabs:", Style.BOLD), "spanx, wrap 30lp"); JLabel label; @@ -118,7 +126,7 @@ public abstract class FinSetConfig extends RocketComponentConfig { DoubleModel length2; DoubleModel length_2; JSpinner spin; - + length = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0); length2 = new DoubleModel(component, "Length", 0.5, UnitGroup.UNITS_LENGTH, 0); length_2 = new DoubleModel(component, "Length", -0.5, UnitGroup.UNITS_LENGTH, 0); @@ -132,13 +140,13 @@ public abstract class FinSetConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx 1"); + panel.add(spin, "growx 1"); - panel.add(new UnitSelector(m),"growx 1"); + panel.add(new UnitSelector(m), "growx 1"); panel.add(new BasicSlider(m.getSliderModel(DoubleModel.ZERO, length)), "w 100lp, growx 5, wrap"); - + //// Tab length label = new JLabel("Tab height:"); label.setToolTipText("The spanwise height of the fin tab."); @@ -148,13 +156,13 @@ public abstract class FinSetConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); + panel.add(spin, "growx"); - panel.add(new UnitSelector(m),"growx"); + panel.add(new UnitSelector(m), "growx"); panel.add(new BasicSlider(m.getSliderModel(DoubleModel.ZERO, length2)), "w 100lp, growx 5, wrap para"); - + //// Tab position label = new JLabel("Tab position:"); label.setToolTipText("The position of the fin tab."); @@ -164,28 +172,28 @@ public abstract class FinSetConfig extends RocketComponentConfig { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); - panel.add(spin,"growx"); - - panel.add(new UnitSelector(m),"growx"); - panel.add(new BasicSlider(m.getSliderModel(length_2, length2)),"w 100lp, growx 5, wrap"); - + panel.add(spin, "growx"); + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(length_2, length2)), "w 100lp, growx 5, wrap"); + + label = new JLabel("relative to"); panel.add(label, "right, gapright unrel"); - EnumModel em = - new EnumModel(component, "TabRelativePosition"); + EnumModel em = + new EnumModel(component, "TabRelativePosition"); panel.add(new JComboBox(em), "spanx 3, growx"); return panel; } - + @Override public void updateFields() { super.updateFields(); if (split != null) - split.setEnabled(((FinSet)component).getFinCount() > 1); + split.setEnabled(((FinSet) component).getFinCount() > 1); } } diff --git a/src/net/sf/openrocket/gui/main/ComponentAddButtons.java b/src/net/sf/openrocket/gui/main/ComponentAddButtons.java index af1d1bb1..e5429e3a 100644 --- a/src/net/sf/openrocket/gui/main/ComponentAddButtons.java +++ b/src/net/sf/openrocket/gui/main/ComponentAddButtons.java @@ -30,6 +30,7 @@ import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.configdialog.ComponentConfigDialog; import net.sf.openrocket.gui.main.componenttree.ComponentTreeModel; +import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.rocketcomponent.BodyComponent; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.Bulkhead; @@ -49,6 +50,7 @@ import net.sf.openrocket.rocketcomponent.Streamer; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.rocketcomponent.TrapezoidFinSet; import net.sf.openrocket.rocketcomponent.TubeCoupler; +import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Pair; import net.sf.openrocket.util.Prefs; @@ -63,6 +65,7 @@ import net.sf.openrocket.util.Reflection; */ public class ComponentAddButtons extends JPanel implements Scrollable { + private static final LogHelper log = Application.getLogger(); private static final int ROWS = 3; private static final int MAXCOLS = 6; @@ -364,6 +367,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable { @Override protected void fireActionPerformed(ActionEvent event) { super.fireActionPerformed(event); + log.user("Adding component of type " + componentClass.getSimpleName()); RocketComponent c = null; Integer position = null; @@ -374,6 +378,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable { Pair pos = getAdditionPosition(c); if (pos == null) { // Cancel addition + log.info("No position to add component"); return; } c = pos.getU(); @@ -396,11 +401,9 @@ public class ComponentAddButtons extends JPanel implements Scrollable { try { component = (RocketComponent) constructor.newInstance(); } catch (InstantiationException e) { - throw new BugException("Could not construct new instance of class " + - constructor, e); + throw new BugException("Could not construct new instance of class " + constructor, e); } catch (IllegalAccessException e) { - throw new BugException("Could not construct new instance of class " + - constructor, e); + throw new BugException("Could not construct new instance of class " + constructor, e); } catch (InvocationTargetException e) { throw Reflection.handleWrappedException(e); } @@ -408,7 +411,9 @@ public class ComponentAddButtons extends JPanel implements Scrollable { // Next undo position is set by opening the configuration dialog document.addUndoPosition("Add " + component.getComponentName()); - + log.info("Adding component " + component.getComponentName() + " to component " + c.getComponentName() + + " position=" + position); + if (position == null) c.addChild(component); else diff --git a/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java b/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java index 09d229bc..ef13629a 100644 --- a/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java +++ b/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java @@ -10,31 +10,30 @@ import javax.swing.DropMode; import javax.swing.Icon; import javax.swing.JTree; import javax.swing.ToolTipManager; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; import net.sf.openrocket.document.OpenRocketDocument; public class ComponentTree extends JTree { - private static final long serialVersionUID = 1L; public ComponentTree(OpenRocketDocument document) { super(); this.setModel(new ComponentTreeModel(document.getRocket(), this)); this.setToggleClickCount(0); - javax.swing.plaf.basic.BasicTreeUI ui = new javax.swing.plaf.basic.BasicTreeUI(); - this.setUI(ui); - - ui.setExpandedIcon(TreeIcon.MINUS); - ui.setCollapsedIcon(TreeIcon.PLUS); - - ui.setLeftChildIndent(15); + javax.swing.plaf.basic.BasicTreeUI plainUI = new javax.swing.plaf.basic.BasicTreeUI(); + this.setUI(plainUI); + plainUI.setExpandedIcon(TreeIcon.MINUS); + plainUI.setCollapsedIcon(TreeIcon.PLUS); + plainUI.setLeftChildIndent(15); - setBackground(Color.WHITE); - setShowsRootHandles(false); + this.setBackground(Color.WHITE); + this.setShowsRootHandles(false); - setCellRenderer(new ComponentTreeRenderer()); + this.setCellRenderer(new ComponentTreeRenderer()); this.setDragEnabled(true); this.setDropMode(DropMode.INSERT); @@ -52,9 +51,43 @@ public class ComponentTree extends JTree { public void expandTree() { for (int i = 0; i < getRowCount(); i++) expandRow(i); - } + @Override + public void treeDidChange() { + super.treeDidChange(); + expandChildlessNodes(); + } + + /** + * Expand all nodes in the tree that are visible and have no children. This can be used + * to avoid the situation where a non-leaf node is marked as being expandable, but when + * expanding it it has no children. + */ + private void expandChildlessNodes() { + TreeModel model = this.getModel(); + if (model == null) { + return; + } + Object root = model.getRoot(); + expandChildlessNodes(model, new TreePath(root)); + } + + private void expandChildlessNodes(TreeModel model, TreePath path) { + Object object = path.getLastPathComponent(); + if (this.isVisible(path)) { + int count = model.getChildCount(object); + if (count == 0) { + this.expandPath(path); + } + for (int i = 0; i < count; i++) { + expandChildlessNodes(model, path.pathByAddingChild(model.getChild(object, i))); + } + } + } + + + private static class TreeIcon implements Icon { public static final Icon PLUS = new TreeIcon(true); public static final Icon MINUS = new TreeIcon(false); diff --git a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java index 3e76b251..f51f4650 100644 --- a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java +++ b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java @@ -3,11 +3,14 @@ package net.sf.openrocket.rocketcomponent; import java.util.ArrayList; import java.util.Arrays; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; public class FreeformFinSet extends FinSet { + private static final LogHelper log = Application.getLogger(); private ArrayList points = new ArrayList(); @@ -50,6 +53,7 @@ public class FreeformFinSet extends FinSet { * @return the new freeform fin set. */ public static FreeformFinSet convertFinSet(FinSet finset) { + log.info("Converting " + finset.getComponentName() + " into freeform fin set"); final RocketComponent root = finset.getRoot(); FreeformFinSet freeform; diff --git a/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index f6d575e3..2e0a784c 100644 --- a/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -206,7 +206,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @see #isCompatible(Class) */ public final boolean isCompatible(RocketComponent c) { - checkState(); return isCompatible(c.getClass()); } @@ -380,7 +379,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * to use the default color. */ public final Color getColor() { - checkState(); return color; } @@ -388,25 +386,24 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * Set the color of the object to use in 2D figures. */ public final void setColor(Color c) { - checkState(); if ((color == null && c == null) || (color != null && color.equals(c))) return; + checkState(); this.color = c; fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } public final LineStyle getLineStyle() { - checkState(); return lineStyle; } public final void setLineStyle(LineStyle style) { - checkState(); if (this.lineStyle == style) return; + checkState(); this.lineStyle = style; fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } @@ -421,7 +418,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return the override mass */ public final double getOverrideMass() { - checkState(); return overrideMass; } @@ -432,6 +428,8 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param m the override mass */ public final void setOverrideMass(double m) { + if (MathUtil.equals(m, overrideMass)) + return; checkState(); overrideMass = Math.max(m, 0); if (massOverriden) @@ -445,7 +443,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return whether the mass is overridden */ public final boolean isMassOverridden() { - checkState(); return massOverriden; } @@ -455,11 +452,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param o whether the mass is overridden */ public final void setMassOverridden(boolean o) { - checkState(); - if (massOverriden != o) { - massOverriden = o; - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); + if (massOverriden == o) { + return; } + checkState(); + massOverriden = o; + fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } @@ -472,7 +470,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return the override CG */ public final Coordinate getOverrideCG() { - checkState(); return getComponentCG().setX(overrideCGX); } @@ -482,7 +479,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return the x-coordinate of the override CG. */ public final double getOverrideCGX() { - checkState(); return overrideCGX; } @@ -492,9 +488,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param x the x-coordinate of the override CG to set. */ public final void setOverrideCGX(double x) { - checkState(); if (MathUtil.equals(overrideCGX, x)) return; + checkState(); this.overrideCGX = x; if (isCGOverridden()) fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); @@ -508,7 +504,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return whether the CG is overridden */ public final boolean isCGOverridden() { - checkState(); return cgOverriden; } @@ -518,11 +513,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param o whether the CG is overridden */ public final void setCGOverridden(boolean o) { - checkState(); - if (cgOverriden != o) { - cgOverriden = o; - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); + if (cgOverriden == o) { + return; } + checkState(); + cgOverriden = o; + fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } @@ -538,7 +534,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return whether the current mass and/or CG override overrides subcomponents as well. */ public boolean getOverrideSubcomponents() { - checkState(); return overrideSubcomponents; } @@ -550,11 +545,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param override whether the mass and/or CG override overrides all subcomponent. */ public void setOverrideSubcomponents(boolean override) { - checkState(); - if (overrideSubcomponents != override) { - overrideSubcomponents = override; - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); + if (overrideSubcomponents == override) { + return; } + checkState(); + overrideSubcomponents = override; + fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } /** @@ -568,7 +564,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return whether the option to override subcomponents is currently enabled. */ public boolean isOverrideSubcomponentsEnabled() { - checkState(); return isCGOverridden() || isMassOverridden(); } @@ -587,6 +582,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * the default name, currently the component name. */ public final void setName(String name) { + if (this.name.equals(name)) { + return; + } checkState(); if (name == null || name.matches("^\\s*$")) this.name = getComponentName(); @@ -603,7 +601,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return the comment of the component. */ public final String getComment() { - checkState(); return comment; } @@ -613,9 +610,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param comment the comment of the component. */ public final void setComment(String comment) { - checkState(); if (this.comment.equals(comment)) return; + checkState(); if (comment == null) this.comment = ""; else @@ -653,7 +650,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * itself. */ public final double getLength() { - checkState(); return length; } @@ -663,7 +659,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * but can be provided by a subclass. */ public final Position getRelativePosition() { - checkState(); return relativePosition; } @@ -680,9 +675,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param position the relative positioning. */ protected void setRelativePosition(RocketComponent.Position position) { - checkState(); if (this.relativePosition == position) return; + checkState(); // Update position so as not to move the component if (this.parent != null) { @@ -724,7 +719,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return the positional value. */ public final double getPositionValue() { - checkState(); return position; } @@ -741,9 +735,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @param value the position value of the component. */ public void setPositionValue(double value) { - checkState(); if (MathUtil.equals(this.position, value)) return; + checkState(); this.position = value; } @@ -885,7 +879,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, * @return The mass of the component or the given override mass. */ public final double getMass() { - checkState(); if (massOverriden) return overrideMass; return getComponentMass(); @@ -1332,8 +1325,8 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, /** * Checks whether this component has been invalidated and should no longer be used. * This is a safety check that in-place replaced components are no longer used. - * All non-trivial methods should call this method as the first thing, unless the - * method may be used in debugging cases. + * All non-trivial methods (with the exception of methods simply getting a property) + * should call this method before changing or computing anything. * * @throws BugException if this component has been invalidated by {@link #copyFrom(RocketComponent)}. */ diff --git a/test/net/sf/openrocket/IntegrationTest.java b/test/net/sf/openrocket/IntegrationTest.java index fa60aaa9..c864ec96 100644 --- a/test/net/sf/openrocket/IntegrationTest.java +++ b/test/net/sf/openrocket/IntegrationTest.java @@ -259,6 +259,8 @@ public class IntegrationTest { // Check cg+cp + altitude checkCgCp(0.221, 0.0797, 0.320, 12.0); checkAlt(32.7); + + } private String massComponentID = null;