Source for javax.swing.UIManager

   1: /* UIManager.java --
   2:    Copyright (C) 2002, 2003, 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.Color;
  44: import java.awt.Dimension;
  45: import java.awt.Font;
  46: import java.awt.Insets;
  47: import java.beans.PropertyChangeListener;
  48: import java.beans.PropertyChangeSupport;
  49: import java.io.Serializable;
  50: import java.util.Enumeration;
  51: import java.util.Locale;
  52: 
  53: import javax.swing.border.Border;
  54: import javax.swing.plaf.ComponentUI;
  55: import javax.swing.plaf.metal.MetalLookAndFeel;
  56: 
  57: /**
  58:  * Manages the current {@link LookAndFeel} and any auxiliary {@link LookAndFeel}
  59:  * instances.
  60:  */
  61: public class UIManager implements Serializable
  62: {
  63:   /**
  64:    * Represents the basic information about a {@link LookAndFeel} (LAF), so
  65:    * that a list of installed LAFs can be presented without actually loading
  66:    * the LAF class(es).
  67:    */
  68:   public static class LookAndFeelInfo
  69:   {
  70:     String name, clazz;
  71: 
  72:     /**
  73:      * Creates a new instance.
  74:      *
  75:      * @param name  the look and feel name.
  76:      * @param clazz  the look and feel class name.
  77:      */
  78:     public LookAndFeelInfo(String name,
  79:                            String clazz)
  80:     {
  81:       this.name  = name;
  82:       this.clazz = clazz;
  83:     }
  84: 
  85:     /**
  86:      * Returns the name of the look and feel.
  87:      *
  88:      * @return The name of the look and feel.
  89:      */
  90:     public String getName()
  91:     {
  92:       return name;
  93:     }
  94: 
  95:     /**
  96:      * Returns the fully qualified class name for the {@link LookAndFeel}.
  97:      *
  98:      * @return The fully qualified class name for the {@link LookAndFeel}.
  99:      */
 100:     public String getClassName()
 101:     {
 102:       return clazz;
 103:     }
 104: 
 105:     /**
 106:      * Returns a String representation of the LookAndFeelInfo object.
 107:      *
 108:      * @return a String representation of the LookAndFeelInfo object
 109:      */
 110:     public String toString()
 111:     {
 112:       CPStringBuilder s = new CPStringBuilder();
 113:       s.append(getClass().getName());
 114:       s.append('[');
 115:       s.append(getName());
 116:       s.append(' ');
 117:       s.append(getClassName());
 118:       s.append(']');
 119:       return s.toString();
 120:     }
 121:   }
 122: 
 123:   /**
 124:    * A UIDefaults subclass that multiplexes between itself and a 'fallback'
 125:    * UIDefaults instance. This is used to protect the L&F UIDefaults from beeing
 126:    * overwritten by applications.
 127:    */
 128:   private static class MultiplexUIDefaults
 129:     extends UIDefaults
 130:   {
 131:     private class MultiplexEnumeration
 132:       implements Enumeration
 133:     {
 134:       Enumeration[] enums;
 135:       int i;
 136:       MultiplexEnumeration(Enumeration e1, Enumeration e2)
 137:       {
 138:         enums = new Enumeration[]{ e1, e2 };
 139:         i = 0;
 140:       }
 141: 
 142:       public boolean hasMoreElements()
 143:       {
 144:         return enums[i].hasMoreElements() || i < enums.length - 1;
 145:       }
 146: 
 147:       public Object nextElement()
 148:       {
 149:         Object val = enums[i].nextElement();
 150:         if (! enums[i].hasMoreElements() && i < enums.length - 1)
 151:           i++;
 152:         return val;
 153:       }
 154: 
 155:     }
 156: 
 157:     UIDefaults fallback;
 158: 
 159:     /**
 160:      * Creates a new <code>MultiplexUIDefaults</code> instance with
 161:      * <code>d</code> as the fallback defaults.
 162:      *
 163:      * @param d  the fallback defaults (<code>null</code> not permitted).
 164:      */
 165:     MultiplexUIDefaults(UIDefaults d)
 166:     {
 167:       if (d == null)
 168:         throw new NullPointerException();
 169:       fallback = d;
 170:     }
 171: 
 172:     public Object get(Object key)
 173:     {
 174:       Object val = super.get(key);
 175:       if (val == null)
 176:         val = fallback.get(key);
 177:       return val;
 178:     }
 179: 
 180:     public Object get(Object key, Locale l)
 181:     {
 182:       Object val = super.get(key, l);
 183:       if (val == null)
 184:         val = fallback.get(key, l);
 185:       return val;
 186:     }
 187: 
 188:     public Object remove(Object key)
 189:     {
 190:       Object val = super.remove(key);
 191:       if (val == null)
 192:         val = fallback.remove(key);
 193:       return val;
 194:     }
 195: 
 196:     public int size()
 197:     {
 198:       return super.size() + fallback.size();
 199:     }
 200: 
 201:     public Enumeration keys()
 202:     {
 203:       return new MultiplexEnumeration(super.keys(), fallback.keys());
 204:     }
 205: 
 206:     public Enumeration elements()
 207:     {
 208:       return new MultiplexEnumeration(super.elements(), fallback.elements());
 209:     }
 210:   }
 211: 
 212:   private static final long serialVersionUID = -5547433830339189365L;
 213: 
 214:   /** The installed look and feel(s). */
 215:   static LookAndFeelInfo [] installed = {
 216:     new LookAndFeelInfo("Metal", "javax.swing.plaf.metal.MetalLookAndFeel"),
 217:     new LookAndFeelInfo("GNU", "gnu.javax.swing.plaf.gnu.GNULookAndFeel")
 218:   };
 219: 
 220:   /** The installed auxiliary look and feels. */
 221:   static LookAndFeel[] auxLookAndFeels;
 222: 
 223:   /** The current look and feel. */
 224:   static LookAndFeel currentLookAndFeel;
 225: 
 226:   static MultiplexUIDefaults currentUIDefaults;
 227: 
 228:   static UIDefaults lookAndFeelDefaults;
 229: 
 230:   /** Property change listener mechanism. */
 231:   static PropertyChangeSupport listeners
 232:       = new PropertyChangeSupport(UIManager.class);
 233: 
 234:   static
 235:   {
 236:     String defaultlaf = System.getProperty("swing.defaultlaf");
 237:     try
 238:       {
 239:         if (defaultlaf != null)
 240:           {
 241:             setLookAndFeel(defaultlaf);
 242:           }
 243:         else
 244:           {
 245:             setLookAndFeel(new MetalLookAndFeel());
 246:           }
 247:       }
 248:     catch (Exception ex)
 249:       {
 250:         System.err.println("cannot initialize Look and Feel: " + defaultlaf);
 251:         System.err.println("error: " + ex.toString());
 252:         ex.printStackTrace();
 253:         System.err.println("falling back to Metal Look and Feel");
 254:         try
 255:           {
 256:             setLookAndFeel(new MetalLookAndFeel());
 257:           }
 258:         catch (Exception ex2)
 259:         {
 260:           throw (Error) new AssertionError("There must be no problem installing"
 261:                                            + " the MetalLookAndFeel.")
 262:                                            .initCause(ex2);
 263:         }
 264:       }
 265:   }
 266: 
 267:   /**
 268:    * Creates a new instance of the <code>UIManager</code>.  There is no need
 269:    * to construct an instance of this class, since all methods are static.
 270:    */
 271:   public UIManager()
 272:   {
 273:     // Do nothing here.
 274:   }
 275: 
 276:   /**
 277:    * Add a <code>PropertyChangeListener</code> to the listener list.
 278:    *
 279:    * @param listener the listener to add
 280:    */
 281:   public static void addPropertyChangeListener(PropertyChangeListener listener)
 282:   {
 283:     listeners.addPropertyChangeListener(listener);
 284:   }
 285: 
 286:   /**
 287:    * Remove a <code>PropertyChangeListener</code> from the listener list.
 288:    *
 289:    * @param listener the listener to remove
 290:    */
 291:   public static void removePropertyChangeListener(PropertyChangeListener
 292:           listener)
 293:   {
 294:     listeners.removePropertyChangeListener(listener);
 295:   }
 296: 
 297:   /**
 298:    * Returns an array of all added <code>PropertyChangeListener</code> objects.
 299:    *
 300:    * @return an array of listeners
 301:    *
 302:    * @since 1.4
 303:    */
 304:   public static PropertyChangeListener[] getPropertyChangeListeners()
 305:   {
 306:     return listeners.getPropertyChangeListeners();
 307:   }
 308: 
 309:   /**
 310:    * Add a {@link LookAndFeel} to the list of auxiliary look and feels.
 311:    *
 312:    * @param laf  the auxiliary look and feel (<code>null</code> not permitted).
 313:    *
 314:    * @throws NullPointerException if <code>laf</code> is <code>null</code>.
 315:    *
 316:    * @see #getAuxiliaryLookAndFeels()
 317:    */
 318:   public static void addAuxiliaryLookAndFeel(LookAndFeel laf)
 319:   {
 320:     if (laf == null)
 321:       throw new NullPointerException("Null 'laf' argument.");
 322:     if (auxLookAndFeels == null)
 323:       {
 324:         auxLookAndFeels = new LookAndFeel[1];
 325:         auxLookAndFeels[0] = laf;
 326:         return;
 327:       }
 328: 
 329:     LookAndFeel[] temp = new LookAndFeel[auxLookAndFeels.length + 1];
 330:     System.arraycopy(auxLookAndFeels, 0, temp, 0, auxLookAndFeels.length);
 331:     auxLookAndFeels = temp;
 332:     auxLookAndFeels[auxLookAndFeels.length - 1] = laf;
 333:   }
 334: 
 335:   /**
 336:    * Removes a {@link LookAndFeel} (LAF) from the list of auxiliary LAFs.
 337:    *
 338:    * @param laf  the LAF to remove.
 339:    *
 340:    * @return <code>true</code> if the LAF was removed, and <code>false</code>
 341:    *         otherwise.
 342:    */
 343:   public static boolean removeAuxiliaryLookAndFeel(LookAndFeel laf)
 344:   {
 345:     if (auxLookAndFeels == null)
 346:       return false;
 347:     int count = auxLookAndFeels.length;
 348:     if (count == 1 && auxLookAndFeels[0] == laf)
 349:       {
 350:         auxLookAndFeels = null;
 351:         return true;
 352:       }
 353:     for (int i = 0; i < count; i++)
 354:       {
 355:         if (auxLookAndFeels[i] == laf)
 356:           {
 357:             LookAndFeel[] temp = new LookAndFeel[auxLookAndFeels.length - 1];
 358:             if (i == 0)
 359:               {
 360:                 System.arraycopy(auxLookAndFeels, 1, temp, 0, count - 1);
 361:               }
 362:             else if (i == count - 1)
 363:               {
 364:                 System.arraycopy(auxLookAndFeels, 0, temp, 0, count - 1);
 365:               }
 366:             else
 367:               {
 368:                 System.arraycopy(auxLookAndFeels, 0, temp, 0, i);
 369:                 System.arraycopy(auxLookAndFeels, i + 1, temp, i,
 370:                         count - i - 1);
 371:               }
 372:             auxLookAndFeels = temp;
 373:             return true;
 374:           }
 375:       }
 376:     return false;
 377:   }
 378: 
 379:   /**
 380:    * Returns an array (possibly <code>null</code>) containing the auxiliary
 381:    * {@link LookAndFeel}s that are in use.  These are used by the
 382:    * {@link javax.swing.plaf.multi.MultiLookAndFeel} class.
 383:    *
 384:    * @return The auxiliary look and feels (possibly <code>null</code>).
 385:    *
 386:    * @see #addAuxiliaryLookAndFeel(LookAndFeel)
 387:    */
 388:   public static LookAndFeel[] getAuxiliaryLookAndFeels()
 389:   {
 390:     return auxLookAndFeels;
 391:   }
 392: 
 393:   /**
 394:    * Returns an object from the {@link UIDefaults} table for the current
 395:    * {@link LookAndFeel}.
 396:    *
 397:    * @param key  the key.
 398:    *
 399:    * @return The object.
 400:    */
 401:   public static Object get(Object key)
 402:   {
 403:     return getDefaults().get(key);
 404:   }
 405: 
 406:   /**
 407:    * Returns an object from the {@link UIDefaults} table for the current
 408:    * {@link LookAndFeel}.
 409:    *
 410:    * @param key  the key.
 411:    *
 412:    * @return The object.
 413:    *
 414:    * @since 1.4
 415:    */
 416:   public static Object get(Object key, Locale locale)
 417:   {
 418:     return getDefaults().get(key, locale);
 419:   }
 420: 
 421:   /**
 422:    * Returns a boolean value from the defaults table.  If there is no value
 423:    * for the specified key, or the value is not an instance of {@link Boolean},
 424:    * this method returns <code>false</code>.
 425:    *
 426:    * @param key  the key (<code>null</code> not permitted).
 427:    *
 428:    * @return The boolean value associated with the specified key.
 429:    *
 430:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 431:    *
 432:    * @since 1.4
 433:    */
 434:   public static boolean getBoolean(Object key)
 435:   {
 436:     Object value = get(key);
 437:     if (value instanceof Boolean)
 438:       return ((Boolean) value).booleanValue();
 439:     return false;
 440:   }
 441: 
 442:   /**
 443:    * Returns a boolean value from the defaults table.  If there is no value
 444:    * for the specified key, or the value is not an instance of {@link Boolean},
 445:    * this method returns <code>false</code>.
 446:    *
 447:    * @param key  the key (<code>null</code> not permitted).
 448:    * @param locale  the locale.
 449:    *
 450:    * @return The boolean value associated with the specified key.
 451:    *
 452:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 453:    *
 454:    * @since 1.4
 455:    */
 456:   public static boolean getBoolean(Object key, Locale locale)
 457:   {
 458:     Object value = get(key, locale);
 459:     if (value instanceof Boolean)
 460:       return ((Boolean) value).booleanValue();
 461:     return false;
 462:   }
 463: 
 464:   /**
 465:    * Returns a border from the defaults table.
 466:    *
 467:    * @param key  the key (<code>null</code> not permitted).
 468:    *
 469:    * @return The border associated with the given key, or <code>null</code>.
 470:    *
 471:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 472:    */
 473:   public static Border getBorder(Object key)
 474:   {
 475:     Object value = get(key);
 476:     if (value instanceof Border)
 477:       return (Border) value;
 478:     return null;
 479:   }
 480: 
 481:   /**
 482:    * Returns a border from the defaults table.
 483:    *
 484:    * @param key  the key (<code>null</code> not permitted).
 485:    * @param locale  the locale.
 486:    *
 487:    * @return The border associated with the given key, or <code>null</code>.
 488:    *
 489:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 490:    *
 491:    * @since 1.4
 492:    */
 493:   public static Border getBorder(Object key, Locale locale)
 494:   {
 495:     Object value = get(key, locale);
 496:     if (value instanceof Border)
 497:       return (Border) value;
 498:     return null;
 499:   }
 500: 
 501:   /**
 502:    * Returns a drawing color from the defaults table.
 503:    *
 504:    * @param key  the key (<code>null</code> not permitted).
 505:    *
 506:    * @return The color associated with the given key, or <code>null</code>.
 507:    *
 508:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 509:    */
 510:   public static Color getColor(Object key)
 511:   {
 512:     Object value = get(key);
 513:     if (value instanceof Color)
 514:       return (Color) value;
 515:     return null;
 516:   }
 517: 
 518:   /**
 519:    * Returns a drawing color from the defaults table.
 520:    *
 521:    * @param key  the key (<code>null</code> not permitted).
 522:    * @param locale  the locale.
 523:    *
 524:    * @return The color associated with the given key, or <code>null</code>.
 525:    *
 526:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 527:    *
 528:    * @since 1.4
 529:    */
 530:   public static Color getColor(Object key, Locale locale)
 531:   {
 532:     Object value = get(key, locale);
 533:     if (value instanceof Color)
 534:       return (Color) value;
 535:     return null;
 536:   }
 537: 
 538:   /**
 539:    * The fully qualified class name of the cross platform (Metal) look and feel.
 540:    * This string can be passed to Class.forName()
 541:    *
 542:    * @return <code>"javax.swing.plaf.metal.MetalLookAndFeel"</code>
 543:    */
 544:   public static String getCrossPlatformLookAndFeelClassName()
 545:   {
 546:     return "javax.swing.plaf.metal.MetalLookAndFeel";
 547:   }
 548: 
 549:   /**
 550:    * Returns the default values for this look and feel.
 551:    *
 552:    * @return The {@link UIDefaults} for the current {@link LookAndFeel}.
 553:    */
 554:   public static UIDefaults getDefaults()
 555:   {
 556:     if (currentUIDefaults == null)
 557:       currentUIDefaults = new MultiplexUIDefaults(new UIDefaults());
 558:     return currentUIDefaults;
 559:   }
 560: 
 561:   /**
 562:    * Returns a dimension from the defaults table.
 563:    *
 564:    * @param key  the key (<code>null</code> not permitted).
 565:    *
 566:    * @return The color associated with the given key, or <code>null</code>.
 567:    *
 568:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 569:    */
 570:   public static Dimension getDimension(Object key)
 571:   {
 572:     Object value = get(key);
 573:     if (value instanceof Dimension)
 574:       return (Dimension) value;
 575:     return null;
 576:   }
 577: 
 578:   /**
 579:    * Returns a dimension from the defaults table.
 580:    *
 581:    * @param key  the key (<code>null</code> not permitted).
 582:    * @param locale  the locale.
 583:    *
 584:    * @return The color associated with the given key, or <code>null</code>.
 585:    *
 586:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 587:    * @since 1.4
 588:    */
 589:   public static Dimension getDimension(Object key, Locale locale)
 590:   {
 591:     Object value = get(key, locale);
 592:     if (value instanceof Dimension)
 593:       return (Dimension) value;
 594:     return null;
 595:   }
 596: 
 597:   /**
 598:    * Retrieves a font from the defaults table of the current
 599:    * LookAndFeel.
 600:    *
 601:    * @param key an Object that specifies the font. Typically,
 602:    *        this is a String such as
 603:    *        <code>TitledBorder.font</code>.
 604:    *
 605:    * @return The font associated with the given key, or <code>null</code>.
 606:    *
 607:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 608:    */
 609:   public static Font getFont(Object key)
 610:   {
 611:     Object value = get(key);
 612:     if (value instanceof Font)
 613:       return (Font) value;
 614:     return null;
 615:   }
 616: 
 617:   /**
 618:    * Retrieves a font from the defaults table of the current
 619:    * LookAndFeel.
 620:    *
 621:    * @param key an Object that specifies the font. Typically,
 622:    *        this is a String such as
 623:    *        <code>TitledBorder.font</code>.
 624:    * @param locale  the locale.
 625:    *
 626:    * @return The font associated with the given key, or <code>null</code>.
 627:    *
 628:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 629:    *
 630:    * @since 1.4
 631:    */
 632:   public static Font getFont(Object key, Locale locale)
 633:   {
 634:     Object value = get(key, locale);
 635:     if (value instanceof Font)
 636:       return (Font) value;
 637:     return null;
 638:   }
 639: 
 640:   /**
 641:    * Returns an icon from the defaults table.
 642:    *
 643:    * @param key  the key (<code>null</code> not permitted).
 644:    *
 645:    * @return The icon associated with the given key, or <code>null</code>.
 646:    *
 647:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 648:    */
 649:   public static Icon getIcon(Object key)
 650:   {
 651:     Object value = get(key);
 652:     if (value instanceof Icon)
 653:       return (Icon) value;
 654:     return null;
 655:   }
 656: 
 657:   /**
 658:    * Returns an icon from the defaults table.
 659:    *
 660:    * @param key  the key (<code>null</code> not permitted).
 661:    * @param locale  the locale.
 662:    *
 663:    * @return The icon associated with the given key, or <code>null</code>.
 664:    *
 665:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 666:    * @since 1.4
 667:    */
 668:   public static Icon getIcon(Object key, Locale locale)
 669:   {
 670:     Object value = get(key, locale);
 671:     if (value instanceof Icon)
 672:       return (Icon) value;
 673:     return null;
 674:   }
 675: 
 676:   /**
 677:    * Returns an Insets object from the defaults table.
 678:    *
 679:    * @param key  the key (<code>null</code> not permitted).
 680:    *
 681:    * @return The insets associated with the given key, or <code>null</code>.
 682:    *
 683:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 684:    */
 685:   public static Insets getInsets(Object key)
 686:   {
 687:     Object o = get(key);
 688:     if (o instanceof Insets)
 689:       return (Insets) o;
 690:     else
 691:       return null;
 692:   }
 693: 
 694:   /**
 695:    * Returns an Insets object from the defaults table.
 696:    *
 697:    * @param key  the key (<code>null</code> not permitted).
 698:    * @param locale  the locale.
 699:    *
 700:    * @return The insets associated with the given key, or <code>null</code>.
 701:    *
 702:    * @throws NullPointerException if <code>key</code> is <code>null</code>.
 703:    * @since 1.4
 704:    */
 705:   public static Insets getInsets(Object key, Locale locale)
 706:   {
 707:     Object o = get(key, locale);
 708:     if (o instanceof Insets)
 709:       return (Insets) o;
 710:     else
 711:       return null;
 712:   }
 713: 
 714:   /**
 715:    * Returns an array containing information about the {@link LookAndFeel}s
 716:    * that are installed.
 717:    *
 718:    * @return A list of the look and feels that are available (installed).
 719:    */
 720:   public static LookAndFeelInfo[] getInstalledLookAndFeels()
 721:   {
 722:     return installed;
 723:   }
 724: 
 725:   /**
 726:    * Returns the integer value of the {@link Integer} associated with the
 727:    * given key.  If there is no value, or the value is not an instance of
 728:    * {@link Integer}, this method returns 0.
 729:    *
 730:    * @param key  the key (<code>null</code> not permitted).
 731:    *
 732:    * @return The integer value associated with the given key, or 0.
 733:    */
 734:   public static int getInt(Object key)
 735:   {
 736:     Object x = get(key);
 737:     if (x instanceof Integer)
 738:       return ((Integer) x).intValue();
 739:     return 0;
 740:   }
 741: 
 742:   /**
 743:    * Returns the integer value of the {@link Integer} associated with the
 744:    * given key.  If there is no value, or the value is not an instance of
 745:    * {@link Integer}, this method returns 0.
 746:    *
 747:    * @param key  the key (<code>null</code> not permitted).
 748:    * @param locale  the locale.
 749:    *
 750:    * @return The integer value associated with the given key, or 0.
 751:    *
 752:    * @since 1.4
 753:    */
 754:   public static int getInt(Object key, Locale locale)
 755:   {
 756:     Object x = get(key, locale);
 757:     if (x instanceof Integer)
 758:       return ((Integer) x).intValue();
 759:     return 0;
 760:   }
 761: 
 762:   /**
 763:    * Returns the current look and feel (which may be <code>null</code>).
 764:    *
 765:    * @return The current look and feel.
 766:    *
 767:    * @see #setLookAndFeel(LookAndFeel)
 768:    */
 769:   public static LookAndFeel getLookAndFeel()
 770:   {
 771:     return currentLookAndFeel;
 772:   }
 773: 
 774:   /**
 775:    * Returns the <code>UIDefaults</code> table of the currently active
 776:    * look and feel.
 777:    *
 778:    * @return The {@link UIDefaults} for the current {@link LookAndFeel}.
 779:    */
 780:   public static UIDefaults getLookAndFeelDefaults()
 781:   {
 782:     return lookAndFeelDefaults;
 783:   }
 784: 
 785:   /**
 786:    * Returns the {@link String} associated with the given key.  If the value
 787:    * is not a {@link String}, this method returns <code>null</code>.
 788:    *
 789:    * @param key  the key (<code>null</code> not permitted).
 790:    *
 791:    * @return The string associated with the given key, or <code>null</code>.
 792:    */
 793:   public static String getString(Object key)
 794:   {
 795:     Object s = get(key);
 796:     if (s instanceof String)
 797:       return (String) s;
 798:     return null;
 799:   }
 800: 
 801:   /**
 802:    * Returns the {@link String} associated with the given key.  If the value
 803:    * is not a {@link String}, this method returns <code>null</code>.
 804:    *
 805:    * @param key  the key (<code>null</code> not permitted).
 806:    * @param locale  the locale.
 807:    *
 808:    * @return The string associated with the given key, or <code>null</code>.
 809:    *
 810:    * @since 1.4
 811:    */
 812:   public static String getString(Object key, Locale locale)
 813:   {
 814:     Object s = get(key, locale);
 815:     if (s instanceof String)
 816:       return (String) s;
 817:     return null;
 818:   }
 819: 
 820:   /**
 821:    * Returns the name of the {@link LookAndFeel} class that implements the
 822:    * native systems look and feel if there is one, otherwise the name
 823:    * of the default cross platform LookAndFeel class.
 824:    *
 825:    * @return The fully qualified class name for the system look and feel.
 826:    *
 827:    * @see #getCrossPlatformLookAndFeelClassName()
 828:    */
 829:   public static String getSystemLookAndFeelClassName()
 830:   {
 831:     return getCrossPlatformLookAndFeelClassName();
 832:   }
 833: 
 834:   /**
 835:    * Returns UI delegate from the current {@link LookAndFeel} that renders the
 836:    * target component.
 837:    *
 838:    * @param target  the target component.
 839:    */
 840:   public static ComponentUI getUI(JComponent target)
 841:   {
 842:     return getDefaults().getUI(target);
 843:   }
 844: 
 845:   /**
 846:    * Creates a new look and feel and adds it to the current array.
 847:    *
 848:    * @param name  the look and feel name.
 849:    * @param className  the fully qualified name of the class that implements the
 850:    *                   look and feel.
 851:    */
 852:   public static void installLookAndFeel(String name, String className)
 853:   {
 854:     installLookAndFeel(new LookAndFeelInfo(name, className));
 855:   }
 856: 
 857:   /**
 858:    * Adds the specified look and feel to the current array and then calls
 859:    * setInstalledLookAndFeels(javax.swing.UIManager.LookAndFeelInfo[]).
 860:    */
 861:   public static void installLookAndFeel(LookAndFeelInfo info)
 862:   {
 863:     LookAndFeelInfo[] newInstalled = new LookAndFeelInfo[installed.length + 1];
 864:     System.arraycopy(installed, 0, newInstalled, 0, installed.length);
 865:     newInstalled[newInstalled.length - 1] = info;
 866:     setInstalledLookAndFeels(newInstalled);
 867:   }
 868: 
 869:   /**
 870:    * Stores an object in the defaults table.
 871:    *
 872:    * @param key  the key.
 873:    * @param value  the value.
 874:    */
 875:   public static Object put(Object key, Object value)
 876:   {
 877:     return getDefaults().put(key, value);
 878:   }
 879: 
 880:   /**
 881:    * Replaces the current array of installed LookAndFeelInfos.
 882:    */
 883:   public static void setInstalledLookAndFeels(UIManager.LookAndFeelInfo[] infos)
 884:   {
 885:     installed = infos;
 886:   }
 887: 
 888:   /**
 889:    * Sets the current {@link LookAndFeel}.
 890:    *
 891:    * @param newLookAndFeel  the new look and feel (<code>null</code> permitted).
 892:    *
 893:    * @throws UnsupportedLookAndFeelException if the look and feel is not
 894:    *         supported on the current platform.
 895:    *
 896:    * @see LookAndFeel#isSupportedLookAndFeel()
 897:    */
 898:   public static void setLookAndFeel(LookAndFeel newLookAndFeel)
 899:     throws UnsupportedLookAndFeelException
 900:   {
 901:     if (newLookAndFeel != null && ! newLookAndFeel.isSupportedLookAndFeel())
 902:       throw new UnsupportedLookAndFeelException(newLookAndFeel.getName()
 903:                                          + " not supported on this platform");
 904:     LookAndFeel oldLookAndFeel = currentLookAndFeel;
 905:     if (oldLookAndFeel != null)
 906:       oldLookAndFeel.uninitialize();
 907: 
 908:     // Set the current default look and feel using a LookAndFeel object.
 909:     currentLookAndFeel = newLookAndFeel;
 910:     if (newLookAndFeel != null)
 911:       {
 912:         newLookAndFeel.initialize();
 913:         lookAndFeelDefaults = newLookAndFeel.getDefaults();
 914:         if (currentUIDefaults == null)
 915:           currentUIDefaults =
 916:             new MultiplexUIDefaults(lookAndFeelDefaults);
 917:         else
 918:           currentUIDefaults.fallback = lookAndFeelDefaults;
 919:       }
 920:     else
 921:       {
 922:         currentUIDefaults = null;
 923:       }
 924:     listeners.firePropertyChange("lookAndFeel", oldLookAndFeel, newLookAndFeel);
 925:     //revalidate();
 926:     //repaint();
 927:   }
 928: 
 929:   /**
 930:    * Set the current default look and feel using a class name.
 931:    *
 932:    * @param className  the look and feel class name.
 933:    *
 934:    * @throws UnsupportedLookAndFeelException if the look and feel is not
 935:    *         supported on the current platform.
 936:    *
 937:    * @see LookAndFeel#isSupportedLookAndFeel()
 938:    */
 939:   public static void setLookAndFeel(String className)
 940:     throws ClassNotFoundException, InstantiationException, IllegalAccessException,
 941:     UnsupportedLookAndFeelException
 942:   {
 943:     Class c = Class.forName(className, true,
 944:                             Thread.currentThread().getContextClassLoader());
 945:     LookAndFeel a = (LookAndFeel) c.newInstance(); // throws class-cast-exception
 946:     setLookAndFeel(a);
 947:   }
 948: }