bug fix + more logging
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 8 Oct 2010 22:09:20 +0000 (22:09 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Fri, 8 Oct 2010 22:09:20 +0000 (22:09 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@91 180e2498-e6e9-4542-8430-84ac67f01cd8

ChangeLog
src/net/sf/openrocket/gui/adaptors/BooleanModel.java
src/net/sf/openrocket/gui/adaptors/DoubleModel.java
src/net/sf/openrocket/gui/adaptors/IntegerModel.java
src/net/sf/openrocket/gui/configdialog/FinSetConfig.java
src/net/sf/openrocket/gui/main/ComponentAddButtons.java
src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java
src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
src/net/sf/openrocket/rocketcomponent/RocketComponent.java
test/net/sf/openrocket/IntegrationTest.java

index 8429a3d4f12dcdb9a6e03de8c9d334a3ec7d3083..0f4e934f3b1e493e7228da50bd2251a235c26200 100644 (file)
--- 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
index e474a9ee86dcfb9ea7ba8c107fa105016ee622fd..2aa651c642d670233499a2c8bded21997683d043 100644 (file)
@@ -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<Component> components = new ArrayList<Component>();
        private final List<Boolean> componentEnableState = new ArrayList<Boolean>();
        
+       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;
        }
 }
index 20b2ad94349743aeae7c06b8e46347a22619350f..a81381dca284088a41cd9ec4b6ff32feb0231474 100644 (file)
@@ -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<Double> 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<PropertyChangeListener> propertyChangeListeners = 
-                       new ArrayList<PropertyChangeListener>();
+               ArrayList<PropertyChangeListener> propertyChangeListeners =
+                               new ArrayList<PropertyChangeListener>();
+               
                @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; i<l.length; i++) {
-                               ((PropertyChangeListener)l[i]).propertyChange(event);
+                       for (int i = 0; i < l.length; i++) {
+                               ((PropertyChangeListener) l[i]).propertyChange(event);
                        }
                }
-
+               
                public void actionPerformed(ActionEvent e) {
                        // Setting performed in putValue
                }
-
+               
        }
        
        /**
@@ -425,16 +457,15 @@ public class DoubleModel implements ChangeListener, ChangeSource {
        }
        
        
-       
-       
 
 
-       ////////////  Main model  /////////////
 
+       ////////////  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;
        private final double multiplier;
@@ -449,36 +480,38 @@ public class DoubleModel implements ChangeListener, ChangeSource {
        
        private final UnitGroup units;
        private Unit currentUnit;
-
+       
        private final double minValue;
        private final double 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 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<l.length; i++)
-                       ((ChangeListener)l[i]).stateChanged(event);
+               for (int i = 0; i < l.length; i++)
+                       ((ChangeListener) l[i]).stateChanged(event);
                firing--;
        }
-
+       
        /**
         * Called when the component changes.  Checks whether the modeled value has changed, and if
         * it has, updates lastValue and generates ChangeEvents for all listeners of the model.
@@ -764,14 +811,20 @@ public class DoubleModel implements ChangeListener, ChangeSource {
                lastAutomatic = b;
                fireStateChanged();
        }
-
+       
+       
        /**
         * Explain the DoubleModel as a String.
         */
        @Override
        public String toString() {
-               if (source == null)
-                       return "DoubleModel[constant="+lastValue+"]";
-               return "DoubleModel["+source.getClass().getCanonicalName()+":"+valueName+"]";
+               if (toString == null) {
+                       if (source == null) {
+                               toString = "DoubleModel[constant=" + lastValue + "]";
+                       } else {
+                               toString = "DoubleModel[" + source.getClass().getSimpleName() + ":" + valueName + "]";
+                       }
+               }
+               return toString;
        }
 }
index 35efe7fe260a4be5b1cc24c64f0e11e3e2519b64..8cf103652359ad4ab83bd925c7581b8e172bfc60 100644 (file)
@@ -9,14 +9,17 @@ 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.util.BugException;
 import net.sf.openrocket.util.ChangeSource;
 import net.sf.openrocket.util.Reflection;
 
 
 public class IntegerModel implements ChangeListener {
-
-
+       private static final LogHelper log = Application.getLogger();
+       
+       
        //////////// JSpinner Model ////////////
        
        private class IntegerSpinnerModel extends SpinnerNumberModel {
@@ -24,44 +27,43 @@ public class IntegerModel implements ChangeListener {
                public Object getValue() {
                        return IntegerModel.this.getValue();
                }
-
+               
                @Override
                public void setValue(Object value) {
-                       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 " + 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<ChangeListener> listeners = new ArrayList<ChangeListener>();
-
+       
        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<l.length; i++)
-                       ((ChangeListener)l[i]).stateChanged(event);
+               for (int i = 0; i < l.length; i++)
+                       ((ChangeListener) l[i]).stateChanged(event);
                firing--;
        }
-
+       
        /**
         * Called when the source changes.  Checks whether the modeled value has changed, and if
         * it has, updates lastValue and generates ChangeEvents for all listeners of the model.
@@ -221,13 +237,16 @@ public class IntegerModel implements ChangeListener {
                lastValue = v;
                fireStateChanged();
        }
-
+       
        /**
         * Explain the DoubleModel as a String.
         */
        @Override
        public String toString() {
-               return "IntegerModel["+source.getClass().getCanonicalName()+":"+valueName+"]";
+               if (toString == null) {
+                       toString = "IntegerModel[" + source.getClass().getSimpleName() + ":" + valueName + "]";
+               }
+               return toString;
        }
        
 }
index df5ce634fa42f71816e0188a57d9d489ac45e04e..ccc1174f49fa96b4a9dcf1407c9e9233d23b7303 100644 (file)
@@ -18,14 +18,17 @@ import net.sf.openrocket.gui.components.BasicSlider;
 import net.sf.openrocket.gui.components.StyledLabel;
 import net.sf.openrocket.gui.components.UnitSelector;
 import net.sf.openrocket.gui.components.StyledLabel.Style;
+import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.rocketcomponent.FinSet;
 import net.sf.openrocket.rocketcomponent.FreeformFinSet;
 import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.startup.Application;
 import net.sf.openrocket.unit.UnitGroup;
 
 
 public abstract class FinSetConfig extends RocketComponentConfig {
-
+       private static final LogHelper log = Application.getLogger();
+       
        private JButton split = null;
        
        public FinSetConfig(RocketComponent component) {
@@ -33,11 +36,11 @@ public abstract class FinSetConfig extends RocketComponentConfig {
                
                tabbedPane.insertTab("Fin tabs", null, finTabPanel(), "Through-the-wall fin tabs", 0);
        }
-
        
        
+
        protected void addFinSetButtons() {
-               JButton convert=null;
+               JButton convert = null;
                
                //// Convert buttons
                if (!(component instanceof FreeformFinSet)) {
@@ -46,70 +49,75 @@ public abstract class FinSetConfig extends RocketComponentConfig {
                        convert.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
+                                       log.user("Converting " + component.getComponentName() + " into freeform fin set");
+                                       
                                        // Do change in future for overall safety
                                        SwingUtilities.invokeLater(new Runnable() {
                                                @Override
                                                public void run() {
                                                        ComponentConfigDialog.addUndoPosition("Convert fin set");
-                                                       RocketComponent freeform = 
-                                                               FreeformFinSet.convertFinSet((FinSet)component);
+                                                       RocketComponent freeform =
+                                                                       FreeformFinSet.convertFinSet((FinSet) component);
                                                        ComponentConfigDialog.showDialog(freeform);
                                                }
                                        });
-
+                                       
                                        ComponentConfigDialog.hideDialog();
                                }
                        });
                }
-
+               
                split = new JButton("Split fins");
                split.setToolTipText("Split the fin set into separate fins");
                split.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
+                               log.user("Splitting " + component.getComponentName() + " into separate fins, fin count=" +
+                                               ((FinSet) component).getFinCount());
+                               
                                // Do change in future for overall safety
                                SwingUtilities.invokeLater(new Runnable() {
                                        @Override
                                        public void run() {
                                                RocketComponent parent = component.getParent();
                                                int index = parent.getChildPosition(component);
-                                               int count = ((FinSet)component).getFinCount();
-                                               double base = ((FinSet)component).getBaseRotation();
+                                               int count = ((FinSet) component).getFinCount();
+                                               double base = ((FinSet) component).getBaseRotation();
                                                if (count <= 1)
                                                        return;
                                                
                                                ComponentConfigDialog.addUndoPosition("Split fin set");
                                                parent.removeChild(index);
-                                               for (int i=0; i<count; i++) {
-                                                       FinSet copy = (FinSet)component.copy();
+                                               for (int i = 0; i < count; i++) {
+                                                       FinSet copy = (FinSet) component.copy();
                                                        copy.setFinCount(1);
-                                                       copy.setBaseRotation(base + i*2*Math.PI/count);
-                                                       copy.setName(copy.getName() + " #" + (i+1));
-                                                       parent.addChild(copy, index+i);
+                                                       copy.setBaseRotation(base + i * 2 * Math.PI / count);
+                                                       copy.setName(copy.getName() + " #" + (i + 1));
+                                                       parent.addChild(copy, index + i);
                                                }
                                        }
                                });
-
+                               
                                ComponentConfigDialog.hideDialog();
                        }
                });
-               split.setEnabled(((FinSet)component).getFinCount() > 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<FinSet.TabRelativePosition> em = 
-                       new EnumModel<FinSet.TabRelativePosition>(component, "TabRelativePosition");
+               EnumModel<FinSet.TabRelativePosition> em =
+                               new EnumModel<FinSet.TabRelativePosition>(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);
        }
 }
index af1d1bb103fd229a545244170b72aa7a12dcb43e..e5429e3aec1b4a694783b7425e7feb5985f58b5b 100644 (file)
@@ -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<RocketComponent, Integer> 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
index 09d229bc0106598dc7282fa70ae167821175c46e..ef13629a7e46626b3080a0ce9fa0ee95a231a91e 100644 (file)
@@ -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);
index 3e76b2514206a2588a7d22414d95a26d0f88ddb9..f51f4650fabe7f818dc972bdf927b0e1b21e2727 100644 (file)
@@ -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<Coordinate> points = new ArrayList<Coordinate>();
        
@@ -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;
                
index f6d575e3056566abde83255dff9bd6528199624f..2e0a784cdcbbb4a74989187a9c98a031d9b64cdf 100644 (file)
@@ -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)}.
         */
index fa60aaa96cd03f2c18910f16382e0143d8a35510..c864ec96e506616a8762e2621d813a13bd7fdb68 100644 (file)
@@ -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;