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