View Javadoc

1   /**
2    * This program is free software: you can redistribute it and/or modify
3    * it under the terms of the GNU General Public License as published by
4    * the Free Software Foundation, version 3.
5    *
6    * This program is distributed in the hope that it will be useful,
7    * but WITHOUT ANY WARRANTY; without even the implied warranty of
8    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9    * GNU General Public License for more details.
10   *
11   * You should have received a copy of the GNU General Public License
12   * along with this program. If not, see <http://www.gnu.org/licenses/>.
13   */
14  
15  package net.curre.prefcount.service;
16  
17  import javax.swing.LookAndFeel;
18  import javax.swing.SwingUtilities;
19  import javax.swing.UIManager;
20  import java.awt.Frame;
21  import java.util.logging.Level;
22  import java.util.logging.Logger;
23  
24  import net.curre.prefcount.gui.theme.skin.AquaSkin;
25  import net.curre.prefcount.gui.theme.skin.BusinessSkin;
26  import net.curre.prefcount.gui.theme.skin.CremeSkin;
27  import net.curre.prefcount.gui.theme.skin.DefaultSkin;
28  import net.curre.prefcount.gui.theme.skin.FieldOfWheatSkin;
29  import net.curre.prefcount.gui.theme.skin.FindingNemoSkin;
30  import net.curre.prefcount.gui.theme.skin.GreenMagicSkin;
31  import net.curre.prefcount.gui.theme.skin.MangoSkin;
32  import net.curre.prefcount.gui.theme.skin.ModerateSkin;
33  import net.curre.prefcount.gui.theme.skin.NebulaSkin;
34  import net.curre.prefcount.gui.theme.skin.OfficeBlue2007Skin;
35  import net.curre.prefcount.gui.theme.skin.PrefSkin;
36  import net.curre.prefcount.util.Utilities;
37  
38  import org.jvnet.substance.SubstanceLookAndFeel;
39  
40  /**
41   * This is a helper class to assist with
42   * Look and Feel issues.
43   * <p/>
44   * Created date: Jun 11, 2007
45   *
46   * @author Yevgeny Nyden
47   */
48  public class LafThemeService {
49  
50    /** Private class logger. */
51    private static Logger log = Logger.getLogger(LafThemeService.class.toString());
52  
53    /** Array of available themes/skins. */
54    public static final PrefSkin[] AVAILABLE_SKINS = {
55        new DefaultSkin(), new AquaSkin(), new BusinessSkin(),
56        new ModerateSkin(), new NebulaSkin(), new OfficeBlue2007Skin(),
57        new GreenMagicSkin(), new MangoSkin(), new CremeSkin(),
58        new FieldOfWheatSkin(), new FindingNemoSkin()
59    };
60  
61    /** This holds a reference to the singleton instance. */
62    private static LafThemeService instance = new LafThemeService();
63  
64    /** Reference to the substance LAF object. */
65    private SubstanceLookAndFeel substanceLaf;
66  
67    /** Reference to the current skin; */
68    private PrefSkin currentSkin;
69  
70    /** Reference to the pending skin; */
71    private PrefSkin pendingSkin;
72  
73    /** Flag to indicate that Substance LaF is active. */
74    private boolean substanceLafActive;
75  
76    /** Private constructor. */
77    private LafThemeService() {
78      this.currentSkin = AVAILABLE_SKINS[0];
79    }
80  
81    /**
82     * Returns an instance of this class to use.
83     *
84     * @return singleton instance of this class to use.
85     */
86    public static LafThemeService getInstance() {
87      return instance;
88    }
89  
90    /**
91     * Returns reference to the current skin.
92     *
93     * @return reference to the current skin.
94     */
95    public PrefSkin getCurrentSkin() {
96      return this.currentSkin;
97    }
98  
99    /**
100    * Returns reference to the pending skin -
101    * the skin that was chosen but was activated yet.
102    *
103    * @return reference to the pending skin.
104    */
105   public PrefSkin getPendingSkin() {
106     return this.pendingSkin;
107   }
108 
109   /** Clear the pending skin change (sets the pendingSkin to null). */
110   public void clearPendingSkin() {
111     this.pendingSkin = null;
112   }
113 
114   /**
115    * Sets the Look and Feel according to the
116    * passed theme/skin name.
117    *
118    * @param skinId     Theme/skin ID (resource key) to set the LaF to.
119    * @param isFirstRun Flag to indicate the first run of this method (when true).
120    */
121   public void setLookAndFeel(final String skinId, boolean isFirstRun) {
122 
123     // fetch the skin object given its ID
124     try {
125       if (isFirstRun) {
126         this.pendingSkin = null;
127 
128         // checking which Laf manager to set Substance or system default
129         if (DefaultSkin.NAME_KEY.equals(skinId)) {
130           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
131 
132         } else {
133           UIManager.setLookAndFeel(getSubstanceLaf());
134           setCurrentSkinHelper(skinId);
135         }
136 
137       } else {
138 
139         // checking if the new skin is different
140         if (this.currentSkin.getNameResourceKey().equals(skinId) == false) {
141 
142           // we can't switch from one theme to another if current  UI manager is Substance
143           // and we are switching to the system default theme or to the default Substance theme (Aqua);
144           // we need to restart application for this change take effect
145           if (DefaultSkin.NAME_KEY.equals(skinId) ||
146               this.substanceLafActive && AquaSkin.NAME_KEY.equals(skinId)) {
147             if (this.pendingSkin == null ||
148                 this.pendingSkin.getNameResourceKey().equals(skinId) == false) {
149               this.pendingSkin = findSkinById(skinId);
150               if (Utilities.displayOkCancelMessage("pref.settings.skin.needsRestart",
151                                                    "pref.dialog.buttons.yes",
152                                                    "pref.dialog.buttons.no")) {
153                 MainService.doQuit();
154               }
155             }
156 
157           } else {
158             if (this.substanceLafActive == false) {
159               UIManager.setLookAndFeel(getSubstanceLaf());
160             }
161             setCurrentSkinHelper(skinId);
162           }
163         }
164       }
165 
166     } catch (Exception e) {
167       log.log(Level.WARNING, "Unable to set LAF", e);
168     }
169   }
170 
171   /**
172    * Returns the skin given its ID (resource key).
173    *
174    * @param skinId Skin ID (resource key).
175    * @return The skin with the given ID (resource key).
176    * @throws ServiceException If skin with given ID was not found.
177    */
178   public static PrefSkin findSkinById(String skinId) throws ServiceException {
179     for (PrefSkin skin : AVAILABLE_SKINS) {
180       if (skin.getNameResourceKey().equals(skinId)) {
181         return skin;
182       }
183     }
184     throw new ServiceException("Skin with id \"" + skinId + "\" was not found!");
185   }
186 
187   /**
188    * Helper method to lazy-load the substance Laf.
189    *
190    * @return Substance Laf object.
191    */
192   private synchronized LookAndFeel getSubstanceLaf() {
193     if (this.substanceLaf == null) {
194       this.substanceLaf = new SubstanceLookAndFeel();
195       this.substanceLafActive = true;
196     }
197     return this.substanceLaf;
198   }
199 
200   /**
201    * Assists with changing the skin (for Substance LaF only).
202    *
203    * @param skinId skin id.
204    * @throws ServiceException on error.
205    */
206   private void setCurrentSkinHelper(String skinId) throws ServiceException {
207     this.pendingSkin = null;
208     this.currentSkin = findSkinById(skinId);
209 
210     // no need to set the skin for the default substance theme - Aqua
211     if (AquaSkin.NAME_KEY.equals(skinId) == false) {
212       SubstanceLookAndFeel.setSkin(this.currentSkin.getSubstanceSkinClassName());
213     }
214 
215     // updating component tree for all frames
216     for (Frame frame : Frame.getFrames()) {
217       SwingUtilities.updateComponentTreeUI(frame);
218     }
219   }
220 
221 }