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