001: /*
002: * Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.looks;
032:
033: import java.awt.Color;
034: import java.awt.Component;
035: import java.awt.Toolkit;
036: import java.util.Collections;
037: import java.util.List;
038: import java.util.Locale;
039:
040: import javax.swing.LookAndFeel;
041: import javax.swing.UIManager;
042: import javax.swing.UnsupportedLookAndFeelException;
043:
044: import com.jgoodies.looks.plastic.PlasticLookAndFeel;
045: import com.jgoodies.looks.plastic.PlasticTheme;
046:
047: /**
048: * Provides convenience behavior used by the JGoodies Looks.
049: *
050: * @author Karsten Lentzsch
051: * @version $Revision: 1.9 $
052: */
053: public final class LookUtils {
054:
055: // Basics System Properties **********************************************
056:
057: /**
058: * The <code>java.version</code> System Property.<p>
059: *
060: * Defaults to <code>null</code> if the runtime does not have security
061: * access to read this property or the property does not exist.
062: */
063: private static final String JAVA_VERSION = getSystemProperty("java.version");
064:
065: /**
066: * The <code>os.name</code> System Property. Operating system name.<p>
067: *
068: * Defaults to <code>null</code> if the runtime does not have security
069: * access to read this property or the property does not exist.
070: */
071: private static final String OS_NAME = getSystemProperty("os.name");
072:
073: /**
074: * The <code>os.version</code> System Property. Operating system version.<p>
075: *
076: * Defaults to <code>null</code> if the runtime does not have security
077: * access to read this property or the property does not exist.
078: */
079: private static final String OS_VERSION = getSystemProperty("os.version");
080:
081: // Requesting the Java Version ********************************************
082:
083: /**
084: * True if this is Java 1.4.
085: */
086: public static final boolean IS_JAVA_1_4 = startsWith(JAVA_VERSION,
087: "1.4");
088:
089: /**
090: * True if this is Java 1.4.0_*.
091: */
092: public static final boolean IS_JAVA_1_4_0 = startsWith(
093: JAVA_VERSION, "1.4.0");
094:
095: /**
096: * True if this is Java 1.4.2 or later. Since we assume Java 1.4
097: * we just check for 1.4.0 and 1.4.1.
098: */
099: public static final boolean IS_JAVA_1_4_2_OR_LATER = !startsWith(
100: JAVA_VERSION, "1.4.0")
101: && !startsWith(JAVA_VERSION, "1.4.1");
102:
103: /**
104: * True if this is Java 5.x. We check for a prefix of 1.5.
105: */
106: public static final boolean IS_JAVA_5 = startsWith(JAVA_VERSION,
107: "1.5");
108:
109: /**
110: * True if this is Java 5.x or later. Since we don't support Java 1.3,
111: * we can check that it's not 1.4.
112: */
113: public static final boolean IS_JAVA_5_OR_LATER = !IS_JAVA_1_4;
114:
115: /**
116: * True if this is Java 6. We check for a prefix of 1.6.
117: */
118: public static final boolean IS_JAVA_6 = startsWith(JAVA_VERSION,
119: "1.6");
120:
121: /**
122: * True if this is Java 6.x or later. Since we don't support Java 1.3,
123: * we can check that it's neither 1.4 nor 1.5.
124: */
125: public static final boolean IS_JAVA_6_OR_LATER = !IS_JAVA_1_4
126: && !IS_JAVA_5;
127:
128: /**
129: * True if this is Java 1.4 or Java 5.
130: */
131: public static final boolean IS_JAVA_1_4_OR_5 = IS_JAVA_1_4
132: || IS_JAVA_5;
133:
134: // Requesting the Operating System Name ***********************************
135:
136: /**
137: * True if this is FreeBSD.
138: */
139: public static final boolean IS_OS_FREEBSD = startsWithIgnoreCase(
140: OS_NAME, "FreeBSD");
141:
142: /**
143: * True if this is Linux.
144: */
145: public static final boolean IS_OS_LINUX = startsWithIgnoreCase(
146: OS_NAME, "Linux");
147:
148: /**
149: * True if this is OS/2.
150: */
151: public static final boolean IS_OS_OS2 = startsWith(OS_NAME, "OS/2");
152:
153: /**
154: * True if this is the Mac OS X.
155: */
156: public static final boolean IS_OS_MAC = startsWith(OS_NAME, "Mac");
157:
158: /**
159: * True if this is Windows.
160: */
161: public static final boolean IS_OS_WINDOWS = startsWith(OS_NAME,
162: "Windows");
163:
164: /**
165: * True if this is Windows 98/ME/2000/XP/VISTA.
166: */
167: public static final boolean IS_OS_WINDOWS_MODERN = startsWith(
168: OS_NAME, "Windows")
169: && !startsWith(OS_VERSION, "4.0");
170:
171: /**
172: * True if this is Windows 95.
173: *
174: * @since 2.0
175: */
176: public static final boolean IS_OS_WINDOWS_95 = startsWith(OS_NAME,
177: "Windows 9")
178: && startsWith(OS_VERSION, "4.0");
179:
180: /**
181: * True if this is Windows 98.
182: *
183: * @since 2.0
184: */
185: public static final boolean IS_OS_WINDOWS_98 = startsWith(OS_NAME,
186: "Windows 9")
187: && startsWith(OS_VERSION, "4.1");
188:
189: /**
190: * True if this is Windows NT.
191: *
192: * @since 2.0
193: */
194: public static final boolean IS_OS_WINDOWS_NT = startsWith(OS_NAME,
195: "Windows NT");
196:
197: /**
198: * True if this is Windows ME.
199: *
200: * @since 2.0
201: */
202: public static final boolean IS_OS_WINDOWS_ME = startsWith(OS_NAME,
203: "Windows")
204: && startsWith(OS_VERSION, "4.9");
205:
206: /**
207: * True if this is Windows 2000.
208: *
209: * @since 2.0
210: */
211: public static final boolean IS_OS_WINDOWS_2000 = startsWith(
212: OS_NAME, "Windows")
213: && startsWith(OS_VERSION, "5.0");
214:
215: /**
216: * True if this is Windows XP.
217: */
218: public static final boolean IS_OS_WINDOWS_XP = startsWith(OS_NAME,
219: "Windows")
220: && startsWith(OS_VERSION, "5.1");
221:
222: /**
223: * True if this is Windows Vista.
224: *
225: * @since 2.0
226: */
227: public static final boolean IS_OS_WINDOWS_VISTA = startsWith(
228: OS_NAME, "Windows")
229: && startsWith(OS_VERSION, "6.0");
230:
231: /**
232: * True if this is Solaris.
233: */
234: public static final boolean IS_OS_SOLARIS = startsWith(OS_NAME,
235: "Solaris");
236:
237: // Other Properties *******************************************************
238:
239: /**
240: * True if the Windows XP Look&Feel is enabled.
241: */
242: public static final boolean IS_LAF_WINDOWS_XP_ENABLED = isWindowsXPLafEnabled();
243:
244: /**
245: * True if if the screen resolution is smaller than 120 dpi.
246: *
247: * @see Toolkit#getScreenResolution()
248: */
249: public static final boolean IS_LOW_RESOLUTION = isLowResolution();
250:
251: private static boolean loggingEnabled = true;
252:
253: private LookUtils() {
254: // Override default constructor; prevents instantiation.
255: }
256:
257: // Accessing System Configuration *****************************************
258:
259: /**
260: * Tries to look up the System property for the given key.
261: * In untrusted environments this may throw a SecurityException.
262: * In this case we catch the exception and answer <code>null</code>.
263: *
264: * @param key the name of the system property
265: * @return the system property's String value, or <code>null</code> if there's
266: * no such value, or a SecurityException has been caught
267: */
268: public static String getSystemProperty(String key) {
269: try {
270: return System.getProperty(key);
271: } catch (SecurityException e) {
272: log("Can't read the System property " + key + ".");
273: return null;
274: }
275: }
276:
277: /**
278: * Tries to look up the System property for the given key.
279: * In untrusted environments this may throw a SecurityException.
280: * In this case, we catch the exception and answer the default value.
281: *
282: * @param key the name of the system property
283: * @param defaultValue the default value if no property exists.
284: * @return the system property's String value, or the defaultValue
285: * if there's no such value, or a SecurityException has been caught
286: */
287: public static String getSystemProperty(String key,
288: String defaultValue) {
289: try {
290: return System.getProperty(key, defaultValue);
291: } catch (SecurityException e) {
292: log("Can't read the System property " + key + ".");
293: return defaultValue;
294: }
295: }
296:
297: /**
298: * Checks if a boolean system property has been set for the given key,
299: * and returns the associated Boolean, or <code>null</code> if no value
300: * has been set. The test for the property ignores case.
301: * If a Boolean value has been set, a message is logged
302: * with the given prefix.
303: *
304: * @param key the key used to lookup the system property value
305: * @param logMessage a prefix used when a message is logged
306: * @return <code>Boolean.TRUE</code> if the system property has been set to
307: * "true" (case ignored), <code>Boolean.FALSE</code> if it has been set to
308: * "false", <code>null</code> otherwise
309: */
310: public static Boolean getBooleanSystemProperty(String key,
311: String logMessage) {
312: String value = getSystemProperty(key, "");
313: Boolean result;
314: if (value.equalsIgnoreCase("false"))
315: result = Boolean.FALSE;
316: else if (value.equalsIgnoreCase("true"))
317: result = Boolean.TRUE;
318: else
319: result = null;
320: if (result != null) {
321: LookUtils.log(logMessage + " have been "
322: + (result.booleanValue() ? "en" : "dis")
323: + "abled in the system properties.");
324: }
325: return result;
326: }
327:
328: /**
329: * Checks and answers whether the Windows XP style is enabled.
330: * This method is intended to be called only if a Windows look&feel
331: * is about to be installed or already active in the UIManager.
332: * The XP style of the Windows look&feel is enabled by default on
333: * Windows XP platforms since the J2SE 1.4.2; it can be disabled either
334: * in the Windows desktop as well as in the Java runtime by setting
335: * a System property.<p>
336: *
337: * First checks the platform, platform version and Java version. Then
338: * checks whether the desktop property <tt>win.xpstyle.themeActive</tt>
339: * is set or not.
340: *
341: * @return true if the Windows XP style is enabled
342: */
343: private static boolean isWindowsXPLafEnabled() {
344: return (IS_OS_WINDOWS_XP || IS_OS_WINDOWS_VISTA)
345: && IS_JAVA_1_4_2_OR_LATER
346: && Boolean.TRUE.equals(Toolkit.getDefaultToolkit()
347: .getDesktopProperty("win.xpstyle.themeActive"))
348: && getSystemProperty("swing.noxp") == null;
349: }
350:
351: /**
352: * Checks and answers whether we have a true color system.
353: *
354: * @param c the component used to determine the toolkit
355: * @return true if the component's toolkit has a pixel size >= 24
356: */
357: public static boolean isTrueColor(Component c) {
358: return c.getToolkit().getColorModel().getPixelSize() >= 24;
359: }
360:
361: /**
362: * Checks and answers whether this toolkit provides native drop shadows
363: * for popups such as the Mac OS X. Currently this is used to
364: * determine if the Looks' popup drop shadow feature is active or not
365: * - even if it's enabled.
366: *
367: * @return true if the toolkit provides native drop shadows
368: *
369: * @see Options#isPopupDropShadowActive()
370: */
371: public static boolean getToolkitUsesNativeDropShadows() {
372: return IS_OS_MAC;
373: }
374:
375: /**
376: * Computes and returns a Color that is slightly brighter
377: * than the specified Color.
378: *
379: * @param color the color used as basis for the brightened color
380: * @return a slightly brighter color
381: */
382: public static Color getSlightlyBrighter(Color color) {
383: return getSlightlyBrighter(color, 1.1f);
384: }
385:
386: /**
387: * Computes and returns a Color that is slightly brighter
388: * than the specified Color.
389: *
390: * @param color the color used as basis for the brightened color
391: * @param factor the factor used to compute the brightness
392: * @return a slightly brighter color
393: */
394: public static Color getSlightlyBrighter(Color color, float factor) {
395: float[] hsbValues = new float[3];
396: Color.RGBtoHSB(color.getRed(), color.getGreen(), color
397: .getBlue(), hsbValues);
398: float hue = hsbValues[0];
399: float saturation = hsbValues[1];
400: float brightness = hsbValues[2];
401: float newBrightness = Math.min(brightness * factor, 1.0f);
402: return Color.getHSBColor(hue, saturation, newBrightness);
403: }
404:
405: // Accessing Look, Theme, and Font Settings *****************************
406:
407: public static void setLookAndTheme(LookAndFeel laf, Object theme)
408: throws UnsupportedLookAndFeelException {
409: if ((laf instanceof PlasticLookAndFeel) && (theme != null)
410: && (theme instanceof PlasticTheme)) {
411: PlasticLookAndFeel.setPlasticTheme((PlasticTheme) theme);
412: }
413: UIManager.setLookAndFeel(laf);
414: }
415:
416: public static Object getDefaultTheme(LookAndFeel laf) {
417: return laf instanceof PlasticLookAndFeel ? PlasticLookAndFeel
418: .createMyDefaultTheme() : null;
419: }
420:
421: public static List getInstalledThemes(LookAndFeel laf) {
422: return laf instanceof PlasticLookAndFeel ? PlasticLookAndFeel
423: .getInstalledThemes() : Collections.EMPTY_LIST;
424: }
425:
426: // Minimal logging ******************************************************
427:
428: /**
429: * Enables or disables the Looks logging.
430: *
431: * @param enabled true to enable logging, false to disable it
432: */
433: public static void setLoggingEnabled(boolean enabled) {
434: loggingEnabled = enabled;
435: }
436:
437: /**
438: * Prints a new line to the console if logging is enabled.
439: */
440: public static void log() {
441: if (loggingEnabled) {
442: System.out.println();
443: }
444: }
445:
446: /**
447: * Prints the given message to the console if logging is enabled.
448: *
449: * @param message the message to print
450: */
451: public static void log(String message) {
452: if (loggingEnabled) {
453: System.out.println("JGoodies Looks: " + message);
454: }
455: }
456:
457: // Private Helper Methods ***********************************************
458:
459: /**
460: * Checks and answers whether the screen resolution is low or high.
461: * Resolutions below 120 dpi are considere low, all others are high.
462: *
463: * @return true if the screen resolution is smaller than 120 dpi
464: */
465: private static boolean isLowResolution() {
466: return Toolkit.getDefaultToolkit().getScreenResolution() < 120;
467: }
468:
469: private static boolean startsWith(String str, String prefix) {
470: return str != null && str.startsWith(prefix);
471: }
472:
473: private static boolean startsWithIgnoreCase(String str,
474: String prefix) {
475: return str != null
476: && str.toUpperCase(Locale.ENGLISH).startsWith(
477: prefix.toUpperCase(Locale.ENGLISH));
478: }
479:
480: }
|