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