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 */ 25package javax.swing; 26 27import java.awt.Component; 28import java.awt.Image; 29import java.awt.*; 30import java.text.*; 31import java.awt.geom.*; 32import java.beans.JavaBean; 33import java.beans.BeanProperty; 34import java.beans.Transient; 35 36import java.io.ObjectOutputStream; 37import java.io.IOException; 38 39import javax.swing.plaf.LabelUI; 40import javax.accessibility.*; 41import javax.swing.text.*; 42 43/** 44 * A display area for a short text string or an image, 45 * or both. 46 * A label does not react to input events. 47 * As a result, it cannot get the keyboard focus. 48 * A label can, however, display a keyboard alternative 49 * as a convenience for a nearby component 50 * that has a keyboard alternative but can't display it. 51 * <p> 52 * A <code>JLabel</code> object can display 53 * either text, an image, or both. 54 * You can specify where in the label's display area 55 * the label's contents are aligned 56 * by setting the vertical and horizontal alignment. 57 * By default, labels are vertically centered 58 * in their display area. 59 * Text-only labels are leading edge aligned, by default; 60 * image-only labels are horizontally centered, by default. 61 * <p> 62 * You can also specify the position of the text 63 * relative to the image. 64 * By default, text is on the trailing edge of the image, 65 * with the text and image vertically aligned. 66 * <p> 67 * A label's leading and trailing edge are determined from the value of its 68 * {@link java.awt.ComponentOrientation} property. At present, the default 69 * ComponentOrientation setting maps the leading edge to left and the trailing 70 * edge to right. 71 * 72 * <p> 73 * Finally, you can use the <code>setIconTextGap</code> method 74 * to specify how many pixels 75 * should appear between the text and the image. 76 * The default is 4 pixels. 77 * <p> 78 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/label.html">How to Use Labels</a> 79 * in <em>The Java Tutorial</em> 80 * for further documentation. 81 * <p> 82 * <strong>Warning:</strong> Swing is not thread safe. For more 83 * information see <a 84 * href="package-summary.html#threading">Swing's Threading 85 * Policy</a>. 86 * <p> 87 * <strong>Warning:</strong> 88 * Serialized objects of this class will not be compatible with 89 * future Swing releases. The current serialization support is 90 * appropriate for short term storage or RMI between applications running 91 * the same version of Swing. As of 1.4, support for long term storage 92 * of all JavaBeans™ 93 * has been added to the <code>java.beans</code> package. 94 * Please see {@link java.beans.XMLEncoder}. 95 * 96 * @author Hans Muller 97 * @since 1.2 98 */ 99@JavaBean(defaultProperty = "UI", description = "A component that displays a short string and an icon.") 100@SwingContainer(false) 101@SuppressWarnings("serial") 102public class JLabel extends JComponent implements SwingConstants, Accessible 103{ 104 /** 105 * @see #getUIClassID 106 * @see #readObject 107 */ 108 private static final String uiClassID = "LabelUI"; 109 110 private int mnemonic = '\0'; 111 private int mnemonicIndex = -1; 112 113 private String text = ""; // "" rather than null, for BeanBox 114 private Icon defaultIcon = null; 115 private Icon disabledIcon = null; 116 private boolean disabledIconSet = false; 117 118 private int verticalAlignment = CENTER; 119 private int horizontalAlignment = LEADING; 120 private int verticalTextPosition = CENTER; 121 private int horizontalTextPosition = TRAILING; 122 private int iconTextGap = 4; 123 124 /** 125 * The Component this label is for; null if the label 126 * is not the label for a component 127 */ 128 protected Component labelFor = null; 129 130 /** 131 * Client property key used to determine what label is labeling the 132 * component. This is generally not used by labels, but is instead 133 * used by components such as text areas that are being labeled by 134 * labels. When the labelFor property of a label is set, it will 135 * automatically set the LABELED_BY_PROPERTY of the component being 136 * labelled. 137 * 138 * @see #setLabelFor 139 */ 140 static final String LABELED_BY_PROPERTY = "labeledBy"; 141 142 /** 143 * Creates a <code>JLabel</code> instance with the specified 144 * text, image, and horizontal alignment. 145 * The label is centered vertically in its display area. 146 * The text is on the trailing edge of the image. 147 * 148 * @param text The text to be displayed by the label. 149 * @param icon The image to be displayed by the label. 150 * @param horizontalAlignment One of the following constants 151 * defined in <code>SwingConstants</code>: 152 * <code>LEFT</code>, 153 * <code>CENTER</code>, 154 * <code>RIGHT</code>, 155 * <code>LEADING</code> or 156 * <code>TRAILING</code>. 157 */ 158 public JLabel(String text, Icon icon, int horizontalAlignment) { 159 setText(text); 160 setIcon(icon); 161 setHorizontalAlignment(horizontalAlignment); 162 updateUI(); 163 setAlignmentX(LEFT_ALIGNMENT); 164 } 165 166 /** 167 * Creates a <code>JLabel</code> instance with the specified 168 * text and horizontal alignment. 169 * The label is centered vertically in its display area. 170 * 171 * @param text The text to be displayed by the label. 172 * @param horizontalAlignment One of the following constants 173 * defined in <code>SwingConstants</code>: 174 * <code>LEFT</code>, 175 * <code>CENTER</code>, 176 * <code>RIGHT</code>, 177 * <code>LEADING</code> or 178 * <code>TRAILING</code>. 179 */ 180 public JLabel(String text, int horizontalAlignment) { 181 this(text, null, horizontalAlignment); 182 } 183 184 /** 185 * Creates a <code>JLabel</code> instance with the specified text. 186 * The label is aligned against the leading edge of its display area, 187 * and centered vertically. 188 * 189 * @param text The text to be displayed by the label. 190 */ 191 public JLabel(String text) { 192 this(text, null, LEADING); 193 } 194 195 /** 196 * Creates a <code>JLabel</code> instance with the specified 197 * image and horizontal alignment. 198 * The label is centered vertically in its display area. 199 * 200 * @param image The image to be displayed by the label. 201 * @param horizontalAlignment One of the following constants 202 * defined in <code>SwingConstants</code>: 203 * <code>LEFT</code>, 204 * <code>CENTER</code>, 205 * <code>RIGHT</code>, 206 * <code>LEADING</code> or 207 * <code>TRAILING</code>. 208 */ 209 public JLabel(Icon image, int horizontalAlignment) { 210 this(null, image, horizontalAlignment); 211 } 212 213 /** 214 * Creates a <code>JLabel</code> instance with the specified image. 215 * The label is centered vertically and horizontally 216 * in its display area. 217 * 218 * @param image The image to be displayed by the label. 219 */ 220 public JLabel(Icon image) { 221 this(null, image, CENTER); 222 } 223 224 /** 225 * Creates a <code>JLabel</code> instance with 226 * no image and with an empty string for the title. 227 * The label is centered vertically 228 * in its display area. 229 * The label's contents, once set, will be displayed on the leading edge 230 * of the label's display area. 231 */ 232 public JLabel() { 233 this("", null, LEADING); 234 } 235 236 237 /** 238 * Returns the L&F object that renders this component. 239 * 240 * @return LabelUI object 241 */ 242 public LabelUI getUI() { 243 return (LabelUI)ui; 244 } 245 246 247 /** 248 * Sets the L&F object that renders this component. 249 * 250 * @param ui the LabelUI L&F object 251 * @see UIDefaults#getUI 252 */ 253 @BeanProperty(hidden = true, visualUpdate = true, description 254 = "The UI object that implements the Component's LookAndFeel.") 255 public void setUI(LabelUI ui) { 256 super.setUI(ui); 257 // disabled icon is generated by LF so it should be unset here 258 if (!disabledIconSet && disabledIcon != null) { 259 setDisabledIcon(null); 260 } 261 } 262 263 264 /** 265 * Resets the UI property to a value from the current look and feel. 266 * 267 * @see JComponent#updateUI 268 */ 269 public void updateUI() { 270 setUI((LabelUI) UIManager.getUI(this)); 271 } 272 273 274 /** 275 * Returns a string that specifies the name of the l&f class 276 * that renders this component. 277 * 278 * @return String "LabelUI" 279 * 280 * @see JComponent#getUIClassID 281 * @see UIDefaults#getUI 282 */ 283 @BeanProperty(bound = false) 284 public String getUIClassID() { 285 return uiClassID; 286 } 287 288 289 /** 290 * Returns the text string that the label displays. 291 * 292 * @return a String 293 * @see #setText 294 */ 295 public String getText() { 296 return text; 297 } 298 299 300 /** 301 * Defines the single line of text this component will display. If 302 * the value of text is null or empty string, nothing is displayed. 303 * <p> 304 * The default value of this property is null. 305 * <p> 306 * This is a JavaBeans bound property. 307 * 308 * @param text the single line of text this component will display 309 * @see #setVerticalTextPosition 310 * @see #setHorizontalTextPosition 311 * @see #setIcon 312 */ 313 @BeanProperty(preferred = true, visualUpdate = true, description 314 = "Defines the single line of text this component will display.") 315 public void setText(String text) { 316 317 String oldAccessibleName = null; 318 if (accessibleContext != null) { 319 oldAccessibleName = accessibleContext.getAccessibleName(); 320 } 321 322 String oldValue = this.text; 323 this.text = text; 324 firePropertyChange("text", oldValue, text); 325 326 setDisplayedMnemonicIndex( 327 SwingUtilities.findDisplayedMnemonicIndex( 328 text, getDisplayedMnemonic())); 329 330 if ((accessibleContext != null) 331 && (accessibleContext.getAccessibleName() != oldAccessibleName)) { 332 accessibleContext.firePropertyChange( 333 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, 334 oldAccessibleName, 335 accessibleContext.getAccessibleName()); 336 } 337 if (text == null || oldValue == null || !text.equals(oldValue)) { 338 revalidate(); 339 repaint(); 340 } 341 } 342 343 344 /** 345 * Returns the graphic image (glyph, icon) that the label displays. 346 * 347 * @return an Icon 348 * @see #setIcon 349 */ 350 public Icon getIcon() { 351 return defaultIcon; 352 } 353 354 /** 355 * Defines the icon this component will display. If 356 * the value of icon is null, nothing is displayed. 357 * <p> 358 * The default value of this property is null. 359 * <p> 360 * This is a JavaBeans bound property. 361 * 362 * @param icon the default icon this component will display 363 * @see #setVerticalTextPosition 364 * @see #setHorizontalTextPosition 365 * @see #getIcon 366 */ 367 @BeanProperty(preferred = true, visualUpdate = true, description 368 = "The icon this component will display.") 369 public void setIcon(Icon icon) { 370 Icon oldValue = defaultIcon; 371 defaultIcon = icon; 372 373 /* If the default icon has really changed and we had 374 * generated the disabled icon for this component 375 * (in other words, setDisabledIcon() was never called), then 376 * clear the disabledIcon field. 377 */ 378 if ((defaultIcon != oldValue) && !disabledIconSet) { 379 disabledIcon = null; 380 } 381 382 firePropertyChange("icon", oldValue, defaultIcon); 383 384 if ((accessibleContext != null) && (oldValue != defaultIcon)) { 385 accessibleContext.firePropertyChange( 386 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, 387 oldValue, defaultIcon); 388 } 389 390 /* If the default icon has changed and the new one is 391 * a different size, then revalidate. Repaint if the 392 * default icon has changed. 393 */ 394 if (defaultIcon != oldValue) { 395 if ((defaultIcon == null) || 396 (oldValue == null) || 397 (defaultIcon.getIconWidth() != oldValue.getIconWidth()) || 398 (defaultIcon.getIconHeight() != oldValue.getIconHeight())) { 399 revalidate(); 400 } 401 repaint(); 402 } 403 } 404 405 406 /** 407 * Returns the icon used by the label when it's disabled. 408 * If no disabled icon has been set this will forward the call to 409 * the look and feel to construct an appropriate disabled Icon. 410 * <p> 411 * Some look and feels might not render the disabled Icon, in which 412 * case they will ignore this. 413 * 414 * @return the <code>disabledIcon</code> property 415 * @see #setDisabledIcon 416 * @see javax.swing.LookAndFeel#getDisabledIcon 417 * @see ImageIcon 418 */ 419 @Transient 420 public Icon getDisabledIcon() { 421 if (!disabledIconSet && disabledIcon == null && defaultIcon != null) { 422 disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, defaultIcon); 423 if (disabledIcon != null) { 424 firePropertyChange("disabledIcon", null, disabledIcon); 425 } 426 } 427 return disabledIcon; 428 } 429 430 431 /** 432 * Set the icon to be displayed if this JLabel is "disabled" 433 * (JLabel.setEnabled(false)). 434 * <p> 435 * The default value of this property is null. 436 * 437 * @param disabledIcon the Icon to display when the component is disabled 438 * @see #getDisabledIcon 439 * @see #setEnabled 440 */ 441 @BeanProperty(visualUpdate = true, description 442 = "The icon to display if the label is disabled.") 443 public void setDisabledIcon(Icon disabledIcon) { 444 Icon oldValue = this.disabledIcon; 445 this.disabledIcon = disabledIcon; 446 disabledIconSet = (disabledIcon != null); 447 firePropertyChange("disabledIcon", oldValue, disabledIcon); 448 if (disabledIcon != oldValue) { 449 if (disabledIcon == null || oldValue == null || 450 disabledIcon.getIconWidth() != oldValue.getIconWidth() || 451 disabledIcon.getIconHeight() != oldValue.getIconHeight()) { 452 revalidate(); 453 } 454 if (!isEnabled()) { 455 repaint(); 456 } 457 } 458 } 459 460 461 /** 462 * Specify a keycode that indicates a mnemonic key. 463 * This property is used when the label is part of a larger component. 464 * If the labelFor property of the label is not null, the label will 465 * call the requestFocus method of the component specified by the 466 * labelFor property when the mnemonic is activated. 467 * 468 * @param key a keycode that indicates a mnemonic key 469 * @see #getLabelFor 470 * @see #setLabelFor 471 */ 472 @BeanProperty(visualUpdate = true, description 473 = "The mnemonic keycode.") 474 public void setDisplayedMnemonic(int key) { 475 int oldKey = mnemonic; 476 mnemonic = key; 477 firePropertyChange("displayedMnemonic", oldKey, mnemonic); 478 479 setDisplayedMnemonicIndex( 480 SwingUtilities.findDisplayedMnemonicIndex(getText(), mnemonic)); 481 482 if (key != oldKey) { 483 revalidate(); 484 repaint(); 485 } 486 } 487 488 489 /** 490 * Specifies the displayedMnemonic as a char value. 491 * 492 * @param aChar a char specifying the mnemonic to display 493 * @see #setDisplayedMnemonic(int) 494 */ 495 public void setDisplayedMnemonic(char aChar) { 496 int vk = java.awt.event.KeyEvent.getExtendedKeyCodeForChar(aChar); 497 if (vk != java.awt.event.KeyEvent.VK_UNDEFINED) { 498 setDisplayedMnemonic(vk); 499 } 500 } 501 502 503 /** 504 * Return the keycode that indicates a mnemonic key. 505 * This property is used when the label is part of a larger component. 506 * If the labelFor property of the label is not null, the label will 507 * call the requestFocus method of the component specified by the 508 * labelFor property when the mnemonic is activated. 509 * 510 * @return int value for the mnemonic key 511 * 512 * @see #getLabelFor 513 * @see #setLabelFor 514 */ 515 public int getDisplayedMnemonic() { 516 return mnemonic; 517 } 518 519 /** 520 * Provides a hint to the look and feel as to which character in the 521 * text should be decorated to represent the mnemonic. Not all look and 522 * feels may support this. A value of -1 indicates either there is no 523 * mnemonic, the mnemonic character is not contained in the string, or 524 * the developer does not wish the mnemonic to be displayed. 525 * <p> 526 * The value of this is updated as the properties relating to the 527 * mnemonic change (such as the mnemonic itself, the text...). 528 * You should only ever have to call this if 529 * you do not wish the default character to be underlined. For example, if 530 * the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A' 531 * to be decorated, as 'Save <u>A</u>s', you would have to invoke 532 * <code>setDisplayedMnemonicIndex(5)</code> after invoking 533 * <code>setDisplayedMnemonic(KeyEvent.VK_A)</code>. 534 * 535 * @since 1.4 536 * @param index Index into the String to underline 537 * @exception IllegalArgumentException will be thrown if <code>index</code> 538 * is >= length of the text, or < -1 539 */ 540 @BeanProperty(visualUpdate = true, description 541 = "the index into the String to draw the keyboard character mnemonic at") 542 public void setDisplayedMnemonicIndex(int index) 543 throws IllegalArgumentException { 544 int oldValue = mnemonicIndex; 545 if (index == -1) { 546 mnemonicIndex = -1; 547 } else { 548 String text = getText(); 549 int textLength = (text == null) ? 0 : text.length(); 550 if (index < -1 || index >= textLength) { // index out of range 551 throw new IllegalArgumentException("index == " + index); 552 } 553 } 554 mnemonicIndex = index; 555 firePropertyChange("displayedMnemonicIndex", oldValue, index); 556 if (index != oldValue) { 557 revalidate(); 558 repaint(); 559 } 560 } 561 562 /** 563 * Returns the character, as an index, that the look and feel should 564 * provide decoration for as representing the mnemonic character. 565 * 566 * @since 1.4 567 * @return index representing mnemonic character 568 * @see #setDisplayedMnemonicIndex 569 */ 570 public int getDisplayedMnemonicIndex() { 571 return mnemonicIndex; 572 } 573 574 /** 575 * Verify that key is a legal value for the horizontalAlignment properties. 576 * 577 * @param key the property value to check 578 * @param message the IllegalArgumentException detail message 579 * @return the key value if {@code key} is a a legal value for the 580 * horizontalAlignment properties 581 * @exception IllegalArgumentException if key isn't LEFT, CENTER, RIGHT, 582 * LEADING or TRAILING. 583 * @see #setHorizontalTextPosition 584 * @see #setHorizontalAlignment 585 */ 586 protected int checkHorizontalKey(int key, String message) { 587 if ((key == LEFT) || 588 (key == CENTER) || 589 (key == RIGHT) || 590 (key == LEADING) || 591 (key == TRAILING)) { 592 return key; 593 } 594 else { 595 throw new IllegalArgumentException(message); 596 } 597 } 598 599 600 /** 601 * Verify that key is a legal value for the 602 * verticalAlignment or verticalTextPosition properties. 603 * 604 * @param key the property value to check 605 * @param message the IllegalArgumentException detail message 606 * @return the key value if {@code key} is a legal value for the 607 * verticalAlignment or verticalTextPosition properties 608 * @exception IllegalArgumentException if key isn't TOP, CENTER, or BOTTOM. 609 * @see #setVerticalAlignment 610 * @see #setVerticalTextPosition 611 */ 612 protected int checkVerticalKey(int key, String message) { 613 if ((key == TOP) || (key == CENTER) || (key == BOTTOM)) { 614 return key; 615 } 616 else { 617 throw new IllegalArgumentException(message); 618 } 619 } 620 621 622 /** 623 * Returns the amount of space between the text and the icon 624 * displayed in this label. 625 * 626 * @return an int equal to the number of pixels between the text 627 * and the icon. 628 * @see #setIconTextGap 629 */ 630 public int getIconTextGap() { 631 return iconTextGap; 632 } 633 634 635 /** 636 * If both the icon and text properties are set, this property 637 * defines the space between them. 638 * <p> 639 * The default value of this property is 4 pixels. 640 * <p> 641 * This is a JavaBeans bound property. 642 * 643 * @param iconTextGap the space between the icon and text properties 644 * @see #getIconTextGap 645 */ 646 @BeanProperty(visualUpdate = true, description 647 = "If both the icon and text properties are set, this property defines the space between them.") 648 public void setIconTextGap(int iconTextGap) { 649 int oldValue = this.iconTextGap; 650 this.iconTextGap = iconTextGap; 651 firePropertyChange("iconTextGap", oldValue, iconTextGap); 652 if (iconTextGap != oldValue) { 653 revalidate(); 654 repaint(); 655 } 656 } 657 658 659 660 /** 661 * Returns the alignment of the label's contents along the Y axis. 662 * 663 * @return The value of the verticalAlignment property, one of the 664 * following constants defined in <code>SwingConstants</code>: 665 * <code>TOP</code>, 666 * <code>CENTER</code>, or 667 * <code>BOTTOM</code>. 668 * 669 * @see SwingConstants 670 * @see #setVerticalAlignment 671 */ 672 public int getVerticalAlignment() { 673 return verticalAlignment; 674 } 675 676 677 /** 678 * Sets the alignment of the label's contents along the Y axis. 679 * <p> 680 * The default value of this property is CENTER. 681 * 682 * @param alignment One of the following constants 683 * defined in <code>SwingConstants</code>: 684 * <code>TOP</code>, 685 * <code>CENTER</code> (the default), or 686 * <code>BOTTOM</code>. 687 * 688 * @see SwingConstants 689 * @see #getVerticalAlignment 690 */ 691 @BeanProperty(visualUpdate = true, enumerationValues = { 692 "SwingConstants.TOP", 693 "SwingConstants.CENTER", 694 "SwingConstants.BOTTOM"}, 695 description = "The alignment of the label's contents along the Y axis.") 696 public void setVerticalAlignment(int alignment) { 697 if (alignment == verticalAlignment) return; 698 int oldValue = verticalAlignment; 699 verticalAlignment = checkVerticalKey(alignment, "verticalAlignment"); 700 firePropertyChange("verticalAlignment", oldValue, verticalAlignment); 701 repaint(); 702 } 703 704 705 /** 706 * Returns the alignment of the label's contents along the X axis. 707 * 708 * @return The value of the horizontalAlignment property, one of the 709 * following constants defined in <code>SwingConstants</code>: 710 * <code>LEFT</code>, 711 * <code>CENTER</code>, 712 * <code>RIGHT</code>, 713 * <code>LEADING</code> or 714 * <code>TRAILING</code>. 715 * 716 * @see #setHorizontalAlignment 717 * @see SwingConstants 718 */ 719 public int getHorizontalAlignment() { 720 return horizontalAlignment; 721 } 722 723 /** 724 * Sets the alignment of the label's contents along the X axis. 725 * <p> 726 * This is a JavaBeans bound property. 727 * 728 * @param alignment One of the following constants 729 * defined in <code>SwingConstants</code>: 730 * <code>LEFT</code>, 731 * <code>CENTER</code> (the default for image-only labels), 732 * <code>RIGHT</code>, 733 * <code>LEADING</code> (the default for text-only labels) or 734 * <code>TRAILING</code>. 735 * 736 * @see SwingConstants 737 * @see #getHorizontalAlignment 738 */ 739 @BeanProperty(visualUpdate = true, enumerationValues = { 740 "SwingConstants.LEFT", 741 "SwingConstants.CENTER", 742 "SwingConstants.RIGHT", 743 "SwingConstants.LEADING", 744 "SwingConstants.TRAILING"}, description 745 = "The alignment of the label's content along the X axis.") 746 public void setHorizontalAlignment(int alignment) { 747 if (alignment == horizontalAlignment) return; 748 int oldValue = horizontalAlignment; 749 horizontalAlignment = checkHorizontalKey(alignment, 750 "horizontalAlignment"); 751 firePropertyChange("horizontalAlignment", 752 oldValue, horizontalAlignment); 753 repaint(); 754 } 755 756 757 /** 758 * Returns the vertical position of the label's text, 759 * relative to its image. 760 * 761 * @return One of the following constants 762 * defined in <code>SwingConstants</code>: 763 * <code>TOP</code>, 764 * <code>CENTER</code>, or 765 * <code>BOTTOM</code>. 766 * 767 * @see #setVerticalTextPosition 768 * @see SwingConstants 769 */ 770 public int getVerticalTextPosition() { 771 return verticalTextPosition; 772 } 773 774 775 /** 776 * Sets the vertical position of the label's text, 777 * relative to its image. 778 * <p> 779 * The default value of this property is CENTER. 780 * <p> 781 * This is a JavaBeans bound property. 782 * 783 * @param textPosition One of the following constants 784 * defined in <code>SwingConstants</code>: 785 * <code>TOP</code>, 786 * <code>CENTER</code> (the default), or 787 * <code>BOTTOM</code>. 788 * 789 * @see SwingConstants 790 * @see #getVerticalTextPosition 791 */ 792 @BeanProperty(expert = true, visualUpdate = true, enumerationValues = { 793 "SwingConstants.TOP", 794 "SwingConstants.CENTER", 795 "SwingConstants.BOTTOM"}, 796 description = "The vertical position of the text relative to it's image.") 797 public void setVerticalTextPosition(int textPosition) { 798 if (textPosition == verticalTextPosition) return; 799 int old = verticalTextPosition; 800 verticalTextPosition = checkVerticalKey(textPosition, 801 "verticalTextPosition"); 802 firePropertyChange("verticalTextPosition", old, verticalTextPosition); 803 revalidate(); 804 repaint(); 805 } 806 807 808 /** 809 * Returns the horizontal position of the label's text, 810 * relative to its image. 811 * 812 * @return One of the following constants 813 * defined in <code>SwingConstants</code>: 814 * <code>LEFT</code>, 815 * <code>CENTER</code>, 816 * <code>RIGHT</code>, 817 * <code>LEADING</code> or 818 * <code>TRAILING</code>. 819 * 820 * @see SwingConstants 821 */ 822 public int getHorizontalTextPosition() { 823 return horizontalTextPosition; 824 } 825 826 827 /** 828 * Sets the horizontal position of the label's text, 829 * relative to its image. 830 * 831 * @param textPosition One of the following constants 832 * defined in <code>SwingConstants</code>: 833 * <code>LEFT</code>, 834 * <code>CENTER</code>, 835 * <code>RIGHT</code>, 836 * <code>LEADING</code>, or 837 * <code>TRAILING</code> (the default). 838 * 839 * @see SwingConstants 840 */ 841 @BeanProperty(expert = true, visualUpdate = true, enumerationValues = { 842 "SwingConstants.LEFT", 843 "SwingConstants.CENTER", 844 "SwingConstants.RIGHT", 845 "SwingConstants.LEADING", 846 "SwingConstants.TRAILING"}, description 847 = "The horizontal position of the label's text, relative to its image.") 848 public void setHorizontalTextPosition(int textPosition) { 849 int old = horizontalTextPosition; 850 this.horizontalTextPosition = checkHorizontalKey(textPosition, 851 "horizontalTextPosition"); 852 firePropertyChange("horizontalTextPosition", 853 old, horizontalTextPosition); 854 revalidate(); 855 repaint(); 856 } 857 858 859 /** 860 * This is overridden to return false if the current Icon's Image is 861 * not equal to the passed in Image <code>img</code>. 862 * 863 * @see java.awt.image.ImageObserver 864 * @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int) 865 */ 866 public boolean imageUpdate(Image img, int infoflags, 867 int x, int y, int w, int h) { 868 // Don't use getDisabledIcon, will trigger creation of icon if icon 869 // not set. 870 if (!isShowing() || 871 !SwingUtilities.doesIconReferenceImage(getIcon(), img) && 872 !SwingUtilities.doesIconReferenceImage(disabledIcon, img)) { 873 874 return false; 875 } 876 return super.imageUpdate(img, infoflags, x, y, w, h); 877 } 878 879 880 /** 881 * See readObject() and writeObject() in JComponent for more 882 * information about serialization in Swing. 883 */ 884 private void writeObject(ObjectOutputStream s) throws IOException { 885 s.defaultWriteObject(); 886 if (getUIClassID().equals(uiClassID)) { 887 byte count = JComponent.getWriteObjCounter(this); 888 JComponent.setWriteObjCounter(this, --count); 889 if (count == 0 && ui != null) { 890 ui.installUI(this); 891 } 892 } 893 } 894 895 896 /** 897 * Returns a string representation of this JLabel. This method 898 * is intended to be used only for debugging purposes, and the 899 * content and format of the returned string may vary between 900 * implementations. The returned string may be empty but may not 901 * be <code>null</code>. 902 * 903 * @return a string representation of this JLabel. 904 */ 905 protected String paramString() { 906 String textString = (text != null ? 907 text : ""); 908 String defaultIconString = ((defaultIcon != null) 909 && (defaultIcon != this) ? 910 defaultIcon.toString() : ""); 911 String disabledIconString = ((disabledIcon != null) 912 && (disabledIcon != this) ? 913 disabledIcon.toString() : ""); 914 String labelForString = (labelFor != null ? 915 labelFor.toString() : ""); 916 String verticalAlignmentString; 917 if (verticalAlignment == TOP) { 918 verticalAlignmentString = "TOP"; 919 } else if (verticalAlignment == CENTER) { 920 verticalAlignmentString = "CENTER"; 921 } else if (verticalAlignment == BOTTOM) { 922 verticalAlignmentString = "BOTTOM"; 923 } else verticalAlignmentString = ""; 924 String horizontalAlignmentString; 925 if (horizontalAlignment == LEFT) { 926 horizontalAlignmentString = "LEFT"; 927 } else if (horizontalAlignment == CENTER) { 928 horizontalAlignmentString = "CENTER"; 929 } else if (horizontalAlignment == RIGHT) { 930 horizontalAlignmentString = "RIGHT"; 931 } else if (horizontalAlignment == LEADING) { 932 horizontalAlignmentString = "LEADING"; 933 } else if (horizontalAlignment == TRAILING) { 934 horizontalAlignmentString = "TRAILING"; 935 } else horizontalAlignmentString = ""; 936 String verticalTextPositionString; 937 if (verticalTextPosition == TOP) { 938 verticalTextPositionString = "TOP"; 939 } else if (verticalTextPosition == CENTER) { 940 verticalTextPositionString = "CENTER"; 941 } else if (verticalTextPosition == BOTTOM) { 942 verticalTextPositionString = "BOTTOM"; 943 } else verticalTextPositionString = ""; 944 String horizontalTextPositionString; 945 if (horizontalTextPosition == LEFT) { 946 horizontalTextPositionString = "LEFT"; 947 } else if (horizontalTextPosition == CENTER) { 948 horizontalTextPositionString = "CENTER"; 949 } else if (horizontalTextPosition == RIGHT) { 950 horizontalTextPositionString = "RIGHT"; 951 } else if (horizontalTextPosition == LEADING) { 952 horizontalTextPositionString = "LEADING"; 953 } else if (horizontalTextPosition == TRAILING) { 954 horizontalTextPositionString = "TRAILING"; 955 } else horizontalTextPositionString = ""; 956 957 return super.paramString() + 958 ",defaultIcon=" + defaultIconString + 959 ",disabledIcon=" + disabledIconString + 960 ",horizontalAlignment=" + horizontalAlignmentString + 961 ",horizontalTextPosition=" + horizontalTextPositionString + 962 ",iconTextGap=" + iconTextGap + 963 ",labelFor=" + labelForString + 964 ",text=" + textString + 965 ",verticalAlignment=" + verticalAlignmentString + 966 ",verticalTextPosition=" + verticalTextPositionString; 967 } 968 969 /** 970 * --- Accessibility Support --- 971 */ 972 973 /** 974 * Get the component this is labelling. 975 * 976 * @return the Component this is labelling. Can be null if this 977 * does not label a Component. If the displayedMnemonic 978 * property is set and the labelFor property is also set, the label 979 * will call the requestFocus method of the component specified by the 980 * labelFor property when the mnemonic is activated. 981 * 982 * @see #getDisplayedMnemonic 983 * @see #setDisplayedMnemonic 984 */ 985 public Component getLabelFor() { 986 return labelFor; 987 } 988 989 /** 990 * Set the component this is labelling. Can be null if this does not 991 * label a Component. If the displayedMnemonic property is set 992 * and the labelFor property is also set, the label will 993 * call the requestFocus method of the component specified by the 994 * labelFor property when the mnemonic is activated. 995 * 996 * @param c the Component this label is for, or null if the label is 997 * not the label for a component 998 * 999 * @see #getDisplayedMnemonic 1000 * @see #setDisplayedMnemonic 1001 */ 1002 @BeanProperty(description 1003 = "The component this is labelling.") 1004 public void setLabelFor(Component c) { 1005 Component oldC = labelFor; 1006 labelFor = c; 1007 firePropertyChange("labelFor", oldC, c); 1008 1009 if (oldC instanceof JComponent) { 1010 ((JComponent)oldC).putClientProperty(LABELED_BY_PROPERTY, null); 1011 } 1012 if (c instanceof JComponent) { 1013 ((JComponent)c).putClientProperty(LABELED_BY_PROPERTY, this); 1014 } 1015 } 1016 1017 /** 1018 * Get the AccessibleContext of this object 1019 * 1020 * @return the AccessibleContext of this object 1021 */ 1022 @BeanProperty(bound = false, expert = true, description 1023 = "The AccessibleContext associated with this Label.") 1024 public AccessibleContext getAccessibleContext() { 1025 if (accessibleContext == null) { 1026 accessibleContext = new AccessibleJLabel(); 1027 } 1028 return accessibleContext; 1029 } 1030 1031 /** 1032 * The class used to obtain the accessible role for this object. 1033 * <p> 1034 * <strong>Warning:</strong> 1035 * Serialized objects of this class will not be compatible with 1036 * future Swing releases. The current serialization support is 1037 * appropriate for short term storage or RMI between applications running 1038 * the same version of Swing. As of 1.4, support for long term storage 1039 * of all JavaBeans™ 1040 * has been added to the <code>java.beans</code> package. 1041 * Please see {@link java.beans.XMLEncoder}. 1042 */ 1043 @SuppressWarnings("serial") 1044 protected class AccessibleJLabel extends AccessibleJComponent 1045 implements AccessibleText, AccessibleExtendedComponent { 1046 1047 /** 1048 * Get the accessible name of this object. 1049 * 1050 * @return the localized name of the object -- can be null if this 1051 * object does not have a name 1052 * @see AccessibleContext#setAccessibleName 1053 */ 1054 public String getAccessibleName() { 1055 String name = accessibleName; 1056 1057 if (name == null) { 1058 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); 1059 } 1060 if (name == null) { 1061 name = JLabel.this.getText(); 1062 } 1063 if (name == null) { 1064 name = super.getAccessibleName(); 1065 } 1066 return name; 1067 } 1068 1069 /** 1070 * Get the role of this object. 1071 * 1072 * @return an instance of AccessibleRole describing the role of the 1073 * object 1074 * @see AccessibleRole 1075 */ 1076 public AccessibleRole getAccessibleRole() { 1077 return AccessibleRole.LABEL; 1078 } 1079 1080 /** 1081 * Get the AccessibleIcons associated with this object if one 1082 * or more exist. Otherwise return null. 1083 * @since 1.3 1084 */ 1085 public AccessibleIcon [] getAccessibleIcon() { 1086 Icon icon = getIcon(); 1087 if (icon instanceof Accessible) { 1088 AccessibleContext ac = 1089 ((Accessible)icon).getAccessibleContext(); 1090 if (ac != null && ac instanceof AccessibleIcon) { 1091 return new AccessibleIcon[] { (AccessibleIcon)ac }; 1092 } 1093 } 1094 return null; 1095 } 1096 1097 /** 1098 * Get the AccessibleRelationSet associated with this object if one 1099 * exists. Otherwise return null. 1100 * @see AccessibleRelation 1101 * @since 1.3 1102 */ 1103 public AccessibleRelationSet getAccessibleRelationSet() { 1104 // Check where the AccessibleContext's relation 1105 // set already contains a LABEL_FOR relation. 1106 AccessibleRelationSet relationSet 1107 = super.getAccessibleRelationSet(); 1108 1109 if (!relationSet.contains(AccessibleRelation.LABEL_FOR)) { 1110 Component c = JLabel.this.getLabelFor(); 1111 if (c != null) { 1112 AccessibleRelation relation 1113 = new AccessibleRelation(AccessibleRelation.LABEL_FOR); 1114 relation.setTarget(c); 1115 relationSet.add(relation); 1116 } 1117 } 1118 return relationSet; 1119 } 1120 1121 1122 /* AccessibleText ---------- */ 1123 1124 public AccessibleText getAccessibleText() { 1125 View view = (View)JLabel.this.getClientProperty("html"); 1126 if (view != null) { 1127 return this; 1128 } else { 1129 return null; 1130 } 1131 } 1132 1133 /** 1134 * Given a point in local coordinates, return the zero-based index 1135 * of the character under that Point. If the point is invalid, 1136 * this method returns -1. 1137 * 1138 * @param p the Point in local coordinates 1139 * @return the zero-based index of the character under Point p; if 1140 * Point is invalid returns -1. 1141 * @since 1.3 1142 */ 1143 public int getIndexAtPoint(Point p) { 1144 View view = (View) JLabel.this.getClientProperty("html"); 1145 if (view != null) { 1146 Rectangle r = getTextRectangle(); 1147 if (r == null) { 1148 return -1; 1149 } 1150 Rectangle2D.Float shape = 1151 new Rectangle2D.Float(r.x, r.y, r.width, r.height); 1152 Position.Bias bias[] = new Position.Bias[1]; 1153 return view.viewToModel(p.x, p.y, shape, bias); 1154 } else { 1155 return -1; 1156 } 1157 } 1158 1159 /** 1160 * Returns the bounding box of the character at the given 1161 * index in the string. The bounds are returned in local 1162 * coordinates. If the index is invalid, <code>null</code> is returned. 1163 * 1164 * @param i the index into the String 1165 * @return the screen coordinates of the character's bounding box. 1166 * If the index is invalid, <code>null</code> is returned. 1167 * @since 1.3 1168 */ 1169 public Rectangle getCharacterBounds(int i) { 1170 View view = (View) JLabel.this.getClientProperty("html"); 1171 if (view != null) { 1172 Rectangle r = getTextRectangle(); 1173 if (r == null) { 1174 return null; 1175 } 1176 Rectangle2D.Float shape = 1177 new Rectangle2D.Float(r.x, r.y, r.width, r.height); 1178 try { 1179 Shape charShape = 1180 view.modelToView(i, shape, Position.Bias.Forward); 1181 return charShape.getBounds(); 1182 } catch (BadLocationException e) { 1183 return null; 1184 } 1185 } else { 1186 return null; 1187 } 1188 } 1189 1190 /** 1191 * Return the number of characters (valid indicies) 1192 * 1193 * @return the number of characters 1194 * @since 1.3 1195 */ 1196 public int getCharCount() { 1197 View view = (View) JLabel.this.getClientProperty("html"); 1198 if (view != null) { 1199 Document d = view.getDocument(); 1200 if (d instanceof StyledDocument) { 1201 StyledDocument doc = (StyledDocument)d; 1202 return doc.getLength(); 1203 } 1204 } 1205 return accessibleContext.getAccessibleName().length(); 1206 } 1207 1208 /** 1209 * Return the zero-based offset of the caret. 1210 * 1211 * Note: That to the right of the caret will have the same index 1212 * value as the offset (the caret is between two characters). 1213 * @return the zero-based offset of the caret. 1214 * @since 1.3 1215 */ 1216 public int getCaretPosition() { 1217 // There is no caret. 1218 return -1; 1219 } 1220 1221 /** 1222 * Returns the String at a given index. 1223 * 1224 * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, 1225 * or AccessibleText.SENTENCE to retrieve 1226 * @param index an index within the text >= 0 1227 * @return the letter, word, or sentence, 1228 * null for an invalid index or part 1229 * @since 1.3 1230 */ 1231 public String getAtIndex(int part, int index) { 1232 if (index < 0 || index >= getCharCount()) { 1233 return null; 1234 } 1235 switch (part) { 1236 case AccessibleText.CHARACTER: 1237 try { 1238 return getText(index, 1); 1239 } catch (BadLocationException e) { 1240 return null; 1241 } 1242 case AccessibleText.WORD: 1243 try { 1244 String s = getText(0, getCharCount()); 1245 BreakIterator words = BreakIterator.getWordInstance(getLocale()); 1246 words.setText(s); 1247 int end = words.following(index); 1248 return s.substring(words.previous(), end); 1249 } catch (BadLocationException e) { 1250 return null; 1251 } 1252 case AccessibleText.SENTENCE: 1253 try { 1254 String s = getText(0, getCharCount()); 1255 BreakIterator sentence = 1256 BreakIterator.getSentenceInstance(getLocale()); 1257 sentence.setText(s); 1258 int end = sentence.following(index); 1259 return s.substring(sentence.previous(), end); 1260 } catch (BadLocationException e) { 1261 return null; 1262 } 1263 default: 1264 return null; 1265 } 1266 } 1267 1268 /** 1269 * Returns the String after a given index. 1270 * 1271 * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, 1272 * or AccessibleText.SENTENCE to retrieve 1273 * @param index an index within the text >= 0 1274 * @return the letter, word, or sentence, null for an invalid 1275 * index or part 1276 * @since 1.3 1277 */ 1278 public String getAfterIndex(int part, int index) { 1279 if (index < 0 || index >= getCharCount()) { 1280 return null; 1281 } 1282 switch (part) { 1283 case AccessibleText.CHARACTER: 1284 if (index+1 >= getCharCount()) { 1285 return null; 1286 } 1287 try { 1288 return getText(index+1, 1); 1289 } catch (BadLocationException e) { 1290 return null; 1291 } 1292 case AccessibleText.WORD: 1293 try { 1294 String s = getText(0, getCharCount()); 1295 BreakIterator words = BreakIterator.getWordInstance(getLocale()); 1296 words.setText(s); 1297 int start = words.following(index); 1298 if (start == BreakIterator.DONE || start >= s.length()) { 1299 return null; 1300 } 1301 int end = words.following(start); 1302 if (end == BreakIterator.DONE || end >= s.length()) { 1303 return null; 1304 } 1305 return s.substring(start, end); 1306 } catch (BadLocationException e) { 1307 return null; 1308 } 1309 case AccessibleText.SENTENCE: 1310 try { 1311 String s = getText(0, getCharCount()); 1312 BreakIterator sentence = 1313 BreakIterator.getSentenceInstance(getLocale()); 1314 sentence.setText(s); 1315 int start = sentence.following(index); 1316 if (start == BreakIterator.DONE || start > s.length()) { 1317 return null; 1318 } 1319 int end = sentence.following(start); 1320 if (end == BreakIterator.DONE || end > s.length()) { 1321 return null; 1322 } 1323 return s.substring(start, end); 1324 } catch (BadLocationException e) { 1325 return null; 1326 } 1327 default: 1328 return null; 1329 } 1330 } 1331 1332 /** 1333 * Returns the String before a given index. 1334 * 1335 * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, 1336 * or AccessibleText.SENTENCE to retrieve 1337 * @param index an index within the text >= 0 1338 * @return the letter, word, or sentence, null for an invalid index 1339 * or part 1340 * @since 1.3 1341 */ 1342 public String getBeforeIndex(int part, int index) { 1343 if (index < 0 || index > getCharCount()-1) { 1344 return null; 1345 } 1346 switch (part) { 1347 case AccessibleText.CHARACTER: 1348 if (index == 0) { 1349 return null; 1350 } 1351 try { 1352 return getText(index-1, 1); 1353 } catch (BadLocationException e) { 1354 return null; 1355 } 1356 case AccessibleText.WORD: 1357 try { 1358 String s = getText(0, getCharCount()); 1359 BreakIterator words = BreakIterator.getWordInstance(getLocale()); 1360 words.setText(s); 1361 int end = words.following(index); 1362 end = words.previous(); 1363 int start = words.previous(); 1364 if (start == BreakIterator.DONE) { 1365 return null; 1366 } 1367 return s.substring(start, end); 1368 } catch (BadLocationException e) { 1369 return null; 1370 } 1371 case AccessibleText.SENTENCE: 1372 try { 1373 String s = getText(0, getCharCount()); 1374 BreakIterator sentence = 1375 BreakIterator.getSentenceInstance(getLocale()); 1376 sentence.setText(s); 1377 int end = sentence.following(index); 1378 end = sentence.previous(); 1379 int start = sentence.previous(); 1380 if (start == BreakIterator.DONE) { 1381 return null; 1382 } 1383 return s.substring(start, end); 1384 } catch (BadLocationException e) { 1385 return null; 1386 } 1387 default: 1388 return null; 1389 } 1390 } 1391 1392 /** 1393 * Return the AttributeSet for a given character at a given index 1394 * 1395 * @param i the zero-based index into the text 1396 * @return the AttributeSet of the character 1397 * @since 1.3 1398 */ 1399 public AttributeSet getCharacterAttribute(int i) { 1400 View view = (View) JLabel.this.getClientProperty("html"); 1401 if (view != null) { 1402 Document d = view.getDocument(); 1403 if (d instanceof StyledDocument) { 1404 StyledDocument doc = (StyledDocument)d; 1405 Element elem = doc.getCharacterElement(i); 1406 if (elem != null) { 1407 return elem.getAttributes(); 1408 } 1409 } 1410 } 1411 return null; 1412 } 1413 1414 /** 1415 * Returns the start offset within the selected text. 1416 * If there is no selection, but there is 1417 * a caret, the start and end offsets will be the same. 1418 * 1419 * @return the index into the text of the start of the selection 1420 * @since 1.3 1421 */ 1422 public int getSelectionStart() { 1423 // Text cannot be selected. 1424 return -1; 1425 } 1426 1427 /** 1428 * Returns the end offset within the selected text. 1429 * If there is no selection, but there is 1430 * a caret, the start and end offsets will be the same. 1431 * 1432 * @return the index into the text of the end of the selection 1433 * @since 1.3 1434 */ 1435 public int getSelectionEnd() { 1436 // Text cannot be selected. 1437 return -1; 1438 } 1439 1440 /** 1441 * Returns the portion of the text that is selected. 1442 * 1443 * @return the String portion of the text that is selected 1444 * @since 1.3 1445 */ 1446 public String getSelectedText() { 1447 // Text cannot be selected. 1448 return null; 1449 } 1450 1451 /* 1452 * Returns the text substring starting at the specified 1453 * offset with the specified length. 1454 */ 1455 private String getText(int offset, int length) 1456 throws BadLocationException { 1457 1458 View view = (View) JLabel.this.getClientProperty("html"); 1459 if (view != null) { 1460 Document d = view.getDocument(); 1461 if (d instanceof StyledDocument) { 1462 StyledDocument doc = (StyledDocument)d; 1463 return doc.getText(offset, length); 1464 } 1465 } 1466 return null; 1467 } 1468 1469 /* 1470 * Returns the bounding rectangle for the component text. 1471 */ 1472 private Rectangle getTextRectangle() { 1473 1474 String text = JLabel.this.getText(); 1475 Icon icon = (JLabel.this.isEnabled()) ? JLabel.this.getIcon() : JLabel.this.getDisabledIcon(); 1476 1477 if ((icon == null) && (text == null)) { 1478 return null; 1479 } 1480 1481 Rectangle paintIconR = new Rectangle(); 1482 Rectangle paintTextR = new Rectangle(); 1483 Rectangle paintViewR = new Rectangle(); 1484 Insets paintViewInsets = new Insets(0, 0, 0, 0); 1485 1486 paintViewInsets = JLabel.this.getInsets(paintViewInsets); 1487 paintViewR.x = paintViewInsets.left; 1488 paintViewR.y = paintViewInsets.top; 1489 paintViewR.width = JLabel.this.getWidth() - (paintViewInsets.left + paintViewInsets.right); 1490 paintViewR.height = JLabel.this.getHeight() - (paintViewInsets.top + paintViewInsets.bottom); 1491 1492 String clippedText = SwingUtilities.layoutCompoundLabel( 1493 (JComponent)JLabel.this, 1494 getFontMetrics(getFont()), 1495 text, 1496 icon, 1497 JLabel.this.getVerticalAlignment(), 1498 JLabel.this.getHorizontalAlignment(), 1499 JLabel.this.getVerticalTextPosition(), 1500 JLabel.this.getHorizontalTextPosition(), 1501 paintViewR, 1502 paintIconR, 1503 paintTextR, 1504 JLabel.this.getIconTextGap()); 1505 1506 return paintTextR; 1507 } 1508 1509 // ----- AccessibleExtendedComponent 1510 1511 /** 1512 * Returns the AccessibleExtendedComponent 1513 * 1514 * @return the AccessibleExtendedComponent 1515 */ 1516 AccessibleExtendedComponent getAccessibleExtendedComponent() { 1517 return this; 1518 } 1519 1520 /** 1521 * Returns the tool tip text 1522 * 1523 * @return the tool tip text, if supported, of the object; 1524 * otherwise, null 1525 * @since 1.4 1526 */ 1527 public String getToolTipText() { 1528 return JLabel.this.getToolTipText(); 1529 } 1530 1531 /** 1532 * Returns the titled border text 1533 * 1534 * @return the titled border text, if supported, of the object; 1535 * otherwise, null 1536 * @since 1.4 1537 */ 1538 public String getTitledBorderText() { 1539 return super.getTitledBorderText(); 1540 } 1541 1542 /** 1543 * Returns key bindings associated with this object 1544 * 1545 * @return the key bindings, if supported, of the object; 1546 * otherwise, null 1547 * @see AccessibleKeyBinding 1548 * @since 1.4 1549 */ 1550 public AccessibleKeyBinding getAccessibleKeyBinding() { 1551 int mnemonic = JLabel.this.getDisplayedMnemonic(); 1552 if (mnemonic == 0) { 1553 return null; 1554 } 1555 return new LabelKeyBinding(mnemonic); 1556 } 1557 1558 class LabelKeyBinding implements AccessibleKeyBinding { 1559 int mnemonic; 1560 1561 LabelKeyBinding(int mnemonic) { 1562 this.mnemonic = mnemonic; 1563 } 1564 1565 /** 1566 * Returns the number of key bindings for this object 1567 * 1568 * @return the zero-based number of key bindings for this object 1569 */ 1570 public int getAccessibleKeyBindingCount() { 1571 return 1; 1572 } 1573 1574 /** 1575 * Returns a key binding for this object. The value returned is an 1576 * java.lang.Object which must be cast to appropriate type depending 1577 * on the underlying implementation of the key. For example, if the 1578 * Object returned is a javax.swing.KeyStroke, the user of this 1579 * method should do the following: 1580 * <nf><code> 1581 * Component c = <get the component that has the key bindings> 1582 * AccessibleContext ac = c.getAccessibleContext(); 1583 * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding(); 1584 * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) { 1585 * Object o = akb.getAccessibleKeyBinding(i); 1586 * if (o instanceof javax.swing.KeyStroke) { 1587 * javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o; 1588 * <do something with the key binding> 1589 * } 1590 * } 1591 * </code></nf> 1592 * 1593 * @param i zero-based index of the key bindings 1594 * @return a javax.lang.Object which specifies the key binding 1595 * @exception IllegalArgumentException if the index is 1596 * out of bounds 1597 * @see #getAccessibleKeyBindingCount 1598 */ 1599 public java.lang.Object getAccessibleKeyBinding(int i) { 1600 if (i != 0) { 1601 throw new IllegalArgumentException(); 1602 } 1603 return KeyStroke.getKeyStroke(mnemonic, 0); 1604 } 1605 } 1606 1607 } // AccessibleJComponent 1608} 1609