Source for javax.swing.JLabel

   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.classpath.NotImplementedException;
  42: 
  43: import java.awt.Component;
  44: import java.awt.Font;
  45: import java.awt.Image;
  46: import java.awt.Point;
  47: import java.awt.Rectangle;
  48: import java.awt.event.KeyEvent;
  49: 
  50: import javax.accessibility.Accessible;
  51: import javax.accessibility.AccessibleContext;
  52: import javax.accessibility.AccessibleExtendedComponent;
  53: import javax.accessibility.AccessibleRole;
  54: import javax.accessibility.AccessibleText;
  55: import javax.swing.plaf.LabelUI;
  56: import javax.swing.text.AttributeSet;
  57: import javax.swing.text.SimpleAttributeSet;
  58: 
  59: /**
  60:  * A swing widget that displays a text message and/or an icon.
  61:  */
  62: public class JLabel extends JComponent implements Accessible, SwingConstants
  63: {
  64: 
  65:   /**
  66:    * Provides the accessibility features for the <code>JLabel</code>
  67:    * component.
  68:    */
  69:   protected class AccessibleJLabel
  70:     extends JComponent.AccessibleJComponent
  71:     implements AccessibleText, AccessibleExtendedComponent
  72:   {
  73:     
  74:     /**
  75:      * Returns the accessible name.
  76:      * 
  77:      * @return The accessible name.
  78:      */
  79:     public String getAccessibleName()
  80:     {
  81:       if (accessibleName != null)
  82:         return accessibleName;
  83:       if (text != null)
  84:         return text;
  85:       else
  86:         return super.getAccessibleName();
  87:     }
  88:     
  89:     /**
  90:      * Returns the accessible role for the <code>JLabel</code> component.
  91:      *
  92:      * @return {@link AccessibleRole#LABEL}.
  93:      */
  94:     public AccessibleRole getAccessibleRole()
  95:     {
  96:       return AccessibleRole.LABEL;
  97:     }
  98:     
  99:     /**
 100:      * Returns the selected text. This is null since JLabels
 101:      * are not selectable.
 102:      *
 103:      * @return <code>null</code> because JLabels cannot have selected text
 104:      */
 105:     public String getSelectedText()
 106:     {
 107:       // We return null here since JLabel's text is not selectable.
 108:       return null;
 109:     }
 110: 
 111:     /**
 112:      * Returns the start index of the selected text.
 113:      *
 114:      * @return the start index of the selected text
 115:      */
 116:     public int getSelectionStart()
 117:     {
 118:       // JLabel don't have selected text, so we return -1 here.
 119:       return -1;
 120:     }
 121: 
 122:     /**
 123:      * Returns the end index of the selected text.
 124:      *
 125:      * @return the end index of the selected text
 126:      */
 127:     public int getSelectionEnd()
 128:     {
 129:       // JLabel don't have selected text, so we return -1 here.
 130:       return -1;
 131:     }
 132: 
 133:     /**
 134:      * Returns an {@link AttributeSet} that reflects the text attributes of
 135:      * the specified character. We return an empty
 136:      * <code>AttributeSet</code> here, because JLabels don't support text
 137:      * attributes (at least not yet).
 138:      *
 139:      * @param index the index of the character
 140:      *
 141:      * @return an {@link AttributeSet} that reflects the text attributes of
 142:      *         the specified character
 143:      */
 144:     public AttributeSet getCharacterAttribute(int index)
 145:     {
 146:       // FIXME: Return null here for simple labels, and query the HTML
 147:       // view for HTML labels.
 148:       return new SimpleAttributeSet();
 149:     }
 150: 
 151:     /**
 152:      * Returns the character, word or sentence at the specified index. The
 153:      * <code>part</code> parameter determines what is returned, the character,
 154:      * word or sentence after the index.
 155:      *
 156:      * @param part one of {@link AccessibleText#CHARACTER},
 157:      *             {@link AccessibleText#WORD} or
 158:      *             {@link AccessibleText#SENTENCE}, specifying what is returned
 159:      * @param index the index
 160:      *
 161:      * @return the character, word or sentence after <code>index</code>
 162:      */
 163:     public String getAtIndex(int part, int index)
 164:     {
 165:       String result = "";
 166:       int startIndex = -1;
 167:       int endIndex = -1;
 168:       switch(part)
 169:         {
 170:         case AccessibleText.CHARACTER:
 171:           result = String.valueOf(text.charAt(index));
 172:           break;
 173:         case AccessibleText.WORD:
 174:           startIndex = text.lastIndexOf(' ', index);
 175:           endIndex = text.indexOf(' ', startIndex + 1);
 176:           if (endIndex == -1)
 177:             endIndex = startIndex + 1;
 178:           result = text.substring(startIndex + 1, endIndex);
 179:           break;
 180:         case AccessibleText.SENTENCE:
 181:         default:
 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:         }
 189:       return result;
 190:     }
 191: 
 192:     /**
 193:      * Returns the character, word or sentence after the specified index. The
 194:      * <code>part</code> parameter determines what is returned, the character,
 195:      * word or sentence after the index.
 196:      *
 197:      * @param part one of {@link AccessibleText#CHARACTER},
 198:      *             {@link AccessibleText#WORD} or
 199:      *             {@link AccessibleText#SENTENCE}, specifying what is returned
 200:      * @param index the index
 201:      *
 202:      * @return the character, word or sentence after <code>index</code>
 203:      */
 204:     public String getAfterIndex(int part, int index)
 205:     {
 206:       String result = "";
 207:       int startIndex = -1;
 208:       int endIndex = -1;
 209:       switch(part)
 210:         {
 211:         case AccessibleText.CHARACTER:
 212:           result = String.valueOf(text.charAt(index + 1));
 213:           break;
 214:         case AccessibleText.WORD:
 215:           startIndex = text.indexOf(' ', index);
 216:           endIndex = text.indexOf(' ', startIndex + 1);
 217:           if (endIndex == -1)
 218:             endIndex = startIndex + 1;
 219:           result = text.substring(startIndex + 1, endIndex);
 220:           break;
 221:         case AccessibleText.SENTENCE:
 222:         default:
 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:         }
 230:       return result;
 231:     }
 232: 
 233:     /**
 234:      * Returns the character, word or sentence before the specified index. The
 235:      * <code>part</code> parameter determines what is returned, the character,
 236:      * word or sentence before the index.
 237:      *
 238:      * @param part one of {@link AccessibleText#CHARACTER},
 239:      *             {@link AccessibleText#WORD} or
 240:      *             {@link AccessibleText#SENTENCE}, specifying what is returned
 241:      * @param index the index
 242:      *
 243:      * @return the character, word or sentence before <code>index</code>
 244:      */
 245:     public String getBeforeIndex(int part, int index)
 246:     {
 247:       String result = "";
 248:       int startIndex = -1;
 249:       int endIndex = -1;
 250:       switch(part)
 251:         {
 252:         case AccessibleText.CHARACTER:
 253:           result = String.valueOf(text.charAt(index - 1));
 254:           break;
 255:         case AccessibleText.WORD:
 256:           endIndex = text.lastIndexOf(' ', index);
 257:           if (endIndex == -1)
 258:             endIndex = 0;
 259:           startIndex = text.lastIndexOf(' ', endIndex - 1);
 260:           result = text.substring(startIndex + 1, endIndex);
 261:           break;
 262:         case AccessibleText.SENTENCE:
 263:         default:
 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:         }
 271:       return result;
 272:     }
 273: 
 274:     /**
 275:      * Returns the caret position. This method returns -1 because JLabel don't
 276:      * have a caret.
 277:      *
 278:      * @return the caret position
 279:      */
 280:     public int getCaretPosition()
 281:     {
 282:       return -1;
 283:     }
 284: 
 285:     /**
 286:      * Returns the number of characters that are displayed by the JLabel.
 287:      *
 288:      * @return the number of characters that are displayed by the JLabel
 289:      */
 290:     public int getCharCount()
 291:     {
 292:       // FIXME: Query HTML view for HTML labels.
 293:       return text.length();
 294:     }
 295: 
 296:     /**
 297:      * Returns the bounding box of the character at the specified index.
 298:      *
 299:      * @param index the index of the character that we return the
 300:      *        bounds for
 301:      *
 302:      * @return the bounding box of the character at the specified index
 303:      */
 304:     public Rectangle getCharacterBounds(int index)
 305:       throws NotImplementedException
 306:     {
 307:       // FIXME: Implement this correctly.
 308:       return new Rectangle();
 309:     }
 310: 
 311:     /**
 312:      * Returns the index of the character that is located at the specified
 313:      * point.
 314:      *
 315:      * @param point the location that we lookup the character for
 316:      *
 317:      * @return the index of the character that is located at the specified
 318:      *         point
 319:      */
 320:     public int getIndexAtPoint(Point point)
 321:       throws NotImplementedException
 322:     {
 323:       // FIXME: Implement this correctly.
 324:       return 0;
 325:     }
 326:   }
 327: 
 328:   private static final long serialVersionUID = 5496508283662221534L;
 329: 
 330:   static final String LABEL_PROPERTY = "labeledBy";
 331: 
 332:   /**
 333:    * The Component the label will give focus to when its mnemonic is
 334:    * activated.
 335:    */
 336:   protected Component labelFor;
 337: 
 338:   /** The label's text. */
 339:   transient String text;
 340: 
 341:   /** Where the label will be positioned horizontally. */
 342:   private transient int horizontalAlignment = LEADING;
 343: 
 344:   /** Where the label text will be placed horizontally relative to the icon. */
 345:   private transient int horizontalTextPosition = TRAILING;
 346: 
 347:   /** Where the label will be positioned vertically. */
 348:   private transient int verticalAlignment = CENTER;
 349: 
 350:   /** Where the label text will be place vertically relative to the icon. */
 351:   private transient int verticalTextPosition = CENTER;
 352: 
 353:   /** The icon painted when the label is enabled. */
 354:   private transient Icon icon;
 355: 
 356:   /** The icon painted when the label is disabled. */
 357:   private transient Icon disabledIcon;
 358: 
 359:   /** The label's mnemnonic key. */
 360:   private transient int displayedMnemonic = KeyEvent.VK_UNDEFINED;
 361: 
 362:   /** The index of the menemonic character in the text. */
 363:   private transient int displayedMnemonicIndex = -1;
 364: 
 365:   /** The gap between the icon and the text. */
 366:   private transient int iconTextGap = 4;
 367: 
 368:   /**
 369:    * Creates a new vertically centered, horizontally on the leading edge
 370:    * JLabel object with text and no icon.
 371:    */
 372:   public JLabel()
 373:   {
 374:     this("", null, LEADING);
 375:   }
 376: 
 377:   /**
 378:    * Creates a new vertically and horizontally centered
 379:    * JLabel object with no text and the given icon.
 380:    *
 381:    * @param image The icon to use with the label.
 382:    */
 383:   public JLabel(Icon image)
 384:   {
 385:     this("", image, CENTER);
 386:   }
 387: 
 388:   /**
 389:    * Creates a new vertically centered JLabel object with no text and the
 390:    * given icon and horizontal alignment. By default, the text is TRAILING
 391:    * the image.
 392:    *
 393:    * @param image The icon to use with the label.
 394:    * @param horizontalAlignment The horizontal alignment of the label.
 395:    */
 396:   public JLabel(Icon image, int horizontalAlignment)
 397:   {
 398:     this("", image, horizontalAlignment);
 399:   }
 400: 
 401:   /**
 402:    * Creates a new horizontally leading and vertically centered JLabel 
 403:    * object with no icon and the given text.
 404:    *
 405:    * @param text The text to use with the label.
 406:    */
 407:   public JLabel(String text)
 408:   {
 409:     this(text, null, LEADING);
 410:   }
 411: 
 412:   /**
 413:    * Creates a new vertically centered JLabel object with no icon and the
 414:    * given text and horizontal alignment.
 415:    *
 416:    * @param text The text to use with the label.
 417:    * @param horizontalAlignment The horizontal alignment of the label.
 418:    */
 419:   public JLabel(String text, int horizontalAlignment)
 420:   {
 421:     this(text, null, horizontalAlignment);
 422:   }
 423: 
 424:   /**
 425:    * Creates a new vertically centered JLabel object with the given text,
 426:    * icon, and horizontal alignment.
 427:    *
 428:    * @param text The text to use with the label.
 429:    * @param icon The icon to use with the label.
 430:    * @param horizontalAlignment The horizontal alignment of the label.
 431:    */
 432:   public JLabel(String text, Icon icon, int horizontalAlignment)
 433:   {
 434:     this.text = text;
 435:     this.icon = icon;
 436:     this.horizontalAlignment = horizontalAlignment;
 437:     setAlignmentX(0.0F);
 438:     updateUI();
 439:   }
 440: 
 441:   /**
 442:    * This method returns the label's UI delegate.
 443:    *
 444:    * @return The label's UI delegate.
 445:    */
 446:   public LabelUI getUI()
 447:   {
 448:     return (LabelUI) ui;
 449:   }
 450: 
 451:   /**
 452:    * This method sets the label's UI delegate.
 453:    *
 454:    * @param ui The label's UI delegate.
 455:    */
 456:   public void setUI(LabelUI ui)
 457:   {
 458:     super.setUI(ui);
 459:   }
 460: 
 461:   /**
 462:    * This method resets the label's UI delegate to the default UI for the
 463:    * current look and feel.
 464:    */
 465:   public void updateUI()
 466:   {
 467:     setUI((LabelUI) UIManager.getUI(this));
 468:   }
 469: 
 470:   /**
 471:    * This method returns a name to identify which look and feel class will be
 472:    * the UI delegate for this label.
 473:    *
 474:    * @return The UIClass identifier. "LabelUI"
 475:    */
 476:   public String getUIClassID()
 477:   {
 478:     return "LabelUI";
 479:   }
 480: 
 481:   /**
 482:    * Returns a string describing the attributes for the <code>JLabel</code>
 483:    * component, for use in debugging.  The return value is guaranteed to be 
 484:    * non-<code>null</code>, but the format of the string may vary between
 485:    * implementations.
 486:    *
 487:    * @return A string describing the attributes of the <code>JLabel</code>.
 488:    */
 489:   protected String paramString()
 490:   {
 491:     StringBuffer sb = new StringBuffer(super.paramString());
 492:     sb.append(",defaultIcon=");
 493:     if (icon != null)
 494:       sb.append(icon);
 495:     sb.append(",disabledIcon=");
 496:     if (disabledIcon != null)
 497:       sb.append(disabledIcon);
 498:     sb.append(",horizontalAlignment=");
 499:     sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString(
 500:         horizontalAlignment));
 501:     sb.append(",horizontalTextPosition=");
 502:     sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString(
 503:         horizontalTextPosition));
 504:     sb.append(",iconTextGap=").append(iconTextGap);
 505:     sb.append(",labelFor=");
 506:     if (labelFor != null)
 507:       sb.append(labelFor);
 508:     sb.append(",text=");
 509:     if (text != null)
 510:       sb.append(text);
 511:     sb.append(",verticalAlignment=");
 512:     sb.append(SwingUtilities.convertVerticalAlignmentCodeToString(
 513:         verticalAlignment));
 514:     sb.append(",verticalTextPosition=");
 515:     sb.append(SwingUtilities.convertVerticalAlignmentCodeToString(
 516:         verticalTextPosition));
 517:     return sb.toString();
 518:   }
 519: 
 520:   /**
 521:    * This method returns the label text.
 522:    *
 523:    * @return The label text.
 524:    */
 525:   public String getText()
 526:   {
 527:     return text;
 528:   }
 529: 
 530:   /**
 531:    * This method changes the "text" property. The given text will be painted
 532:    * in the label.
 533:    *
 534:    * @param newText The label's text.
 535:    */
 536:   public void setText(String newText)
 537:   {
 538:     if (text != newText)
 539:       {
 540:         String oldText = text;
 541:         text = newText;
 542:         firePropertyChange("text", oldText, newText);
 543: 
 544:         if (text != null && text.length() <= displayedMnemonicIndex)
 545:           setDisplayedMnemonicIndex(text.length() - 1);
 546:         revalidate();
 547:         repaint();
 548:       }
 549:   }
 550: 
 551:   /**
 552:    * This method returns the active icon. The active icon is painted when the
 553:    * label is enabled.
 554:    *
 555:    * @return The active icon.
 556:    */
 557:   public Icon getIcon()
 558:   {
 559:     return icon;
 560:   }
 561: 
 562:   /**
 563:    * This method changes the "icon" property. This icon (the active icon) will
 564:    * be the one displayed when the label is enabled.
 565:    *
 566:    * @param newIcon The active icon.
 567:    */
 568:   public void setIcon(Icon newIcon)
 569:   {
 570:     if (icon != newIcon)
 571:       {
 572:     Icon oldIcon = icon;
 573:     icon = newIcon;
 574:     firePropertyChange("icon", oldIcon, newIcon);
 575:     repaint();
 576:       }
 577:   }
 578: 
 579:   /**
 580:    * This method returns the disabled icon. The disabled icon is painted when
 581:    * the label is disabled. If the disabled icon is null and the active icon
 582:    * is an ImageIcon, this method returns a grayed version of the icon. The
 583:    * grayed  version of the icon becomes the disabledIcon.
 584:    *
 585:    * @return The disabled icon.
 586:    */
 587:   public Icon getDisabledIcon()
 588:   {
 589:     if (disabledIcon == null && icon instanceof ImageIcon)
 590:       disabledIcon = new ImageIcon(GrayFilter.createDisabledImage(((ImageIcon) icon)
 591:                                                                   .getImage()));
 592: 
 593:     return disabledIcon;
 594:   }
 595: 
 596:   /**
 597:    * This method changes the "disabledIcon" property. This icon (the disabled
 598:    * icon) will be the one displayed when the label is disabled.
 599:    *
 600:    * @param newIcon The disabled icon.
 601:    */
 602:   public void setDisabledIcon(Icon newIcon)
 603:   {
 604:     if (disabledIcon != newIcon)
 605:       {
 606:     Icon oldIcon = disabledIcon;
 607:     disabledIcon = newIcon;
 608:     firePropertyChange("disabledIcon", oldIcon, newIcon);
 609:       }
 610:   }
 611: 
 612:   /**
 613:    * This method sets the keycode that will be the label's mnemonic. If the
 614:    * label is used as a label for another component, the label will give
 615:    * focus to that component when the mnemonic is activated.
 616:    *
 617:    * @param mnemonic The keycode to use for the mnemonic.
 618:    */
 619:   public void setDisplayedMnemonic(int mnemonic)
 620:   {
 621:     if (displayedMnemonic != mnemonic)
 622:       {
 623:     firePropertyChange("displayedMnemonic",
 624:                        displayedMnemonic, mnemonic);
 625:     displayedMnemonic = mnemonic;
 626: 
 627:     if (text != null)
 628:       setDisplayedMnemonicIndex(text.toUpperCase().indexOf(mnemonic));
 629:       }
 630:   }
 631: 
 632:   /**
 633:    * This method sets the character that will be the mnemonic used. If the
 634:    * label is used as a label for another component, the label will give
 635:    * focus to that component when the mnemonic is activated.
 636:    *
 637:    * @param mnemonic The character to use for the mnemonic.
 638:    */
 639:   public void setDisplayedMnemonic(char mnemonic)
 640:   {
 641:     setDisplayedMnemonic((int) Character.toUpperCase(mnemonic));
 642:   }
 643: 
 644:   /**
 645:    * This method returns the keycode that is used for the label's mnemonic.
 646:    *
 647:    * @return The keycode that is used for the label's mnemonic.
 648:    */
 649:   public int getDisplayedMnemonic()
 650:   {
 651:     return (int) displayedMnemonic;
 652:   }
 653: 
 654:   /**
 655:    * This method sets which character in the text will be the underlined
 656:    * character. If the given index is -1, then this indicates  that there is
 657:    * no mnemonic. If the index is less than -1 or if the index is equal to
 658:    * the length, this method will throw an IllegalArgumentException.
 659:    *
 660:    * @param newIndex The index of the character to underline.
 661:    *
 662:    * @throws IllegalArgumentException If index less than -1 or index equals
 663:    *         length.
 664:    */
 665:   public void setDisplayedMnemonicIndex(int newIndex)
 666:     throws IllegalArgumentException
 667:   {
 668:     if (newIndex < -1 || (text != null && newIndex >= text.length()))
 669:       throw new IllegalArgumentException();
 670: 
 671:     if (newIndex == -1
 672:         || text == null
 673:     || text.charAt(newIndex) != displayedMnemonic)
 674:       newIndex = -1;
 675: 
 676:     if (newIndex != displayedMnemonicIndex)
 677:       {
 678:     int oldIndex = displayedMnemonicIndex;
 679:     displayedMnemonicIndex = newIndex;
 680:     firePropertyChange("displayedMnemonicIndex",
 681:                        oldIndex, newIndex);
 682:       }
 683:   }
 684: 
 685:   /**
 686:    * This method returns which character in the text will be  the underlined
 687:    * character.
 688:    *
 689:    * @return The index of the character that will be underlined.
 690:    */
 691:   public int getDisplayedMnemonicIndex()
 692:   {
 693:     return displayedMnemonicIndex;
 694:   }
 695: 
 696:   /**
 697:    * This method ensures that the key is valid as a horizontal alignment.
 698:    * Valid keys are: LEFT, CENTER, RIGHT, LEADING, TRAILING
 699:    *
 700:    * @param key The key to check.
 701:    * @param message The message of the exception to be thrown if the key is
 702:    *        invalid.
 703:    *
 704:    * @return The key if it's valid.
 705:    *
 706:    * @throws IllegalArgumentException If the key is invalid.
 707:    */
 708:   protected int checkHorizontalKey(int key, String message)
 709:   {
 710:     if (key != LEFT && key != CENTER && key != RIGHT && key != LEADING
 711:         && key != TRAILING)
 712:       throw new IllegalArgumentException(message);
 713:     else
 714:       return key;
 715:   }
 716: 
 717:   /**
 718:    * This method ensures that the key is valid as a  vertical alignment. Valid
 719:    * keys are: TOP, CENTER, and BOTTOM.
 720:    *
 721:    * @param key The key to check.
 722:    * @param message The message of the exception to be thrown if the key is
 723:    *        invalid.
 724:    *
 725:    * @return The key if it's valid.
 726:    *
 727:    * @throws IllegalArgumentException If the key is invalid.
 728:    */
 729:   protected int checkVerticalKey(int key, String message)
 730:   {
 731:     if (key != TOP && key != BOTTOM && key != CENTER)
 732:       throw new IllegalArgumentException(message);
 733:     else
 734:       return key;
 735:   }
 736: 
 737:   /**
 738:    * This method returns the gap between the icon and the text.
 739:    *
 740:    * @return The gap between the icon and the text.
 741:    */
 742:   public int getIconTextGap()
 743:   {
 744:     return iconTextGap;
 745:   }
 746: 
 747:   /**
 748:    * This method changes the "iconTextGap" property. The iconTextGap
 749:    * determines how much space there is between the icon and the text.
 750:    *
 751:    * @param newGap The gap between the icon and the text.
 752:    */
 753:   public void setIconTextGap(int newGap)
 754:   {
 755:     if (iconTextGap != newGap)
 756:       {
 757:     firePropertyChange("iconTextGap", iconTextGap, newGap);
 758:     iconTextGap = newGap;
 759:       }
 760:   }
 761: 
 762:   /**
 763:    * This method returns the vertical alignment of the label.
 764:    *
 765:    * @return The vertical alignment of the label.
 766:    */
 767:   public int getVerticalAlignment()
 768:   {
 769:     return verticalAlignment;
 770:   }
 771: 
 772:   /**
 773:    * This method changes the "verticalAlignment" property of the label. The
 774:    * vertical alignment determines how where the label will be placed
 775:    * vertically. If the alignment is not valid, it will default to the
 776:    * center.
 777:    *
 778:    * @param alignment The vertical alignment of the label.
 779:    */
 780:   public void setVerticalAlignment(int alignment)
 781:   {
 782:     if (alignment == verticalAlignment)
 783:       return;
 784: 
 785:     int oldAlignment = verticalAlignment;
 786:     verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
 787:     firePropertyChange("verticalAlignment", oldAlignment, verticalAlignment);
 788:   }
 789: 
 790:   /**
 791:    * This method returns the horziontal alignment of the label.
 792:    *
 793:    * @return The horizontal alignment of the label.
 794:    */
 795:   public int getHorizontalAlignment()
 796:   {
 797:     return horizontalAlignment;
 798:   }
 799: 
 800:   /**
 801:    * This method changes the "horizontalAlignment" property. The horizontal
 802:    * alignment determines where the label will be placed horizontally.
 803:    *
 804:    * @param alignment The horizontal alignment of the label.
 805:    */
 806:   public void setHorizontalAlignment(int alignment)
 807:   {
 808:     if (horizontalAlignment == alignment)
 809:       return;
 810:     
 811:     int oldAlignment = horizontalAlignment;
 812:     horizontalAlignment = checkHorizontalKey(alignment, "horizontalAlignment");
 813:     firePropertyChange("horizontalAlignment", oldAlignment,
 814:                        horizontalAlignment);
 815:   }
 816: 
 817:   /**
 818:    * This method returns the vertical text position of the label.
 819:    *
 820:    * @return The vertical text position of the label.
 821:    */
 822:   public int getVerticalTextPosition()
 823:   {
 824:     return verticalTextPosition;
 825:   }
 826: 
 827:   /**
 828:    * This method changes the "verticalTextPosition" property of the label. The
 829:    * vertical text position determines where the text will be placed
 830:    * vertically relative to the icon.
 831:    *
 832:    * @param textPosition The vertical text position.
 833:    */
 834:   public void setVerticalTextPosition(int textPosition)
 835:   {
 836:     if (textPosition != verticalTextPosition)
 837:       {
 838:     int oldPos = verticalTextPosition;
 839:     verticalTextPosition = checkVerticalKey(textPosition,
 840:                                             "verticalTextPosition");
 841:     firePropertyChange("verticalTextPosition", oldPos,
 842:                        verticalTextPosition);
 843:       }
 844:   }
 845: 
 846:   /**
 847:    * This method returns the horizontal text position of the label.
 848:    *
 849:    * @return The horizontal text position.
 850:    */
 851:   public int getHorizontalTextPosition()
 852:   {
 853:     return horizontalTextPosition;
 854:   }
 855: 
 856:   /**
 857:    * This method changes the "horizontalTextPosition" property of the label.
 858:    * The horizontal text position determines where the text will be placed
 859:    * horizontally relative to the icon.
 860:    *
 861:    * @param textPosition The horizontal text position.
 862:    */
 863:   public void setHorizontalTextPosition(int textPosition)
 864:   {
 865:     if (textPosition != horizontalTextPosition)
 866:       {
 867:     int oldPos = horizontalTextPosition;
 868:     horizontalTextPosition = checkHorizontalKey(textPosition,
 869:                                                 "horizontalTextPosition");
 870:     firePropertyChange("horizontalTextPosition", oldPos,
 871:                        horizontalTextPosition);
 872:       }
 873:   }
 874: 
 875:   /**
 876:    * This method simply returns false if the current icon image (current  icon
 877:    * will depend on whether the label is enabled) is not equal to the passed
 878:    * in image.
 879:    *
 880:    * @param img The image to check.
 881:    * @param infoflags The bitwise inclusive OR of ABORT, ALLBITS, ERROR,
 882:    *        FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, and WIDTH
 883:    * @param x The x position
 884:    * @param y The y position
 885:    * @param w The width
 886:    * @param h The height
 887:    *
 888:    * @return Whether the current icon image is equal to the image given.
 889:    */
 890:   public boolean imageUpdate(Image img, int infoflags, int x, int y, int w,
 891:                              int h)
 892:   {
 893:     Icon currIcon = isEnabled() ? icon : disabledIcon;
 894: 
 895:     // XXX: Is this the correct way to check for image equality?
 896:     if (currIcon != null && currIcon instanceof ImageIcon)
 897:       return (((ImageIcon) currIcon).getImage() == img);
 898: 
 899:     return false;
 900:   }
 901: 
 902:   /**
 903:    * This method returns the component that the label gives focus to  when the
 904:    * mnemonic is activated.
 905:    *
 906:    * @return The component that gets focus when the label's mnemonic is
 907:    *         activated.
 908:    */
 909:   public Component getLabelFor()
 910:   {
 911:     return labelFor;
 912:   }
 913: 
 914:   /**
 915:    * This method changes the "labelFor" property. The component that the label
 916:    * is acting as a label for will request focus when the label's  mnemonic
 917:    * is activated.
 918:    *
 919:    * @param c The component that gets focus when the label's mnemonic is
 920:    *        activated.
 921:    */
 922:   public void setLabelFor(Component c)
 923:   {
 924:     if (c != labelFor)
 925:       {
 926:         Component oldLabelFor = labelFor;
 927:         labelFor = c;
 928:         firePropertyChange("labelFor", oldLabelFor, labelFor);
 929: 
 930:         // We put the label into the client properties for the labeled
 931:         // component so that it can be read by the AccessibleJComponent.
 932:         // The other option would be to reserve a default visible field
 933:         // in JComponent, but since this is relatively seldomly used, it
 934:         // would be unnecessary waste of memory to do so.
 935:         if (oldLabelFor instanceof JComponent)
 936:           {
 937:             ((JComponent) oldLabelFor).putClientProperty(LABEL_PROPERTY, null);
 938:           }
 939: 
 940:         if (labelFor instanceof JComponent)
 941:           {
 942:             ((JComponent) labelFor).putClientProperty(LABEL_PROPERTY, this);
 943:           }
 944: 
 945:       }
 946:   }
 947: 
 948:   /**
 949:    * This method overrides setFont so that we can call for a repaint after the
 950:    * font is changed.
 951:    *
 952:    * @param f The font for this label.
 953:    */
 954:   public void setFont(Font f)
 955:   {
 956:     super.setFont(f);
 957:     repaint();
 958:   }
 959: 
 960:   /**
 961:    * Returns the object that provides accessibility features for this
 962:    * <code>JLabel</code> component.
 963:    *
 964:    * @return The accessible context (an instance of {@link AccessibleJLabel}).
 965:    */
 966:   public AccessibleContext getAccessibleContext()
 967:   {
 968:     if (accessibleContext == null)
 969:       accessibleContext = new AccessibleJLabel();
 970:     return accessibleContext;
 971:   }
 972: }