001 /* JLabel.java -- 002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package javax.swing; 040 041 import java.awt.Component; 042 import java.awt.Font; 043 import java.awt.FontMetrics; 044 import java.awt.Image; 045 import java.awt.Insets; 046 import java.awt.Point; 047 import java.awt.Rectangle; 048 import java.awt.Shape; 049 import java.awt.event.KeyEvent; 050 import java.beans.PropertyChangeEvent; 051 052 import javax.accessibility.Accessible; 053 import javax.accessibility.AccessibleContext; 054 import javax.accessibility.AccessibleExtendedComponent; 055 import javax.accessibility.AccessibleRole; 056 import javax.accessibility.AccessibleText; 057 import javax.swing.plaf.LabelUI; 058 import javax.swing.plaf.basic.BasicHTML; 059 import javax.swing.text.AttributeSet; 060 import javax.swing.text.BadLocationException; 061 import javax.swing.text.Position; 062 import javax.swing.text.SimpleAttributeSet; 063 import javax.swing.text.View; 064 065 /** 066 * A component that displays a static text message and/or an icon. 067 */ 068 public class JLabel extends JComponent implements Accessible, SwingConstants 069 { 070 071 /** 072 * Provides the accessibility features for the <code>JLabel</code> 073 * component. 074 */ 075 protected class AccessibleJLabel 076 extends JComponent.AccessibleJComponent 077 implements AccessibleText, AccessibleExtendedComponent 078 { 079 080 /** 081 * Returns the accessible name. 082 * 083 * @return The accessible name. 084 */ 085 public String getAccessibleName() 086 { 087 if (accessibleName != null) 088 return accessibleName; 089 if (text != null) 090 return text; 091 else 092 return super.getAccessibleName(); 093 } 094 095 /** 096 * Returns the accessible role for the <code>JLabel</code> component. 097 * 098 * @return {@link AccessibleRole#LABEL}. 099 */ 100 public AccessibleRole getAccessibleRole() 101 { 102 return AccessibleRole.LABEL; 103 } 104 105 /** 106 * Returns the selected text. This is null since JLabels 107 * are not selectable. 108 * 109 * @return <code>null</code> because JLabels cannot have selected text 110 */ 111 public String getSelectedText() 112 { 113 // We return null here since JLabel's text is not selectable. 114 return null; 115 } 116 117 /** 118 * Returns the start index of the selected text. 119 * 120 * @return the start index of the selected text 121 */ 122 public int getSelectionStart() 123 { 124 // JLabel don't have selected text, so we return -1 here. 125 return -1; 126 } 127 128 /** 129 * Returns the end index of the selected text. 130 * 131 * @return the end index of the selected text 132 */ 133 public int getSelectionEnd() 134 { 135 // JLabel don't have selected text, so we return -1 here. 136 return -1; 137 } 138 139 /** 140 * Returns an {@link AttributeSet} that reflects the text attributes of 141 * the specified character. We return an empty 142 * <code>AttributeSet</code> here, because JLabels don't support text 143 * attributes (at least not yet). 144 * 145 * @param index the index of the character 146 * 147 * @return an {@link AttributeSet} that reflects the text attributes of 148 * the specified character 149 */ 150 public AttributeSet getCharacterAttribute(int index) 151 { 152 // FIXME: Return null here for simple labels, and query the HTML 153 // view for HTML labels. 154 return new SimpleAttributeSet(); 155 } 156 157 /** 158 * Returns the character, word or sentence at the specified index. The 159 * <code>part</code> parameter determines what is returned, the character, 160 * word or sentence after the index. 161 * 162 * @param part one of {@link AccessibleText#CHARACTER}, 163 * {@link AccessibleText#WORD} or 164 * {@link AccessibleText#SENTENCE}, specifying what is returned 165 * @param index the index 166 * 167 * @return the character, word or sentence after <code>index</code> 168 */ 169 public String getAtIndex(int part, int index) 170 { 171 String result = ""; 172 int startIndex = -1; 173 int endIndex = -1; 174 switch(part) 175 { 176 case AccessibleText.CHARACTER: 177 result = String.valueOf(text.charAt(index)); 178 break; 179 case AccessibleText.WORD: 180 startIndex = text.lastIndexOf(' ', index); 181 endIndex = text.indexOf(' ', startIndex + 1); 182 if (endIndex == -1) 183 endIndex = startIndex + 1; 184 result = text.substring(startIndex + 1, endIndex); 185 break; 186 case AccessibleText.SENTENCE: 187 default: 188 startIndex = text.lastIndexOf('.', index); 189 endIndex = text.indexOf('.', startIndex + 1); 190 if (endIndex == -1) 191 endIndex = startIndex + 1; 192 result = text.substring(startIndex + 1, endIndex); 193 break; 194 } 195 return result; 196 } 197 198 /** 199 * Returns the character, word or sentence after the specified index. The 200 * <code>part</code> parameter determines what is returned, the character, 201 * word or sentence after the index. 202 * 203 * @param part one of {@link AccessibleText#CHARACTER}, 204 * {@link AccessibleText#WORD} or 205 * {@link AccessibleText#SENTENCE}, specifying what is returned 206 * @param index the index 207 * 208 * @return the character, word or sentence after <code>index</code> 209 */ 210 public String getAfterIndex(int part, int index) 211 { 212 String result = ""; 213 int startIndex = -1; 214 int endIndex = -1; 215 switch(part) 216 { 217 case AccessibleText.CHARACTER: 218 result = String.valueOf(text.charAt(index + 1)); 219 break; 220 case AccessibleText.WORD: 221 startIndex = text.indexOf(' ', index); 222 endIndex = text.indexOf(' ', startIndex + 1); 223 if (endIndex == -1) 224 endIndex = startIndex + 1; 225 result = text.substring(startIndex + 1, endIndex); 226 break; 227 case AccessibleText.SENTENCE: 228 default: 229 startIndex = text.indexOf('.', index); 230 endIndex = text.indexOf('.', startIndex + 1); 231 if (endIndex == -1) 232 endIndex = startIndex + 1; 233 result = text.substring(startIndex + 1, endIndex); 234 break; 235 } 236 return result; 237 } 238 239 /** 240 * Returns the character, word or sentence before the specified index. The 241 * <code>part</code> parameter determines what is returned, the character, 242 * word or sentence before the index. 243 * 244 * @param part one of {@link AccessibleText#CHARACTER}, 245 * {@link AccessibleText#WORD} or 246 * {@link AccessibleText#SENTENCE}, specifying what is returned 247 * @param index the index 248 * 249 * @return the character, word or sentence before <code>index</code> 250 */ 251 public String getBeforeIndex(int part, int index) 252 { 253 String result = ""; 254 int startIndex = -1; 255 int endIndex = -1; 256 switch(part) 257 { 258 case AccessibleText.CHARACTER: 259 result = String.valueOf(text.charAt(index - 1)); 260 break; 261 case AccessibleText.WORD: 262 endIndex = text.lastIndexOf(' ', index); 263 if (endIndex == -1) 264 endIndex = 0; 265 startIndex = text.lastIndexOf(' ', endIndex - 1); 266 result = text.substring(startIndex + 1, endIndex); 267 break; 268 case AccessibleText.SENTENCE: 269 default: 270 endIndex = text.lastIndexOf('.', index); 271 if (endIndex == -1) 272 endIndex = 0; 273 startIndex = text.lastIndexOf('.', endIndex - 1); 274 result = text.substring(startIndex + 1, endIndex); 275 break; 276 } 277 return result; 278 } 279 280 /** 281 * Returns the caret position. This method returns -1 because JLabel don't 282 * have a caret. 283 * 284 * @return the caret position 285 */ 286 public int getCaretPosition() 287 { 288 return -1; 289 } 290 291 /** 292 * Returns the number of characters that are displayed by the JLabel. 293 * 294 * @return the number of characters that are displayed by the JLabel 295 */ 296 public int getCharCount() 297 { 298 // FIXME: Query HTML view for HTML labels. 299 return text.length(); 300 } 301 302 /** 303 * Returns the bounding box of the character at the specified index. 304 * 305 * @param index the index of the character that we return the 306 * bounds for 307 * 308 * @return the bounding box of the character at the specified index 309 */ 310 public Rectangle getCharacterBounds(int index) 311 { 312 Rectangle bounds = null; 313 View view = (View) getClientProperty(BasicHTML.propertyKey); 314 if (view != null) 315 { 316 Rectangle textR = getTextRectangle(); 317 try 318 { 319 Shape s = view.modelToView(index, textR, Position.Bias.Forward); 320 bounds = s.getBounds(); 321 } 322 catch (BadLocationException ex) 323 { 324 // Can't return something reasonable in this case. 325 } 326 } 327 return bounds; 328 } 329 330 /** 331 * Returns the rectangle inside the JLabel, in which the actual text is 332 * rendered. This method has been adopted from the Mauve testcase 333 * gnu.testlet.javax.swing.JLabel.AccessibleJLabel.getCharacterBounds. 334 * 335 * @return the rectangle inside the JLabel, in which the actual text is 336 * rendered 337 */ 338 private Rectangle getTextRectangle() 339 { 340 JLabel l = JLabel.this; 341 Rectangle textR = new Rectangle(); 342 Rectangle iconR = new Rectangle(); 343 Insets i = l.getInsets(); 344 int w = l.getWidth(); 345 int h = l.getHeight(); 346 Rectangle viewR = new Rectangle(i.left, i.top, w - i.left - i.right, 347 h - i.top - i.bottom); 348 FontMetrics fm = l.getFontMetrics(l.getFont()); 349 SwingUtilities.layoutCompoundLabel(l, fm, l.getText(), l.getIcon(), 350 l.getVerticalAlignment(), 351 l.getHorizontalAlignment(), 352 l.getVerticalTextPosition(), 353 l.getHorizontalTextPosition(), 354 viewR, iconR, textR, 355 l.getIconTextGap()); 356 return textR; 357 } 358 359 /** 360 * Returns the index of the character that is located at the specified 361 * point. 362 * 363 * @param point the location that we lookup the character for 364 * 365 * @return the index of the character that is located at the specified 366 * point 367 */ 368 public int getIndexAtPoint(Point point) 369 { 370 int index = -1; 371 View view = (View) getClientProperty(BasicHTML.propertyKey); 372 if (view != null) 373 { 374 Rectangle r = getTextRectangle(); 375 index = view.viewToModel(point.x, point.y, r, new Position.Bias[0]); 376 } 377 return index; 378 } 379 } 380 381 private static final long serialVersionUID = 5496508283662221534L; 382 383 static final String LABEL_PROPERTY = "labeledBy"; 384 385 /** 386 * The Component the label will give focus to when its mnemonic is 387 * activated. 388 */ 389 protected Component labelFor; 390 391 /** The label's text. */ 392 transient String text; 393 394 /** Where the label will be positioned horizontally. */ 395 private transient int horizontalAlignment = LEADING; 396 397 /** Where the label text will be placed horizontally relative to the icon. */ 398 private transient int horizontalTextPosition = TRAILING; 399 400 /** Where the label will be positioned vertically. */ 401 private transient int verticalAlignment = CENTER; 402 403 /** Where the label text will be place vertically relative to the icon. */ 404 private transient int verticalTextPosition = CENTER; 405 406 /** The icon painted when the label is enabled. */ 407 private transient Icon icon; 408 409 /** The icon painted when the label is disabled. */ 410 private transient Icon disabledIcon; 411 412 /** The label's mnemnonic key. */ 413 private transient int displayedMnemonic = KeyEvent.VK_UNDEFINED; 414 415 /** The index of the mnemonic character in the text. */ 416 private transient int displayedMnemonicIndex = -1; 417 418 /** The gap between the icon and the text. */ 419 private transient int iconTextGap = 4; 420 421 /** 422 * Creates a new vertically centered, horizontally on the leading edge 423 * JLabel object with text and no icon. 424 */ 425 public JLabel() 426 { 427 this("", null, LEADING); 428 } 429 430 /** 431 * Creates a new vertically and horizontally centered 432 * JLabel object with no text and the given icon. 433 * 434 * @param image The icon to use with the label, <code>null</code> permitted. 435 */ 436 public JLabel(Icon image) 437 { 438 this(null, image, CENTER); 439 } 440 441 /** 442 * Creates a new vertically centered JLabel object with no text and the 443 * given icon and horizontal alignment. By default, the text is TRAILING 444 * the image. 445 * 446 * @param image The icon to use with the label, <code>null</code> premitted. 447 * @param horizontalAlignment The horizontal alignment of the label, must be 448 * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>, 449 * <code>LEADING</code> or <code>TRAILING</code>. 450 */ 451 public JLabel(Icon image, int horizontalAlignment) 452 { 453 this(null, image, horizontalAlignment); 454 } 455 456 /** 457 * Creates a new horizontally leading and vertically centered JLabel 458 * object with no icon and the given text. 459 * 460 * @param text The text to use with the label, <code>null</code> permitted. 461 */ 462 public JLabel(String text) 463 { 464 this(text, null, LEADING); 465 } 466 467 /** 468 * Creates a new vertically centered JLabel object with no icon and the 469 * given text and horizontal alignment. 470 * 471 * @param text The text to use with the label, <code>null</code> permitted. 472 * @param horizontalAlignment The horizontal alignment of the label, must be 473 * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>, 474 * <code>LEADING</code> or <code>TRAILING</code>. 475 */ 476 public JLabel(String text, int horizontalAlignment) 477 { 478 this(text, null, horizontalAlignment); 479 } 480 481 /** 482 * Creates a new vertically centered JLabel object with the given text, 483 * icon, and horizontal alignment. 484 * 485 * @param text The text to use with the label, <code>null</code> permitted. 486 * @param icon The icon to use with the label, <code>null</code> premitted. 487 * @param horizontalAlignment The horizontal alignment of the label, must be 488 * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>, 489 * <code>LEADING</code> or <code>TRAILING</code>. 490 */ 491 public JLabel(String text, Icon icon, int horizontalAlignment) 492 { 493 if (horizontalAlignment != SwingConstants.LEFT 494 && horizontalAlignment != SwingConstants.RIGHT 495 && horizontalAlignment != SwingConstants.CENTER 496 && horizontalAlignment != SwingConstants.LEADING 497 && horizontalAlignment != SwingConstants.TRAILING) 498 throw new IllegalArgumentException(); 499 500 this.text = text; 501 this.icon = icon; 502 this.horizontalAlignment = horizontalAlignment; 503 setAlignmentX(0.0F); 504 setInheritsPopupMenu(true); 505 updateUI(); 506 } 507 508 /** 509 * Returns the label's UI delegate. 510 * 511 * @return The label's UI delegate. 512 */ 513 public LabelUI getUI() 514 { 515 return (LabelUI) ui; 516 } 517 518 /** 519 * Sets the label's UI delegate. 520 * 521 * @param ui The label's UI delegate (<code>null</code> not permitted). 522 */ 523 public void setUI(LabelUI ui) 524 { 525 super.setUI(ui); 526 } 527 528 /** 529 * Resets the label's UI delegate to the default UI for the current look and 530 * feel. 531 */ 532 public void updateUI() 533 { 534 setUI((LabelUI) UIManager.getUI(this)); 535 } 536 537 /** 538 * Returns a name to identify which look and feel class will be 539 * the UI delegate for this label. 540 * 541 * @return <code>"LabelUI"</code> 542 */ 543 public String getUIClassID() 544 { 545 return "LabelUI"; 546 } 547 548 /** 549 * Returns a string describing the attributes for the <code>JLabel</code> 550 * component, for use in debugging. The return value is guaranteed to be 551 * non-<code>null</code>, but the format of the string may vary between 552 * implementations. 553 * 554 * @return A string describing the attributes of the <code>JLabel</code>. 555 */ 556 protected String paramString() 557 { 558 StringBuffer sb = new StringBuffer(super.paramString()); 559 sb.append(",defaultIcon="); 560 if (icon != null) 561 sb.append(icon); 562 sb.append(",disabledIcon="); 563 if (disabledIcon != null) 564 sb.append(disabledIcon); 565 sb.append(",horizontalAlignment="); 566 sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString( 567 horizontalAlignment)); 568 sb.append(",horizontalTextPosition="); 569 sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString( 570 horizontalTextPosition)); 571 sb.append(",iconTextGap=").append(iconTextGap); 572 sb.append(",labelFor="); 573 if (labelFor != null) 574 sb.append(labelFor); 575 sb.append(",text="); 576 if (text != null) 577 sb.append(text); 578 sb.append(",verticalAlignment="); 579 sb.append(SwingUtilities.convertVerticalAlignmentCodeToString( 580 verticalAlignment)); 581 sb.append(",verticalTextPosition="); 582 sb.append(SwingUtilities.convertVerticalAlignmentCodeToString( 583 verticalTextPosition)); 584 return sb.toString(); 585 } 586 587 /** 588 * Returns the text displayed by the label. 589 * 590 * @return The label text (possibly <code>null</code>). 591 * 592 * @see #setText(String) 593 */ 594 public String getText() 595 { 596 return text; 597 } 598 599 /** 600 * Sets the text for the label and sends a {@link PropertyChangeEvent} (with 601 * the name 'text') to all registered listeners. This method will also 602 * update the <code>displayedMnemonicIndex</code>, if necessary. 603 * 604 * @param newText The text (<code>null</code> permitted). 605 * 606 * @see #getText() 607 * @see #getDisplayedMnemonicIndex() 608 */ 609 public void setText(String newText) 610 { 611 if (text == null && newText == null) 612 return; 613 if (text != null && text.equals(newText)) 614 return; 615 616 String oldText = text; 617 text = newText; 618 firePropertyChange("text", oldText, newText); 619 620 if (text != null) 621 setDisplayedMnemonicIndex(text.toUpperCase().indexOf(displayedMnemonic)); 622 else 623 setDisplayedMnemonicIndex(-1); 624 revalidate(); 625 repaint(); 626 } 627 628 /** 629 * Returns the active icon. The active icon is painted when the label is 630 * enabled. 631 * 632 * @return The active icon. 633 * 634 * @see #setIcon(Icon) 635 * @see #getDisabledIcon() 636 */ 637 public Icon getIcon() 638 { 639 return icon; 640 } 641 642 /** 643 * Sets the icon for the label (this is a bound property with the name 644 * 'icon'). This icon will be displayed when the label is enabled. 645 * 646 * @param newIcon The icon (<code>null</code> permitted). 647 * 648 * @see #getIcon() 649 * @see #setDisabledIcon(Icon) 650 */ 651 public void setIcon(Icon newIcon) 652 { 653 if (icon != newIcon) 654 { 655 Icon oldIcon = icon; 656 icon = newIcon; 657 firePropertyChange("icon", oldIcon, newIcon); 658 repaint(); 659 } 660 } 661 662 /** 663 * Returns the disabled icon. The disabled icon is painted when the label is 664 * disabled. If the disabled icon is <code>null</code> and the active icon 665 * is an {@link ImageIcon}, this method returns a grayed version of the icon. 666 * The grayed version of the icon becomes the <code>disabledIcon</code>. 667 * 668 * @return The disabled icon. 669 * 670 * @see #setDisabledIcon(Icon) 671 */ 672 public Icon getDisabledIcon() 673 { 674 if (disabledIcon == null && icon instanceof ImageIcon) 675 disabledIcon = new ImageIcon( 676 GrayFilter.createDisabledImage(((ImageIcon) icon).getImage())); 677 678 return disabledIcon; 679 } 680 681 /** 682 * Sets the icon displayed when the label is disabled (this is a bound 683 * property with the name 'disabledIcon'). 684 * 685 * @param newIcon The disabled icon (<code>null</code> permitted). 686 * 687 * @see #getDisabledIcon() 688 */ 689 public void setDisabledIcon(Icon newIcon) 690 { 691 if (disabledIcon != newIcon) 692 { 693 Icon oldIcon = disabledIcon; 694 disabledIcon = newIcon; 695 firePropertyChange("disabledIcon", oldIcon, newIcon); 696 } 697 } 698 699 /** 700 * Sets the keycode that will be the label's mnemonic (this is a bound 701 * property with the name 'displayedMnemonic'). If the label is used as a 702 * label for another component, the label will give focus to that component 703 * when the mnemonic is activated. 704 * 705 * @param mnemonic The keycode to use for the mnemonic. 706 * 707 * @see #getDisplayedMnemonic() 708 */ 709 public void setDisplayedMnemonic(int mnemonic) 710 { 711 if (displayedMnemonic != mnemonic) 712 { 713 int old = displayedMnemonic; 714 displayedMnemonic = mnemonic; 715 firePropertyChange("displayedMnemonic", old, displayedMnemonic); 716 if (text != null) 717 setDisplayedMnemonicIndex(text.toUpperCase().indexOf(mnemonic)); 718 } 719 } 720 721 /** 722 * Sets the character that will be the label's mnemonic. If the 723 * label is used as a label for another component, the label will give 724 * focus to that component when the mnemonic is activated via the keyboard. 725 * 726 * @param mnemonic The character to use for the mnemonic (this will be 727 * converted to the equivalent upper case character). 728 * 729 * @see #getDisplayedMnemonic() 730 */ 731 public void setDisplayedMnemonic(char mnemonic) 732 { 733 setDisplayedMnemonic((int) Character.toUpperCase(mnemonic)); 734 } 735 736 /** 737 * Returns the keycode that is used for the label's mnemonic. 738 * 739 * @return The keycode that is used for the label's mnemonic. 740 * 741 * @see #setDisplayedMnemonic(int) 742 */ 743 public int getDisplayedMnemonic() 744 { 745 return displayedMnemonic; 746 } 747 748 /** 749 * Sets the index of the character in the text that will be underlined to 750 * indicate that it is the mnemonic character for the label. You only need 751 * to call this method if you wish to override the automatically calculated 752 * character index. For instance, for a label "Find Next" with the mnemonic 753 * character 'n', you might wish to underline the second occurrence of 'n' 754 * rather than the first (which is the default). 755 * <br><br> 756 * Note that this method does not validate the character at the specified 757 * index to ensure that it matches the key code returned by 758 * {@link #getDisplayedMnemonic()}. 759 * 760 * @param newIndex The index of the character to underline. 761 * 762 * @throws IllegalArgumentException If index less than -1 or index is greater 763 * than or equal to the label length. 764 * 765 * @see #getDisplayedMnemonicIndex() 766 * @since 1.4 767 */ 768 public void setDisplayedMnemonicIndex(int newIndex) 769 throws IllegalArgumentException 770 { 771 int maxValid = -1; 772 if (text != null) 773 maxValid = text.length() - 1; 774 if (newIndex < -1 || newIndex > maxValid) 775 throw new IllegalArgumentException(); 776 777 if (newIndex != displayedMnemonicIndex) 778 { 779 int oldIndex = displayedMnemonicIndex; 780 displayedMnemonicIndex = newIndex; 781 firePropertyChange("displayedMnemonicIndex", oldIndex, newIndex); 782 } 783 } 784 785 /** 786 * Returns the index of the character in the label's text that will be 787 * underlined (to indicate that it is the mnemonic character), or -1 if no 788 * character is to be underlined. 789 * 790 * @return The index of the character that will be underlined. 791 * 792 * @see #setDisplayedMnemonicIndex(int) 793 * @since 1.4 794 */ 795 public int getDisplayedMnemonicIndex() 796 { 797 return displayedMnemonicIndex; 798 } 799 800 /** 801 * Checks the specified key to ensure that it is valid as a horizontal 802 * alignment, throwing an {@link IllegalArgumentException} if the key is 803 * invalid. Valid keys are {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 804 * {@link #LEADING} and {@link #TRAILING}. 805 * 806 * @param key The key to check. 807 * @param message The message of the exception to be thrown if the key is 808 * invalid. 809 * 810 * @return The key if it is valid. 811 * 812 * @throws IllegalArgumentException If the key is invalid. 813 */ 814 protected int checkHorizontalKey(int key, String message) 815 { 816 if (key != LEFT && key != CENTER && key != RIGHT && key != LEADING 817 && key != TRAILING) 818 throw new IllegalArgumentException(message); 819 else 820 return key; 821 } 822 823 /** 824 * Checks the specified key to ensure that it is valid as a vertical 825 * alignment, throwing an {@link IllegalArgumentException} if the key is 826 * invalid. Valid keys are {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}. 827 * 828 * @param key The key to check. 829 * @param message The message of the exception to be thrown if the key is 830 * invalid. 831 * 832 * @return The key if it is valid. 833 * 834 * @throws IllegalArgumentException If the key is invalid. 835 */ 836 protected int checkVerticalKey(int key, String message) 837 { 838 if (key != TOP && key != BOTTOM && key != CENTER) 839 throw new IllegalArgumentException(message); 840 else 841 return key; 842 } 843 844 /** 845 * Returns the gap between the icon and the text. 846 * 847 * @return The gap between the icon and the text. 848 * 849 * @see #setIconTextGap(int) 850 */ 851 public int getIconTextGap() 852 { 853 return iconTextGap; 854 } 855 856 /** 857 * Sets the gap between the icon and the text, in the case that both are 858 * visible (this is a bound property with the name 'iconTextGap'). 859 * 860 * @param newGap The gap (in pixels). 861 * 862 * @see #getIconTextGap() 863 */ 864 public void setIconTextGap(int newGap) 865 { 866 if (iconTextGap != newGap) 867 { 868 firePropertyChange("iconTextGap", iconTextGap, newGap); 869 iconTextGap = newGap; 870 } 871 } 872 873 /** 874 * Returns the vertical alignment of the label (one of 875 * {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}). The default value 876 * depends on the installed look and feel, but is usually {@link #CENTER}. 877 * 878 * @return The vertical alignment. 879 * 880 * @see #setVerticalAlignment(int) 881 */ 882 public int getVerticalAlignment() 883 { 884 return verticalAlignment; 885 } 886 887 /** 888 * Sets the vertical alignment for the label (this is a bound property with 889 * the name 'verticalAlignment'). The vertical alignment determines where 890 * the label (icon and text) will be placed vertically within the component 891 * bounds. Valid alignment codes are {@link #TOP}, {@link #CENTER} and 892 * {@link #BOTTOM}. 893 * 894 * @param alignment The vertical alignment of the label. 895 * 896 * @throws IllegalArgumentException if <code>alignment</code> is not one of 897 * the specified values. 898 * 899 * @see #getVerticalAlignment() 900 */ 901 public void setVerticalAlignment(int alignment) 902 { 903 if (alignment == verticalAlignment) 904 return; 905 906 int oldAlignment = verticalAlignment; 907 verticalAlignment = checkVerticalKey(alignment, "verticalAlignment"); 908 firePropertyChange("verticalAlignment", oldAlignment, verticalAlignment); 909 } 910 911 /** 912 * Returns the horizontal alignment of the label (one of {@link #LEFT}, 913 * {@link #CENTER}, {@link #RIGHT}, {@link #LEADING} and {@link #TRAILING}). 914 * The default value depends on the installed look and feel, but is usually 915 * {@link #LEFT}. 916 * 917 * @return The horizontal alignment. 918 * 919 * @see #setHorizontalAlignment(int) 920 */ 921 public int getHorizontalAlignment() 922 { 923 return horizontalAlignment; 924 } 925 926 /** 927 * Sets the horizontal alignment for the label (this is a bound property with 928 * the name 'horizontalAlignment'). The horizontal alignment determines where 929 * the label (icon and text) will be placed horizontally within the 930 * component bounds. Valid alignment codes are {@link #LEFT}, 931 * {@link #CENTER}, {@link #RIGHT}, {@link #LEADING} and {@link #TRAILING}. 932 * 933 * @param alignment The horizontal alignment of the label. 934 * 935 * @throws IllegalArgumentException if <code>alignment</code> is not one of 936 * the specified values. 937 * 938 * @see #getHorizontalAlignment() 939 */ 940 public void setHorizontalAlignment(int alignment) 941 { 942 if (horizontalAlignment == alignment) 943 return; 944 945 int oldAlignment = horizontalAlignment; 946 horizontalAlignment = checkHorizontalKey(alignment, "horizontalAlignment"); 947 firePropertyChange("horizontalAlignment", oldAlignment, 948 horizontalAlignment); 949 } 950 951 /** 952 * Returns the vertical position of the label's text relative to the icon. 953 * This will be one of {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}. 954 * 955 * @return The vertical position of the label's text relative to the icon. 956 * 957 * @see #setVerticalTextPosition(int) 958 */ 959 public int getVerticalTextPosition() 960 { 961 return verticalTextPosition; 962 } 963 964 /** 965 * Sets the vertical position of the label's text relative to the icon (this 966 * is a bound property with the name 'verticalTextPosition'). Valid 967 * positions are {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}. 968 * 969 * @param textPosition The vertical text position. 970 * 971 * @throws IllegalArgumentException if <code>textPosition</code> is not one 972 * of the specified values. 973 */ 974 public void setVerticalTextPosition(int textPosition) 975 { 976 if (textPosition != verticalTextPosition) 977 { 978 int oldPos = verticalTextPosition; 979 verticalTextPosition = checkVerticalKey(textPosition, 980 "verticalTextPosition"); 981 firePropertyChange("verticalTextPosition", oldPos, 982 verticalTextPosition); 983 } 984 } 985 986 /** 987 * Returns the horizontal position of the label's text relative to the icon. 988 * This will be one of {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 989 * {@link #LEADING} and {@link #TRAILING}. 990 * 991 * @return The horizontal position of the label's text relative to the icon. 992 * 993 * @see #setHorizontalTextPosition(int) 994 */ 995 public int getHorizontalTextPosition() 996 { 997 return horizontalTextPosition; 998 } 999 1000 /** 1001 * Sets the horizontal position of the label's text relative to the icon (this 1002 * is a bound property with the name 'horizontalTextPosition'). Valid 1003 * positions are {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 1004 * {@link #LEADING} and {@link #TRAILING}. 1005 * 1006 * @param textPosition The horizontal text position. 1007 * 1008 * @throws IllegalArgumentException if <code>textPosition</code> is not one 1009 * of the specified values. 1010 */ 1011 public void setHorizontalTextPosition(int textPosition) 1012 { 1013 if (textPosition != horizontalTextPosition) 1014 { 1015 int oldPos = horizontalTextPosition; 1016 horizontalTextPosition = checkHorizontalKey(textPosition, 1017 "horizontalTextPosition"); 1018 firePropertyChange("horizontalTextPosition", oldPos, 1019 horizontalTextPosition); 1020 } 1021 } 1022 1023 /** 1024 * Returns false if the current icon image (current icon will depend on 1025 * whether the label is enabled) is not equal to the passed in image. 1026 * 1027 * @param img The image to check. 1028 * @param infoflags The bitwise inclusive OR of ABORT, ALLBITS, ERROR, 1029 * FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, and WIDTH 1030 * @param x The x position 1031 * @param y The y position 1032 * @param w The width 1033 * @param h The height 1034 * 1035 * @return Whether the current icon image is equal to the image given. 1036 */ 1037 public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, 1038 int h) 1039 { 1040 Icon currIcon = isEnabled() ? icon : disabledIcon; 1041 1042 // XXX: Is this the correct way to check for image equality? 1043 if (currIcon != null && currIcon instanceof ImageIcon) 1044 return (((ImageIcon) currIcon).getImage() == img); 1045 1046 return false; 1047 } 1048 1049 /** 1050 * Returns the component that this <code>JLabel</code> is providing the label 1051 * for. This component will typically receive the focus when the label's 1052 * mnemonic key is activated via the keyboard. 1053 * 1054 * @return The component (possibly <code>null</code>). 1055 */ 1056 public Component getLabelFor() 1057 { 1058 return labelFor; 1059 } 1060 1061 /** 1062 * Sets the component that this <code>JLabel</code> is providing the label 1063 * for (this is a bound property with the name 'labelFor'). This component 1064 * will typically receive the focus when the label's mnemonic key is 1065 * activated via the keyboard. 1066 * 1067 * @param c the component (<code>null</code> permitted). 1068 * 1069 * @see #getLabelFor() 1070 */ 1071 public void setLabelFor(Component c) 1072 { 1073 if (c != labelFor) 1074 { 1075 Component oldLabelFor = labelFor; 1076 labelFor = c; 1077 firePropertyChange("labelFor", oldLabelFor, labelFor); 1078 1079 // We put the label into the client properties for the labeled 1080 // component so that it can be read by the AccessibleJComponent. 1081 // The other option would be to reserve a default visible field 1082 // in JComponent, but since this is relatively seldomly used, it 1083 // would be unnecessary waste of memory to do so. 1084 if (oldLabelFor instanceof JComponent) 1085 { 1086 ((JComponent) oldLabelFor).putClientProperty(LABEL_PROPERTY, null); 1087 } 1088 1089 if (labelFor instanceof JComponent) 1090 { 1091 ((JComponent) labelFor).putClientProperty(LABEL_PROPERTY, this); 1092 } 1093 1094 } 1095 } 1096 1097 /** 1098 * Sets the font for the label (this a bound property with the name 'font'). 1099 * 1100 * @param f The font (<code>null</code> permitted). 1101 */ 1102 public void setFont(Font f) 1103 { 1104 super.setFont(f); 1105 repaint(); 1106 } 1107 1108 /** 1109 * Returns the object that provides accessibility features for this 1110 * <code>JLabel</code> component. 1111 * 1112 * @return The accessible context (an instance of {@link AccessibleJLabel}). 1113 */ 1114 public AccessibleContext getAccessibleContext() 1115 { 1116 if (accessibleContext == null) 1117 accessibleContext = new AccessibleJLabel(); 1118 return accessibleContext; 1119 } 1120 }