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