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