1 |
/* DefaultButtonModel.java -- |
/* DefaultButtonModel.java -- |
2 |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
44 |
import java.awt.event.KeyEvent; |
import java.awt.event.KeyEvent; |
45 |
import java.io.Serializable; |
import java.io.Serializable; |
46 |
import java.util.EventListener; |
import java.util.EventListener; |
|
|
|
47 |
import javax.swing.event.ChangeEvent; |
import javax.swing.event.ChangeEvent; |
48 |
import javax.swing.event.ChangeListener; |
import javax.swing.event.ChangeListener; |
49 |
import javax.swing.event.EventListenerList; |
import javax.swing.event.EventListenerList; |
50 |
|
|
51 |
|
|
52 |
/** |
/** |
53 |
* The purpose of this class is to model the dynamic state of an abstract |
* The purpose of this class is to model the dynamic state of an abstract |
54 |
* button. The concrete button type holding this state may be a a "toggle" |
* button. The concrete button type holding this state may be a a "toggle" |
55 |
* button (checkbox, radio button) or a "push" button (menu button, button). |
* button (checkbox, radio button) or a "push" button (menu button, button). |
56 |
* |
* If the model is disabled, only the "selected" property can be changed. An |
57 |
* If the model is disabled, only the "selected" property can be changed. |
* attempt to change the "armed", "rollover" or "pressed" properties while |
58 |
* An attempt to change the "armed", "rollover" or "pressed" properties |
* the model is disabled will be blocked. Any successful (non-blocked) change |
59 |
* while the model is disabled will be blocked. |
* to the model's properties will trigger the firing of a ChangeEvent. Any |
60 |
* |
* change to the "selected" property will trigger the firing of an ItemEvent |
61 |
* Any successful (non-blocked) change to the model's properties will |
* in addition to ChangeEvent. This is true whether the model is enabled or |
62 |
* trigger the firing of a ChangeEvent. |
* not. One other state change is special: the transition from "enabled, |
63 |
* |
* armed and pressd" to "enabled, armed and not-pressed". This is considered |
64 |
* Any change to the "selected" property will trigger the firing of an |
* the "trailing edge" of a successful mouse click, and therefore fires an |
65 |
* ItemEvent in addition to ChangeEvent. This is true whether the model is |
* ActionEvent in addition to a ChangeEvent. In all other respects this class |
66 |
* enabled or not. |
* is just a container of boolean flags. |
|
* |
|
|
* One other state change is special: the transition from "enabled, armed |
|
|
* and pressd" to "enabled, armed and not-pressed". This is considered the |
|
|
* "trailing edge" of a successful mouse click, and therefore fires an |
|
|
* ActionEvent in addition to a ChangeEvent. |
|
67 |
* |
* |
68 |
* In all other respects this class is just a container of boolean flags. |
* @author Graydon Hoare (graydon_at_redhat.com) |
|
* |
|
|
* @author Graydon Hoare (graydon@redhat.com) |
|
69 |
*/ |
*/ |
70 |
public class DefaultButtonModel implements ButtonModel, Serializable |
public class DefaultButtonModel implements ButtonModel, Serializable |
71 |
{ |
{ |
72 |
|
/** DOCUMENT ME! */ |
73 |
static final long serialVersionUID = -5342609566534980231L; |
static final long serialVersionUID = -5342609566534980231L; |
74 |
|
|
75 |
/** Indicates that the button is <em>partially</em> committed to being |
/** |
76 |
pressed, but not entirely. This usually happens when a user has pressed |
* Indicates that the button is <em>partially</em> committed to being |
77 |
but not yet released the mouse button. */ |
* pressed, but not entirely. This usually happens when a user has pressed |
78 |
|
* but not yet released the mouse button. |
79 |
|
*/ |
80 |
public static final int ARMED = 1; |
public static final int ARMED = 1; |
81 |
|
|
82 |
/** State constant indicating that the button is enabled. Buttons cannot |
/** |
83 |
be pressed or selected unless they are enabled. */ |
* State constant indicating that the button is enabled. Buttons cannot be |
84 |
|
* pressed or selected unless they are enabled. |
85 |
|
*/ |
86 |
public static final int ENABLED = 8; |
public static final int ENABLED = 8; |
87 |
|
|
88 |
/** State constant indicating that the user is holding down the button. |
/** |
89 |
When this transitions from true to false, an ActionEvent may be fired, |
* State constant indicating that the user is holding down the button. When |
90 |
depending on the value of the "armed" property.*/ |
* this transitions from true to false, an ActionEvent may be fired, |
91 |
|
* depending on the value of the "armed" property. |
92 |
|
*/ |
93 |
public static final int PRESSED = 4; |
public static final int PRESSED = 4; |
94 |
|
|
95 |
/** State constant indicating that the mouse is currently positioned over |
/** |
96 |
the button. */ |
* State constant indicating that the mouse is currently positioned over the |
97 |
|
* button. |
98 |
|
*/ |
99 |
public static final int ROLLOVER = 16; |
public static final int ROLLOVER = 16; |
100 |
|
|
101 |
/** State constant indicating that the button is selected. This constant |
/** |
102 |
is only meaningful for toggle-type buttons (radio buttons, |
* State constant indicating that the button is selected. This constant is |
103 |
checkboxes). */ |
* only meaningful for toggle-type buttons (radio buttons, checkboxes). |
104 |
|
*/ |
105 |
public static final int SELECTED = 2; |
public static final int SELECTED = 2; |
106 |
|
|
107 |
/** Represents the "state properties" (armed, enabled, pressed, rollover |
/** |
108 |
and selected) by a bitwise combination of integer constants. */ |
* Represents the "state properties" (armed, enabled, pressed, rollover and |
109 |
|
* selected) by a bitwise combination of integer constants. |
110 |
|
*/ |
111 |
protected int stateMask = ENABLED; |
protected int stateMask = ENABLED; |
112 |
|
|
113 |
/** List of ItemListeners, ChangeListeners, and ActionListeners |
/** |
114 |
registered on this model. */ |
* List of ItemListeners, ChangeListeners, and ActionListeners registered on |
115 |
protected EventListenerList listenerList = new EventListenerList();; |
* this model. |
116 |
|
*/ |
117 |
|
protected EventListenerList listenerList = new EventListenerList(); |
118 |
|
; |
119 |
|
|
120 |
/** The single ChangeEvent this model (re)uses to call its |
/** The single ChangeEvent this model (re)uses to call its ChangeListeners. */ |
|
ChangeListeners. */ |
|
121 |
protected ChangeEvent changeEvent = new ChangeEvent(this); |
protected ChangeEvent changeEvent = new ChangeEvent(this); |
122 |
|
|
123 |
/** The group this model belongs to. Only one button in a group may be |
/** |
124 |
selected at any given time. */ |
* The group this model belongs to. Only one button in a group may be |
125 |
|
* selected at any given time. |
126 |
|
*/ |
127 |
protected ButtonGroup group; |
protected ButtonGroup group; |
128 |
|
|
129 |
/** The key code (one of {@link java.awt.event.KeyEvent} VK_*) used to |
/** |
130 |
press this button via a keyboard interface. */ |
* The key code (one of {@link java.awt.event.KeyEvent} VK_) used to press |
131 |
|
* this button via a keyboard interface. |
132 |
|
*/ |
133 |
protected int mnemonic = KeyEvent.VK_UNDEFINED; |
protected int mnemonic = KeyEvent.VK_UNDEFINED; |
134 |
|
|
135 |
/** The string used as the "command" property of any ActionEvent this |
/** |
136 |
model sends. */ |
* The string used as the "command" property of any ActionEvent this model |
137 |
|
* sends. |
138 |
|
*/ |
139 |
protected String actionCommand; |
protected String actionCommand; |
140 |
|
|
141 |
|
/** |
142 |
|
* Creates a new DefaultButtonModel object. |
143 |
|
*/ |
144 |
public DefaultButtonModel() |
public DefaultButtonModel() |
145 |
{ |
{ |
146 |
} |
} |
151 |
* |
* |
152 |
* @return <code>null</code> |
* @return <code>null</code> |
153 |
*/ |
*/ |
154 |
public Object[] getSelectedObjects() |
public Object[] getSelectedObjects() |
155 |
{ |
{ |
156 |
return null; |
return null; |
157 |
} |
} |
158 |
|
|
159 |
/** |
/** |
160 |
* Returns a specified class of listeners. |
* Returns a specified class of listeners. |
167 |
{ |
{ |
168 |
return listenerList.getListeners(listenerType); |
return listenerList.getListeners(listenerType); |
169 |
} |
} |
170 |
|
|
171 |
/** |
/** |
172 |
* Add an ActionListener to the model. Usually only called to subscribe |
* Add an ActionListener to the model. Usually only called to subscribe an |
173 |
* an AbstractButton's listener to the model. |
* AbstractButton's listener to the model. |
174 |
* |
* |
175 |
* @param l The listener to add |
* @param l The listener to add |
176 |
*/ |
*/ |
178 |
{ |
{ |
179 |
listenerList.add(ActionListener.class, l); |
listenerList.add(ActionListener.class, l); |
180 |
} |
} |
181 |
|
|
182 |
/** |
/** |
183 |
* Remove an ActionListener to the model. Usually only called to |
* Remove an ActionListener to the model. Usually only called to unsubscribe |
184 |
* unsubscribe an AbstractButton's listener to the model. |
* an AbstractButton's listener to the model. |
185 |
* |
* |
186 |
* @param l The listener to remove |
* @param l The listener to remove |
187 |
*/ |
*/ |
201 |
} |
} |
202 |
|
|
203 |
/** |
/** |
204 |
* Add an ItemListener to the model. Usually only called to subscribe |
* Add an ItemListener to the model. Usually only called to subscribe an |
205 |
* an AbstractButton's listener to the model. |
* AbstractButton's listener to the model. |
206 |
* |
* |
207 |
* @param l The listener to add |
* @param l The listener to add |
208 |
*/ |
*/ |
212 |
} |
} |
213 |
|
|
214 |
/** |
/** |
215 |
* Remove an ItemListener to the model. Usually only called to |
* Remove an ItemListener to the model. Usually only called to unsubscribe |
216 |
* unsubscribe an AbstractButton's listener to the model. |
* an AbstractButton's listener to the model. |
217 |
* |
* |
218 |
* @param l The listener to remove |
* @param l The listener to remove |
219 |
*/ |
*/ |
233 |
} |
} |
234 |
|
|
235 |
/** |
/** |
236 |
* Add a ChangeListener to the model. Usually only called to subscribe |
* Add a ChangeListener to the model. Usually only called to subscribe an |
237 |
* an AbstractButton's listener to the model. |
* AbstractButton's listener to the model. |
238 |
* |
* |
239 |
* @param l The listener to add |
* @param l The listener to add |
240 |
*/ |
*/ |
244 |
} |
} |
245 |
|
|
246 |
/** |
/** |
247 |
* Remove a ChangeListener to the model. Usually only called to |
* Remove a ChangeListener to the model. Usually only called to unsubscribe |
248 |
* unsubscribe an AbstractButton's listener to the model. |
* an AbstractButton's listener to the model. |
249 |
* |
* |
250 |
* @param l The listener to remove |
* @param l The listener to remove |
251 |
*/ |
*/ |
274 |
public void fireItemStateChanged(ItemEvent e) |
public void fireItemStateChanged(ItemEvent e) |
275 |
{ |
{ |
276 |
ItemListener[] ll = getItemListeners(); |
ItemListener[] ll = getItemListeners(); |
277 |
|
|
278 |
for (int i = 0; i < ll.length; i++) |
for (int i = 0; i < ll.length; i++) |
279 |
ll[i].itemStateChanged(e); |
ll[i].itemStateChanged(e); |
280 |
} |
} |
281 |
|
|
282 |
/** |
/** |
283 |
* Inform each ActionListener in the {@link listenerList} that an |
* Inform each ActionListener in the {@link listenerList} that an |
284 |
* ActionEvent has occurred. This happens in response to the any change |
* ActionEvent has occurred. This happens in response to the any change to |
285 |
* to the {@link stateMask} field which makes the enabled, armed and |
* the {@link stateMask} field which makes the enabled, armed and pressed |
286 |
* pressed properties all simultaneously <code>true</code>. |
* properties all simultaneously <code>true</code>. |
287 |
* |
* |
288 |
* @param e The ActionEvent to fire |
* @param e The ActionEvent to fire |
289 |
*/ |
*/ |
290 |
public void fireActionPerformed(ActionEvent e) |
public void fireActionPerformed(ActionEvent e) |
291 |
{ |
{ |
292 |
ActionListener[] ll = getActionListeners(); |
ActionListener[] ll = getActionListeners(); |
293 |
|
|
294 |
for (int i = 0; i < ll.length; i++) |
for (int i = 0; i < ll.length; i++) |
295 |
ll[i].actionPerformed(e); |
ll[i].actionPerformed(e); |
296 |
} |
} |
297 |
|
|
298 |
/** |
/** |
299 |
* Inform each ChangeListener in the {@link listenerList} that a |
* Inform each ChangeListener in the {@link listenerList} that a ChangeEvent |
300 |
* ChangeEvent has occurred. This happens in response to the any change |
* has occurred. This happens in response to the any change to a property |
301 |
* to a property of the model. |
* of the model. |
|
* |
|
|
* @param event The ChangeEvent to fire |
|
302 |
*/ |
*/ |
303 |
public void fireStateChanged() |
public void fireStateChanged() |
304 |
{ |
{ |
305 |
ChangeListener[] ll = getChangeListeners(); |
ChangeListener[] ll = getChangeListeners(); |
306 |
|
|
307 |
for (int i = 0; i < ll.length; i++) |
for (int i = 0; i < ll.length; i++) |
308 |
ll[i].stateChanged(changeEvent); |
ll[i].stateChanged(changeEvent); |
309 |
} |
} |
310 |
|
|
311 |
/** |
/** |
312 |
* Helper method to fire a ChangeEvent with the model as the event's |
* Helper method to fire a ChangeEvent with the model as the event's source. |
313 |
* source. |
* |
314 |
|
* @param stateflag DOCUMENT ME! |
315 |
|
* @param b DOCUMENT ME! |
316 |
*/ |
*/ |
317 |
protected void changeState(int stateflag, boolean b) |
protected void changeState(int stateflag, boolean b) |
318 |
{ |
{ |
319 |
int oldstate = stateMask; |
int oldstate = stateMask; |
320 |
int newstate; |
int newstate; |
321 |
|
|
322 |
if (b) |
if (b) |
323 |
newstate = oldstate | stateflag; |
newstate = oldstate | stateflag; |
324 |
else |
else |
325 |
newstate = oldstate & ~stateflag; |
newstate = oldstate & ~ stateflag; |
326 |
|
|
327 |
if (oldstate == newstate) |
if (oldstate == newstate) |
328 |
return; |
return; |
329 |
|
|
330 |
if ((stateflag != SELECTED) |
if ((stateflag != SELECTED) && (stateflag != ENABLED) |
|
&& (stateflag != ENABLED) |
|
331 |
&& (stateMask & ENABLED) == 0) |
&& (stateMask & ENABLED) == 0) |
332 |
return; |
return; |
333 |
|
|
335 |
|
|
336 |
fireStateChanged(); |
fireStateChanged(); |
337 |
|
|
338 |
if ((oldstate & SELECTED) == 0 |
if ((oldstate & SELECTED) == 0 && (newstate & SELECTED) == SELECTED) |
|
&& (newstate & SELECTED) == SELECTED) |
|
|
fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, |
|
|
null, ItemEvent.SELECTED)); |
|
|
|
|
|
else if ((oldstate & SELECTED) == SELECTED |
|
|
&& (newstate & SELECTED) == 0) |
|
|
fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, |
|
|
null, ItemEvent.DESELECTED)); |
|
|
|
|
|
else if (((oldstate & ARMED) == ARMED && (oldstate & PRESSED) == PRESSED) |
|
|
&& |
|
|
((newstate & ARMED) == ARMED && (newstate & PRESSED) == 0)) |
|
339 |
{ |
{ |
340 |
fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, |
fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, |
341 |
actionCommand)); |
null, ItemEvent.SELECTED)); |
342 |
|
group.setSelected(this, true); |
343 |
} |
} |
344 |
} |
|
345 |
|
else if ((oldstate & SELECTED) == SELECTED && (newstate & SELECTED) == 0) |
346 |
|
{ |
347 |
|
fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, |
348 |
|
null, ItemEvent.DESELECTED)); |
349 |
|
group.setSelected(this, false); |
350 |
|
} |
351 |
|
|
352 |
|
else if (((oldstate & ARMED) == ARMED && (oldstate & PRESSED) == PRESSED) |
353 |
|
&& ((newstate & ARMED) == ARMED && (newstate & PRESSED) == 0)) |
354 |
|
fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, |
355 |
|
actionCommand)); |
356 |
|
} |
357 |
|
|
358 |
/** |
/** |
359 |
* Get the value of the model's "armed" property. |
* Get the value of the model's "armed" property. |
360 |
* |
* |
361 |
* @return The current "armed" property |
* @return The current "armed" property |
362 |
*/ |
*/ |
363 |
public boolean isArmed() |
public boolean isArmed() |
364 |
{ |
{ |
365 |
return (stateMask & ARMED) == ARMED; |
return (stateMask & ARMED) == ARMED; |
366 |
} |
} |
367 |
|
|
368 |
/** |
/** |
369 |
* Set the value of the model's "armed" property. |
* Set the value of the model's "armed" property. |
370 |
* |
* |
381 |
* @return The current "enabled" property. |
* @return The current "enabled" property. |
382 |
*/ |
*/ |
383 |
public boolean isEnabled() |
public boolean isEnabled() |
384 |
{ |
{ |
385 |
return (stateMask & ENABLED) == ENABLED; |
return (stateMask & ENABLED) == ENABLED; |
386 |
} |
} |
387 |
|
|
388 |
/** |
/** |
389 |
* Set the value of the model's "enabled" property. |
* Set the value of the model's "enabled" property. |
401 |
* @param p The new "pressed" property |
* @param p The new "pressed" property |
402 |
*/ |
*/ |
403 |
public void setPressed(boolean p) |
public void setPressed(boolean p) |
404 |
{ |
{ |
405 |
changeState(PRESSED, p); |
changeState(PRESSED, p); |
406 |
} |
} |
407 |
|
|
408 |
/** |
/** |
409 |
* Get the value of the model's "pressed" property. |
* Get the value of the model's "pressed" property. |
425 |
changeState(ROLLOVER, r); |
changeState(ROLLOVER, r); |
426 |
} |
} |
427 |
|
|
|
|
|
428 |
/** |
/** |
429 |
* Set the value of the model's "selected" property. |
* Set the value of the model's "selected" property. |
430 |
* |
* |
451 |
* @return The current "rollover" property |
* @return The current "rollover" property |
452 |
*/ |
*/ |
453 |
public boolean isRollover() |
public boolean isRollover() |
454 |
{ |
{ |
455 |
return (stateMask & ROLLOVER) == ROLLOVER; |
return (stateMask & ROLLOVER) == ROLLOVER; |
456 |
} |
} |
457 |
|
|
458 |
/** |
/** |
459 |
* Get the value of the model's "mnemonic" property. |
* Get the value of the model's "mnemonic" property. |
461 |
* @return The current "mnemonic" property |
* @return The current "mnemonic" property |
462 |
*/ |
*/ |
463 |
public int getMnemonic() |
public int getMnemonic() |
464 |
{ |
{ |
465 |
return mnemonic; |
return mnemonic; |
466 |
} |
} |
467 |
|
|
474 |
{ |
{ |
475 |
if (mnemonic != key) |
if (mnemonic != key) |
476 |
{ |
{ |
477 |
mnemonic = key; |
mnemonic = key; |
478 |
fireStateChanged(); |
fireStateChanged(); |
479 |
} |
} |
480 |
} |
} |
481 |
|
|
482 |
/** |
/** |
483 |
* Set the value of the model's "actionCommand" property. This property |
* Set the value of the model's "actionCommand" property. This property is |
484 |
* is used as the "command" property of the {@link ActionEvent} fired |
* used as the "command" property of the {@link ActionEvent} fired from the |
485 |
* from the model. |
* model. |
486 |
* |
* |
487 |
* @param s The new "actionCommand" property. |
* @param s The new "actionCommand" property. |
488 |
*/ |
*/ |
490 |
{ |
{ |
491 |
if (actionCommand != s) |
if (actionCommand != s) |
492 |
{ |
{ |
493 |
actionCommand = s; |
actionCommand = s; |
494 |
fireStateChanged(); |
fireStateChanged(); |
495 |
} |
} |
496 |
} |
} |
497 |
|
|
498 |
/** |
/** |
499 |
* Returns the current value of the model's "actionCommand" property. |
* Returns the current value of the model's "actionCommand" property. |
500 |
* |
* |
506 |
} |
} |
507 |
|
|
508 |
/** |
/** |
509 |
* Set the value of the model's "group" property. The model is said to be |
* Set the value of the model's "group" property. The model is said to be a |
510 |
* a member of the {@link ButtonGroup} held in its "group" property, and |
* member of the {@link ButtonGroup} held in its "group" property, and only |
511 |
* only one model in a given group can have their "selected" property be |
* one model in a given group can have their "selected" property be |
512 |
* <code>true</code> at a time. |
* <code>true</code> at a time. |
513 |
* |
* |
514 |
* @param g The new "group" property |
* @param g The new "group" property |
517 |
{ |
{ |
518 |
if (group != g) |
if (group != g) |
519 |
{ |
{ |
520 |
group = g; |
group = g; |
521 |
fireStateChanged(); |
fireStateChanged(); |
522 |
} |
} |
523 |
} |
} |
524 |
|
|