001: /*
002: * Copyright (c) 2001-2005 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 contrib.com.jgoodies.looks;
032:
033: import java.awt.Dimension;
034: import java.util.HashMap;
035: import java.util.Map;
036:
037: import javax.swing.UIManager;
038:
039: import org.jvnet.lafwidget.utils.LookUtils;
040:
041: import contrib.com.jgoodies.looks.common.ShadowPopup;
042:
043: /**
044: * Provides access to several optional properties for the
045: * JGoodies L&Fs, either by a key to the <code>UIDefaults</code> table
046: * or via a method or both.
047: *
048: * @author Karsten Lentzsch
049: * @version $Revision: 1.3 $
050: */
051:
052: public final class Options {
053:
054: // Look & Feel Names ****************************************************
055:
056: public static final String PLASTIC_NAME = "com.jgoodies.looks.plastic.PlasticLookAndFeel";
057:
058: public static final String PLASTIC3D_NAME = "com.jgoodies.looks.plastic.Plastic3DLookAndFeel";
059:
060: public static final String PLASTICXP_NAME = "com.jgoodies.looks.plastic.PlasticXPLookAndFeel";
061:
062: public static final String JGOODIES_WINDOWS_NAME = "com.jgoodies.looks.windows.WindowsLookAndFeel";
063:
064: /**
065: * This outdated constant will be removed in the Looks version 1.4.
066: *
067: * @deprecated Replaced by {@link #JGOODIES_WINDOWS_NAME}.
068: */
069: public static final String EXT_WINDOWS_NAME = JGOODIES_WINDOWS_NAME;
070:
071: public static final String DEFAULT_LOOK_NAME = PLASTIC3D_NAME;
072:
073: /**
074: * Holds a Map that enables the look&feel replacement
075: * mechanism to replace one look by another.
076: * Maps the original class names to their replacement class names.
077: */
078: private static final Map LAF_REPLACEMENTS;
079: static {
080: LAF_REPLACEMENTS = new HashMap();
081: initializeDefaultReplacements();
082: }
083:
084: // Keys for Overriding Font Settings ************************************
085:
086: public static final String MENU_FONT_KEY = "jgoodies.menuFont";
087:
088: public static final String CONTROL_FONT_KEY = "jgoodies.controlFont";
089:
090: public static final String FONT_SIZE_HINTS_KEY = "jgoodies.fontSizeHints";
091:
092: public static final String USE_SYSTEM_FONTS_KEY = "swing.useSystemFontSettings";
093:
094: public static final String USE_SYSTEM_FONTS_APP_KEY = "Application.useSystemFontSettings";
095:
096: // Optional Global User Properties **************************************
097:
098: public static final String DEFAULT_ICON_SIZE_KEY = "jgoodies.defaultIconSize";
099:
100: public static final String USE_NARROW_BUTTONS_KEY = "jgoodies.useNarrowButtons";
101:
102: public static final String TAB_ICONS_ENABLED_KEY = "jgoodies.tabIconsEnabled";
103:
104: public static final String POPUP_DROP_SHADOW_ENABLED_KEY = "jgoodies.popupDropShadowEnabled";
105:
106: // Optional Client Properties *******************************************
107:
108: /**
109: * Hint that the button margin should be narrow.
110: */
111: public static final String IS_NARROW_KEY = "jgoodies.isNarrow";
112:
113: /**
114: * Hint that the scroll pane border should be etched.
115: */
116: public static final String IS_ETCHED_KEY = "jgoodies.isEtched";
117:
118: /**
119: * Hint for the style: Single or Both, see <code>HeaderStyle</code>.
120: */
121: public static final String HEADER_STYLE_KEY = "jgoodies.headerStyle";
122:
123: /**
124: * Hint that the menu items in the menu have no icons.
125: */
126: public static final String NO_ICONS_KEY = "jgoodies.noIcons";
127:
128: /**
129: * A client property key for JTrees.
130: * Used with the angled and none style values.
131: */
132: public static final String TREE_LINE_STYLE_KEY = "JTree.lineStyle";
133:
134: /**
135: * A client property value for JTrees
136: * that indicates that lines shall be drawn.
137: */
138: public static final String TREE_LINE_STYLE_ANGLED_VALUE = "Angled";
139:
140: /**
141: * A client property value for JTrees
142: * that indicates that lines shall be hidden.
143: */
144: public static final String TREE_LINE_STYLE_NONE_VALUE = "None";
145:
146: /**
147: * A client property key for JTabbedPanes that indicates
148: * that no content border shall be painted.
149: * Supported by the Plastic look&feel family.
150: * This effect will be achieved also if the EMBEDDED property is true.
151: */
152: public static final String NO_CONTENT_BORDER_KEY = "jgoodies.noContentBorder";
153:
154: /**
155: * A client property key for JTabbedPanes that indicates
156: * that tabs are painted with a special embedded appearance.
157: * Supported by the Plastic look&feel family.
158: * This effect will be achieved also if the EMBEDDED property is true.
159: */
160: public static final String EMBEDDED_TABS_KEY = "jgoodies.embeddedTabs";
161:
162: // System Settings ********************************************************
163:
164: /**
165: * Holds the Boolean system property value for the tab icon enablement,
166: * or null, if it has not been set. If this property has been
167: * set, we log a message about the choosen value.
168: *
169: * @see #isTabIconsEnabled()
170: */
171: private static final Boolean TAB_ICONS_ENABLED_SYSTEM_VALUE = LookUtils
172: .getBooleanSystemProperty(TAB_ICONS_ENABLED_KEY,
173: "Icons in tabbed panes");
174:
175: /**
176: * Holds the Boolean system property value for the popup drop shadow
177: * enablement, or null, if it has not been set. If this property has been
178: * set, we log a message about the choosen value.<p>
179: *
180: * This property just set the feature's enablement, not its actual
181: * activation. For example, drop shadows are always inactive on
182: * the Mac OS X, because this platform already provides shadows.
183: * The activation is requested in <code>#isPopupDropShadowActive</code>.
184: *
185: * @see #isPopupDropShadowEnabled()
186: * @see #isPopupDropShadowActive()
187: */
188: private static final Boolean POPUP_DROP_SHADOW_ENABLED_SYSTEM_VALUE = LookUtils
189: .getBooleanSystemProperty(POPUP_DROP_SHADOW_ENABLED_KEY,
190: "Popup drop shadows");
191:
192: // Private ****************************************************************
193:
194: private static final Dimension DEFAULT_ICON_SIZE = new Dimension(
195: 20, 20);
196:
197: private Options() {
198: // Override default constructor; prevents instantiation.
199: }
200:
201: // Accessing Options ******************************************************
202:
203: /**
204: * Returns whether a hint is set in the UIManager that indicates,
205: * that a look&feel may use the native system fonts.
206: *
207: * @return true if the UIManager indicates that system fonts shall be used
208: * @see #setUseSystemFonts(boolean)
209: */
210: public static boolean getUseSystemFonts() {
211: return UIManager.get(USE_SYSTEM_FONTS_APP_KEY).equals(
212: Boolean.TRUE);
213: }
214:
215: /**
216: * Sets a value in the UIManager to indicate,
217: * that a look&feel may use the native system fonts.
218: *
219: * @param useSystemFonts true to enable system fonts in the UIManager
220: * @see #getUseSystemFonts()
221: */
222: public static void setUseSystemFonts(boolean useSystemFonts) {
223: UIManager.put(USE_SYSTEM_FONTS_APP_KEY, Boolean
224: .valueOf(useSystemFonts));
225: }
226:
227: /**
228: * Returns the default icon size that is used in menus, menu items and
229: * toolbars. Menu items that have no icon set are aligned using the default
230: * icon dimensions.
231: *
232: * @return the dimension of the default icon
233: * @see #setDefaultIconSize(Dimension)
234: */
235: public static Dimension getDefaultIconSize() {
236: Dimension size = UIManager.getDimension(DEFAULT_ICON_SIZE_KEY);
237: return size == null ? DEFAULT_ICON_SIZE : size;
238: }
239:
240: /**
241: * Sets the default icon size.
242: *
243: * @param defaultIconSize the default icon size to set
244: * @see #getDefaultIconSize()
245: */
246: public static void setDefaultIconSize(Dimension defaultIconSize) {
247: UIManager.put(DEFAULT_ICON_SIZE_KEY, defaultIconSize);
248: }
249:
250: /**
251: * Returns the global <code>FontSizeHints</code>
252: * that can be overriden by a look-specific setting.
253: *
254: * @return the gobally used FontSizeHints object
255: * @see #setGlobalFontSizeHints(FontSizeHints)
256: */
257: public static FontSizeHints getGlobalFontSizeHints() {
258: Object value = UIManager.get(FONT_SIZE_HINTS_KEY);
259: if (value != null)
260: return (FontSizeHints) value;
261:
262: String name = LookUtils.getSystemProperty(FONT_SIZE_HINTS_KEY,
263: "");
264: try {
265: return FontSizeHints.valueOf(name);
266: } catch (IllegalArgumentException e) {
267: return FontSizeHints.DEFAULT;
268: }
269: }
270:
271: /**
272: * Sets the global <code>FontSizeHints</code>.
273: *
274: * @param hints the FontSizeHints object to be used globally
275: * @see #getGlobalFontSizeHints()
276: */
277: public static void setGlobalFontSizeHints(FontSizeHints hints) {
278: UIManager.put(FONT_SIZE_HINTS_KEY, hints);
279: }
280:
281: /**
282: * Checks and answers if we shall use narrow button margins of 4 pixels.
283: * Sun's L&F implementations use a much wider button margin of 14 pixels,
284: * which leads to good button minimum width in the typical case.<p>
285: *
286: * Using narrow button margins can potentially cause compatibility issues,
287: * so this feature must be switched on programmatically.<p>
288: *
289: * If you use narrow margin, you should take care of minimum button width,
290: * either by the layout management or appropriate ButtonUI minimum widths.
291: *
292: * @return true if all buttons shall use narrow margins
293: * @see #setUseNarrowButtons(boolean)
294: */
295: public static boolean getUseNarrowButtons() {
296: return UIManager.getBoolean(USE_NARROW_BUTTONS_KEY);
297: }
298:
299: /**
300: * Sets if we use narrow or standard button margins.
301: *
302: * @param b true to use narrow button margins globally
303: * @see #getUseNarrowButtons()
304: */
305: public static void setUseNarrowButtons(boolean b) {
306: UIManager.put(USE_NARROW_BUTTONS_KEY, Boolean.valueOf(b));
307: }
308:
309: /**
310: * Checks and answers if we shall use icons in JTabbedPanes.
311: * By default, tab icons are enabled. If the user has set a system property,
312: * we log a message about the choosen style.
313: *
314: * @return true if icons in tabbed panes are enabled, false if disabled
315: * @see #setTabIconsEnabled(boolean)
316: */
317: public static boolean isTabIconsEnabled() {
318: return TAB_ICONS_ENABLED_SYSTEM_VALUE == null ? !Boolean.FALSE
319: .equals(UIManager.get(TAB_ICONS_ENABLED_KEY))
320: : TAB_ICONS_ENABLED_SYSTEM_VALUE.booleanValue();
321: }
322:
323: /**
324: * Enables or disables the use of icons in JTabbedPanes.
325: *
326: * @param b true to enable icons in tabbed panes, false to disable them
327: * @see #isTabIconsEnabled()
328: */
329: public static void setTabIconsEnabled(boolean b) {
330: UIManager.put(TAB_ICONS_ENABLED_KEY, Boolean.valueOf(b));
331: }
332:
333: /**
334: * Checks and answers whether popup drop shadows are active.
335: * This feature shall be inactive with toolkits that use
336: * native drop shadows, such as Aqua on the Mac OS X.
337: * It is also inactive if the ShadowPopup cannot snapshot
338: * the desktop background (due to security and AWT exceptions).
339: * Otherwise the feature's enablement state is returned.<p>
340: *
341: * Currently only the Mac OS X is detected as platform where
342: * the toolkit uses native drop shadows.
343: *
344: * @return true if drop shadows are active, false if inactive
345: *
346: * @see #isPopupDropShadowEnabled()
347: * @see #setPopupDropShadowEnabled(boolean)
348: */
349: public static boolean isPopupDropShadowActive() {
350: return !LookUtils.getToolkitUsesNativeDropShadows()
351: && ShadowPopup.canSnapshot()
352: && isPopupDropShadowEnabled();
353: }
354:
355: /**
356: * Checks and answers whether the optional drop shadows for
357: * PopupMenus are enabled or disabled.
358: *
359: * @return true if drop shadows are enabled, false if disabled
360: *
361: * @see #isPopupDropShadowActive()
362: * @see #setPopupDropShadowEnabled(boolean)
363: */
364: public static boolean isPopupDropShadowEnabled() {
365: if (POPUP_DROP_SHADOW_ENABLED_SYSTEM_VALUE != null)
366: return POPUP_DROP_SHADOW_ENABLED_SYSTEM_VALUE
367: .booleanValue();
368:
369: Object value = UIManager.get(POPUP_DROP_SHADOW_ENABLED_KEY);
370: return value == null ? isPopupDropShadowEnabledDefault()
371: : Boolean.TRUE.equals(value);
372: }
373:
374: /**
375: * Enables or disables drop shadows in PopupMenus.
376: * Note that drop shadows are always inactive on platforms
377: * that provide native drop shadows such as the Mac OS X.<p>
378: *
379: * It is recommended to enable this feature only on platforms that
380: * accelerate translucency and snapshots with the hardware.
381: *
382: * @param b true to enable drop shadows, false to disable them
383: *
384: * @see #isPopupDropShadowActive()
385: * @see #isPopupDropShadowEnabled()
386: */
387: public static void setPopupDropShadowEnabled(boolean b) {
388: UIManager
389: .put(POPUP_DROP_SHADOW_ENABLED_KEY, Boolean.valueOf(b));
390: }
391:
392: /**
393: * Checks and answers whether popup drop shadows are enabled
394: * or disabled by default. True for modern Windows platforms:
395: * Windows 98/ME/2000/XP.<p>
396: *
397: * TODO: Consider enabling popup drop shadows on Linux by default.<p>
398: *
399: * TODO: Consider moving the default to the individual L&F's
400: * component defaults initialization. For example Plastic and Plastic3D
401: * may disable this feature by default, while PlasticXP enables it
402: * by default.
403: *
404: * @return false
405: */
406: private static boolean isPopupDropShadowEnabledDefault() {
407: return LookUtils.IS_OS_WINDOWS_MODERN;
408: }
409:
410: // Look And Feel Replacements *******************************************
411:
412: /**
413: * Puts a replacement name for a given <code>LookAndFeel</code>
414: * class name in the list of all look and feel replacements.
415: *
416: * @param original the name of the look-and-feel to replace
417: * @param replacement the name of the replacement look-and-feel
418: * @see #removeLookAndFeelReplacement(String)
419: * @see #getReplacementClassNameFor(String)
420: */
421: public static void putLookAndFeelReplacement(String original,
422: String replacement) {
423: LAF_REPLACEMENTS.put(original, replacement);
424: }
425:
426: /**
427: * Removes a replacement name for a given <code>LookAndFeel</code>
428: * class name from the list of all look and feel replacements.
429: *
430: * @param original the name of the look-and-feel that has been replaced
431: * @see #putLookAndFeelReplacement(String, String)
432: * @see #getReplacementClassNameFor(String)
433: */
434: public static void removeLookAndFeelReplacement(String original) {
435: LAF_REPLACEMENTS.remove(original);
436: }
437:
438: /**
439: * Initializes some default class name replacements, that replace
440: * Sun's Java look and feel, and Sun's Windows look and feel by
441: * the appropriate JGoodies replacements.
442: *
443: * @see #putLookAndFeelReplacement(String, String)
444: * @see #removeLookAndFeelReplacement(String)
445: * @see #getReplacementClassNameFor(String)
446: */
447: public static void initializeDefaultReplacements() {
448: putLookAndFeelReplacement(
449: "javax.swing.plaf.metal.MetalLookAndFeel",
450: PLASTIC3D_NAME);
451: putLookAndFeelReplacement(
452: "com.sun.java.swing.plaf.windows.WindowsLookAndFeel",
453: JGOODIES_WINDOWS_NAME);
454: }
455:
456: /**
457: * Returns the class name that can be used to replace the specified
458: * <code>LookAndFeel</code> class name.
459: *
460: * @param className the name of the look-and-feel class
461: * @return the name of the suggested replacement class
462: * @see #putLookAndFeelReplacement(String, String)
463: * @see #removeLookAndFeelReplacement(String)
464: * @see #initializeDefaultReplacements()
465: */
466: public static String getReplacementClassNameFor(String className) {
467: String replacement = (String) LAF_REPLACEMENTS.get(className);
468: return replacement == null ? className : replacement;
469: }
470:
471: /**
472: * Returns the class name for a cross-platform <code>LookAndFeel</code>.
473: *
474: * @return the name of a cross platform look-and-feel class
475: * @see #getSystemLookAndFeelClassName()
476: */
477: public static String getCrossPlatformLookAndFeelClassName() {
478: return PLASTIC3D_NAME;
479: }
480:
481: /**
482: * Returns the class name for a system specific <code>LookAndFeel</code>.
483: *
484: * @return the name of the system look-and-feel class
485: * @see #getCrossPlatformLookAndFeelClassName()
486: */
487: public static String getSystemLookAndFeelClassName() {
488: String osName = System.getProperty("os.name");
489: if (osName.startsWith("Windows"))
490: return Options.JGOODIES_WINDOWS_NAME;
491: else if (osName.startsWith("Mac"))
492: return UIManager.getSystemLookAndFeelClassName();
493: else
494: return getCrossPlatformLookAndFeelClassName();
495: }
496:
497: }
|