Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
LookAndFeelMgr |
|
| 3.7142857142857144;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 | } |