Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/swing/AbstractButton.java
38829 views
1
/*
2
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
package javax.swing;
26
27
import java.awt.*;
28
import java.awt.event.*;
29
import java.awt.image.*;
30
import java.text.*;
31
import java.awt.geom.*;
32
import java.beans.PropertyChangeEvent;
33
import java.beans.PropertyChangeListener;
34
import java.beans.Transient;
35
import java.util.Enumeration;
36
import java.util.Vector;
37
import java.io.Serializable;
38
import javax.swing.event.*;
39
import javax.swing.border.*;
40
import javax.swing.plaf.*;
41
import javax.accessibility.*;
42
import javax.swing.text.*;
43
import javax.swing.text.html.*;
44
import javax.swing.plaf.basic.*;
45
import java.util.*;
46
47
/**
48
* Defines common behaviors for buttons and menu items.
49
* <p>
50
* Buttons can be configured, and to some degree controlled, by
51
* <code><a href="Action.html">Action</a></code>s. Using an
52
* <code>Action</code> with a button has many benefits beyond directly
53
* configuring a button. Refer to <a href="Action.html#buttonActions">
54
* Swing Components Supporting <code>Action</code></a> for more
55
* details, and you can find more information in <a
56
* href="https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
57
* to Use Actions</a>, a section in <em>The Java Tutorial</em>.
58
* <p>
59
* For further information see
60
* <a
61
href="https://docs.oracle.com/javase/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>,
62
* a section in <em>The Java Tutorial</em>.
63
* <p>
64
* <strong>Warning:</strong>
65
* Serialized objects of this class will not be compatible with
66
* future Swing releases. The current serialization support is
67
* appropriate for short term storage or RMI between applications running
68
* the same version of Swing. As of 1.4, support for long term storage
69
* of all JavaBeans&trade;
70
* has been added to the <code>java.beans</code> package.
71
* Please see {@link java.beans.XMLEncoder}.
72
*
73
* @author Jeff Dinkins
74
*/
75
public abstract class AbstractButton extends JComponent implements ItemSelectable, SwingConstants {
76
77
// *********************************
78
// ******* Button properties *******
79
// *********************************
80
81
/** Identifies a change in the button model. */
82
public static final String MODEL_CHANGED_PROPERTY = "model";
83
/** Identifies a change in the button's text. */
84
public static final String TEXT_CHANGED_PROPERTY = "text";
85
/** Identifies a change to the button's mnemonic. */
86
public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
87
88
// Text positioning and alignment
89
/** Identifies a change in the button's margins. */
90
public static final String MARGIN_CHANGED_PROPERTY = "margin";
91
/** Identifies a change in the button's vertical alignment. */
92
public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
93
/** Identifies a change in the button's horizontal alignment. */
94
public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
95
96
/** Identifies a change in the button's vertical text position. */
97
public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
98
/** Identifies a change in the button's horizontal text position. */
99
public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
100
101
// Paint options
102
/**
103
* Identifies a change to having the border drawn,
104
* or having it not drawn.
105
*/
106
public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
107
/**
108
* Identifies a change to having the border highlighted when focused,
109
* or not.
110
*/
111
public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
112
/**
113
* Identifies a change from rollover enabled to disabled or back
114
* to enabled.
115
*/
116
public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
117
/**
118
* Identifies a change to having the button paint the content area.
119
*/
120
public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
121
122
// Icons
123
/** Identifies a change to the icon that represents the button. */
124
public static final String ICON_CHANGED_PROPERTY = "icon";
125
126
/**
127
* Identifies a change to the icon used when the button has been
128
* pressed.
129
*/
130
public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
131
/**
132
* Identifies a change to the icon used when the button has
133
* been selected.
134
*/
135
public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
136
137
/**
138
* Identifies a change to the icon used when the cursor is over
139
* the button.
140
*/
141
public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
142
/**
143
* Identifies a change to the icon used when the cursor is
144
* over the button and it has been selected.
145
*/
146
public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
147
148
/**
149
* Identifies a change to the icon used when the button has
150
* been disabled.
151
*/
152
public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
153
/**
154
* Identifies a change to the icon used when the button has been
155
* disabled and selected.
156
*/
157
public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
158
159
160
/** The data model that determines the button's state. */
161
protected ButtonModel model = null;
162
163
private String text = ""; // for BeanBox
164
private Insets margin = null;
165
private Insets defaultMargin = null;
166
167
// Button icons
168
// PENDING(jeff) - hold icons in an array
169
private Icon defaultIcon = null;
170
private Icon pressedIcon = null;
171
private Icon disabledIcon = null;
172
173
private Icon selectedIcon = null;
174
private Icon disabledSelectedIcon = null;
175
176
private Icon rolloverIcon = null;
177
private Icon rolloverSelectedIcon = null;
178
179
// Display properties
180
private boolean paintBorder = true;
181
private boolean paintFocus = true;
182
private boolean rolloverEnabled = false;
183
private boolean contentAreaFilled = true;
184
185
// Icon/Label Alignment
186
private int verticalAlignment = CENTER;
187
private int horizontalAlignment = CENTER;
188
189
private int verticalTextPosition = CENTER;
190
private int horizontalTextPosition = TRAILING;
191
192
private int iconTextGap = 4;
193
194
private int mnemonic;
195
private int mnemonicIndex = -1;
196
197
private long multiClickThreshhold = 0;
198
199
private boolean borderPaintedSet = false;
200
private boolean rolloverEnabledSet = false;
201
private boolean iconTextGapSet = false;
202
private boolean contentAreaFilledSet = false;
203
204
// Whether or not we've set the LayoutManager.
205
private boolean setLayout = false;
206
207
// This is only used by JButton, promoted to avoid an extra
208
// boolean field in JButton
209
boolean defaultCapable = true;
210
211
/**
212
* Combined listeners: ActionListener, ChangeListener, ItemListener.
213
*/
214
private Handler handler;
215
216
/**
217
* The button model's <code>changeListener</code>.
218
*/
219
protected ChangeListener changeListener = null;
220
/**
221
* The button model's <code>ActionListener</code>.
222
*/
223
protected ActionListener actionListener = null;
224
/**
225
* The button model's <code>ItemListener</code>.
226
*/
227
protected ItemListener itemListener = null;
228
229
/**
230
* Only one <code>ChangeEvent</code> is needed per button
231
* instance since the
232
* event's only state is the source property. The source of events
233
* generated is always "this".
234
*/
235
protected transient ChangeEvent changeEvent;
236
237
private boolean hideActionText = false;
238
239
/**
240
* Sets the <code>hideActionText</code> property, which determines
241
* whether the button displays text from the <code>Action</code>.
242
* This is useful only if an <code>Action</code> has been
243
* installed on the button.
244
*
245
* @param hideActionText <code>true</code> if the button's
246
* <code>text</code> property should not reflect
247
* that of the <code>Action</code>; the default is
248
* <code>false</code>
249
* @see <a href="Action.html#buttonActions">Swing Components Supporting
250
* <code>Action</code></a>
251
* @since 1.6
252
* @beaninfo
253
* bound: true
254
* expert: true
255
* description: Whether the text of the button should come from
256
* the <code>Action</code>.
257
*/
258
public void setHideActionText(boolean hideActionText) {
259
if (hideActionText != this.hideActionText) {
260
this.hideActionText = hideActionText;
261
if (getAction() != null) {
262
setTextFromAction(getAction(), false);
263
}
264
firePropertyChange("hideActionText", !hideActionText,
265
hideActionText);
266
}
267
}
268
269
/**
270
* Returns the value of the <code>hideActionText</code> property, which
271
* determines whether the button displays text from the
272
* <code>Action</code>. This is useful only if an <code>Action</code>
273
* has been installed on the button.
274
*
275
* @return <code>true</code> if the button's <code>text</code>
276
* property should not reflect that of the
277
* <code>Action</code>; the default is <code>false</code>
278
* @since 1.6
279
*/
280
public boolean getHideActionText() {
281
return hideActionText;
282
}
283
284
/**
285
* Returns the button's text.
286
* @return the buttons text
287
* @see #setText
288
*/
289
public String getText() {
290
return text;
291
}
292
293
/**
294
* Sets the button's text.
295
* @param text the string used to set the text
296
* @see #getText
297
* @beaninfo
298
* bound: true
299
* preferred: true
300
* attribute: visualUpdate true
301
* description: The button's text.
302
*/
303
public void setText(String text) {
304
String oldValue = this.text;
305
this.text = text;
306
firePropertyChange(TEXT_CHANGED_PROPERTY, oldValue, text);
307
updateDisplayedMnemonicIndex(text, getMnemonic());
308
309
if (accessibleContext != null) {
310
accessibleContext.firePropertyChange(
311
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
312
oldValue, text);
313
}
314
if (text == null || oldValue == null || !text.equals(oldValue)) {
315
revalidate();
316
repaint();
317
}
318
}
319
320
321
/**
322
* Returns the state of the button. True if the
323
* toggle button is selected, false if it's not.
324
* @return true if the toggle button is selected, otherwise false
325
*/
326
public boolean isSelected() {
327
return model.isSelected();
328
}
329
330
/**
331
* Sets the state of the button. Note that this method does not
332
* trigger an <code>actionEvent</code>.
333
* Call <code>doClick</code> to perform a programmatic action change.
334
*
335
* @param b true if the button is selected, otherwise false
336
*/
337
public void setSelected(boolean b) {
338
boolean oldValue = isSelected();
339
340
// TIGER - 4840653
341
// Removed code which fired an AccessibleState.SELECTED
342
// PropertyChangeEvent since this resulted in two
343
// identical events being fired since
344
// AbstractButton.fireItemStateChanged also fires the
345
// same event. This caused screen readers to speak the
346
// name of the item twice.
347
348
model.setSelected(b);
349
}
350
351
/**
352
* Programmatically perform a "click". This does the same
353
* thing as if the user had pressed and released the button.
354
*/
355
public void doClick() {
356
doClick(68);
357
}
358
359
/**
360
* Programmatically perform a "click". This does the same
361
* thing as if the user had pressed and released the button.
362
* The button stays visually "pressed" for <code>pressTime</code>
363
* milliseconds.
364
*
365
* @param pressTime the time to "hold down" the button, in milliseconds
366
*/
367
public void doClick(int pressTime) {
368
Dimension size = getSize();
369
model.setArmed(true);
370
model.setPressed(true);
371
paintImmediately(new Rectangle(0,0, size.width, size.height));
372
try {
373
Thread.currentThread().sleep(pressTime);
374
} catch(InterruptedException ie) {
375
}
376
model.setPressed(false);
377
model.setArmed(false);
378
}
379
380
/**
381
* Sets space for margin between the button's border and
382
* the label. Setting to <code>null</code> will cause the button to
383
* use the default margin. The button's default <code>Border</code>
384
* object will use this value to create the proper margin.
385
* However, if a non-default border is set on the button,
386
* it is that <code>Border</code> object's responsibility to create the
387
* appropriate margin space (else this property will
388
* effectively be ignored).
389
*
390
* @param m the space between the border and the label
391
*
392
* @beaninfo
393
* bound: true
394
* attribute: visualUpdate true
395
* description: The space between the button's border and the label.
396
*/
397
public void setMargin(Insets m) {
398
// Cache the old margin if it comes from the UI
399
if(m instanceof UIResource) {
400
defaultMargin = m;
401
} else if(margin instanceof UIResource) {
402
defaultMargin = margin;
403
}
404
405
// If the client passes in a null insets, restore the margin
406
// from the UI if possible
407
if(m == null && defaultMargin != null) {
408
m = defaultMargin;
409
}
410
411
Insets old = margin;
412
margin = m;
413
firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m);
414
if (old == null || !old.equals(m)) {
415
revalidate();
416
repaint();
417
}
418
}
419
420
/**
421
* Returns the margin between the button's border and
422
* the label.
423
*
424
* @return an <code>Insets</code> object specifying the margin
425
* between the botton's border and the label
426
* @see #setMargin
427
*/
428
public Insets getMargin() {
429
return (margin == null) ? null : (Insets) margin.clone();
430
}
431
432
/**
433
* Returns the default icon.
434
* @return the default <code>Icon</code>
435
* @see #setIcon
436
*/
437
public Icon getIcon() {
438
return defaultIcon;
439
}
440
441
/**
442
* Sets the button's default icon. This icon is
443
* also used as the "pressed" and "disabled" icon if
444
* there is no explicitly set pressed icon.
445
*
446
* @param defaultIcon the icon used as the default image
447
* @see #getIcon
448
* @see #setPressedIcon
449
* @beaninfo
450
* bound: true
451
* attribute: visualUpdate true
452
* description: The button's default icon
453
*/
454
public void setIcon(Icon defaultIcon) {
455
Icon oldValue = this.defaultIcon;
456
this.defaultIcon = defaultIcon;
457
458
/* If the default icon has really changed and we had
459
* generated the disabled icon for this component,
460
* (i.e. setDisabledIcon() was never called) then
461
* clear the disabledIcon field.
462
*/
463
if (defaultIcon != oldValue && (disabledIcon instanceof UIResource)) {
464
disabledIcon = null;
465
}
466
467
firePropertyChange(ICON_CHANGED_PROPERTY, oldValue, defaultIcon);
468
if (accessibleContext != null) {
469
accessibleContext.firePropertyChange(
470
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
471
oldValue, defaultIcon);
472
}
473
if (defaultIcon != oldValue) {
474
if (defaultIcon == null || oldValue == null ||
475
defaultIcon.getIconWidth() != oldValue.getIconWidth() ||
476
defaultIcon.getIconHeight() != oldValue.getIconHeight()) {
477
revalidate();
478
}
479
repaint();
480
}
481
}
482
483
/**
484
* Returns the pressed icon for the button.
485
* @return the <code>pressedIcon</code> property
486
* @see #setPressedIcon
487
*/
488
public Icon getPressedIcon() {
489
return pressedIcon;
490
}
491
492
/**
493
* Sets the pressed icon for the button.
494
* @param pressedIcon the icon used as the "pressed" image
495
* @see #getPressedIcon
496
* @beaninfo
497
* bound: true
498
* attribute: visualUpdate true
499
* description: The pressed icon for the button.
500
*/
501
public void setPressedIcon(Icon pressedIcon) {
502
Icon oldValue = this.pressedIcon;
503
this.pressedIcon = pressedIcon;
504
firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, oldValue, pressedIcon);
505
if (accessibleContext != null) {
506
accessibleContext.firePropertyChange(
507
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
508
oldValue, pressedIcon);
509
}
510
if (pressedIcon != oldValue) {
511
if (getModel().isPressed()) {
512
repaint();
513
}
514
}
515
}
516
517
/**
518
* Returns the selected icon for the button.
519
* @return the <code>selectedIcon</code> property
520
* @see #setSelectedIcon
521
*/
522
public Icon getSelectedIcon() {
523
return selectedIcon;
524
}
525
526
/**
527
* Sets the selected icon for the button.
528
* @param selectedIcon the icon used as the "selected" image
529
* @see #getSelectedIcon
530
* @beaninfo
531
* bound: true
532
* attribute: visualUpdate true
533
* description: The selected icon for the button.
534
*/
535
public void setSelectedIcon(Icon selectedIcon) {
536
Icon oldValue = this.selectedIcon;
537
this.selectedIcon = selectedIcon;
538
539
/* If the default selected icon has really changed and we had
540
* generated the disabled selected icon for this component,
541
* (i.e. setDisabledSelectedIcon() was never called) then
542
* clear the disabledSelectedIcon field.
543
*/
544
if (selectedIcon != oldValue &&
545
disabledSelectedIcon instanceof UIResource) {
546
547
disabledSelectedIcon = null;
548
}
549
550
firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, oldValue, selectedIcon);
551
if (accessibleContext != null) {
552
accessibleContext.firePropertyChange(
553
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
554
oldValue, selectedIcon);
555
}
556
if (selectedIcon != oldValue) {
557
if (isSelected()) {
558
repaint();
559
}
560
}
561
}
562
563
/**
564
* Returns the rollover icon for the button.
565
* @return the <code>rolloverIcon</code> property
566
* @see #setRolloverIcon
567
*/
568
public Icon getRolloverIcon() {
569
return rolloverIcon;
570
}
571
572
/**
573
* Sets the rollover icon for the button.
574
* @param rolloverIcon the icon used as the "rollover" image
575
* @see #getRolloverIcon
576
* @beaninfo
577
* bound: true
578
* attribute: visualUpdate true
579
* description: The rollover icon for the button.
580
*/
581
public void setRolloverIcon(Icon rolloverIcon) {
582
Icon oldValue = this.rolloverIcon;
583
this.rolloverIcon = rolloverIcon;
584
firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, oldValue, rolloverIcon);
585
if (accessibleContext != null) {
586
accessibleContext.firePropertyChange(
587
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
588
oldValue, rolloverIcon);
589
}
590
setRolloverEnabled(true);
591
if (rolloverIcon != oldValue) {
592
// No way to determine whether we are currently in
593
// a rollover state, so repaint regardless
594
repaint();
595
}
596
597
}
598
599
/**
600
* Returns the rollover selection icon for the button.
601
* @return the <code>rolloverSelectedIcon</code> property
602
* @see #setRolloverSelectedIcon
603
*/
604
public Icon getRolloverSelectedIcon() {
605
return rolloverSelectedIcon;
606
}
607
608
/**
609
* Sets the rollover selected icon for the button.
610
* @param rolloverSelectedIcon the icon used as the
611
* "selected rollover" image
612
* @see #getRolloverSelectedIcon
613
* @beaninfo
614
* bound: true
615
* attribute: visualUpdate true
616
* description: The rollover selected icon for the button.
617
*/
618
public void setRolloverSelectedIcon(Icon rolloverSelectedIcon) {
619
Icon oldValue = this.rolloverSelectedIcon;
620
this.rolloverSelectedIcon = rolloverSelectedIcon;
621
firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, oldValue, rolloverSelectedIcon);
622
if (accessibleContext != null) {
623
accessibleContext.firePropertyChange(
624
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
625
oldValue, rolloverSelectedIcon);
626
}
627
setRolloverEnabled(true);
628
if (rolloverSelectedIcon != oldValue) {
629
// No way to determine whether we are currently in
630
// a rollover state, so repaint regardless
631
if (isSelected()) {
632
repaint();
633
}
634
}
635
}
636
637
/**
638
* Returns the icon used by the button when it's disabled.
639
* If no disabled icon has been set this will forward the call to
640
* the look and feel to construct an appropriate disabled Icon.
641
* <p>
642
* Some look and feels might not render the disabled Icon, in which
643
* case they will ignore this.
644
*
645
* @return the <code>disabledIcon</code> property
646
* @see #getPressedIcon
647
* @see #setDisabledIcon
648
* @see javax.swing.LookAndFeel#getDisabledIcon
649
*/
650
@Transient
651
public Icon getDisabledIcon() {
652
if (disabledIcon == null) {
653
disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, getIcon());
654
if (disabledIcon != null) {
655
firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, null, disabledIcon);
656
}
657
}
658
return disabledIcon;
659
}
660
661
/**
662
* Sets the disabled icon for the button.
663
* @param disabledIcon the icon used as the disabled image
664
* @see #getDisabledIcon
665
* @beaninfo
666
* bound: true
667
* attribute: visualUpdate true
668
* description: The disabled icon for the button.
669
*/
670
public void setDisabledIcon(Icon disabledIcon) {
671
Icon oldValue = this.disabledIcon;
672
this.disabledIcon = disabledIcon;
673
firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, oldValue, disabledIcon);
674
if (accessibleContext != null) {
675
accessibleContext.firePropertyChange(
676
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
677
oldValue, disabledIcon);
678
}
679
if (disabledIcon != oldValue) {
680
if (!isEnabled()) {
681
repaint();
682
}
683
}
684
}
685
686
/**
687
* Returns the icon used by the button when it's disabled and selected.
688
* If no disabled selection icon has been set, this will forward
689
* the call to the LookAndFeel to construct an appropriate disabled
690
* Icon from the selection icon if it has been set and to
691
* <code>getDisabledIcon()</code> otherwise.
692
* <p>
693
* Some look and feels might not render the disabled selected Icon, in
694
* which case they will ignore this.
695
*
696
* @return the <code>disabledSelectedIcon</code> property
697
* @see #getDisabledIcon
698
* @see #setDisabledSelectedIcon
699
* @see javax.swing.LookAndFeel#getDisabledSelectedIcon
700
*/
701
public Icon getDisabledSelectedIcon() {
702
if (disabledSelectedIcon == null) {
703
if (selectedIcon != null) {
704
disabledSelectedIcon = UIManager.getLookAndFeel().
705
getDisabledSelectedIcon(this, getSelectedIcon());
706
} else {
707
return getDisabledIcon();
708
}
709
}
710
return disabledSelectedIcon;
711
}
712
713
/**
714
* Sets the disabled selection icon for the button.
715
* @param disabledSelectedIcon the icon used as the disabled
716
* selection image
717
* @see #getDisabledSelectedIcon
718
* @beaninfo
719
* bound: true
720
* attribute: visualUpdate true
721
* description: The disabled selection icon for the button.
722
*/
723
public void setDisabledSelectedIcon(Icon disabledSelectedIcon) {
724
Icon oldValue = this.disabledSelectedIcon;
725
this.disabledSelectedIcon = disabledSelectedIcon;
726
firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, oldValue, disabledSelectedIcon);
727
if (accessibleContext != null) {
728
accessibleContext.firePropertyChange(
729
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
730
oldValue, disabledSelectedIcon);
731
}
732
if (disabledSelectedIcon != oldValue) {
733
if (disabledSelectedIcon == null || oldValue == null ||
734
disabledSelectedIcon.getIconWidth() != oldValue.getIconWidth() ||
735
disabledSelectedIcon.getIconHeight() != oldValue.getIconHeight()) {
736
revalidate();
737
}
738
if (!isEnabled() && isSelected()) {
739
repaint();
740
}
741
}
742
}
743
744
/**
745
* Returns the vertical alignment of the text and icon.
746
*
747
* @return the <code>verticalAlignment</code> property, one of the
748
* following values:
749
* <ul>
750
* <li>{@code SwingConstants.CENTER} (the default)
751
* <li>{@code SwingConstants.TOP}
752
* <li>{@code SwingConstants.BOTTOM}
753
* </ul>
754
*/
755
public int getVerticalAlignment() {
756
return verticalAlignment;
757
}
758
759
/**
760
* Sets the vertical alignment of the icon and text.
761
* @param alignment one of the following values:
762
* <ul>
763
* <li>{@code SwingConstants.CENTER} (the default)
764
* <li>{@code SwingConstants.TOP}
765
* <li>{@code SwingConstants.BOTTOM}
766
* </ul>
767
* @throws IllegalArgumentException if the alignment is not one of the legal
768
* values listed above
769
* @beaninfo
770
* bound: true
771
* enum: TOP SwingConstants.TOP
772
* CENTER SwingConstants.CENTER
773
* BOTTOM SwingConstants.BOTTOM
774
* attribute: visualUpdate true
775
* description: The vertical alignment of the icon and text.
776
*/
777
public void setVerticalAlignment(int alignment) {
778
if (alignment == verticalAlignment) return;
779
int oldValue = verticalAlignment;
780
verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
781
firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, oldValue, verticalAlignment); repaint();
782
}
783
784
/**
785
* Returns the horizontal alignment of the icon and text.
786
* {@code AbstractButton}'s default is {@code SwingConstants.CENTER},
787
* but subclasses such as {@code JCheckBox} may use a different default.
788
*
789
* @return the <code>horizontalAlignment</code> property,
790
* one of the following values:
791
* <ul>
792
* <li>{@code SwingConstants.RIGHT}
793
* <li>{@code SwingConstants.LEFT}
794
* <li>{@code SwingConstants.CENTER}
795
* <li>{@code SwingConstants.LEADING}
796
* <li>{@code SwingConstants.TRAILING}
797
* </ul>
798
*/
799
public int getHorizontalAlignment() {
800
return horizontalAlignment;
801
}
802
803
/**
804
* Sets the horizontal alignment of the icon and text.
805
* {@code AbstractButton}'s default is {@code SwingConstants.CENTER},
806
* but subclasses such as {@code JCheckBox} may use a different default.
807
*
808
* @param alignment the alignment value, one of the following values:
809
* <ul>
810
* <li>{@code SwingConstants.RIGHT}
811
* <li>{@code SwingConstants.LEFT}
812
* <li>{@code SwingConstants.CENTER}
813
* <li>{@code SwingConstants.LEADING}
814
* <li>{@code SwingConstants.TRAILING}
815
* </ul>
816
* @throws IllegalArgumentException if the alignment is not one of the
817
* valid values
818
* @beaninfo
819
* bound: true
820
* enum: LEFT SwingConstants.LEFT
821
* CENTER SwingConstants.CENTER
822
* RIGHT SwingConstants.RIGHT
823
* LEADING SwingConstants.LEADING
824
* TRAILING SwingConstants.TRAILING
825
* attribute: visualUpdate true
826
* description: The horizontal alignment of the icon and text.
827
*/
828
public void setHorizontalAlignment(int alignment) {
829
if (alignment == horizontalAlignment) return;
830
int oldValue = horizontalAlignment;
831
horizontalAlignment = checkHorizontalKey(alignment,
832
"horizontalAlignment");
833
firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY,
834
oldValue, horizontalAlignment);
835
repaint();
836
}
837
838
839
/**
840
* Returns the vertical position of the text relative to the icon.
841
* @return the <code>verticalTextPosition</code> property,
842
* one of the following values:
843
* <ul>
844
* <li>{@code SwingConstants.CENTER} (the default)
845
* <li>{@code SwingConstants.TOP}
846
* <li>{@code SwingConstants.BOTTOM}
847
* </ul>
848
*/
849
public int getVerticalTextPosition() {
850
return verticalTextPosition;
851
}
852
853
/**
854
* Sets the vertical position of the text relative to the icon.
855
* @param textPosition one of the following values:
856
* <ul>
857
* <li>{@code SwingConstants.CENTER} (the default)
858
* <li>{@code SwingConstants.TOP}
859
* <li>{@code SwingConstants.BOTTOM}
860
* </ul>
861
* @beaninfo
862
* bound: true
863
* enum: TOP SwingConstants.TOP
864
* CENTER SwingConstants.CENTER
865
* BOTTOM SwingConstants.BOTTOM
866
* attribute: visualUpdate true
867
* description: The vertical position of the text relative to the icon.
868
*/
869
public void setVerticalTextPosition(int textPosition) {
870
if (textPosition == verticalTextPosition) return;
871
int oldValue = verticalTextPosition;
872
verticalTextPosition = checkVerticalKey(textPosition, "verticalTextPosition");
873
firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, oldValue, verticalTextPosition);
874
revalidate();
875
repaint();
876
}
877
878
/**
879
* Returns the horizontal position of the text relative to the icon.
880
* @return the <code>horizontalTextPosition</code> property,
881
* one of the following values:
882
* <ul>
883
* <li>{@code SwingConstants.RIGHT}
884
* <li>{@code SwingConstants.LEFT}
885
* <li>{@code SwingConstants.CENTER}
886
* <li>{@code SwingConstants.LEADING}
887
* <li>{@code SwingConstants.TRAILING} (the default)
888
* </ul>
889
*/
890
public int getHorizontalTextPosition() {
891
return horizontalTextPosition;
892
}
893
894
/**
895
* Sets the horizontal position of the text relative to the icon.
896
* @param textPosition one of the following values:
897
* <ul>
898
* <li>{@code SwingConstants.RIGHT}
899
* <li>{@code SwingConstants.LEFT}
900
* <li>{@code SwingConstants.CENTER}
901
* <li>{@code SwingConstants.LEADING}
902
* <li>{@code SwingConstants.TRAILING} (the default)
903
* </ul>
904
* @exception IllegalArgumentException if <code>textPosition</code>
905
* is not one of the legal values listed above
906
* @beaninfo
907
* bound: true
908
* enum: LEFT SwingConstants.LEFT
909
* CENTER SwingConstants.CENTER
910
* RIGHT SwingConstants.RIGHT
911
* LEADING SwingConstants.LEADING
912
* TRAILING SwingConstants.TRAILING
913
* attribute: visualUpdate true
914
* description: The horizontal position of the text relative to the icon.
915
*/
916
public void setHorizontalTextPosition(int textPosition) {
917
if (textPosition == horizontalTextPosition) return;
918
int oldValue = horizontalTextPosition;
919
horizontalTextPosition = checkHorizontalKey(textPosition,
920
"horizontalTextPosition");
921
firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY,
922
oldValue,
923
horizontalTextPosition);
924
revalidate();
925
repaint();
926
}
927
928
/**
929
* Returns the amount of space between the text and the icon
930
* displayed in this button.
931
*
932
* @return an int equal to the number of pixels between the text
933
* and the icon.
934
* @since 1.4
935
* @see #setIconTextGap
936
*/
937
public int getIconTextGap() {
938
return iconTextGap;
939
}
940
941
/**
942
* If both the icon and text properties are set, this property
943
* defines the space between them.
944
* <p>
945
* The default value of this property is 4 pixels.
946
* <p>
947
* This is a JavaBeans bound property.
948
*
949
* @since 1.4
950
* @see #getIconTextGap
951
* @beaninfo
952
* bound: true
953
* attribute: visualUpdate true
954
* description: If both the icon and text properties are set, this
955
* property defines the space between them.
956
*/
957
public void setIconTextGap(int iconTextGap) {
958
int oldValue = this.iconTextGap;
959
this.iconTextGap = iconTextGap;
960
iconTextGapSet = true;
961
firePropertyChange("iconTextGap", oldValue, iconTextGap);
962
if (iconTextGap != oldValue) {
963
revalidate();
964
repaint();
965
}
966
}
967
968
/**
969
* Verify that the {@code key} argument is a legal value for the
970
* {@code horizontalAlignment} and {@code horizontalTextPosition}
971
* properties. Valid values are:
972
* <ul>
973
* <li>{@code SwingConstants.RIGHT}
974
* <li>{@code SwingConstants.LEFT}
975
* <li>{@code SwingConstants.CENTER}
976
* <li>{@code SwingConstants.LEADING}
977
* <li>{@code SwingConstants.TRAILING}
978
* </ul>
979
*
980
* @param key the property value to check
981
* @param exception the message to use in the
982
* {@code IllegalArgumentException} that is thrown for an invalid
983
* value
984
* @return the {@code key} argument
985
* @exception IllegalArgumentException if key is not one of the legal
986
* values listed above
987
* @see #setHorizontalTextPosition
988
* @see #setHorizontalAlignment
989
*/
990
protected int checkHorizontalKey(int key, String exception) {
991
if ((key == LEFT) ||
992
(key == CENTER) ||
993
(key == RIGHT) ||
994
(key == LEADING) ||
995
(key == TRAILING)) {
996
return key;
997
} else {
998
throw new IllegalArgumentException(exception);
999
}
1000
}
1001
1002
/**
1003
* Verify that the {@code key} argument is a legal value for the
1004
* vertical properties. Valid values are:
1005
* <ul>
1006
* <li>{@code SwingConstants.CENTER}
1007
* <li>{@code SwingConstants.TOP}
1008
* <li>{@code SwingConstants.BOTTOM}
1009
* </ul>
1010
*
1011
* @param key the property value to check
1012
* @param exception the message to use in the
1013
* {@code IllegalArgumentException} that is thrown for an invalid
1014
* value
1015
* @return the {@code key} argument
1016
* @exception IllegalArgumentException if key is not one of the legal
1017
* values listed above
1018
*/
1019
protected int checkVerticalKey(int key, String exception) {
1020
if ((key == TOP) || (key == CENTER) || (key == BOTTOM)) {
1021
return key;
1022
} else {
1023
throw new IllegalArgumentException(exception);
1024
}
1025
}
1026
1027
/**
1028
*{@inheritDoc}
1029
*
1030
* @since 1.6
1031
*/
1032
public void removeNotify() {
1033
super.removeNotify();
1034
if(isRolloverEnabled()) {
1035
getModel().setRollover(false);
1036
}
1037
}
1038
1039
/**
1040
* Sets the action command for this button.
1041
* @param actionCommand the action command for this button
1042
*/
1043
public void setActionCommand(String actionCommand) {
1044
getModel().setActionCommand(actionCommand);
1045
}
1046
1047
/**
1048
* Returns the action command for this button.
1049
* @return the action command for this button
1050
*/
1051
public String getActionCommand() {
1052
String ac = getModel().getActionCommand();
1053
if(ac == null) {
1054
ac = getText();
1055
}
1056
return ac;
1057
}
1058
1059
private Action action;
1060
private PropertyChangeListener actionPropertyChangeListener;
1061
1062
/**
1063
* Sets the <code>Action</code>.
1064
* The new <code>Action</code> replaces any previously set
1065
* <code>Action</code> but does not affect <code>ActionListeners</code>
1066
* independently added with <code>addActionListener</code>.
1067
* If the <code>Action</code> is already a registered
1068
* <code>ActionListener</code> for the button, it is not re-registered.
1069
* <p>
1070
* Setting the <code>Action</code> results in immediately changing
1071
* all the properties described in <a href="Action.html#buttonActions">
1072
* Swing Components Supporting <code>Action</code></a>.
1073
* Subsequently, the button's properties are automatically updated
1074
* as the <code>Action</code>'s properties change.
1075
* <p>
1076
* This method uses three other methods to set
1077
* and help track the <code>Action</code>'s property values.
1078
* It uses the <code>configurePropertiesFromAction</code> method
1079
* to immediately change the button's properties.
1080
* To track changes in the <code>Action</code>'s property values,
1081
* this method registers the <code>PropertyChangeListener</code>
1082
* returned by <code>createActionPropertyChangeListener</code>. The
1083
* default {@code PropertyChangeListener} invokes the
1084
* {@code actionPropertyChanged} method when a property in the
1085
* {@code Action} changes.
1086
*
1087
* @param a the <code>Action</code> for the <code>AbstractButton</code>,
1088
* or <code>null</code>
1089
* @since 1.3
1090
* @see Action
1091
* @see #getAction
1092
* @see #configurePropertiesFromAction
1093
* @see #createActionPropertyChangeListener
1094
* @see #actionPropertyChanged
1095
* @beaninfo
1096
* bound: true
1097
* attribute: visualUpdate true
1098
* description: the Action instance connected with this ActionEvent source
1099
*/
1100
public void setAction(Action a) {
1101
Action oldValue = getAction();
1102
if (action==null || !action.equals(a)) {
1103
action = a;
1104
if (oldValue!=null) {
1105
removeActionListener(oldValue);
1106
oldValue.removePropertyChangeListener(actionPropertyChangeListener);
1107
actionPropertyChangeListener = null;
1108
}
1109
configurePropertiesFromAction(action);
1110
if (action!=null) {
1111
// Don't add if it is already a listener
1112
if (!isListener(ActionListener.class, action)) {
1113
addActionListener(action);
1114
}
1115
// Reverse linkage:
1116
actionPropertyChangeListener = createActionPropertyChangeListener(action);
1117
action.addPropertyChangeListener(actionPropertyChangeListener);
1118
}
1119
firePropertyChange("action", oldValue, action);
1120
}
1121
}
1122
1123
private boolean isListener(Class c, ActionListener a) {
1124
boolean isListener = false;
1125
Object[] listeners = listenerList.getListenerList();
1126
for (int i = listeners.length-2; i>=0; i-=2) {
1127
if (listeners[i]==c && listeners[i+1]==a) {
1128
isListener=true;
1129
}
1130
}
1131
return isListener;
1132
}
1133
1134
/**
1135
* Returns the currently set <code>Action</code> for this
1136
* <code>ActionEvent</code> source, or <code>null</code>
1137
* if no <code>Action</code> is set.
1138
*
1139
* @return the <code>Action</code> for this <code>ActionEvent</code>
1140
* source, or <code>null</code>
1141
* @since 1.3
1142
* @see Action
1143
* @see #setAction
1144
*/
1145
public Action getAction() {
1146
return action;
1147
}
1148
1149
/**
1150
* Sets the properties on this button to match those in the specified
1151
* <code>Action</code>. Refer to <a href="Action.html#buttonActions">
1152
* Swing Components Supporting <code>Action</code></a> for more
1153
* details as to which properties this sets.
1154
*
1155
* @param a the <code>Action</code> from which to get the properties,
1156
* or <code>null</code>
1157
* @since 1.3
1158
* @see Action
1159
* @see #setAction
1160
*/
1161
protected void configurePropertiesFromAction(Action a) {
1162
setMnemonicFromAction(a);
1163
setTextFromAction(a, false);
1164
AbstractAction.setToolTipTextFromAction(this, a);
1165
setIconFromAction(a);
1166
setActionCommandFromAction(a);
1167
AbstractAction.setEnabledFromAction(this, a);
1168
if (AbstractAction.hasSelectedKey(a) &&
1169
shouldUpdateSelectedStateFromAction()) {
1170
setSelectedFromAction(a);
1171
}
1172
setDisplayedMnemonicIndexFromAction(a, false);
1173
}
1174
1175
void clientPropertyChanged(Object key, Object oldValue,
1176
Object newValue) {
1177
if (key == "hideActionText") {
1178
boolean current = (newValue instanceof Boolean) ?
1179
(Boolean)newValue : false;
1180
if (getHideActionText() != current) {
1181
setHideActionText(current);
1182
}
1183
}
1184
}
1185
1186
/**
1187
* Button subclasses that support mirroring the selected state from
1188
* the action should override this to return true. AbstractButton's
1189
* implementation returns false.
1190
*/
1191
boolean shouldUpdateSelectedStateFromAction() {
1192
return false;
1193
}
1194
1195
/**
1196
* Updates the button's state in response to property changes in the
1197
* associated action. This method is invoked from the
1198
* {@code PropertyChangeListener} returned from
1199
* {@code createActionPropertyChangeListener}. Subclasses do not normally
1200
* need to invoke this. Subclasses that support additional {@code Action}
1201
* properties should override this and
1202
* {@code configurePropertiesFromAction}.
1203
* <p>
1204
* Refer to the table at <a href="Action.html#buttonActions">
1205
* Swing Components Supporting <code>Action</code></a> for a list of
1206
* the properties this method sets.
1207
*
1208
* @param action the <code>Action</code> associated with this button
1209
* @param propertyName the name of the property that changed
1210
* @since 1.6
1211
* @see Action
1212
* @see #configurePropertiesFromAction
1213
*/
1214
protected void actionPropertyChanged(Action action, String propertyName) {
1215
if (propertyName == Action.NAME) {
1216
setTextFromAction(action, true);
1217
} else if (propertyName == "enabled") {
1218
AbstractAction.setEnabledFromAction(this, action);
1219
} else if (propertyName == Action.SHORT_DESCRIPTION) {
1220
AbstractAction.setToolTipTextFromAction(this, action);
1221
} else if (propertyName == Action.SMALL_ICON) {
1222
smallIconChanged(action);
1223
} else if (propertyName == Action.MNEMONIC_KEY) {
1224
setMnemonicFromAction(action);
1225
} else if (propertyName == Action.ACTION_COMMAND_KEY) {
1226
setActionCommandFromAction(action);
1227
} else if (propertyName == Action.SELECTED_KEY &&
1228
AbstractAction.hasSelectedKey(action) &&
1229
shouldUpdateSelectedStateFromAction()) {
1230
setSelectedFromAction(action);
1231
} else if (propertyName == Action.DISPLAYED_MNEMONIC_INDEX_KEY) {
1232
setDisplayedMnemonicIndexFromAction(action, true);
1233
} else if (propertyName == Action.LARGE_ICON_KEY) {
1234
largeIconChanged(action);
1235
}
1236
}
1237
1238
private void setDisplayedMnemonicIndexFromAction(
1239
Action a, boolean fromPropertyChange) {
1240
Integer iValue = (a == null) ? null :
1241
(Integer)a.getValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY);
1242
if (fromPropertyChange || iValue != null) {
1243
int value;
1244
if (iValue == null) {
1245
value = -1;
1246
} else {
1247
value = iValue;
1248
String text = getText();
1249
if (text == null || value >= text.length()) {
1250
value = -1;
1251
}
1252
}
1253
setDisplayedMnemonicIndex(value);
1254
}
1255
}
1256
1257
private void setMnemonicFromAction(Action a) {
1258
Integer n = (a == null) ? null :
1259
(Integer)a.getValue(Action.MNEMONIC_KEY);
1260
setMnemonic((n == null) ? '\0' : n);
1261
}
1262
1263
private void setTextFromAction(Action a, boolean propertyChange) {
1264
boolean hideText = getHideActionText();
1265
if (!propertyChange) {
1266
setText((a != null && !hideText) ?
1267
(String)a.getValue(Action.NAME) : null);
1268
}
1269
else if (!hideText) {
1270
setText((String)a.getValue(Action.NAME));
1271
}
1272
}
1273
1274
void setIconFromAction(Action a) {
1275
Icon icon = null;
1276
if (a != null) {
1277
icon = (Icon)a.getValue(Action.LARGE_ICON_KEY);
1278
if (icon == null) {
1279
icon = (Icon)a.getValue(Action.SMALL_ICON);
1280
}
1281
}
1282
setIcon(icon);
1283
}
1284
1285
void smallIconChanged(Action a) {
1286
if (a.getValue(Action.LARGE_ICON_KEY) == null) {
1287
setIconFromAction(a);
1288
}
1289
}
1290
1291
void largeIconChanged(Action a) {
1292
setIconFromAction(a);
1293
}
1294
1295
private void setActionCommandFromAction(Action a) {
1296
setActionCommand((a != null) ?
1297
(String)a.getValue(Action.ACTION_COMMAND_KEY) :
1298
null);
1299
}
1300
1301
/**
1302
* Sets the seleted state of the button from the action. This is defined
1303
* here, but not wired up. Subclasses like JToggleButton and
1304
* JCheckBoxMenuItem make use of it.
1305
*
1306
* @param a the Action
1307
*/
1308
private void setSelectedFromAction(Action a) {
1309
boolean selected = false;
1310
if (a != null) {
1311
selected = AbstractAction.isSelected(a);
1312
}
1313
if (selected != isSelected()) {
1314
// This won't notify ActionListeners, but that should be
1315
// ok as the change is coming from the Action.
1316
setSelected(selected);
1317
// Make sure the change actually took effect
1318
if (!selected && isSelected()) {
1319
if (getModel() instanceof DefaultButtonModel) {
1320
ButtonGroup group = ((DefaultButtonModel)getModel()).getGroup();
1321
if (group != null) {
1322
group.clearSelection();
1323
}
1324
}
1325
}
1326
}
1327
}
1328
1329
/**
1330
* Creates and returns a <code>PropertyChangeListener</code> that is
1331
* responsible for listening for changes from the specified
1332
* <code>Action</code> and updating the appropriate properties.
1333
* <p>
1334
* <b>Warning:</b> If you subclass this do not create an anonymous
1335
* inner class. If you do the lifetime of the button will be tied to
1336
* that of the <code>Action</code>.
1337
*
1338
* @param a the button's action
1339
* @since 1.3
1340
* @see Action
1341
* @see #setAction
1342
*/
1343
protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
1344
return createActionPropertyChangeListener0(a);
1345
}
1346
1347
1348
PropertyChangeListener createActionPropertyChangeListener0(Action a) {
1349
return new ButtonActionPropertyChangeListener(this, a);
1350
}
1351
1352
@SuppressWarnings("serial")
1353
private static class ButtonActionPropertyChangeListener
1354
extends ActionPropertyChangeListener<AbstractButton> {
1355
ButtonActionPropertyChangeListener(AbstractButton b, Action a) {
1356
super(b, a);
1357
}
1358
protected void actionPropertyChanged(AbstractButton button,
1359
Action action,
1360
PropertyChangeEvent e) {
1361
if (AbstractAction.shouldReconfigure(e)) {
1362
button.configurePropertiesFromAction(action);
1363
} else {
1364
button.actionPropertyChanged(action, e.getPropertyName());
1365
}
1366
}
1367
}
1368
1369
/**
1370
* Gets the <code>borderPainted</code> property.
1371
*
1372
* @return the value of the <code>borderPainted</code> property
1373
* @see #setBorderPainted
1374
*/
1375
public boolean isBorderPainted() {
1376
return paintBorder;
1377
}
1378
1379
/**
1380
* Sets the <code>borderPainted</code> property.
1381
* If <code>true</code> and the button has a border,
1382
* the border is painted. The default value for the
1383
* <code>borderPainted</code> property is <code>true</code>.
1384
* <p>
1385
* Some look and feels might not support
1386
* the <code>borderPainted</code> property,
1387
* in which case they ignore this.
1388
*
1389
* @param b if true and border property is not <code>null</code>,
1390
* the border is painted
1391
* @see #isBorderPainted
1392
* @beaninfo
1393
* bound: true
1394
* attribute: visualUpdate true
1395
* description: Whether the border should be painted.
1396
*/
1397
public void setBorderPainted(boolean b) {
1398
boolean oldValue = paintBorder;
1399
paintBorder = b;
1400
borderPaintedSet = true;
1401
firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, oldValue, paintBorder);
1402
if (b != oldValue) {
1403
revalidate();
1404
repaint();
1405
}
1406
}
1407
1408
/**
1409
* Paint the button's border if <code>BorderPainted</code>
1410
* property is true and the button has a border.
1411
* @param g the <code>Graphics</code> context in which to paint
1412
*
1413
* @see #paint
1414
* @see #setBorder
1415
*/
1416
protected void paintBorder(Graphics g) {
1417
if (isBorderPainted()) {
1418
super.paintBorder(g);
1419
}
1420
}
1421
1422
/**
1423
* Gets the <code>paintFocus</code> property.
1424
*
1425
* @return the <code>paintFocus</code> property
1426
* @see #setFocusPainted
1427
*/
1428
public boolean isFocusPainted() {
1429
return paintFocus;
1430
}
1431
1432
/**
1433
* Sets the <code>paintFocus</code> property, which must
1434
* be <code>true</code> for the focus state to be painted.
1435
* The default value for the <code>paintFocus</code> property
1436
* is <code>true</code>.
1437
* Some look and feels might not paint focus state;
1438
* they will ignore this property.
1439
*
1440
* @param b if <code>true</code>, the focus state should be painted
1441
* @see #isFocusPainted
1442
* @beaninfo
1443
* bound: true
1444
* attribute: visualUpdate true
1445
* description: Whether focus should be painted
1446
*/
1447
public void setFocusPainted(boolean b) {
1448
boolean oldValue = paintFocus;
1449
paintFocus = b;
1450
firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, oldValue, paintFocus);
1451
if (b != oldValue && isFocusOwner()) {
1452
revalidate();
1453
repaint();
1454
}
1455
}
1456
1457
/**
1458
* Gets the <code>contentAreaFilled</code> property.
1459
*
1460
* @return the <code>contentAreaFilled</code> property
1461
* @see #setContentAreaFilled
1462
*/
1463
public boolean isContentAreaFilled() {
1464
return contentAreaFilled;
1465
}
1466
1467
/**
1468
* Sets the <code>contentAreaFilled</code> property.
1469
* If <code>true</code> the button will paint the content
1470
* area. If you wish to have a transparent button, such as
1471
* an icon only button, for example, then you should set
1472
* this to <code>false</code>. Do not call <code>setOpaque(false)</code>.
1473
* The default value for the the <code>contentAreaFilled</code>
1474
* property is <code>true</code>.
1475
* <p>
1476
* This function may cause the component's opaque property to change.
1477
* <p>
1478
* The exact behavior of calling this function varies on a
1479
* component-by-component and L&amp;F-by-L&amp;F basis.
1480
*
1481
* @param b if true, the content should be filled; if false
1482
* the content area is not filled
1483
* @see #isContentAreaFilled
1484
* @see #setOpaque
1485
* @beaninfo
1486
* bound: true
1487
* attribute: visualUpdate true
1488
* description: Whether the button should paint the content area
1489
* or leave it transparent.
1490
*/
1491
public void setContentAreaFilled(boolean b) {
1492
boolean oldValue = contentAreaFilled;
1493
contentAreaFilled = b;
1494
contentAreaFilledSet = true;
1495
firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, oldValue, contentAreaFilled);
1496
if (b != oldValue) {
1497
repaint();
1498
}
1499
}
1500
1501
/**
1502
* Gets the <code>rolloverEnabled</code> property.
1503
*
1504
* @return the value of the <code>rolloverEnabled</code> property
1505
* @see #setRolloverEnabled
1506
*/
1507
public boolean isRolloverEnabled() {
1508
return rolloverEnabled;
1509
}
1510
1511
/**
1512
* Sets the <code>rolloverEnabled</code> property, which
1513
* must be <code>true</code> for rollover effects to occur.
1514
* The default value for the <code>rolloverEnabled</code>
1515
* property is <code>false</code>.
1516
* Some look and feels might not implement rollover effects;
1517
* they will ignore this property.
1518
*
1519
* @param b if <code>true</code>, rollover effects should be painted
1520
* @see #isRolloverEnabled
1521
* @beaninfo
1522
* bound: true
1523
* attribute: visualUpdate true
1524
* description: Whether rollover effects should be enabled.
1525
*/
1526
public void setRolloverEnabled(boolean b) {
1527
boolean oldValue = rolloverEnabled;
1528
rolloverEnabled = b;
1529
rolloverEnabledSet = true;
1530
firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, oldValue, rolloverEnabled);
1531
if (b != oldValue) {
1532
repaint();
1533
}
1534
}
1535
1536
/**
1537
* Returns the keyboard mnemonic from the the current model.
1538
* @return the keyboard mnemonic from the model
1539
*/
1540
public int getMnemonic() {
1541
return mnemonic;
1542
}
1543
1544
/**
1545
* Sets the keyboard mnemonic on the current model.
1546
* The mnemonic is the key which when combined with the look and feel's
1547
* mouseless modifier (usually Alt) will activate this button
1548
* if focus is contained somewhere within this button's ancestor
1549
* window.
1550
* <p>
1551
* A mnemonic must correspond to a single key on the keyboard
1552
* and should be specified using one of the <code>VK_XXX</code>
1553
* keycodes defined in <code>java.awt.event.KeyEvent</code>.
1554
* These codes and the wider array of codes for international
1555
* keyboards may be obtained through
1556
* <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
1557
* Mnemonics are case-insensitive, therefore a key event
1558
* with the corresponding keycode would cause the button to be
1559
* activated whether or not the Shift modifier was pressed.
1560
* <p>
1561
* If the character defined by the mnemonic is found within
1562
* the button's label string, the first occurrence of it
1563
* will be underlined to indicate the mnemonic to the user.
1564
*
1565
* @param mnemonic the key code which represents the mnemonic
1566
* @see java.awt.event.KeyEvent
1567
* @see #setDisplayedMnemonicIndex
1568
*
1569
* @beaninfo
1570
* bound: true
1571
* attribute: visualUpdate true
1572
* description: the keyboard character mnemonic
1573
*/
1574
public void setMnemonic(int mnemonic) {
1575
int oldValue = getMnemonic();
1576
model.setMnemonic(mnemonic);
1577
updateMnemonicProperties();
1578
}
1579
1580
/**
1581
* This method is now obsolete, please use <code>setMnemonic(int)</code>
1582
* to set the mnemonic for a button. This method is only designed
1583
* to handle character values which fall between 'a' and 'z' or
1584
* 'A' and 'Z'.
1585
*
1586
* @param mnemonic a char specifying the mnemonic value
1587
* @see #setMnemonic(int)
1588
* @beaninfo
1589
* bound: true
1590
* attribute: visualUpdate true
1591
* description: the keyboard character mnemonic
1592
*/
1593
public void setMnemonic(char mnemonic) {
1594
int vk = (int) mnemonic;
1595
if(vk >= 'a' && vk <='z')
1596
vk -= ('a' - 'A');
1597
setMnemonic(vk);
1598
}
1599
1600
/**
1601
* Provides a hint to the look and feel as to which character in the
1602
* text should be decorated to represent the mnemonic. Not all look and
1603
* feels may support this. A value of -1 indicates either there is no
1604
* mnemonic, the mnemonic character is not contained in the string, or
1605
* the developer does not wish the mnemonic to be displayed.
1606
* <p>
1607
* The value of this is updated as the properties relating to the
1608
* mnemonic change (such as the mnemonic itself, the text...).
1609
* You should only ever have to call this if
1610
* you do not wish the default character to be underlined. For example, if
1611
* the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A'
1612
* to be decorated, as 'Save <u>A</u>s', you would have to invoke
1613
* <code>setDisplayedMnemonicIndex(5)</code> after invoking
1614
* <code>setMnemonic(KeyEvent.VK_A)</code>.
1615
*
1616
* @since 1.4
1617
* @param index Index into the String to underline
1618
* @exception IllegalArgumentException will be thrown if <code>index</code>
1619
* is &gt;= length of the text, or &lt; -1
1620
* @see #getDisplayedMnemonicIndex
1621
*
1622
* @beaninfo
1623
* bound: true
1624
* attribute: visualUpdate true
1625
* description: the index into the String to draw the keyboard character
1626
* mnemonic at
1627
*/
1628
public void setDisplayedMnemonicIndex(int index)
1629
throws IllegalArgumentException {
1630
int oldValue = mnemonicIndex;
1631
if (index == -1) {
1632
mnemonicIndex = -1;
1633
} else {
1634
String text = getText();
1635
int textLength = (text == null) ? 0 : text.length();
1636
if (index < -1 || index >= textLength) { // index out of range
1637
throw new IllegalArgumentException("index == " + index);
1638
}
1639
}
1640
mnemonicIndex = index;
1641
firePropertyChange("displayedMnemonicIndex", oldValue, index);
1642
if (index != oldValue) {
1643
revalidate();
1644
repaint();
1645
}
1646
}
1647
1648
/**
1649
* Returns the character, as an index, that the look and feel should
1650
* provide decoration for as representing the mnemonic character.
1651
*
1652
* @since 1.4
1653
* @return index representing mnemonic character
1654
* @see #setDisplayedMnemonicIndex
1655
*/
1656
public int getDisplayedMnemonicIndex() {
1657
return mnemonicIndex;
1658
}
1659
1660
/**
1661
* Update the displayedMnemonicIndex property. This method
1662
* is called when either text or mnemonic changes. The new
1663
* value of the displayedMnemonicIndex property is the index
1664
* of the first occurrence of mnemonic in text.
1665
*/
1666
private void updateDisplayedMnemonicIndex(String text, int mnemonic) {
1667
setDisplayedMnemonicIndex(
1668
SwingUtilities.findDisplayedMnemonicIndex(text, mnemonic));
1669
}
1670
1671
/**
1672
* Brings the mnemonic property in accordance with model's mnemonic.
1673
* This is called when model's mnemonic changes. Also updates the
1674
* displayedMnemonicIndex property.
1675
*/
1676
private void updateMnemonicProperties() {
1677
int newMnemonic = model.getMnemonic();
1678
if (mnemonic != newMnemonic) {
1679
int oldValue = mnemonic;
1680
mnemonic = newMnemonic;
1681
firePropertyChange(MNEMONIC_CHANGED_PROPERTY,
1682
oldValue, mnemonic);
1683
updateDisplayedMnemonicIndex(getText(), mnemonic);
1684
revalidate();
1685
repaint();
1686
}
1687
}
1688
1689
/**
1690
* Sets the amount of time (in milliseconds) required between
1691
* mouse press events for the button to generate the corresponding
1692
* action events. After the initial mouse press occurs (and action
1693
* event generated) any subsequent mouse press events which occur
1694
* on intervals less than the threshhold will be ignored and no
1695
* corresponding action event generated. By default the threshhold is 0,
1696
* which means that for each mouse press, an action event will be
1697
* fired, no matter how quickly the mouse clicks occur. In buttons
1698
* where this behavior is not desirable (for example, the "OK" button
1699
* in a dialog), this threshhold should be set to an appropriate
1700
* positive value.
1701
*
1702
* @see #getMultiClickThreshhold
1703
* @param threshhold the amount of time required between mouse
1704
* press events to generate corresponding action events
1705
* @exception IllegalArgumentException if threshhold &lt; 0
1706
* @since 1.4
1707
*/
1708
public void setMultiClickThreshhold(long threshhold) {
1709
if (threshhold < 0) {
1710
throw new IllegalArgumentException("threshhold must be >= 0");
1711
}
1712
this.multiClickThreshhold = threshhold;
1713
}
1714
1715
/**
1716
* Gets the amount of time (in milliseconds) required between
1717
* mouse press events for the button to generate the corresponding
1718
* action events.
1719
*
1720
* @see #setMultiClickThreshhold
1721
* @return the amount of time required between mouse press events
1722
* to generate corresponding action events
1723
* @since 1.4
1724
*/
1725
public long getMultiClickThreshhold() {
1726
return multiClickThreshhold;
1727
}
1728
1729
/**
1730
* Returns the model that this button represents.
1731
* @return the <code>model</code> property
1732
* @see #setModel
1733
*/
1734
public ButtonModel getModel() {
1735
return model;
1736
}
1737
1738
/**
1739
* Sets the model that this button represents.
1740
* @param newModel the new <code>ButtonModel</code>
1741
* @see #getModel
1742
* @beaninfo
1743
* bound: true
1744
* description: Model that the Button uses.
1745
*/
1746
public void setModel(ButtonModel newModel) {
1747
1748
ButtonModel oldModel = getModel();
1749
1750
if (oldModel != null) {
1751
oldModel.removeChangeListener(changeListener);
1752
oldModel.removeActionListener(actionListener);
1753
oldModel.removeItemListener(itemListener);
1754
changeListener = null;
1755
actionListener = null;
1756
itemListener = null;
1757
}
1758
1759
model = newModel;
1760
1761
if (newModel != null) {
1762
changeListener = createChangeListener();
1763
actionListener = createActionListener();
1764
itemListener = createItemListener();
1765
newModel.addChangeListener(changeListener);
1766
newModel.addActionListener(actionListener);
1767
newModel.addItemListener(itemListener);
1768
1769
updateMnemonicProperties();
1770
//We invoke setEnabled() from JComponent
1771
//because setModel() can be called from a constructor
1772
//when the button is not fully initialized
1773
super.setEnabled(newModel.isEnabled());
1774
1775
} else {
1776
mnemonic = '\0';
1777
}
1778
1779
updateDisplayedMnemonicIndex(getText(), mnemonic);
1780
1781
firePropertyChange(MODEL_CHANGED_PROPERTY, oldModel, newModel);
1782
if (newModel != oldModel) {
1783
revalidate();
1784
repaint();
1785
}
1786
}
1787
1788
1789
/**
1790
* Returns the L&amp;F object that renders this component.
1791
* @return the ButtonUI object
1792
* @see #setUI
1793
*/
1794
public ButtonUI getUI() {
1795
return (ButtonUI) ui;
1796
}
1797
1798
1799
/**
1800
* Sets the L&amp;F object that renders this component.
1801
* @param ui the <code>ButtonUI</code> L&amp;F object
1802
* @see #getUI
1803
* @beaninfo
1804
* bound: true
1805
* hidden: true
1806
* attribute: visualUpdate true
1807
* description: The UI object that implements the LookAndFeel.
1808
*/
1809
public void setUI(ButtonUI ui) {
1810
super.setUI(ui);
1811
// disabled icons are generated by the LF so they should be unset here
1812
if (disabledIcon instanceof UIResource) {
1813
setDisabledIcon(null);
1814
}
1815
if (disabledSelectedIcon instanceof UIResource) {
1816
setDisabledSelectedIcon(null);
1817
}
1818
}
1819
1820
1821
/**
1822
* Resets the UI property to a value from the current look
1823
* and feel. Subtypes of <code>AbstractButton</code>
1824
* should override this to update the UI. For
1825
* example, <code>JButton</code> might do the following:
1826
* <pre>
1827
* setUI((ButtonUI)UIManager.getUI(
1828
* "ButtonUI", "javax.swing.plaf.basic.BasicButtonUI", this));
1829
* </pre>
1830
*/
1831
public void updateUI() {
1832
}
1833
1834
/**
1835
* Adds the specified component to this container at the specified
1836
* index, refer to
1837
* {@link java.awt.Container#addImpl(Component, Object, int)}
1838
* for a complete description of this method.
1839
*
1840
* @param comp the component to be added
1841
* @param constraints an object expressing layout constraints
1842
* for this component
1843
* @param index the position in the container's list at which to
1844
* insert the component, where <code>-1</code>
1845
* means append to the end
1846
* @exception IllegalArgumentException if <code>index</code> is invalid
1847
* @exception IllegalArgumentException if adding the container's parent
1848
* to itself
1849
* @exception IllegalArgumentException if adding a window to a container
1850
* @since 1.5
1851
*/
1852
protected void addImpl(Component comp, Object constraints, int index) {
1853
if (!setLayout) {
1854
setLayout(new OverlayLayout(this));
1855
}
1856
super.addImpl(comp, constraints, index);
1857
}
1858
1859
/**
1860
* Sets the layout manager for this container, refer to
1861
* {@link java.awt.Container#setLayout(LayoutManager)}
1862
* for a complete description of this method.
1863
*
1864
* @param mgr the specified layout manager
1865
* @since 1.5
1866
*/
1867
public void setLayout(LayoutManager mgr) {
1868
setLayout = true;
1869
super.setLayout(mgr);
1870
}
1871
1872
/**
1873
* Adds a <code>ChangeListener</code> to the button.
1874
* @param l the listener to be added
1875
*/
1876
public void addChangeListener(ChangeListener l) {
1877
listenerList.add(ChangeListener.class, l);
1878
}
1879
1880
/**
1881
* Removes a ChangeListener from the button.
1882
* @param l the listener to be removed
1883
*/
1884
public void removeChangeListener(ChangeListener l) {
1885
listenerList.remove(ChangeListener.class, l);
1886
}
1887
1888
/**
1889
* Returns an array of all the <code>ChangeListener</code>s added
1890
* to this AbstractButton with addChangeListener().
1891
*
1892
* @return all of the <code>ChangeListener</code>s added or an empty
1893
* array if no listeners have been added
1894
* @since 1.4
1895
*/
1896
public ChangeListener[] getChangeListeners() {
1897
return listenerList.getListeners(ChangeListener.class);
1898
}
1899
1900
/**
1901
* Notifies all listeners that have registered interest for
1902
* notification on this event type. The event instance
1903
* is lazily created.
1904
* @see EventListenerList
1905
*/
1906
protected void fireStateChanged() {
1907
// Guaranteed to return a non-null array
1908
Object[] listeners = listenerList.getListenerList();
1909
// Process the listeners last to first, notifying
1910
// those that are interested in this event
1911
for (int i = listeners.length-2; i>=0; i-=2) {
1912
if (listeners[i]==ChangeListener.class) {
1913
// Lazily create the event:
1914
if (changeEvent == null)
1915
changeEvent = new ChangeEvent(this);
1916
((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
1917
}
1918
}
1919
}
1920
1921
/**
1922
* Adds an <code>ActionListener</code> to the button.
1923
* @param l the <code>ActionListener</code> to be added
1924
*/
1925
public void addActionListener(ActionListener l) {
1926
listenerList.add(ActionListener.class, l);
1927
}
1928
1929
/**
1930
* Removes an <code>ActionListener</code> from the button.
1931
* If the listener is the currently set <code>Action</code>
1932
* for the button, then the <code>Action</code>
1933
* is set to <code>null</code>.
1934
*
1935
* @param l the listener to be removed
1936
*/
1937
public void removeActionListener(ActionListener l) {
1938
if ((l != null) && (getAction() == l)) {
1939
setAction(null);
1940
} else {
1941
listenerList.remove(ActionListener.class, l);
1942
}
1943
}
1944
1945
/**
1946
* Returns an array of all the <code>ActionListener</code>s added
1947
* to this AbstractButton with addActionListener().
1948
*
1949
* @return all of the <code>ActionListener</code>s added or an empty
1950
* array if no listeners have been added
1951
* @since 1.4
1952
*/
1953
public ActionListener[] getActionListeners() {
1954
return listenerList.getListeners(ActionListener.class);
1955
}
1956
1957
/**
1958
* Subclasses that want to handle <code>ChangeEvents</code> differently
1959
* can override this to return another <code>ChangeListener</code>
1960
* implementation.
1961
*
1962
* @return the new <code>ChangeListener</code>
1963
*/
1964
protected ChangeListener createChangeListener() {
1965
return getHandler();
1966
}
1967
1968
/**
1969
* Extends <code>ChangeListener</code> to be serializable.
1970
* <p>
1971
* <strong>Warning:</strong>
1972
* Serialized objects of this class will not be compatible with
1973
* future Swing releases. The current serialization support is
1974
* appropriate for short term storage or RMI between applications running
1975
* the same version of Swing. As of 1.4, support for long term storage
1976
* of all JavaBeans&trade;
1977
* has been added to the <code>java.beans</code> package.
1978
* Please see {@link java.beans.XMLEncoder}.
1979
*/
1980
@SuppressWarnings("serial")
1981
protected class ButtonChangeListener implements ChangeListener, Serializable {
1982
// NOTE: This class is NOT used, instead the functionality has
1983
// been moved to Handler.
1984
ButtonChangeListener() {
1985
}
1986
1987
public void stateChanged(ChangeEvent e) {
1988
getHandler().stateChanged(e);
1989
}
1990
}
1991
1992
1993
/**
1994
* Notifies all listeners that have registered interest for
1995
* notification on this event type. The event instance
1996
* is lazily created using the <code>event</code>
1997
* parameter.
1998
*
1999
* @param event the <code>ActionEvent</code> object
2000
* @see EventListenerList
2001
*/
2002
protected void fireActionPerformed(ActionEvent event) {
2003
// Guaranteed to return a non-null array
2004
Object[] listeners = listenerList.getListenerList();
2005
ActionEvent e = null;
2006
// Process the listeners last to first, notifying
2007
// those that are interested in this event
2008
for (int i = listeners.length-2; i>=0; i-=2) {
2009
if (listeners[i]==ActionListener.class) {
2010
// Lazily create the event:
2011
if (e == null) {
2012
String actionCommand = event.getActionCommand();
2013
if(actionCommand == null) {
2014
actionCommand = getActionCommand();
2015
}
2016
e = new ActionEvent(AbstractButton.this,
2017
ActionEvent.ACTION_PERFORMED,
2018
actionCommand,
2019
event.getWhen(),
2020
event.getModifiers());
2021
}
2022
((ActionListener)listeners[i+1]).actionPerformed(e);
2023
}
2024
}
2025
}
2026
2027
/**
2028
* Notifies all listeners that have registered interest for
2029
* notification on this event type. The event instance
2030
* is lazily created using the <code>event</code> parameter.
2031
*
2032
* @param event the <code>ItemEvent</code> object
2033
* @see EventListenerList
2034
*/
2035
protected void fireItemStateChanged(ItemEvent event) {
2036
// Guaranteed to return a non-null array
2037
Object[] listeners = listenerList.getListenerList();
2038
ItemEvent e = null;
2039
// Process the listeners last to first, notifying
2040
// those that are interested in this event
2041
for (int i = listeners.length-2; i>=0; i-=2) {
2042
if (listeners[i]==ItemListener.class) {
2043
// Lazily create the event:
2044
if (e == null) {
2045
e = new ItemEvent(AbstractButton.this,
2046
ItemEvent.ITEM_STATE_CHANGED,
2047
AbstractButton.this,
2048
event.getStateChange());
2049
}
2050
((ItemListener)listeners[i+1]).itemStateChanged(e);
2051
}
2052
}
2053
if (accessibleContext != null) {
2054
if (event.getStateChange() == ItemEvent.SELECTED) {
2055
accessibleContext.firePropertyChange(
2056
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2057
null, AccessibleState.SELECTED);
2058
accessibleContext.firePropertyChange(
2059
AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
2060
Integer.valueOf(0), Integer.valueOf(1));
2061
} else {
2062
accessibleContext.firePropertyChange(
2063
AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2064
AccessibleState.SELECTED, null);
2065
accessibleContext.firePropertyChange(
2066
AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
2067
Integer.valueOf(1), Integer.valueOf(0));
2068
}
2069
}
2070
}
2071
2072
2073
protected ActionListener createActionListener() {
2074
return getHandler();
2075
}
2076
2077
2078
protected ItemListener createItemListener() {
2079
return getHandler();
2080
}
2081
2082
2083
/**
2084
* Enables (or disables) the button.
2085
* @param b true to enable the button, otherwise false
2086
*/
2087
public void setEnabled(boolean b) {
2088
if (!b && model.isRollover()) {
2089
model.setRollover(false);
2090
}
2091
super.setEnabled(b);
2092
model.setEnabled(b);
2093
}
2094
2095
// *** Deprecated java.awt.Button APIs below *** //
2096
2097
/**
2098
* Returns the label text.
2099
*
2100
* @return a <code>String</code> containing the label
2101
* @deprecated - Replaced by <code>getText</code>
2102
*/
2103
@Deprecated
2104
public String getLabel() {
2105
return getText();
2106
}
2107
2108
/**
2109
* Sets the label text.
2110
*
2111
* @param label a <code>String</code> containing the text
2112
* @deprecated - Replaced by <code>setText(text)</code>
2113
* @beaninfo
2114
* bound: true
2115
* description: Replace by setText(text)
2116
*/
2117
@Deprecated
2118
public void setLabel(String label) {
2119
setText(label);
2120
}
2121
2122
/**
2123
* Adds an <code>ItemListener</code> to the <code>checkbox</code>.
2124
* @param l the <code>ItemListener</code> to be added
2125
*/
2126
public void addItemListener(ItemListener l) {
2127
listenerList.add(ItemListener.class, l);
2128
}
2129
2130
/**
2131
* Removes an <code>ItemListener</code> from the button.
2132
* @param l the <code>ItemListener</code> to be removed
2133
*/
2134
public void removeItemListener(ItemListener l) {
2135
listenerList.remove(ItemListener.class, l);
2136
}
2137
2138
/**
2139
* Returns an array of all the <code>ItemListener</code>s added
2140
* to this AbstractButton with addItemListener().
2141
*
2142
* @return all of the <code>ItemListener</code>s added or an empty
2143
* array if no listeners have been added
2144
* @since 1.4
2145
*/
2146
public ItemListener[] getItemListeners() {
2147
return listenerList.getListeners(ItemListener.class);
2148
}
2149
2150
/**
2151
* Returns an array (length 1) containing the label or
2152
* <code>null</code> if the button is not selected.
2153
*
2154
* @return an array containing 1 Object: the text of the button,
2155
* if the item is selected; otherwise <code>null</code>
2156
*/
2157
public Object[] getSelectedObjects() {
2158
if (isSelected() == false) {
2159
return null;
2160
}
2161
Object[] selectedObjects = new Object[1];
2162
selectedObjects[0] = getText();
2163
return selectedObjects;
2164
}
2165
2166
protected void init(String text, Icon icon) {
2167
if(text != null) {
2168
setText(text);
2169
}
2170
2171
if(icon != null) {
2172
setIcon(icon);
2173
}
2174
2175
// Set the UI
2176
updateUI();
2177
2178
setAlignmentX(LEFT_ALIGNMENT);
2179
setAlignmentY(CENTER_ALIGNMENT);
2180
}
2181
2182
2183
/**
2184
* This is overridden to return false if the current <code>Icon</code>'s
2185
* <code>Image</code> is not equal to the
2186
* passed in <code>Image</code> <code>img</code>.
2187
*
2188
* @param img the <code>Image</code> to be compared
2189
* @param infoflags flags used to repaint the button when the image
2190
* is updated and which determine how much is to be painted
2191
* @param x the x coordinate
2192
* @param y the y coordinate
2193
* @param w the width
2194
* @param h the height
2195
* @see java.awt.image.ImageObserver
2196
* @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int)
2197
*/
2198
public boolean imageUpdate(Image img, int infoflags,
2199
int x, int y, int w, int h) {
2200
Icon iconDisplayed = null;
2201
2202
if (!model.isEnabled()) {
2203
if (model.isSelected()) {
2204
iconDisplayed = getDisabledSelectedIcon();
2205
} else {
2206
iconDisplayed = getDisabledIcon();
2207
}
2208
} else if (model.isPressed() && model.isArmed()) {
2209
iconDisplayed = getPressedIcon();
2210
} else if (isRolloverEnabled() && model.isRollover()) {
2211
if (model.isSelected()) {
2212
iconDisplayed = getRolloverSelectedIcon();
2213
} else {
2214
iconDisplayed = getRolloverIcon();
2215
}
2216
} else if (model.isSelected()) {
2217
iconDisplayed = getSelectedIcon();
2218
}
2219
2220
if (iconDisplayed == null) {
2221
iconDisplayed = getIcon();
2222
}
2223
2224
if (iconDisplayed == null
2225
|| !SwingUtilities.doesIconReferenceImage(iconDisplayed, img)) {
2226
// We don't know about this image, disable the notification so
2227
// we don't keep repainting.
2228
return false;
2229
}
2230
return super.imageUpdate(img, infoflags, x, y, w, h);
2231
}
2232
2233
void setUIProperty(String propertyName, Object value) {
2234
if (propertyName == "borderPainted") {
2235
if (!borderPaintedSet) {
2236
setBorderPainted(((Boolean)value).booleanValue());
2237
borderPaintedSet = false;
2238
}
2239
} else if (propertyName == "rolloverEnabled") {
2240
if (!rolloverEnabledSet) {
2241
setRolloverEnabled(((Boolean)value).booleanValue());
2242
rolloverEnabledSet = false;
2243
}
2244
} else if (propertyName == "iconTextGap") {
2245
if (!iconTextGapSet) {
2246
setIconTextGap(((Number)value).intValue());
2247
iconTextGapSet = false;
2248
}
2249
} else if (propertyName == "contentAreaFilled") {
2250
if (!contentAreaFilledSet) {
2251
setContentAreaFilled(((Boolean)value).booleanValue());
2252
contentAreaFilledSet = false;
2253
}
2254
} else {
2255
super.setUIProperty(propertyName, value);
2256
}
2257
}
2258
2259
/**
2260
* Returns a string representation of this <code>AbstractButton</code>.
2261
* This method
2262
* is intended to be used only for debugging purposes, and the
2263
* content and format of the returned string may vary between
2264
* implementations. The returned string may be empty but may not
2265
* be <code>null</code>.
2266
* <P>
2267
* Overriding <code>paramString</code> to provide information about the
2268
* specific new aspects of the JFC components.
2269
*
2270
* @return a string representation of this <code>AbstractButton</code>
2271
*/
2272
protected String paramString() {
2273
String defaultIconString = ((defaultIcon != null)
2274
&& (defaultIcon != this) ?
2275
defaultIcon.toString() : "");
2276
String pressedIconString = ((pressedIcon != null)
2277
&& (pressedIcon != this) ?
2278
pressedIcon.toString() : "");
2279
String disabledIconString = ((disabledIcon != null)
2280
&& (disabledIcon != this) ?
2281
disabledIcon.toString() : "");
2282
String selectedIconString = ((selectedIcon != null)
2283
&& (selectedIcon != this) ?
2284
selectedIcon.toString() : "");
2285
String disabledSelectedIconString = ((disabledSelectedIcon != null) &&
2286
(disabledSelectedIcon != this) ?
2287
disabledSelectedIcon.toString()
2288
: "");
2289
String rolloverIconString = ((rolloverIcon != null)
2290
&& (rolloverIcon != this) ?
2291
rolloverIcon.toString() : "");
2292
String rolloverSelectedIconString = ((rolloverSelectedIcon != null) &&
2293
(rolloverSelectedIcon != this) ?
2294
rolloverSelectedIcon.toString()
2295
: "");
2296
String paintBorderString = (paintBorder ? "true" : "false");
2297
String paintFocusString = (paintFocus ? "true" : "false");
2298
String rolloverEnabledString = (rolloverEnabled ? "true" : "false");
2299
2300
return super.paramString() +
2301
",defaultIcon=" + defaultIconString +
2302
",disabledIcon=" + disabledIconString +
2303
",disabledSelectedIcon=" + disabledSelectedIconString +
2304
",margin=" + margin +
2305
",paintBorder=" + paintBorderString +
2306
",paintFocus=" + paintFocusString +
2307
",pressedIcon=" + pressedIconString +
2308
",rolloverEnabled=" + rolloverEnabledString +
2309
",rolloverIcon=" + rolloverIconString +
2310
",rolloverSelectedIcon=" + rolloverSelectedIconString +
2311
",selectedIcon=" + selectedIconString +
2312
",text=" + text;
2313
}
2314
2315
2316
private Handler getHandler() {
2317
if (handler == null) {
2318
handler = new Handler();
2319
}
2320
return handler;
2321
}
2322
2323
2324
//
2325
// Listeners that are added to model
2326
//
2327
@SuppressWarnings("serial")
2328
class Handler implements ActionListener, ChangeListener, ItemListener,
2329
Serializable {
2330
//
2331
// ChangeListener
2332
//
2333
public void stateChanged(ChangeEvent e) {
2334
Object source = e.getSource();
2335
2336
updateMnemonicProperties();
2337
if (isEnabled() != model.isEnabled()) {
2338
setEnabled(model.isEnabled());
2339
}
2340
fireStateChanged();
2341
repaint();
2342
}
2343
2344
//
2345
// ActionListener
2346
//
2347
public void actionPerformed(ActionEvent event) {
2348
fireActionPerformed(event);
2349
}
2350
2351
//
2352
// ItemListener
2353
//
2354
public void itemStateChanged(ItemEvent event) {
2355
fireItemStateChanged(event);
2356
if (shouldUpdateSelectedStateFromAction()) {
2357
Action action = getAction();
2358
if (action != null && AbstractAction.hasSelectedKey(action)) {
2359
boolean selected = isSelected();
2360
boolean isActionSelected = AbstractAction.isSelected(
2361
action);
2362
if (isActionSelected != selected) {
2363
action.putValue(Action.SELECTED_KEY, selected);
2364
}
2365
}
2366
}
2367
}
2368
}
2369
2370
///////////////////
2371
// Accessibility support
2372
///////////////////
2373
/**
2374
* This class implements accessibility support for the
2375
* <code>AbstractButton</code> class. It provides an implementation of the
2376
* Java Accessibility API appropriate to button and menu item
2377
* user-interface elements.
2378
* <p>
2379
* <strong>Warning:</strong>
2380
* Serialized objects of this class will not be compatible with
2381
* future Swing releases. The current serialization support is
2382
* appropriate for short term storage or RMI between applications running
2383
* the same version of Swing. As of 1.4, support for long term storage
2384
* of all JavaBeans&trade;
2385
* has been added to the <code>java.beans</code> package.
2386
* Please see {@link java.beans.XMLEncoder}.
2387
* @since 1.4
2388
*/
2389
protected abstract class AccessibleAbstractButton
2390
extends AccessibleJComponent implements AccessibleAction,
2391
AccessibleValue, AccessibleText, AccessibleExtendedComponent {
2392
2393
/**
2394
* Returns the accessible name of this object.
2395
*
2396
* @return the localized name of the object -- can be
2397
* <code>null</code> if this
2398
* object does not have a name
2399
*/
2400
public String getAccessibleName() {
2401
String name = accessibleName;
2402
2403
if (name == null) {
2404
name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
2405
}
2406
if (name == null) {
2407
name = AbstractButton.this.getText();
2408
}
2409
if (name == null) {
2410
name = super.getAccessibleName();
2411
}
2412
return name;
2413
}
2414
2415
/**
2416
* Get the AccessibleIcons associated with this object if one
2417
* or more exist. Otherwise return null.
2418
* @since 1.3
2419
*/
2420
public AccessibleIcon [] getAccessibleIcon() {
2421
Icon defaultIcon = getIcon();
2422
2423
if (defaultIcon instanceof Accessible) {
2424
AccessibleContext ac =
2425
((Accessible)defaultIcon).getAccessibleContext();
2426
if (ac != null && ac instanceof AccessibleIcon) {
2427
return new AccessibleIcon[] { (AccessibleIcon)ac };
2428
}
2429
}
2430
return null;
2431
}
2432
2433
/**
2434
* Get the state set of this object.
2435
*
2436
* @return an instance of AccessibleState containing the current state
2437
* of the object
2438
* @see AccessibleState
2439
*/
2440
public AccessibleStateSet getAccessibleStateSet() {
2441
AccessibleStateSet states = super.getAccessibleStateSet();
2442
if (getModel().isArmed()) {
2443
states.add(AccessibleState.ARMED);
2444
}
2445
if (isFocusOwner()) {
2446
states.add(AccessibleState.FOCUSED);
2447
}
2448
if (getModel().isPressed()) {
2449
states.add(AccessibleState.PRESSED);
2450
}
2451
if (isSelected()) {
2452
states.add(AccessibleState.CHECKED);
2453
}
2454
return states;
2455
}
2456
2457
/**
2458
* Get the AccessibleRelationSet associated with this object if one
2459
* exists. Otherwise return null.
2460
* @see AccessibleRelation
2461
* @since 1.3
2462
*/
2463
public AccessibleRelationSet getAccessibleRelationSet() {
2464
2465
// Check where the AccessibleContext's relation
2466
// set already contains a MEMBER_OF relation.
2467
AccessibleRelationSet relationSet
2468
= super.getAccessibleRelationSet();
2469
2470
if (!relationSet.contains(AccessibleRelation.MEMBER_OF)) {
2471
// get the members of the button group if one exists
2472
ButtonModel model = getModel();
2473
if (model != null && model instanceof DefaultButtonModel) {
2474
ButtonGroup group = ((DefaultButtonModel)model).getGroup();
2475
if (group != null) {
2476
// set the target of the MEMBER_OF relation to be
2477
// the members of the button group.
2478
int len = group.getButtonCount();
2479
Object [] target = new Object[len];
2480
Enumeration<AbstractButton> elem = group.getElements();
2481
for (int i = 0; i < len; i++) {
2482
if (elem.hasMoreElements()) {
2483
target[i] = elem.nextElement();
2484
}
2485
}
2486
AccessibleRelation relation =
2487
new AccessibleRelation(AccessibleRelation.MEMBER_OF);
2488
relation.setTarget(target);
2489
relationSet.add(relation);
2490
}
2491
}
2492
}
2493
return relationSet;
2494
}
2495
2496
/**
2497
* Get the AccessibleAction associated with this object. In the
2498
* implementation of the Java Accessibility API for this class,
2499
* return this object, which is responsible for implementing the
2500
* AccessibleAction interface on behalf of itself.
2501
*
2502
* @return this object
2503
*/
2504
public AccessibleAction getAccessibleAction() {
2505
return this;
2506
}
2507
2508
/**
2509
* Get the AccessibleValue associated with this object. In the
2510
* implementation of the Java Accessibility API for this class,
2511
* return this object, which is responsible for implementing the
2512
* AccessibleValue interface on behalf of itself.
2513
*
2514
* @return this object
2515
*/
2516
public AccessibleValue getAccessibleValue() {
2517
return this;
2518
}
2519
2520
/**
2521
* Returns the number of Actions available in this object. The
2522
* default behavior of a button is to have one action - toggle
2523
* the button.
2524
*
2525
* @return 1, the number of Actions in this object
2526
*/
2527
public int getAccessibleActionCount() {
2528
return 1;
2529
}
2530
2531
/**
2532
* Return a description of the specified action of the object.
2533
*
2534
* @param i zero-based index of the actions
2535
*/
2536
public String getAccessibleActionDescription(int i) {
2537
if (i == 0) {
2538
return UIManager.getString("AbstractButton.clickText");
2539
} else {
2540
return null;
2541
}
2542
}
2543
2544
/**
2545
* Perform the specified Action on the object
2546
*
2547
* @param i zero-based index of actions
2548
* @return true if the the action was performed; else false.
2549
*/
2550
public boolean doAccessibleAction(int i) {
2551
if (i == 0) {
2552
doClick();
2553
return true;
2554
} else {
2555
return false;
2556
}
2557
}
2558
2559
/**
2560
* Get the value of this object as a Number.
2561
*
2562
* @return An Integer of 0 if this isn't selected or an Integer of 1 if
2563
* this is selected.
2564
* @see AbstractButton#isSelected
2565
*/
2566
public Number getCurrentAccessibleValue() {
2567
if (isSelected()) {
2568
return Integer.valueOf(1);
2569
} else {
2570
return Integer.valueOf(0);
2571
}
2572
}
2573
2574
/**
2575
* Set the value of this object as a Number.
2576
*
2577
* @return True if the value was set.
2578
*/
2579
public boolean setCurrentAccessibleValue(Number n) {
2580
// TIGER - 4422535
2581
if (n == null) {
2582
return false;
2583
}
2584
int i = n.intValue();
2585
if (i == 0) {
2586
setSelected(false);
2587
} else {
2588
setSelected(true);
2589
}
2590
return true;
2591
}
2592
2593
/**
2594
* Get the minimum value of this object as a Number.
2595
*
2596
* @return an Integer of 0.
2597
*/
2598
public Number getMinimumAccessibleValue() {
2599
return Integer.valueOf(0);
2600
}
2601
2602
/**
2603
* Get the maximum value of this object as a Number.
2604
*
2605
* @return An Integer of 1.
2606
*/
2607
public Number getMaximumAccessibleValue() {
2608
return Integer.valueOf(1);
2609
}
2610
2611
2612
/* AccessibleText ---------- */
2613
2614
public AccessibleText getAccessibleText() {
2615
View view = (View)AbstractButton.this.getClientProperty("html");
2616
if (view != null) {
2617
return this;
2618
} else {
2619
return null;
2620
}
2621
}
2622
2623
/**
2624
* Given a point in local coordinates, return the zero-based index
2625
* of the character under that Point. If the point is invalid,
2626
* this method returns -1.
2627
*
2628
* Note: the AbstractButton must have a valid size (e.g. have
2629
* been added to a parent container whose ancestor container
2630
* is a valid top-level window) for this method to be able
2631
* to return a meaningful value.
2632
*
2633
* @param p the Point in local coordinates
2634
* @return the zero-based index of the character under Point p; if
2635
* Point is invalid returns -1.
2636
* @since 1.3
2637
*/
2638
public int getIndexAtPoint(Point p) {
2639
View view = (View) AbstractButton.this.getClientProperty("html");
2640
if (view != null) {
2641
Rectangle r = getTextRectangle();
2642
if (r == null) {
2643
return -1;
2644
}
2645
Rectangle2D.Float shape =
2646
new Rectangle2D.Float(r.x, r.y, r.width, r.height);
2647
Position.Bias bias[] = new Position.Bias[1];
2648
return view.viewToModel(p.x, p.y, shape, bias);
2649
} else {
2650
return -1;
2651
}
2652
}
2653
2654
/**
2655
* Determine the bounding box of the character at the given
2656
* index into the string. The bounds are returned in local
2657
* coordinates. If the index is invalid an empty rectangle is
2658
* returned.
2659
*
2660
* Note: the AbstractButton must have a valid size (e.g. have
2661
* been added to a parent container whose ancestor container
2662
* is a valid top-level window) for this method to be able
2663
* to return a meaningful value.
2664
*
2665
* @param i the index into the String
2666
* @return the screen coordinates of the character's the bounding box,
2667
* if index is invalid returns an empty rectangle.
2668
* @since 1.3
2669
*/
2670
public Rectangle getCharacterBounds(int i) {
2671
View view = (View) AbstractButton.this.getClientProperty("html");
2672
if (view != null) {
2673
Rectangle r = getTextRectangle();
2674
if (r == null) {
2675
return null;
2676
}
2677
Rectangle2D.Float shape =
2678
new Rectangle2D.Float(r.x, r.y, r.width, r.height);
2679
try {
2680
Shape charShape =
2681
view.modelToView(i, shape, Position.Bias.Forward);
2682
return charShape.getBounds();
2683
} catch (BadLocationException e) {
2684
return null;
2685
}
2686
} else {
2687
return null;
2688
}
2689
}
2690
2691
/**
2692
* Return the number of characters (valid indicies)
2693
*
2694
* @return the number of characters
2695
* @since 1.3
2696
*/
2697
public int getCharCount() {
2698
View view = (View) AbstractButton.this.getClientProperty("html");
2699
if (view != null) {
2700
Document d = view.getDocument();
2701
if (d instanceof StyledDocument) {
2702
StyledDocument doc = (StyledDocument)d;
2703
return doc.getLength();
2704
}
2705
}
2706
return accessibleContext.getAccessibleName().length();
2707
}
2708
2709
/**
2710
* Return the zero-based offset of the caret.
2711
*
2712
* Note: That to the right of the caret will have the same index
2713
* value as the offset (the caret is between two characters).
2714
* @return the zero-based offset of the caret.
2715
* @since 1.3
2716
*/
2717
public int getCaretPosition() {
2718
// There is no caret.
2719
return -1;
2720
}
2721
2722
/**
2723
* Returns the String at a given index.
2724
*
2725
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2726
* or AccessibleText.SENTENCE to retrieve
2727
* @param index an index within the text &gt;= 0
2728
* @return the letter, word, or sentence,
2729
* null for an invalid index or part
2730
* @since 1.3
2731
*/
2732
public String getAtIndex(int part, int index) {
2733
if (index < 0 || index >= getCharCount()) {
2734
return null;
2735
}
2736
switch (part) {
2737
case AccessibleText.CHARACTER:
2738
try {
2739
return getText(index, 1);
2740
} catch (BadLocationException e) {
2741
return null;
2742
}
2743
case AccessibleText.WORD:
2744
try {
2745
String s = getText(0, getCharCount());
2746
BreakIterator words = BreakIterator.getWordInstance(getLocale());
2747
words.setText(s);
2748
int end = words.following(index);
2749
return s.substring(words.previous(), end);
2750
} catch (BadLocationException e) {
2751
return null;
2752
}
2753
case AccessibleText.SENTENCE:
2754
try {
2755
String s = getText(0, getCharCount());
2756
BreakIterator sentence =
2757
BreakIterator.getSentenceInstance(getLocale());
2758
sentence.setText(s);
2759
int end = sentence.following(index);
2760
return s.substring(sentence.previous(), end);
2761
} catch (BadLocationException e) {
2762
return null;
2763
}
2764
default:
2765
return null;
2766
}
2767
}
2768
2769
/**
2770
* Returns the String after a given index.
2771
*
2772
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2773
* or AccessibleText.SENTENCE to retrieve
2774
* @param index an index within the text &gt;= 0
2775
* @return the letter, word, or sentence, null for an invalid
2776
* index or part
2777
* @since 1.3
2778
*/
2779
public String getAfterIndex(int part, int index) {
2780
if (index < 0 || index >= getCharCount()) {
2781
return null;
2782
}
2783
switch (part) {
2784
case AccessibleText.CHARACTER:
2785
if (index+1 >= getCharCount()) {
2786
return null;
2787
}
2788
try {
2789
return getText(index+1, 1);
2790
} catch (BadLocationException e) {
2791
return null;
2792
}
2793
case AccessibleText.WORD:
2794
try {
2795
String s = getText(0, getCharCount());
2796
BreakIterator words = BreakIterator.getWordInstance(getLocale());
2797
words.setText(s);
2798
int start = words.following(index);
2799
if (start == BreakIterator.DONE || start >= s.length()) {
2800
return null;
2801
}
2802
int end = words.following(start);
2803
if (end == BreakIterator.DONE || end >= s.length()) {
2804
return null;
2805
}
2806
return s.substring(start, end);
2807
} catch (BadLocationException e) {
2808
return null;
2809
}
2810
case AccessibleText.SENTENCE:
2811
try {
2812
String s = getText(0, getCharCount());
2813
BreakIterator sentence =
2814
BreakIterator.getSentenceInstance(getLocale());
2815
sentence.setText(s);
2816
int start = sentence.following(index);
2817
if (start == BreakIterator.DONE || start > s.length()) {
2818
return null;
2819
}
2820
int end = sentence.following(start);
2821
if (end == BreakIterator.DONE || end > s.length()) {
2822
return null;
2823
}
2824
return s.substring(start, end);
2825
} catch (BadLocationException e) {
2826
return null;
2827
}
2828
default:
2829
return null;
2830
}
2831
}
2832
2833
/**
2834
* Returns the String before a given index.
2835
*
2836
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2837
* or AccessibleText.SENTENCE to retrieve
2838
* @param index an index within the text &gt;= 0
2839
* @return the letter, word, or sentence, null for an invalid index
2840
* or part
2841
* @since 1.3
2842
*/
2843
public String getBeforeIndex(int part, int index) {
2844
if (index < 0 || index > getCharCount()-1) {
2845
return null;
2846
}
2847
switch (part) {
2848
case AccessibleText.CHARACTER:
2849
if (index == 0) {
2850
return null;
2851
}
2852
try {
2853
return getText(index-1, 1);
2854
} catch (BadLocationException e) {
2855
return null;
2856
}
2857
case AccessibleText.WORD:
2858
try {
2859
String s = getText(0, getCharCount());
2860
BreakIterator words = BreakIterator.getWordInstance(getLocale());
2861
words.setText(s);
2862
int end = words.following(index);
2863
end = words.previous();
2864
int start = words.previous();
2865
if (start == BreakIterator.DONE) {
2866
return null;
2867
}
2868
return s.substring(start, end);
2869
} catch (BadLocationException e) {
2870
return null;
2871
}
2872
case AccessibleText.SENTENCE:
2873
try {
2874
String s = getText(0, getCharCount());
2875
BreakIterator sentence =
2876
BreakIterator.getSentenceInstance(getLocale());
2877
sentence.setText(s);
2878
int end = sentence.following(index);
2879
end = sentence.previous();
2880
int start = sentence.previous();
2881
if (start == BreakIterator.DONE) {
2882
return null;
2883
}
2884
return s.substring(start, end);
2885
} catch (BadLocationException e) {
2886
return null;
2887
}
2888
default:
2889
return null;
2890
}
2891
}
2892
2893
/**
2894
* Return the AttributeSet for a given character at a given index
2895
*
2896
* @param i the zero-based index into the text
2897
* @return the AttributeSet of the character
2898
* @since 1.3
2899
*/
2900
public AttributeSet getCharacterAttribute(int i) {
2901
View view = (View) AbstractButton.this.getClientProperty("html");
2902
if (view != null) {
2903
Document d = view.getDocument();
2904
if (d instanceof StyledDocument) {
2905
StyledDocument doc = (StyledDocument)d;
2906
Element elem = doc.getCharacterElement(i);
2907
if (elem != null) {
2908
return elem.getAttributes();
2909
}
2910
}
2911
}
2912
return null;
2913
}
2914
2915
/**
2916
* Returns the start offset within the selected text.
2917
* If there is no selection, but there is
2918
* a caret, the start and end offsets will be the same.
2919
*
2920
* @return the index into the text of the start of the selection
2921
* @since 1.3
2922
*/
2923
public int getSelectionStart() {
2924
// Text cannot be selected.
2925
return -1;
2926
}
2927
2928
/**
2929
* Returns the end offset within the selected text.
2930
* If there is no selection, but there is
2931
* a caret, the start and end offsets will be the same.
2932
*
2933
* @return the index into the text of the end of the selection
2934
* @since 1.3
2935
*/
2936
public int getSelectionEnd() {
2937
// Text cannot be selected.
2938
return -1;
2939
}
2940
2941
/**
2942
* Returns the portion of the text that is selected.
2943
*
2944
* @return the String portion of the text that is selected
2945
* @since 1.3
2946
*/
2947
public String getSelectedText() {
2948
// Text cannot be selected.
2949
return null;
2950
}
2951
2952
/*
2953
* Returns the text substring starting at the specified
2954
* offset with the specified length.
2955
*/
2956
private String getText(int offset, int length)
2957
throws BadLocationException {
2958
2959
View view = (View) AbstractButton.this.getClientProperty("html");
2960
if (view != null) {
2961
Document d = view.getDocument();
2962
if (d instanceof StyledDocument) {
2963
StyledDocument doc = (StyledDocument)d;
2964
return doc.getText(offset, length);
2965
}
2966
}
2967
return null;
2968
}
2969
2970
/*
2971
* Returns the bounding rectangle for the component text.
2972
*/
2973
private Rectangle getTextRectangle() {
2974
2975
String text = AbstractButton.this.getText();
2976
Icon icon = (AbstractButton.this.isEnabled()) ? AbstractButton.this.getIcon() : AbstractButton.this.getDisabledIcon();
2977
2978
if ((icon == null) && (text == null)) {
2979
return null;
2980
}
2981
2982
Rectangle paintIconR = new Rectangle();
2983
Rectangle paintTextR = new Rectangle();
2984
Rectangle paintViewR = new Rectangle();
2985
Insets paintViewInsets = new Insets(0, 0, 0, 0);
2986
2987
paintViewInsets = AbstractButton.this.getInsets(paintViewInsets);
2988
paintViewR.x = paintViewInsets.left;
2989
paintViewR.y = paintViewInsets.top;
2990
paintViewR.width = AbstractButton.this.getWidth() - (paintViewInsets.left + paintViewInsets.right);
2991
paintViewR.height = AbstractButton.this.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
2992
2993
String clippedText = SwingUtilities.layoutCompoundLabel(
2994
AbstractButton.this,
2995
getFontMetrics(getFont()),
2996
text,
2997
icon,
2998
AbstractButton.this.getVerticalAlignment(),
2999
AbstractButton.this.getHorizontalAlignment(),
3000
AbstractButton.this.getVerticalTextPosition(),
3001
AbstractButton.this.getHorizontalTextPosition(),
3002
paintViewR,
3003
paintIconR,
3004
paintTextR,
3005
0);
3006
3007
return paintTextR;
3008
}
3009
3010
// ----- AccessibleExtendedComponent
3011
3012
/**
3013
* Returns the AccessibleExtendedComponent
3014
*
3015
* @return the AccessibleExtendedComponent
3016
*/
3017
AccessibleExtendedComponent getAccessibleExtendedComponent() {
3018
return this;
3019
}
3020
3021
/**
3022
* Returns the tool tip text
3023
*
3024
* @return the tool tip text, if supported, of the object;
3025
* otherwise, null
3026
* @since 1.4
3027
*/
3028
public String getToolTipText() {
3029
return AbstractButton.this.getToolTipText();
3030
}
3031
3032
/**
3033
* Returns the titled border text
3034
*
3035
* @return the titled border text, if supported, of the object;
3036
* otherwise, null
3037
* @since 1.4
3038
*/
3039
public String getTitledBorderText() {
3040
return super.getTitledBorderText();
3041
}
3042
3043
/**
3044
* Returns key bindings associated with this object
3045
*
3046
* @return the key bindings, if supported, of the object;
3047
* otherwise, null
3048
* @see AccessibleKeyBinding
3049
* @since 1.4
3050
*/
3051
public AccessibleKeyBinding getAccessibleKeyBinding() {
3052
int mnemonic = AbstractButton.this.getMnemonic();
3053
if (mnemonic == 0) {
3054
return null;
3055
}
3056
return new ButtonKeyBinding(mnemonic);
3057
}
3058
3059
class ButtonKeyBinding implements AccessibleKeyBinding {
3060
int mnemonic;
3061
3062
ButtonKeyBinding(int mnemonic) {
3063
this.mnemonic = mnemonic;
3064
}
3065
3066
/**
3067
* Returns the number of key bindings for this object
3068
*
3069
* @return the zero-based number of key bindings for this object
3070
*/
3071
public int getAccessibleKeyBindingCount() {
3072
return 1;
3073
}
3074
3075
/**
3076
* Returns a key binding for this object. The value returned is an
3077
* java.lang.Object which must be cast to appropriate type depending
3078
* on the underlying implementation of the key. For example, if the
3079
* Object returned is a javax.swing.KeyStroke, the user of this
3080
* method should do the following:
3081
* <nf><code>
3082
* Component c = <get the component that has the key bindings>
3083
* AccessibleContext ac = c.getAccessibleContext();
3084
* AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
3085
* for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
3086
* Object o = akb.getAccessibleKeyBinding(i);
3087
* if (o instanceof javax.swing.KeyStroke) {
3088
* javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
3089
* <do something with the key binding>
3090
* }
3091
* }
3092
* </code></nf>
3093
*
3094
* @param i zero-based index of the key bindings
3095
* @return a javax.lang.Object which specifies the key binding
3096
* @exception IllegalArgumentException if the index is
3097
* out of bounds
3098
* @see #getAccessibleKeyBindingCount
3099
*/
3100
public java.lang.Object getAccessibleKeyBinding(int i) {
3101
if (i != 0) {
3102
throw new IllegalArgumentException();
3103
}
3104
return KeyStroke.getKeyStroke(mnemonic, 0);
3105
}
3106
}
3107
}
3108
}
3109
3110