Refactor model invalidation to dedicated class

This commit is contained in:
SiboVG 2024-01-23 19:58:03 +01:00
parent a793f27f51
commit e3eeecd7ae
9 changed files with 254 additions and 124 deletions

View File

@ -439,8 +439,10 @@ public class Rocket extends ComponentAssembly {
this.configSet.reset();
this.configSet.setDefault(new FlightConfiguration(this));
for (FlightConfigurationId key : source.configSet.map.keySet()) {
FlightConfiguration srcCfg = source.configSet.get(key);
FlightConfiguration newCfg = new FlightConfiguration(this, key);
newCfg.setName(source.configSet.get(key).getNameRaw()); // Copy config name
newCfg.copyStageActiveness(srcCfg);
newCfg.setName(srcCfg.getNameRaw()); // Copy config name
this.configSet.set(key, newCfg);
}
this.selectedConfiguration = this.configSet.get(source.getSelectedConfiguration().getId());

View File

@ -6,6 +6,7 @@ import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
@ -22,8 +23,6 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.Invalidator;
import net.sf.openrocket.util.MemoryManagement;
import net.sf.openrocket.util.Reflection;
import net.sf.openrocket.util.StateChangeListener;
@ -44,6 +43,7 @@ import net.sf.openrocket.util.StateChangeListener;
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class BooleanModel extends AbstractAction implements StateChangeListener, ChangeSource, Invalidatable {
private final ModelInvalidator modelInvalidator; // Composite pattern because f***ing Java doesn't allow multiple inheritance...
private static final long serialVersionUID = -7299680391506320196L;
private static final Logger log = LoggerFactory.getLogger(BooleanModel.class);
@ -68,9 +68,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
private boolean oldValue;
private boolean oldEnabled;
private Invalidator invalidator = new Invalidator(this);
private final ArrayList<EventListener> listeners = new ArrayList<>();
/**
@ -79,6 +77,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
* @param initialValue the initial value of the boolean
*/
public BooleanModel(boolean initialValue) {
this.modelInvalidator = new ModelInvalidator(null, this);
this.valueName = null;
this.source = null;
this.getMethod = null;
@ -102,13 +101,14 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
* @param valueName the name of the getter/setter method (without the get/is/set prefix)
*/
public BooleanModel(ChangeSource source, String valueName) {
this.modelInvalidator = new ModelInvalidator(source, this);
this.source = source;
this.valueName = valueName;
Method getter = null, setter = null;
if(RocketComponent.class.isAssignableFrom(source.getClass())) {
((RocketComponent)source).addChangeListener(this);
if (RocketComponent.class.isAssignableFrom(source.getClass())) {
source.addChangeListener(this);
}
// Try get/is and set
@ -172,7 +172,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
}
public void setValue(boolean b) {
checkState(true);
modelInvalidator.checkState(true);
log.debug("Setting value of " + this + " to " + b);
if (setMethod != null) {
@ -200,7 +200,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
* @param enableState the state in which the component should be enabled.
*/
public void addEnableComponent(Component component, boolean enableState) {
checkState(true);
modelInvalidator.checkState(true);
components.add(component);
componentEnableState.add(enableState);
updateEnableStatus();
@ -211,7 +211,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
* @param component component to remove from the list
*/
public void removeEnableComponent(Component component) {
checkState(true);
modelInvalidator.checkState(true);
components.remove(component);
}
@ -223,7 +223,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
* @see #addEnableComponent(Component, boolean)
*/
public void addEnableComponent(Component component) {
checkState(true);
modelInvalidator.checkState(true);
addEnableComponent(component, true);
}
@ -250,10 +250,14 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
throw Reflection.handleWrappedException(e);
}
}
private List<EventListener> getListeners() {
return modelInvalidator.listeners;
}
@Override
public void stateChanged(EventObject event) {
checkState(true);
modelInvalidator.checkState(true);
if (firing > 0) {
log.debug("Ignoring stateChanged of " + this + ", currently firing events");
@ -277,7 +281,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
setEnabled(e);
}
for (EventListener listener : listeners) {
for (EventListener listener : getListeners()) {
if (listener instanceof StateChangeListener) {
((StateChangeListener) listener).stateChanged(event);
} else if (listener instanceof ChangeListener) {
@ -308,7 +312,7 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
firing--;
}
for (EventListener listener : listeners) {
for (EventListener listener : getListeners()) {
if (listener instanceof StateChangeListener) {
((StateChangeListener) listener).stateChanged(e);
} else if (listener instanceof ChangeListener) {
@ -321,36 +325,18 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
checkState(true);
modelInvalidator.checkState(true);
super.addPropertyChangeListener(listener);
}
/**
* Add a listener to the model. Adds the model as a listener to the value source if this
* is the first listener.
* @param listener Listener to add.
*/
@Override
public void addChangeListener(StateChangeListener listener) {
checkState(true);
if (listeners.add(listener)) {
log.trace(this + " adding listener (total " + listeners.size() + "): " + listener);
}
modelInvalidator.addChangeListener(listener);
}
/**
* 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.
* @param listener Listener to remove.
*/
@Override
public void removeChangeListener(StateChangeListener listener) {
checkState(false);
if (listeners.remove(listener)) {
log.trace(this + " removing listener (total " + listeners.size() + "): " + listener);
}
modelInvalidator.removeChangeListener(listener);
}
@ -361,31 +347,16 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
*/
@Override
public void invalidate() {
invalidator.invalidate();
PropertyChangeListener[] listeners = this.getPropertyChangeListeners();
if (listeners.length > 0) {
log.warn("Invalidating " + this + " while still having listeners " + listeners);
log.warn("Invalidating " + this + " while still having listeners " + Arrays.toString(listeners));
for (PropertyChangeListener l : listeners) {
this.removePropertyChangeListener(l);
}
}
if (!this.listeners.isEmpty()) {
log.warn("Invalidating " + this + " while still having listeners " + this.listeners);
}
this.listeners.clear();
if (source != null) {
source.removeChangeListener(this);
}
MemoryManagement.collectable(this);
modelInvalidator.invalidate();
}
private void checkState(boolean error) {
invalidator.check(error);
}
@Override
public String toString() {

View File

@ -8,6 +8,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.AbstractSpinnerModel;
@ -29,9 +30,7 @@ import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.ExpressionParser;
import net.sf.openrocket.util.InvalidExpressionException;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.Invalidator;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.MemoryManagement;
import net.sf.openrocket.util.Reflection;
import net.sf.openrocket.util.StateChangeListener;
@ -52,7 +51,7 @@ import net.sf.openrocket.util.StateChangeListener;
public class DoubleModel implements StateChangeListener, ChangeSource, Invalidatable {
private static final Logger log = LoggerFactory.getLogger(DoubleModel.class);
private final ModelInvalidator modelInvalidator; // Composite pattern because f***ing Java doesn't allow multiple inheritance...
public static final DoubleModel ZERO = new DoubleModel(0);
@ -613,8 +612,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
private final Method getAutoMethod;
private final Method setAutoMethod;
private final ArrayList<EventListener> listeners = new ArrayList<EventListener>();
private UnitGroup units;
private Unit currentUnit;
@ -632,8 +630,6 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
private double lastValue = 0;
private boolean lastAutomatic = false;
private Invalidator invalidator = new Invalidator(this);
/**
* Generate a DoubleModel that contains an internal double value.
@ -674,6 +670,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* @param max maximum value.
*/
public DoubleModel(double value, UnitGroup unit, double min, double max) {
this.modelInvalidator = new ModelInvalidator(null, this);
this.lastValue = value;
this.minValue = min;
this.maxValue = max;
@ -701,6 +698,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
*/
public DoubleModel(Object source, String valueName, double multiplier, UnitGroup unit,
double min, double max) {
this.modelInvalidator = new ModelInvalidator(source, this);
this.source = source;
this.valueName = valueName;
this.multiplier = multiplier;
@ -808,7 +806,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* @param v New value for parameter in SI units.
*/
public void setValue(double v) {
checkState(true);
modelInvalidator.checkState(true);
double clampedValue = MathUtil.clamp(v, minValue, maxValue);
if (clampedValue != v) {
@ -871,7 +869,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* state change event if automatic setting is not available.
*/
public void setAutomatic(boolean auto) {
checkState(true);
modelInvalidator.checkState(true);
if (setAutoMethod == null) {
log.debug("Setting automatic to " + auto + " for " + this + ", automatic not available");
@ -906,7 +904,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* @param u The unit to set active.
*/
public void setCurrentUnit(Unit u) {
checkState(true);
modelInvalidator.checkState(true);
if (currentUnit == u)
return;
log.debug("Setting unit for " + this + " to '" + u + "'");
@ -930,7 +928,10 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
public UnitGroup getUnitGroup() {
return units;
}
private List<EventListener> getListeners() {
return modelInvalidator.listeners;
}
/**
@ -950,17 +951,16 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* @param l Listener to add.
*/
public void addChangeListener(EventListener l) {
checkState(true);
modelInvalidator.checkState(true);
if (listeners.isEmpty()) {
if (getListeners().isEmpty()) {
if (source != null) {
lastValue = getValue();
lastAutomatic = isAutomatic();
}
}
listeners.add(l);
log.trace(this + " adding listener (total " + listeners.size() + "): " + l);
modelInvalidator.addChangeListener(l);
}
/**
@ -979,10 +979,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* @param l Listener to remove.
*/
public void removeChangeListener(EventListener l) {
checkState(false);
listeners.remove(l);
log.trace(this + " removing listener (total " + listeners.size() + "): " + l);
modelInvalidator.removeChangeListener(l);
}
@ -993,31 +990,15 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
*/
@Override
public void invalidate() {
log.trace("Invalidating " + this);
invalidator.invalidate();
if (!listeners.isEmpty()) {
log.warn("Invalidating " + this + " while still having listeners " + listeners);
}
listeners.clear();
if (source instanceof ChangeSource) {
((ChangeSource) source).removeChangeListener(this);
}
MemoryManagement.collectable(this);
modelInvalidator.invalidate();
}
private void checkState(boolean error) {
invalidator.check(error);
}
// TODO MEDIUM: finalize is deprecated, replace with something better
@Override
protected void finalize() throws Throwable {
super.finalize();
if (!listeners.isEmpty()) {
log.warn(this + " being garbage-collected while having listeners " + listeners);
}
modelInvalidator.finalize();
};
@ -1025,13 +1006,13 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
* Fire a ChangeEvent to all listeners.
*/
protected void fireStateChanged() {
checkState(true);
modelInvalidator.checkState(true);
EventObject event = new EventObject(this);
ChangeEvent cevent = new ChangeEvent(this);
firing++;
// Copy the list before iterating to prevent concurrent modification exceptions.
EventListener[] ls = listeners.toArray(new EventListener[0]);
EventListener[] ls = getListeners().toArray(new EventListener[0]);
for (EventListener l : ls) {
if (l instanceof StateChangeListener) {
((StateChangeListener) l).stateChanged(event);
@ -1048,7 +1029,7 @@ public class DoubleModel implements StateChangeListener, ChangeSource, Invalidat
*/
@Override
public void stateChanged(EventObject e) {
checkState(true);
modelInvalidator.checkState(true);
double v = getValue();
boolean b = isAutomatic();

View File

@ -7,13 +7,15 @@ import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.MutableComboBoxModel;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.Reflection;
import net.sf.openrocket.util.StateChangeListener;
public class EnumModel<T extends Enum<T>> extends AbstractListModel<T>
implements ComboBoxModel<T>, MutableComboBoxModel<T>, StateChangeListener {
implements ComboBoxModel<T>, MutableComboBoxModel<T>, StateChangeListener, Invalidatable {
private static final long serialVersionUID = 7766446027840316797L;
private final ModelInvalidator modelInvalidator;
private final Object source;
private final String valueName;
private final String nullText;
@ -39,6 +41,7 @@ public class EnumModel<T extends Enum<T>> extends AbstractListModel<T>
@SuppressWarnings("unchecked")
public EnumModel(Object source, String valueName, T[] values, String nullText) {
Class<? extends Enum<T>> enumClass;
this.modelInvalidator = new ModelInvalidator(source, this);
this.source = source;
this.valueName = valueName;
@ -124,6 +127,8 @@ public class EnumModel<T extends Enum<T>> extends AbstractListModel<T>
@SuppressWarnings("unchecked")
@Override
public void stateChanged(EventObject e) {
modelInvalidator.checkState(true);
T value = (T) getMethod.invoke(source);
if (value != currentValue) {
currentValue = value;
@ -163,4 +168,8 @@ public class EnumModel<T extends Enum<T>> extends AbstractListModel<T>
this.displayedValues.remove( index );
}
@Override
public void invalidate() {
modelInvalidator.invalidate();
}
}

View File

@ -2,7 +2,6 @@ package net.sf.openrocket.gui.adaptors;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
@ -13,6 +12,7 @@ import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.MathUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,10 +24,12 @@ import net.sf.openrocket.util.Reflection;
import net.sf.openrocket.util.StateChangeListener;
public class IntegerModel implements StateChangeListener {
public class IntegerModel implements StateChangeListener, Invalidatable {
private static final Logger log = LoggerFactory.getLogger(IntegerModel.class);
private final ModelInvalidator modelInvalidator;
//////////// JSpinner Model ////////////
private class IntegerSpinnerModel extends SpinnerNumberModel {
@ -139,8 +141,7 @@ public class IntegerModel implements StateChangeListener {
private final Method getMethod;
private final Method setMethod;
private final ArrayList<EventListener> listeners = new ArrayList<EventListener>();
private final int minValue;
private final int maxValue;
@ -166,6 +167,7 @@ public class IntegerModel implements StateChangeListener {
* @param max Maximum value allowed (in SI units)
*/
public IntegerModel(ChangeSource source, String valueName, int min, int max) {
this.modelInvalidator = new ModelInvalidator(source, this);
this.source = source;
this.valueName = valueName;
@ -237,13 +239,7 @@ public class IntegerModel implements StateChangeListener {
* @param l Listener to add.
*/
public void addChangeListener(EventListener l) {
if (listeners.isEmpty()) {
source.addChangeListener(this);
lastValue = getValue();
}
listeners.add(l);
log.trace(this + " adding listener (total " + listeners.size() + "): " + l);
modelInvalidator.addChangeListener(l);
}
/**
@ -252,25 +248,19 @@ public class IntegerModel implements StateChangeListener {
* @param l Listener to remove.
*/
public void removeChangeListener(ChangeListener l) {
listeners.remove(l);
if (listeners.isEmpty()) {
source.removeChangeListener(this);
}
log.trace(this + " removing listener (total " + listeners.size() + "): " + l);
modelInvalidator.removeChangeListener(l);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (!listeners.isEmpty()) {
log.warn(this + " being garbage-collected while having listeners " + listeners);
}
modelInvalidator.finalize();
};
public void fireStateChanged() {
EventListener[] list = listeners.toArray(new EventListener[0] );
EventListener[] list = modelInvalidator.listeners.toArray(new EventListener[0] );
EventObject event = new EventObject(this);
ChangeEvent cevent = new ChangeEvent(this);
firing++;
@ -290,6 +280,8 @@ public class IntegerModel implements StateChangeListener {
*/
@Override
public void stateChanged(EventObject e) {
modelInvalidator.checkState(true);
int v = getValue();
if (lastValue == v)
return;
@ -307,5 +299,10 @@ public class IntegerModel implements StateChangeListener {
}
return toString;
}
@Override
public void invalidate() {
modelInvalidator.invalidate();
}
}

View File

@ -17,11 +17,13 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.Reflection;
public class MaterialModel extends AbstractListModel<Material> implements
ComboBoxModel<Material>, ComponentChangeListener, DatabaseListener<Material> {
ComboBoxModel<Material>, ComponentChangeListener, DatabaseListener<Material>, Invalidatable {
private static final long serialVersionUID = 4552478532933113655L;
private final ModelInvalidator modelInvalidator;
private final Material custom;
@ -46,6 +48,7 @@ public class MaterialModel extends AbstractListModel<Material> implements
public MaterialModel(Component parent, RocketComponent component, Material.Type type,
String name) {
this.modelInvalidator = new ModelInvalidator(component, this);
this.parentUIComponent = parent;
this.rocketComponent = component;
this.type = type;
@ -166,5 +169,15 @@ public class MaterialModel extends AbstractListModel<Material> implements
public void elementRemoved(Material element, Database<Material> source) {
this.fireContentsChanged(this, 0, database.size());
}
@Override
public void invalidate() {
modelInvalidator.invalidate();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
modelInvalidator.finalize();
}
}

View File

@ -0,0 +1,129 @@
package net.sf.openrocket.gui.adaptors;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Invalidatable;
import net.sf.openrocket.util.Invalidator;
import net.sf.openrocket.util.MemoryManagement;
import net.sf.openrocket.util.StateChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
/**
* A helper model for invalidating value models.
* This class has nothing to do with the actual setting/getting of the value, it's just here to avoid duplicate code
* in invalidating value models.
* This model should probably be used in a composition pattern, where this model is instantiated in a class.
* This class should then delegate the methods of the interface
* to this class.
* Thanks, Java, for not allowing multiple inheritance.
*/
public class ModelInvalidator implements StateChangeListener, Invalidatable, ChangeSource {
private static final Logger log = LoggerFactory.getLogger(ModelInvalidator.class);
private final Invalidator invalidator;
private final Object source;
private final EventListener model;
protected final List<EventListener> listeners = new ArrayList<>();
public ModelInvalidator(Object source, EventListener model) {
this.source = source;
this.model = model;
this.invalidator = new Invalidator(model);
}
/**
* Add a listener to the model. Adds the model as a listener to the value source if this
* is the first listener.
* @param listener Listener to add.
*/
@Override
public void addChangeListener(StateChangeListener listener) {
addChangeListener((EventListener) listener);
}
public void addChangeListener(EventListener listener) {
checkState(true);
if (listeners.add(listener)) {
log.trace(this + " adding listener (total " + listeners.size() + "): " + listener);
} else {
log.warn(this + " adding listener that was already registered: " + listener);
}
}
/**
* 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.
* @param listener Listener to remove.
*/
@Override
public void removeChangeListener(StateChangeListener listener) {
removeChangeListener((EventListener) listener);
}
/**
* 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.
* @param l Listener to remove.
*/
public void removeChangeListener(EventListener l) {
checkState(false);
if (listeners.remove(l)) {
log.trace(this + " removing listener (total " + listeners.size() + "): " + l);
} else {
log.warn(this + " removing listener that was not registered: " + l);
}
}
/**
* Check the state of this model. If the model is invalid, throw an IllegalStateException if `errpr` is true.
* @param error If true, throw an IllegalStateException if the model is invalid.
*/
protected void checkState(boolean error) {
invalidator.check(error);
}
/**
* Invalidates this model by removing all listeners and removing this from
* listening to the source. After invalidation no listeners can be added to this
* model and the value cannot be set.
*/
@Override
public void invalidate() {
log.trace("Invalidating " + this);
invalidator.invalidate();
if (!listeners.isEmpty()) {
log.warn("Invalidating " + this + " while still having listeners " + listeners);
}
listeners.clear();
if (source instanceof ChangeSource && model instanceof StateChangeListener) {
((ChangeSource) source).removeChangeListener((StateChangeListener) model);
} else if (source instanceof RocketComponent && model instanceof ComponentChangeListener) {
((RocketComponent) source).removeComponentChangeListener((ComponentChangeListener) model);
}
MemoryManagement.collectable(model);
MemoryManagement.collectable(this);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (!listeners.isEmpty()) {
log.warn(model + " being garbage-collected while having listeners " + listeners);
}
}
@Override
public void stateChanged(EventObject e) {
// Do nothing
}
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import net.sf.openrocket.util.Invalidatable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,10 +23,12 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
public class PresetModel extends AbstractListModel implements ComboBoxModel, ComponentChangeListener, DatabaseListener<ComponentPreset> {
public class PresetModel extends AbstractListModel
implements ComboBoxModel, ComponentChangeListener, DatabaseListener<ComponentPreset>, Invalidatable {
private static final Logger log = LoggerFactory.getLogger(PresetModel.class);
private static final Translator trans = Application.getTranslator();
private final ModelInvalidator modelInvalidator;
private static final String NONE_SELECTED = String.format("<html><i>%s</i></html>", trans.get("PresetModel.lbl.custompreset"));
@ -37,6 +40,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
private List<ComponentPreset> presets;
public PresetModel(Component parent, OpenRocketDocument document, RocketComponent component) {
this.modelInvalidator = new ModelInvalidator(component, this);
this.parent = parent;
this.document = document;
presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
@ -102,5 +106,15 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
this.fireContentsChanged(this, 0, getSize());
}
@Override
public void invalidate() {
modelInvalidator.invalidate();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
modelInvalidator.finalize();
}
}

View File

@ -4,17 +4,20 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.Invalidatable;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
public class TransitionShapeModel extends AbstractListModel<Transition.Shape>
implements ComboBoxModel<Transition.Shape>, ComponentChangeListener {
implements ComboBoxModel<Transition.Shape>, ComponentChangeListener, Invalidatable {
private final ModelInvalidator modelInvalidator;
private final RocketComponent component;
private final Transition.Shape[] typeList = Transition.Shape.values();
private Transition.Shape previousType;
public TransitionShapeModel(RocketComponent component) {
this.modelInvalidator = new ModelInvalidator(component, this);
this.component = component;
if (component instanceof Transition) {
previousType = ((Transition) component).getShapeType();
@ -61,4 +64,15 @@ public class TransitionShapeModel extends AbstractListModel<Transition.Shape>
fireContentsChanged(this, 0, 0);
}
}
@Override
public void invalidate() {
modelInvalidator.invalidate();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
modelInvalidator.finalize();
}
}