1 package net.sf.openrocket.gui.adaptors;
3 import java.awt.Component;
4 import java.awt.event.ActionEvent;
5 import java.lang.reflect.InvocationTargetException;
6 import java.lang.reflect.Method;
7 import java.util.ArrayList;
10 import javax.swing.AbstractAction;
11 import javax.swing.event.ChangeEvent;
12 import javax.swing.event.ChangeListener;
14 import net.sf.openrocket.util.BugException;
15 import net.sf.openrocket.util.ChangeSource;
16 import net.sf.openrocket.util.Reflection;
20 * A class that adapts an isXXX/setXXX boolean variable. It functions as an Action suitable
21 * for usage in JCheckBox or JToggleButton. You can create a suitable button with
23 * check = new JCheckBox(new BooleanModel(component,"Value"))
24 * check.setText("Label");
26 * This will produce a button that uses isValue() and setValue(boolean) of the corresponding
29 * Additionally a number of component enabled states may be controlled by this class using
30 * the method {@link #addEnableComponent(Component, boolean)}.
32 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
35 public class BooleanModel extends AbstractAction implements ChangeListener {
37 private final ChangeSource source;
38 private final String valueName;
40 private final Method getMethod;
41 private final Method setMethod;
42 private final Method getEnabled;
44 private final List<Component> components = new ArrayList<Component>();
45 private final List<Boolean> componentEnableState = new ArrayList<Boolean>();
47 private int firing = 0;
49 private boolean oldValue;
50 private boolean oldEnabled;
52 public BooleanModel(ChangeSource source, String valueName) {
54 this.valueName = valueName;
56 Method getter=null, setter=null;
61 getter = source.getClass().getMethod("is" + valueName);
62 } catch (NoSuchMethodException ignore) { }
65 getter = source.getClass().getMethod("get" + valueName);
66 } catch (NoSuchMethodException ignore) { }
69 setter = source.getClass().getMethod("set" + valueName,boolean.class);
70 } catch (NoSuchMethodException ignore) { }
72 if (getter==null || setter==null) {
73 throw new IllegalArgumentException("get/is methods for boolean '"+valueName+
74 "' not present in class "+source.getClass().getCanonicalName());
82 e = source.getClass().getMethod("is" + valueName + "Enabled");
83 } catch (NoSuchMethodException ignore) { }
86 oldValue = getValue();
87 oldEnabled = getIsEnabled();
89 this.setEnabled(oldEnabled);
90 this.putValue(SELECTED_KEY, oldValue);
92 source.addChangeListener(this);
95 public boolean getValue() {
97 return (Boolean)getMethod.invoke(source);
98 } catch (IllegalAccessException e) {
99 throw new BugException("getMethod execution error for source "+source,e);
100 } catch (InvocationTargetException e) {
101 throw Reflection.handleInvocationTargetException(e);
105 public void setValue(boolean b) {
107 setMethod.invoke(source, new Object[] { (Boolean)b });
108 } catch (IllegalAccessException e) {
109 throw new BugException("setMethod execution error for source "+source,e);
110 } catch (InvocationTargetException e) {
111 throw Reflection.handleInvocationTargetException(e);
117 * Add a component the enabled status of which will be controlled by the value
118 * of this boolean. The <code>component</code> will be enabled exactly when
119 * the state of this model is equal to that of <code>enableState</code>.
121 * @param component the component to control.
122 * @param enableState the state in which the component should be enabled.
124 public void addEnableComponent(Component component, boolean enableState) {
125 components.add(component);
126 componentEnableState.add(enableState);
127 updateEnableStatus();
131 * Add a component which will be enabled when this boolean is <code>true</code>.
132 * This is equivalent to <code>booleanModel.addEnableComponent(component, true)</code>.
134 * @param component the component to control.
135 * @see #addEnableComponent(Component, boolean)
137 public void addEnableComponent(Component component) {
138 addEnableComponent(component, true);
141 private void updateEnableStatus() {
142 boolean state = getValue();
144 for (int i=0; i < components.size(); i++) {
145 Component c = components.get(i);
146 boolean b = componentEnableState.get(i);
147 c.setEnabled(state == b);
153 // public boolean isEnabled() {
154 // if (getEnabled == null)
157 // return (Boolean)getEnabled.invoke(source);
158 // } catch (IllegalAccessException e) {
159 // throw new RuntimeException("getEnabled execution error for source "+source,e);
160 // } catch (InvocationTargetException e) {
161 // throw new RuntimeException("getEnabled execution error for source "+source,e);
166 private boolean getIsEnabled() {
167 if (getEnabled == null)
170 return (Boolean)getEnabled.invoke(source);
171 } catch (IllegalAccessException e) {
172 throw new BugException("getEnabled execution error for source "+source,e);
173 } catch (InvocationTargetException e) {
174 throw Reflection.handleInvocationTargetException(e);
179 // public Object getValue(String key) {
180 // if (key.equals(SELECTED_KEY)) {
181 // return getValue();
183 // return super.getValue(key);
187 // public void putValue(String key, Object value) {
188 // if (firing > 0) // Ignore if currently firing event
190 // if (key.equals(SELECTED_KEY) && (value instanceof Boolean)) {
191 // setValue((Boolean)value);
193 // super.putValue(key, value);
195 // updateEnableStatus();
200 public void stateChanged(ChangeEvent event) {
204 boolean v = getValue();
205 boolean e = getIsEnabled();
209 this.putValue(SELECTED_KEY, getValue());
210 // this.firePropertyChange(SELECTED_KEY, !v, v);
211 updateEnableStatus();
214 if (oldEnabled != e) {
222 public void actionPerformed(ActionEvent e) {
226 boolean v = (Boolean)this.getValue(SELECTED_KEY);
230 oldValue = getValue();
232 this.putValue(SELECTED_KEY, oldValue);
233 this.setEnabled(getIsEnabled());
234 updateEnableStatus();
240 public String toString() {
241 return "BooleanModel["+source.getClass().getCanonicalName()+":"+valueName+"]";