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