Coverage Report - org.argouml.ui.LookAndFeelMgr
 
Classes in this File Line Coverage Branch Coverage Complexity
LookAndFeelMgr
37%
52/138
23%
18/76
3.714
 
 1  
 /* $Id: LookAndFeelMgr.java 17841 2010-01-12 19:17:52Z linus $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    linus
 11  
  *****************************************************************************
 12  
  *
 13  
  * Some portions of this file was previously release using the BSD License:
 14  
  */
 15  
 
 16  
 // Copyright (c) 1996-2007 The Regents of the University of California. All
 17  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 18  
 // software and its documentation without fee, and without a written
 19  
 // agreement is hereby granted, provided that the above copyright notice
 20  
 // and this paragraph appear in all copies.  This software program and
 21  
 // documentation are copyrighted by The Regents of the University of
 22  
 // California. The software program and documentation are supplied "AS
 23  
 // IS", without any accompanying services from The Regents. The Regents
 24  
 // does not warrant that the operation of the program will be
 25  
 // uninterrupted or error-free. The end-user understands that the program
 26  
 // was developed for research purposes and is advised not to rely
 27  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 28  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 29  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 30  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 31  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 32  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 33  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 34  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 35  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 36  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 37  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 38  
 
 39  
 /*
 40  
  * LookAndFeelMgr.java
 41  
  *
 42  
  * Created on 12 October 2002, 22:25
 43  
  */
 44  
 
 45  
 package org.argouml.ui;
 46  
 
 47  
 import java.awt.Font;
 48  
 
 49  
 import javax.swing.LookAndFeel;
 50  
 import javax.swing.UIManager;
 51  
 import javax.swing.UnsupportedLookAndFeelException;
 52  
 import javax.swing.plaf.metal.DefaultMetalTheme;
 53  
 import javax.swing.plaf.metal.MetalLookAndFeel;
 54  
 import javax.swing.plaf.metal.MetalTheme;
 55  
 
 56  
 import org.apache.log4j.Logger;
 57  
 import org.argouml.application.api.Argo;
 58  
 import org.argouml.configuration.Configuration;
 59  
 
 60  
 /**
 61  
  * Controls the look and feel and theme of ArgoUML. LookAndFeelMgr has a
 62  
  * "Look and Feel" property which represents the Swing Pluggable Look-and-feel.
 63  
  * It also has a "Theme" property which represents a MetalTheme when the
 64  
  * Metal look-and-feel is selected
 65  
  * (for other LAFs, a theme is not supported). <p>
 66  
  *
 67  
  * Themes have 2 kinds of names:
 68  
  * 1. The "display name" shown in the UI,
 69  
  * which is retrieved by theme.getName(), and
 70  
  * 2. the "class name",
 71  
  * which is the name of the theme class,
 72  
  * and is retrieved by theme.getClass().getName().
 73  
  *
 74  
  * @author Bob Tarling
 75  
  * @author Jeremy Jones
 76  
  */
 77  
 public final class LookAndFeelMgr {
 78  
     /**
 79  
      * Logger.
 80  
      */
 81  900
     private static final Logger LOG = Logger.getLogger(LookAndFeelMgr.class);
 82  
 
 83  
     /**
 84  
      * The instance.
 85  
      */
 86  900
     private static final LookAndFeelMgr        SINGLETON = new LookAndFeelMgr();
 87  
 
 88  
     /**
 89  
      * The Metal look and feel class name.
 90  
      */
 91  
     private static final String                 METAL_LAF_CLASS_NAME =
 92  
         "javax.swing.plaf.metal.MetalLookAndFeel";
 93  
 
 94  
     /**
 95  
      * Display name and configuration key for default look and feel and theme.
 96  
      */
 97  
     private static final String                        DEFAULT_KEY = "Default";
 98  
 
 99  
     // JasonsThemes
 100  900
     private static final MetalTheme                DEFAULT_THEME =
 101  
         new JasonsTheme();
 102  900
     private static final MetalTheme                BIG_THEME =
 103  
         new JasonsBigTheme();
 104  900
     private static final MetalTheme                HUGE_THEME =
 105  
         new JasonsHugeTheme();
 106  
 
 107  
     /**
 108  
      * The list of supported MetalThemes.
 109  
      */
 110  900
     private static final MetalTheme[] THEMES = {
 111  
         DEFAULT_THEME,
 112  
         BIG_THEME,
 113  
         HUGE_THEME,
 114  
         new DefaultMetalTheme(),
 115  
     };
 116  
 
 117  
     /**
 118  
      * The class name of Swing's default look and feel (will be used if
 119  
      * the LookAndFeel property is null).
 120  
      */
 121  
     private String                                defaultLafClass;
 122  
 
 123  
     /**
 124  
      * Get the single instance of the LookAndFeelMgr.
 125  
      *
 126  
      * @return the single instance of the LookAndFeelMgr
 127  
      */
 128  
     public static LookAndFeelMgr getInstance() {
 129  17741
         return SINGLETON;
 130  
     }
 131  
 
 132  
     /**
 133  
      * Creates a new instance of LookAndFeelMgr.
 134  
      */
 135  900
     private LookAndFeelMgr() {
 136  900
         LookAndFeel laf = UIManager.getLookAndFeel();
 137  900
         if (laf != null) {
 138  900
             defaultLafClass = laf.getClass().getName();
 139  
         } else {
 140  0
             defaultLafClass = null;
 141  
         }
 142  900
     }
 143  
 
 144  
     /**
 145  
      * Sets the appearance of the UI using the current values of
 146  
      * the LookAndFeel and Theme properties.
 147  
      */
 148  
     public void initializeLookAndFeel() {
 149  900
         String n = getCurrentLookAndFeel();
 150  900
         setLookAndFeel(n);
 151  900
         if (isThemeCompatibleLookAndFeel(n)) {
 152  0
             setTheme(getMetalTheme(getCurrentThemeClassName()));
 153  
         }
 154  900
     }
 155  
 
 156  
     /**
 157  
      * Detecting the theme from the command line.
 158  
      *
 159  
      * @param arg the argument from the command line
 160  
      * @return the theme
 161  
      */
 162  
     public String getThemeClassNameFromArg(String arg) {
 163  1800
         if (arg.equalsIgnoreCase("-big")) {
 164  0
             return BIG_THEME.getClass().getName();
 165  1800
         } else if (arg.equalsIgnoreCase("-huge")) {
 166  0
             return HUGE_THEME.getClass().getName();
 167  
         }
 168  1800
         return null;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Outputs command-line arguments supported by this class.
 173  
      */
 174  
     public void printThemeArgs() {
 175  0
         System.err.println("  -big            use big fonts");
 176  0
         System.err.println("  -huge           use huge fonts");
 177  0
     }
 178  
 
 179  
     /**
 180  
      * Returns the display names of the available look and feel choices.
 181  
      * This may be used to fill a combobox to allow the user
 182  
      * to select the LAF.
 183  
      *
 184  
      * @return        look and feel display names
 185  
      */
 186  
     public String[] getAvailableLookAndFeelNames() {
 187  19
         UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
 188  
 
 189  19
         String[] names = new String[lafs.length + 1];
 190  19
         names[0] = DEFAULT_KEY;
 191  95
         for (int i = 0; i < lafs.length; ++i) {
 192  76
             names[i + 1] = lafs[i].getName();
 193  
         }
 194  
 
 195  19
         return names;
 196  
     }
 197  
 
 198  
     /**
 199  
      * Returns the display names of the available theme choices.
 200  
      * This may be used to fill a combobox to allow the user
 201  
      * to select the theme.
 202  
      *
 203  
      * @return        theme display names
 204  
      */
 205  
     public String[] getAvailableThemeNames() {
 206  19
         String[] names = new String[LookAndFeelMgr.THEMES.length];
 207  95
         for (int i = 0; i < THEMES.length; ++i) {
 208  76
             names[i] = THEMES[i].getName();
 209  
         }
 210  
 
 211  19
         return names;
 212  
     }
 213  
 
 214  
     /**
 215  
      * Returns the Look and Feel class name identifier for the specified
 216  
      * display name, or null if no such Look and Feel is found.
 217  
      *
 218  
      * @param        name        display name of desired look and feel
 219  
      * @return                        class name for desired look and feel
 220  
      */
 221  
     public String getLookAndFeelFromName(String name) {
 222  38
         if (name == null || DEFAULT_KEY.equals(name)) {
 223  38
             return null;
 224  
         }
 225  
 
 226  0
         String className = null;
 227  
 
 228  0
         UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
 229  0
         for (int i = 0; i < lafs.length; ++i) {
 230  0
             if (lafs[i].getName().equals(name)) {
 231  0
                 className = lafs[i].getClassName();
 232  
             }
 233  
         }
 234  
 
 235  0
         return className;
 236  
     }
 237  
 
 238  
     /**
 239  
      * Returns the theme class name identifier for the specified
 240  
      * display name, or null if no such theme is found.
 241  
      *
 242  
      * @param        name        display name of desired theme
 243  
      * @return                        class name for desired theme
 244  
      */
 245  
     public String getThemeFromName(String name) {
 246  0
         if (name == null) {
 247  0
             return null;
 248  
         }
 249  
 
 250  0
         String className = null;
 251  
 
 252  0
         for (int i = 0; i < THEMES.length; ++i) {
 253  0
             if (THEMES[i].getName().equals(name)) {
 254  0
                 className = THEMES[i].getClass().getName();
 255  
             }
 256  
         }
 257  
 
 258  0
         return className;
 259  
     }
 260  
 
 261  
     /**
 262  
      * Returns true if the specified look and feel class
 263  
      * supports setting different themes.
 264  
      *
 265  
      * @param        lafClass        look and feel class name
 266  
      * @return                                true if supports themes
 267  
      */
 268  
     public boolean isThemeCompatibleLookAndFeel(String lafClass) {
 269  938
         if (lafClass == null) {
 270  938
             return false;
 271  
         }
 272  0
         return (/*lafClass == null ||*/ lafClass.equals(METAL_LAF_CLASS_NAME));
 273  
     }
 274  
 
 275  
     /**
 276  
      * Returns the string identifier for the current look and feel.
 277  
      * This is the class name of the LookAndFeel class for the look and feel.
 278  
      * Returns null if no look and feel has been specified, in which case
 279  
      * Swing's default look and feel should be used.
 280  
      *
 281  
      * @return        current look and feel class name
 282  
      */
 283  
     public String getCurrentLookAndFeel() {
 284  919
         String value =
 285  
             Configuration.getString(Argo.KEY_LOOK_AND_FEEL_CLASS, null);
 286  919
         if (DEFAULT_KEY.equals(value)) {
 287  0
             value = null;
 288  
         }
 289  919
         return value;
 290  
     }
 291  
 
 292  
     /**
 293  
      * Returns the display name of the current look and feel.
 294  
      *
 295  
      * @return        look and feel display name
 296  
      */
 297  
     public String getCurrentLookAndFeelName() {
 298  19
         String currentLookAndFeel = getCurrentLookAndFeel();
 299  
 
 300  19
         if (currentLookAndFeel == null) {
 301  19
             return DEFAULT_KEY;
 302  
         }
 303  0
         String name = null;
 304  
 
 305  0
         UIManager.LookAndFeelInfo[] lafs =
 306  
             UIManager.getInstalledLookAndFeels();
 307  0
         for (int i = 0; i < lafs.length; ++i) {
 308  0
             if (lafs[i].getClassName().equals(currentLookAndFeel)) {
 309  0
                 name = lafs[i].getName();
 310  
             }
 311  
         }
 312  
 
 313  0
         return name;
 314  
     }
 315  
 
 316  
     /**
 317  
      * Sets the current look and feel, storing the new value in
 318  
      * Configuration.  If argument is null, indicates that Swing's default
 319  
      * look and feel should be used.
 320  
      *
 321  
      * @param lafName        the name of desired look and feel
 322  
      * @param themeName the name of the theme
 323  
      */
 324  
     public void setCurrentLAFAndThemeByName(String lafName, String themeName) {
 325  0
         String lafClass = getLookAndFeelFromName(lafName);
 326  0
         String currentLookAndFeel = getCurrentLookAndFeel();
 327  
 
 328  0
         if (lafClass == null && currentLookAndFeel == null) {
 329  0
             return;
 330  
         }
 331  
         /* Disabled since it gives various problems: e.g. the toolbar icons
 332  
          * get too wide. Also the default does not give the new java 5.0 looks.
 333  
         if (!(lafClass != null && !lafClass.equals(currentLookAndFeel))) {
 334  
             setLookAndFeel(lafClass);
 335  
             Component tree = ProjectBrowser.getInstance();
 336  
             SwingUtilities.updateComponentTreeUI(
 337  
                     SwingUtilities.getRootPane(tree));
 338  
         }
 339  
         */
 340  
 
 341  0
         if (lafClass == null) {
 342  0
             lafClass = DEFAULT_KEY;
 343  
         }
 344  0
         Configuration.setString(Argo.KEY_LOOK_AND_FEEL_CLASS, lafClass);
 345  
 
 346  0
         setCurrentTheme(getThemeFromName(themeName));
 347  0
     }
 348  
 
 349  
     /**
 350  
      * Returns the string identifier for the current theme.
 351  
      * This is the class name of the MetalTheme class for the theme.
 352  
      * This method returns null when the configuration
 353  
      * does not return a valid metaltheme.
 354  
      *
 355  
      * @return        current theme class name or null
 356  
      */
 357  
     public String getCurrentThemeClassName() {
 358  19
         String value = Configuration.getString(Argo.KEY_THEME_CLASS, null);
 359  19
         if (DEFAULT_KEY.equals(value)) {
 360  0
             value = null;
 361  
         }
 362  19
         return value;
 363  
     }
 364  
 
 365  
     /**
 366  
      * Returns the display name of the current theme.
 367  
      * Guaranteed to return the display name
 368  
      * of one of the themes in the THEMES list.
 369  
      *
 370  
      * @return        theme display name
 371  
      */
 372  
     public String getCurrentThemeName() {
 373  19
         String currentThemeClassName = getCurrentThemeClassName();
 374  
 
 375  19
         if (currentThemeClassName == null) {
 376  
             /* Make up a default */
 377  19
             return THEMES[0].getName();
 378  
         }
 379  
 
 380  0
         for (int i = 0; i < THEMES.length; ++i) {
 381  0
             if (THEMES[i].getClass().getName().equals(currentThemeClassName)) {
 382  0
                 return THEMES[i].getName();
 383  
             }
 384  
         }
 385  0
         return THEMES[0].getName();
 386  
     }
 387  
 
 388  
     /**
 389  
      * Sets the current theme, storing the new value in
 390  
      * Configuration. Argument should not be null, and argument class
 391  
      * should be an instance of MetalTheme.
 392  
      *
 393  
      * @param        themeClass        class name of desired theme
 394  
      */
 395  
     public void setCurrentTheme(String themeClass) {
 396  0
         MetalTheme theme = getMetalTheme(themeClass);
 397  
 
 398  0
         if (theme.getClass().getName().equals(getCurrentThemeClassName())) {
 399  0
             return;
 400  
         }
 401  
 
 402  0
         setTheme(theme);
 403  
 
 404  
         /* Disabled since it gives various problems: e.g. the toolbar icons
 405  
          * get too wide. Also the default does not give the new java 5.0 looks.
 406  
         Component tree = ProjectBrowser.getInstance();
 407  
         SwingUtilities.updateComponentTreeUI(SwingUtilities.getRootPane(tree));
 408  
         */
 409  
 
 410  0
         String themeValue = themeClass;
 411  0
         if (themeValue == null) {
 412  0
             themeValue = DEFAULT_KEY;
 413  
         }
 414  0
         Configuration.setString(Argo.KEY_THEME_CLASS, themeValue);
 415  0
     }
 416  
 
 417  
     /**
 418  
      * @return the standard textfield font
 419  
      */
 420  
     public Font getStandardFont() {
 421  14889
         Font font = UIManager.getDefaults().getFont("TextField.font");
 422  14889
         if (font == null) {
 423  0
             font = (new javax.swing.JTextField()).getFont();
 424  
         }
 425  14889
         return font;
 426  
     }
 427  
 
 428  
     /**
 429  
      * @return the small font
 430  
      */
 431  
     public Font getSmallFont() {
 432  0
         Font font = getStandardFont();
 433  0
         if (font.getSize2D() >= 12f) {
 434  0
             return font.deriveFont(font.getSize2D() - 2f);
 435  
         }
 436  0
         return font;
 437  
     }
 438  
 
 439  
     /**
 440  
      * Sets the look and feel in the GUI by calling UIManager.setLookAndFeel().
 441  
      *
 442  
      * @param        lafClass        class name of look and feel
 443  
      */
 444  
     private void setLookAndFeel(String lafClass) {
 445  
         try {
 446  900
             if (lafClass == null && defaultLafClass != null) {
 447  
                 // Set to the default LAF
 448  900
                 UIManager.setLookAndFeel(defaultLafClass);
 449  
             } else {
 450  
                 // Set a custom LAF
 451  0
                 UIManager.setLookAndFeel(lafClass);
 452  
             }
 453  0
         } catch (UnsupportedLookAndFeelException e) {
 454  0
             LOG.error(e);
 455  0
         } catch (ClassNotFoundException e) {
 456  0
             LOG.error(e);
 457  0
         } catch (InstantiationException e) {
 458  0
             LOG.error(e);
 459  0
         } catch (IllegalAccessException e) {
 460  0
             LOG.error(e);
 461  900
         }
 462  900
     }
 463  
 
 464  
     /**
 465  
      * Sets the metal theme in the GUI by calling
 466  
      * MetalLookAndFeel.setCurrentTheme().
 467  
      *
 468  
      * @param        theme        new MetalTheme to set
 469  
      */
 470  
     private void setTheme(MetalTheme theme) {
 471  0
         String currentLookAndFeel = getCurrentLookAndFeel();
 472  
 
 473  
         // If LAF is Metal (either set explicitly, or as the default)
 474  0
         if ((currentLookAndFeel != null
 475  
                 && currentLookAndFeel.equals(METAL_LAF_CLASS_NAME))
 476  
             || (currentLookAndFeel == null
 477  
                 && defaultLafClass.equals(METAL_LAF_CLASS_NAME))) {
 478  
             try {
 479  0
                 MetalLookAndFeel.setCurrentTheme(theme);
 480  0
                 UIManager.setLookAndFeel(METAL_LAF_CLASS_NAME);
 481  0
             } catch (UnsupportedLookAndFeelException e) {
 482  0
                 LOG.error(e);
 483  0
             } catch (ClassNotFoundException e) {
 484  0
                 LOG.error(e);
 485  0
             } catch (InstantiationException e) {
 486  0
                 LOG.error(e);
 487  0
             } catch (IllegalAccessException e) {
 488  0
                 LOG.error(e);
 489  0
             }
 490  
         }
 491  0
     }
 492  
 
 493  
     /**
 494  
      * Returns the MetalTheme for the specified class name.
 495  
      * Returns the default theme if a corresponding MetalTheme class
 496  
      * can not be found.
 497  
      *
 498  
      * @param        themeClass        MetalTheme class name
 499  
      * @return                                MetalTheme object for class name
 500  
      */
 501  
     private MetalTheme getMetalTheme(String themeClass) {
 502  0
         MetalTheme theme = null;
 503  
 
 504  0
         for (int i = 0; i < THEMES.length; ++i) {
 505  0
             if (THEMES[i].getClass().getName().equals(themeClass)) {
 506  0
                 theme = THEMES[i];
 507  
             }
 508  
         }
 509  
 
 510  0
         if (theme == null) {
 511  0
             theme = DEFAULT_THEME;
 512  
         }
 513  
 
 514  0
         return theme;
 515  
     }
 516  
 }