001 /*
002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package javax.swing;
026
027 import java.awt.*;
028 import java.awt.event.*;
029
030 import javax.swing.event.*;
031 import javax.swing.plaf.*;
032 import javax.accessibility.*;
033
034 import java.io.ObjectOutputStream;
035 import java.io.ObjectInputStream;
036 import java.io.IOException;
037
038 /**
039 * An implementation of a two-state button.
040 * The <code>JRadioButton</code> and <code>JCheckBox</code> classes
041 * are subclasses of this class.
042 * For information on using them see
043 * <a
044 href="http://java.sun.com/docs/books/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>,
045 * a section in <em>The Java Tutorial</em>.
046 * <p>
047 * Buttons can be configured, and to some degree controlled, by
048 * <code><a href="Action.html">Action</a></code>s. Using an
049 * <code>Action</code> with a button has many benefits beyond directly
050 * configuring a button. Refer to <a href="Action.html#buttonActions">
051 * Swing Components Supporting <code>Action</code></a> for more
052 * details, and you can find more information in <a
053 * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/action.html">How
054 * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
055 * <p>
056 * <strong>Warning:</strong> Swing is not thread safe. For more
057 * information see <a
058 * href="package-summary.html#threading">Swing's Threading
059 * Policy</a>.
060 * <p>
061 * <strong>Warning:</strong>
062 * Serialized objects of this class will not be compatible with
063 * future Swing releases. The current serialization support is
064 * appropriate for short term storage or RMI between applications running
065 * the same version of Swing. As of 1.4, support for long term storage
066 * of all JavaBeans<sup><font size="-2">TM</font></sup>
067 * has been added to the <code>java.beans</code> package.
068 * Please see {@link java.beans.XMLEncoder}.
069 *
070 * @beaninfo
071 * attribute: isContainer false
072 * description: An implementation of a two-state button.
073 *
074 * @see JRadioButton
075 * @see JCheckBox
076 * @version 1.68 05/05/07
077 * @author Jeff Dinkins
078 */
079 public class JToggleButton extends AbstractButton implements Accessible {
080
081 /**
082 * @see #getUIClassID
083 * @see #readObject
084 */
085 private static final String uiClassID = "ToggleButtonUI";
086
087 /**
088 * Creates an initially unselected toggle button
089 * without setting the text or image.
090 */
091 public JToggleButton() {
092 this (null, null, false);
093 }
094
095 /**
096 * Creates an initially unselected toggle button
097 * with the specified image but no text.
098 *
099 * @param icon the image that the button should display
100 */
101 public JToggleButton(Icon icon) {
102 this (null, icon, false);
103 }
104
105 /**
106 * Creates a toggle button with the specified image
107 * and selection state, but no text.
108 *
109 * @param icon the image that the button should display
110 * @param selected if true, the button is initially selected;
111 * otherwise, the button is initially unselected
112 */
113 public JToggleButton(Icon icon, boolean selected) {
114 this (null, icon, selected);
115 }
116
117 /**
118 * Creates an unselected toggle button with the specified text.
119 *
120 * @param text the string displayed on the toggle button
121 */
122 public JToggleButton(String text) {
123 this (text, null, false);
124 }
125
126 /**
127 * Creates a toggle button with the specified text
128 * and selection state.
129 *
130 * @param text the string displayed on the toggle button
131 * @param selected if true, the button is initially selected;
132 * otherwise, the button is initially unselected
133 */
134 public JToggleButton(String text, boolean selected) {
135 this (text, null, selected);
136 }
137
138 /**
139 * Creates a toggle button where properties are taken from the
140 * Action supplied.
141 *
142 * @since 1.3
143 */
144 public JToggleButton(Action a) {
145 this ();
146 setAction(a);
147 }
148
149 /**
150 * Creates a toggle button that has the specified text and image,
151 * and that is initially unselected.
152 *
153 * @param text the string displayed on the button
154 * @param icon the image that the button should display
155 */
156 public JToggleButton(String text, Icon icon) {
157 this (text, icon, false);
158 }
159
160 /**
161 * Creates a toggle button with the specified text, image, and
162 * selection state.
163 *
164 * @param text the text of the toggle button
165 * @param icon the image that the button should display
166 * @param selected if true, the button is initially selected;
167 * otherwise, the button is initially unselected
168 */
169 public JToggleButton(String text, Icon icon, boolean selected) {
170 // Create the model
171 setModel(new ToggleButtonModel());
172
173 model.setSelected(selected);
174
175 // initialize
176 init(text, icon);
177 }
178
179 /**
180 * Resets the UI property to a value from the current look and feel.
181 *
182 * @see JComponent#updateUI
183 */
184 public void updateUI() {
185 setUI((ButtonUI) UIManager.getUI(this ));
186 }
187
188 /**
189 * Returns a string that specifies the name of the l&f class
190 * that renders this component.
191 *
192 * @return String "ToggleButtonUI"
193 * @see JComponent#getUIClassID
194 * @see UIDefaults#getUI
195 * @beaninfo
196 * description: A string that specifies the name of the L&F class
197 */
198 public String getUIClassID() {
199 return uiClassID;
200 }
201
202 /**
203 * Overriden to return true, JToggleButton supports
204 * the selected state.
205 */
206 boolean shouldUpdateSelectedStateFromAction() {
207 return true;
208 }
209
210 // *********************************************************************
211
212 /**
213 * The ToggleButton model
214 * <p>
215 * <strong>Warning:</strong>
216 * Serialized objects of this class will not be compatible with
217 * future Swing releases. The current serialization support is
218 * appropriate for short term storage or RMI between applications running
219 * the same version of Swing. As of 1.4, support for long term storage
220 * of all JavaBeans<sup><font size="-2">TM</font></sup>
221 * has been added to the <code>java.beans</code> package.
222 * Please see {@link java.beans.XMLEncoder}.
223 */
224 public static class ToggleButtonModel extends DefaultButtonModel {
225
226 /**
227 * Creates a new ToggleButton Model
228 */
229 public ToggleButtonModel() {
230 }
231
232 /**
233 * Checks if the button is selected.
234 */
235 public boolean isSelected() {
236 // if(getGroup() != null) {
237 // return getGroup().isSelected(this);
238 // } else {
239 return (stateMask & SELECTED) != 0;
240 // }
241 }
242
243 /**
244 * Sets the selected state of the button.
245 * @param b true selects the toggle button,
246 * false deselects the toggle button.
247 */
248 public void setSelected(boolean b) {
249 ButtonGroup group = getGroup();
250 if (group != null) {
251 // use the group model instead
252 group.setSelected(this , b);
253 b = group.isSelected(this );
254 }
255
256 if (isSelected() == b) {
257 return;
258 }
259
260 if (b) {
261 stateMask |= SELECTED;
262 } else {
263 stateMask &= ~SELECTED;
264 }
265
266 // Send ChangeEvent
267 fireStateChanged();
268
269 // Send ItemEvent
270 fireItemStateChanged(new ItemEvent(this ,
271 ItemEvent.ITEM_STATE_CHANGED, this , this
272 .isSelected() ? ItemEvent.SELECTED
273 : ItemEvent.DESELECTED));
274
275 }
276
277 /**
278 * Sets the pressed state of the toggle button.
279 */
280 public void setPressed(boolean b) {
281 if ((isPressed() == b) || !isEnabled()) {
282 return;
283 }
284
285 if (b == false && isArmed()) {
286 setSelected(!this .isSelected());
287 }
288
289 if (b) {
290 stateMask |= PRESSED;
291 } else {
292 stateMask &= ~PRESSED;
293 }
294
295 fireStateChanged();
296
297 if (!isPressed() && isArmed()) {
298 int modifiers = 0;
299 AWTEvent currentEvent = EventQueue.getCurrentEvent();
300 if (currentEvent instanceof InputEvent) {
301 modifiers = ((InputEvent) currentEvent)
302 .getModifiers();
303 } else if (currentEvent instanceof ActionEvent) {
304 modifiers = ((ActionEvent) currentEvent)
305 .getModifiers();
306 }
307 fireActionPerformed(new ActionEvent(this ,
308 ActionEvent.ACTION_PERFORMED,
309 getActionCommand(), EventQueue
310 .getMostRecentEventTime(), modifiers));
311 }
312
313 }
314 }
315
316 /**
317 * See readObject() and writeObject() in JComponent for more
318 * information about serialization in Swing.
319 */
320 private void writeObject(ObjectOutputStream s) throws IOException {
321 s.defaultWriteObject();
322 if (getUIClassID().equals(uiClassID)) {
323 byte count = JComponent.getWriteObjCounter(this );
324 JComponent.setWriteObjCounter(this , --count);
325 if (count == 0 && ui != null) {
326 ui.installUI(this );
327 }
328 }
329 }
330
331 /**
332 * Returns a string representation of this JToggleButton. This method
333 * is intended to be used only for debugging purposes, and the
334 * content and format of the returned string may vary between
335 * implementations. The returned string may be empty but may not
336 * be <code>null</code>.
337 *
338 * @return a string representation of this JToggleButton.
339 */
340 protected String paramString() {
341 return super .paramString();
342 }
343
344 /////////////////
345 // Accessibility support
346 ////////////////
347
348 /**
349 * Gets the AccessibleContext associated with this JToggleButton.
350 * For toggle buttons, the AccessibleContext takes the form of an
351 * AccessibleJToggleButton.
352 * A new AccessibleJToggleButton instance is created if necessary.
353 *
354 * @return an AccessibleJToggleButton that serves as the
355 * AccessibleContext of this JToggleButton
356 * @beaninfo
357 * expert: true
358 * description: The AccessibleContext associated with this ToggleButton.
359 */
360 public AccessibleContext getAccessibleContext() {
361 if (accessibleContext == null) {
362 accessibleContext = new AccessibleJToggleButton();
363 }
364 return accessibleContext;
365 }
366
367 /**
368 * This class implements accessibility support for the
369 * <code>JToggleButton</code> class. It provides an implementation of the
370 * Java Accessibility API appropriate to toggle button user-interface
371 * elements.
372 * <p>
373 * <strong>Warning:</strong>
374 * Serialized objects of this class will not be compatible with
375 * future Swing releases. The current serialization support is
376 * appropriate for short term storage or RMI between applications running
377 * the same version of Swing. As of 1.4, support for long term storage
378 * of all JavaBeans<sup><font size="-2">TM</font></sup>
379 * has been added to the <code>java.beans</code> package.
380 * Please see {@link java.beans.XMLEncoder}.
381 */
382 protected class AccessibleJToggleButton extends
383 AccessibleAbstractButton implements ItemListener {
384
385 public AccessibleJToggleButton() {
386 super ();
387 JToggleButton.this .addItemListener(this );
388 }
389
390 /**
391 * Fire accessible property change events when the state of the
392 * toggle button changes.
393 */
394 public void itemStateChanged(ItemEvent e) {
395 JToggleButton tb = (JToggleButton) e.getSource();
396 if (JToggleButton.this .accessibleContext != null) {
397 if (tb.isSelected()) {
398 JToggleButton.this .accessibleContext
399 .firePropertyChange(
400 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
401 null, AccessibleState.CHECKED);
402 } else {
403 JToggleButton.this .accessibleContext
404 .firePropertyChange(
405 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
406 AccessibleState.CHECKED, null);
407 }
408 }
409 }
410
411 /**
412 * Get the role of this object.
413 *
414 * @return an instance of AccessibleRole describing the role of the
415 * object
416 */
417 public AccessibleRole getAccessibleRole() {
418 return AccessibleRole.TOGGLE_BUTTON;
419 }
420 } // inner class AccessibleJToggleButton
421 }
|