0001: /*
0002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * o Redistributions of source code must retain the above copyright notice,
0008: * this list of conditions and the following disclaimer.
0009: *
0010: * o Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
0015: * its contributors may be used to endorse or promote products derived
0016: * from this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
0025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: */
0030: package org.jvnet.substance;
0031:
0032: import java.awt.*;
0033: import java.beans.PropertyChangeEvent;
0034: import java.beans.PropertyChangeListener;
0035: import java.lang.reflect.Constructor;
0036: import java.util.*;
0037:
0038: import javax.swing.*;
0039: import javax.swing.plaf.UIResource;
0040: import javax.swing.plaf.basic.BasicLookAndFeel;
0041:
0042: import org.jvnet.lafplugin.*;
0043: import org.jvnet.lafwidget.LafWidgetRepository;
0044: import org.jvnet.lafwidget.animation.*;
0045: import org.jvnet.lafwidget.utils.TrackableThread;
0046: import org.jvnet.substance.border.*;
0047: import org.jvnet.substance.button.*;
0048: import org.jvnet.substance.color.ColorScheme;
0049: import org.jvnet.substance.combo.ComboPopupPrototypeCallback;
0050: import org.jvnet.substance.fonts.*;
0051: import org.jvnet.substance.grip.GripPainter;
0052: import org.jvnet.substance.painter.*;
0053: import org.jvnet.substance.painter.decoration.*;
0054: import org.jvnet.substance.painter.highlight.ClassicHighlightPainter;
0055: import org.jvnet.substance.painter.highlight.SubstanceHighlightPainter;
0056: import org.jvnet.substance.painter.text.DefaultTextPainter;
0057: import org.jvnet.substance.painter.text.SubstanceTextPainter;
0058: import org.jvnet.substance.plugin.*;
0059: import org.jvnet.substance.skin.*;
0060: import org.jvnet.substance.tabbed.BaseTabCloseListener;
0061: import org.jvnet.substance.tabbed.TabCloseCallback;
0062: import org.jvnet.substance.theme.*;
0063: import org.jvnet.substance.theme.SubstanceTheme.ThemeKind;
0064: import org.jvnet.substance.utils.*;
0065: import org.jvnet.substance.utils.SubstanceConstants.ImageWatermarkKind;
0066: import org.jvnet.substance.utils.SubstanceConstants.MenuGutterFillKind;
0067: import org.jvnet.substance.utils.params.*;
0068: import org.jvnet.substance.watermark.*;
0069:
0070: import contrib.com.jgoodies.looks.common.ShadowPopupFactory;
0071:
0072: /**
0073: * Main class for <b>Substance </b> look and feel. <b>All</b> static methods in
0074: * this class should be called when Substance is the currently set look and
0075: * feel.<br>
0076: * <br>
0077: * Since version 3.1, <b>Substance</b> no longer extends Metal. As before, this
0078: * is an implementation detail and not part of an official API.
0079: *
0080: * @author Kirill Grouchnikov
0081: */
0082: public class SubstanceLookAndFeel extends BasicLookAndFeel {
0083: /**
0084: * The name of plugin configuration XML resource name. This is used for the
0085: * <a href="https://laf-plugin.dev.java.net">laf-plugin</a> support layer
0086: * of third-party components.
0087: */
0088: public static final String PLUGIN_XML = "META-INF/substance-plugin.xml";
0089:
0090: /**
0091: * Plugin manager for component plugins.
0092: */
0093: protected static ComponentPluginManager componentPlugins;
0094:
0095: /**
0096: * Plugin manager for theme plugins.
0097: */
0098: protected static PluginManager themePlugins;
0099:
0100: /**
0101: * Plugin manager for skin plugins.
0102: */
0103: protected static PluginManager skinPlugins;
0104:
0105: /**
0106: * Plugin manager for watermark plugins.
0107: */
0108: protected static PluginManager watermarkPlugins;
0109:
0110: /**
0111: * Plugin manager for button shaper plugins.
0112: */
0113: protected static PluginManager shaperPlugins;
0114:
0115: /**
0116: * Plugin manager for gradient painter plugins.
0117: */
0118: protected static PluginManager painterPlugins;
0119:
0120: /**
0121: * Plugin manager for title painter plugins.
0122: */
0123: protected static PluginManager titlePainterPlugins;
0124:
0125: /**
0126: * Plugin manager for border painter plugins.
0127: */
0128: protected static PluginManager borderPainterPlugins;
0129:
0130: /**
0131: * List of all listeners on skin changes.
0132: */
0133: protected static Set<SkinChangeListener> skinChangeListeners = new HashSet<SkinChangeListener>();
0134:
0135: /**
0136: * List of all listeners on theme changes.
0137: */
0138: protected static Set<ThemeChangeListener> themeChangeListeners;
0139:
0140: /**
0141: * List of all listeners on watermark changes.
0142: */
0143: protected static Set<WatermarkChangeListener> watermarkChangeListeners;
0144:
0145: /**
0146: * List of all listeners on button shaper changes.
0147: */
0148: protected static Set<ButtonShaperChangeListener> buttonShaperChangeListeners;
0149:
0150: /**
0151: * List of all listeners on gradient painter changes.
0152: */
0153: protected static Set<GradientPainterChangeListener> gradientPainterChangeListeners;
0154:
0155: /**
0156: * List of all listeners on border painter changes.
0157: */
0158: protected static Set<BorderPainterChangeListener> borderPainterChangeListeners;
0159:
0160: /**
0161: * List of all listeners on closing tabs.
0162: */
0163: protected static Set<LocaleChangeListener> localeChangeListeners;
0164:
0165: static {
0166: themeChangeListeners = new HashSet<ThemeChangeListener>();
0167: watermarkChangeListeners = new HashSet<WatermarkChangeListener>();
0168: buttonShaperChangeListeners = new HashSet<ButtonShaperChangeListener>();
0169: gradientPainterChangeListeners = new HashSet<GradientPainterChangeListener>();
0170: borderPainterChangeListeners = new HashSet<BorderPainterChangeListener>();
0171: localeChangeListeners = new HashSet<LocaleChangeListener>();
0172:
0173: themeChangeListeners.add(new ThemeChangeListener() {
0174: public void themeChanged() {
0175: for (Frame frame : Frame.getFrames())
0176: SubstanceCoreUtilities.resetMenuBars(frame);
0177: }
0178: });
0179:
0180: localeChangeListeners.add(new LocaleChangeListener() {
0181: public void localeChanged() {
0182: for (Frame frame : Frame.getFrames())
0183: SubstanceCoreUtilities.resetMenuBars(frame);
0184: }
0185: });
0186:
0187: }
0188:
0189: /**
0190: * Contains a list of all control class names that should ignore the
0191: * animations.
0192: */
0193: protected static Set<String> ignoreAnimationsSet = new HashSet<String>();
0194:
0195: /**
0196: * List of all globally registered mixed themes.
0197: */
0198: protected static Map<String, SubstanceMixTheme> mixedThemes = new HashMap<String, SubstanceMixTheme>();
0199:
0200: /**
0201: * Contains default background composites on per-class basis. This map is
0202: * "consulted" if no {@link #BACKGROUND_COMPOSITE} property is set on the
0203: * control.
0204: *
0205: * @see #BACKGROUND_COMPOSITE
0206: * @see #setBackgroundComposite(Class, ControlBackgroundComposite)
0207: * @see #getBackgroundComposite(Component)
0208: */
0209: protected static Map<Class<?>, ControlBackgroundComposite> backgroundComposites = new HashMap<Class<?>, ControlBackgroundComposite>();
0210:
0211: /**
0212: * Indicates whether extra UI elements (such as menu items in system menu or
0213: * menu search panel) should be shown.
0214: *
0215: * @see #toShowExtraElements()
0216: * @see #NO_EXTRA_ELEMENTS
0217: */
0218: protected static boolean toShowExtraElements;
0219:
0220: /**
0221: * Indicates whether option dialogs (error, question, warning, info) should
0222: * use constant themes for icon coloring. Note that since version 4.0, the
0223: * default setting is <code>true</code> (use constant theme). To use
0224: * theme-consistent coloring, call
0225: * {@link #setToUseConstantThemesOnDialogs(boolean)} and pass
0226: * <code>true</code>.
0227: *
0228: * @see #isToUseConstantThemesOnDialogs()
0229: * @see #setToUseConstantThemesOnDialogs(boolean)
0230: */
0231: protected static boolean toUseConstantThemesOnDialogs = true;
0232:
0233: /**
0234: * Indicates whether inverted themes should be enabled.
0235: *
0236: * @see #toEnableInvertedThemes()
0237: * @see #ENABLE_INVERTED_THEMES
0238: */
0239: protected static boolean toEnableInvertedThemes;
0240:
0241: /**
0242: * Indicates whether inverted themes should be enabled.
0243: *
0244: * @see #toEnableNegatedThemes()
0245: * @see #ENABLE_NEGATED_THEMES
0246: */
0247: protected static boolean toEnableNegatedThemes;
0248:
0249: /**
0250: * Indicates whether the watermark should "bleed" through lists, tables and
0251: * trees.
0252: *
0253: * @see #toBleedWatermark()
0254: * @see #WATERMARK_TO_BLEED
0255: */
0256: protected static boolean toBleedWatermark;
0257:
0258: /**
0259: * Indicates whether the application will be run in debug UI mode
0260: *
0261: * @see #isDebugUiMode()
0262: * @see #DEBUG_UI_MODE
0263: */
0264: protected static boolean isDebugUiMode;
0265:
0266: /**
0267: * Change listener on keyboard focus manager - fix for defect 208.
0268: */
0269: protected PropertyChangeListener focusOwnerChangeListener;
0270:
0271: /**
0272: * The current keyboard focus manager - fix for defect 208.
0273: */
0274: protected KeyboardFocusManager currentKeyboardFocusManager;
0275:
0276: /**
0277: * Fade kind for border animations. Enabled by default, use
0278: * {@link FadeConfigurationManager#disallowFades(FadeKind)} to disable.
0279: */
0280: public static final FadeKind BORDER_ANIMATION_KIND = new FadeKind(
0281: "substancelaf.borderAnimation");
0282:
0283: /**
0284: * <p>
0285: * Fade kind for tree decorations animation kind. Disabled by default, use
0286: * {@link FadeConfigurationManager#allowFades(FadeKind)} to enable.
0287: * </p>
0288: *
0289: * <p>
0290: * Tree decorations include collapse / expand icons and vertical /
0291: * horizontal lines.
0292: * </p>
0293: *
0294: * @since version 3.3
0295: */
0296: public static final FadeKind TREE_DECORATIONS_ANIMATION_KIND = new FadeKind(
0297: "substancelaf.treeDecorationsAnimation", false);
0298:
0299: /**
0300: * Fade kind for smart tree scroll. Disabled by default, use
0301: * {@link FadeConfigurationManager#allowFades(FadeKind)} to enable.
0302: * </p>
0303: *
0304: * <p>
0305: * Smart tree scroll is relevant for scroll panes containing a tree. When
0306: * enabled, it automatically scrolls the tree horizontally when the viewport
0307: * shows mainly empty area (especially relevant for multi-level trees with
0308: * narrow viewports).
0309: * </p>
0310: *
0311: * @since 4.0
0312: */
0313: public final static FadeKind TREE_SMART_SCROLL_ANIMATION_KIND = new FadeKind(
0314: "substancelaf.treeSmartScrollAnimationKind", false);
0315:
0316: /**
0317: * Property name for specifying the debug UI mode. Application running in
0318: * debug UI mode will have additional UI controls for inspecting / changing
0319: * the state of various controls. This property can be set as either VM flag
0320: * (no value needed) or as a global setting on {@link UIManager}. In the
0321: * latter case, the value should be either {@link Boolean#TRUE} or
0322: * {@link Boolean#FALSE}.
0323: *
0324: * <p>
0325: * Example of setting this property via VM flag:
0326: * </p>
0327: * <code>
0328: * -Dsubstancelaf.debugUiMode
0329: * </code>
0330: *
0331: * <p>
0332: * Example of setting this property on {@link UIManager}:
0333: * </p>
0334: * <code>
0335: * UIManager.put(SubstanceLookAndFeel.DEBUG_UI_MODE, Boolean.TRUE);
0336: * </code>
0337: *
0338: * @since version 3.1
0339: */
0340: public static final String DEBUG_UI_MODE = "substancelaf.debugUiMode";
0341:
0342: /**
0343: * Property name for setting theme. This property is used both as a JVM flag
0344: * and as a client property that can be set on a specific component.
0345: *
0346: * <p>
0347: * If this property is used as a JVM flag, the value should be a
0348: * fully-qualified name of the theme class. This class must have a default
0349: * (no-argument) constructor. This means that you can not specify "generic"
0350: * themes such as {@link SubstanceMixTheme} or {@link SubstanceToneTheme}.
0351: * </p>
0352: *
0353: * <p>
0354: * If this property is used as a client property, the value can be one of:
0355: * </p>
0356: * <ul>
0357: * <li>{@link String} - theme display name (only for primitive themes).</li>
0358: * <li>{@link ThemeInfo} object (call {@link #getAllThemes()}).</li>
0359: * <li>{@link SubstanceTheme} object itself.</li>
0360: * </ul>
0361: *
0362: * <p>
0363: * Example of specifying a custom default theme as a VM flag:
0364: * </p>
0365: * <code>
0366: * -Dsubstancelaf.theme=org.jvnet.substance.theme.SubstanceBottleGreenTheme
0367: * </code>
0368: *
0369: * <p>
0370: * Example of using a theme display name as client property value:
0371: * </p>
0372: * <code>
0373: * JCheckBox cb = new JCheckBox("text");<br>
0374: * cb.putClientProperty(SubstanceLookAndFeel.THEME_PROPERTY, "Bottle Green");
0375: * </code>
0376: *
0377: * <p>
0378: * Example of using a {@link ThemeInfo} object as client property value:
0379: * </p>
0380: * <code>
0381: * JCheckBox cb = new JCheckBox("text");<br>
0382: * ThemeInfo ti = SubstanceLookAndFeel.getAllThemes().get("Bottle Green");<br>
0383: * cb.putClientProperty(SubstanceLookAndFeel.THEME_PROPERTY, ti);
0384: * </code>
0385: *
0386: * <p>
0387: * Example of using a {@link SubstanceTheme} object as client property
0388: * value:
0389: * </p>
0390: * <code>
0391: * JCheckBox cb = new JCheckBox("text");<br>
0392: * cb.putClientProperty(SubstanceLookAndFeel.THEME_PROPERTY, <br>
0393: * new SubstanceBottleGreenTheme());
0394: * </code>
0395: *
0396: * @since version 2.0
0397: * @see #getCurrentThemeName()
0398: * @see #getTheme()
0399: * @see #setCurrentTheme(String)
0400: * @see #setCurrentTheme(SubstanceTheme)
0401: * @see #setCurrentTheme(ThemeInfo)
0402: * @see #registerThemeChangeListener(ThemeChangeListener)
0403: * @see #unregisterThemeChangeListener(ThemeChangeListener)
0404: */
0405: public static final String THEME_PROPERTY = "substancelaf.theme";
0406:
0407: /**
0408: * Property name for setting watermark. This is only for JVM flag. The value
0409: * should be a fully-qualified name of the watermark class. This class must
0410: * have a default (no-argument) constructor. This means that you can not
0411: * specify "generic" watermark such as {@link SubstanceNoiseWatermark}.
0412: *
0413: * <p>
0414: * Example of specifying a custom default watermark as a VM flag:
0415: * </p>
0416: * <code>
0417: * -Dsubstancelaf.watermark=org.jvnet.substance.watermark.SubstanceKatakanaWatermark
0418: * </code>
0419: *
0420: * @since version 2.0
0421: * @see #getCurrentWatermark()
0422: * @see #getCurrentWatermarkName()
0423: * @see #setCurrentWatermark(String)
0424: * @see #setCurrentWatermark(SubstanceWatermark)
0425: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
0426: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
0427: */
0428: public static final String WATERMARK_PROPERTY = "substancelaf.watermark";
0429:
0430: /**
0431: * Property name for setting {@link SubstanceImageWatermark} watermark
0432: * image. This is only for JVM flag. The value should be a location of
0433: * watermark image as either filename or <i>http</i>-prefixed URL.
0434: *
0435: * <p>
0436: * Example of specifying a local image as watermark image:
0437: * </p>
0438: * <code>
0439: * -Dsubstancelaf.watermark.image=C:/images/myimage.jpg
0440: * </code>
0441: *
0442: * <p>
0443: * Example of specifying a URL image as watermark image:
0444: * </p>
0445: * <code>
0446: * -Dsubstancelaf.watermark.image=http://images.com/myimage.jpg
0447: * </code>
0448: *
0449: * @since version 2.0
0450: * @see #getImageWatermarkKind()
0451: * @see #getImageWatermarkOpacity()
0452: * @see #setImageWatermarkKind(ImageWatermarkKind)
0453: * @see #setImageWatermarkOpacity(float)
0454: * @see #WATERMARK_IMAGE_KIND
0455: * @see #WATERMARK_IMAGE_OPACITY
0456: */
0457: public static final String WATERMARK_IMAGE_PROPERTY = "substancelaf.watermark.image";
0458:
0459: /**
0460: * Property name for requesting that watermark should bleed through lists,
0461: * trees and tables. This is both a JVM flag and a client property on
0462: * {@link UIManager} (global setting).
0463: *
0464: * <p>
0465: * When this property is used as a JVM flag, there is no need to specify any
0466: * value:
0467: * </p>
0468: * <code>
0469: * -Dsubstancelaf.watermark.tobleed
0470: * </code>
0471: *
0472: * <p>
0473: * When this property is set a client property on {@link UIManager}, the
0474: * value should be one of {@link Boolean#TRUE} or {@link Boolean#FALSE}.
0475: * For example,
0476: * </p>
0477: * <code>
0478: * UIManager.put(SubstanceLookAndFeel.WATERMARK_TO_BLEED, Boolean.TRUE);
0479: * </code>
0480: *
0481: * @since version 2.2
0482: */
0483: public static final String WATERMARK_TO_BLEED = "substancelaf.watermark.tobleed";
0484:
0485: /**
0486: * Client property name for requesting that watermark should not be painted
0487: * on the component and its descendants. This property can be set either as
0488: * client property on some component or as global property on
0489: * {@link UIManager}. The value should be either {@link Boolean#TRUE} or
0490: * {@link Boolean#FALSE}.
0491: *
0492: * <p>
0493: * In order to compute whether the current watermark should be painted on
0494: * some component, the component's hierarchy is traversed bottom up. The
0495: * first component that has this property set, defines the watermark
0496: * visibility. Finally, if neither component not its ancestors define this
0497: * property, the global setting on {@link UIManager} is checked. If there is
0498: * no global setting, the watermark is <b>not</b> ignored (it is painted).
0499: * Here is an example to illustrate the above:
0500: *
0501: * <p>
0502: * <code>
0503: * JPanel topPanel = new JPanel();<br>
0504: * topPanel.putClientProperty(SubstanceLookAndFeel.WATERMARK_IGNORE,<br>
0505: * Boolean.TRUE);<br>
0506: * JPanel panel1 = new JPanel();<br>
0507: * JPanel panel2 = new JPanel();<br>
0508: * panel2.putClientProperty(SubstanceLookAndFeel.WATERMARK_IGNORE, <br>
0509: * Boolean.FALSE);<br>
0510: * JTextField tf1 = new JTextField("field1");<br>
0511: * tf1.putClientProperty(SubstanceLookAndFeel.WATERMARK_IGNORE, Boolean.TRUE);<br>
0512: * JTextField tf2 = new JTextField("field2");<br>
0513: * panel1.add(tf1);<br>
0514: * panel1.add(tf2);<br>
0515: * topPanel.add(panel1);<br>
0516: * topPanel.add(panel2);
0517: * </code>
0518: * </p>
0519: *
0520: * <p>
0521: * In the code above, if {@link UIManager} has no value for this property,
0522: * the watermark will be painted only on <b>panel2</b> and <b>tf1</b>. The
0523: * <b>panel1</b> and <b>tf2</b> "inherit" the watermark-ignore setting
0524: * from their <b>topPanel</b> ancestor.
0525: *
0526: * @since version 2.2
0527: */
0528: public static final String WATERMARK_IGNORE = "substancelaf.watermark.toignore";
0529:
0530: /**
0531: * VM property for specifying the image watermark kind. Should be the name
0532: * of one of the values in {@link SubstanceConstants.ImageWatermarkKind}
0533: * enum. Is used only as a JVM flag. The default value (if no VM flag is
0534: * specified) is
0535: * {@link SubstanceConstants.ImageWatermarkKind#SCREEN_CENTER_SCALE}.
0536: * Example of specifying custom default image watermark kind:
0537: *
0538: * <p>
0539: * <code>
0540: * -Dsubstancelaf.watermark.image.kind=APP_ANCHOR
0541: * </code>
0542: *
0543: * @since version 2.3
0544: * @see #getImageWatermarkKind()
0545: * @see #getImageWatermarkOpacity()
0546: * @see #setImageWatermarkKind(ImageWatermarkKind)
0547: * @see #setImageWatermarkOpacity(float)
0548: * @see #WATERMARK_IMAGE_OPACITY
0549: * @see #WATERMARK_IMAGE_PROPERTY
0550: */
0551: public static final String WATERMARK_IMAGE_KIND = "substancelaf.watermark.image.kind";
0552:
0553: /**
0554: * VM property for specifying the image watermark opacity. Should be in
0555: * 0.0-1.0 range. Is used only as a JVM flag. The default value (if no VM
0556: * flag is specified) is 0.2. The default value is also taken if the VM flag
0557: * value can not be parsed as a float number. If the VM flag value can be
0558: * parsed as a float, but is outside of 0.0-1.0 range, an
0559: * {@link IllegalArgumentException} will be thrown at the application
0560: * startup. Example of setting custom default watermark image opacity: *
0561: *
0562: * <p>
0563: * <code>
0564: * -Dsubstancelaf.watermark.image.opacity=0.6
0565: * </code>
0566: *
0567: * @since version 2.3
0568: * @see #getImageWatermarkKind()
0569: * @see #getImageWatermarkOpacity()
0570: * @see #setImageWatermarkKind(ImageWatermarkKind)
0571: * @see #setImageWatermarkOpacity(float)
0572: * @see #WATERMARK_IMAGE_KIND
0573: * @see #WATERMARK_IMAGE_PROPERTY
0574: */
0575: public static final String WATERMARK_IMAGE_OPACITY = "substancelaf.watermark.image.opacity";
0576:
0577: /**
0578: * Client property name for ignoring default (minimum) dimension for a
0579: * single button. This property can be set either as a client property on a
0580: * specific button or as a global setting on {@link UIManager}. The value
0581: * should be either {@link Boolean#TRUE} or {@link Boolean#FALSE}.
0582: * <p>
0583: * Note that {@link SubstanceButtonShaper} implementations are not required
0584: * to respect this property. The current implementations of the default
0585: * {@link StandardButtonShaper} and {@link ClassicButtonShaper} respect this
0586: * property.
0587: * </p>
0588: *
0589: * <p>
0590: * Example of marking a button to ignore minimum dimension settings:
0591: * </p>
0592: * <code>
0593: * JButton button = new JButton("text");<br>
0594: * button.putClientProperty(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, <br>
0595: * Boolean.TRUE);
0596: * </code>
0597: * <p>
0598: * Example of marking all application buttons to ignore minimum dimension
0599: * settings:
0600: * </p>
0601: * <code>
0602: * UIManager.put(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, <br>
0603: * Boolean.TRUE);
0604: * </code>
0605: *
0606: * @since version 2.1
0607: */
0608: public static final String BUTTON_NO_MIN_SIZE_PROPERTY = "substancelaf.buttonnominsize";
0609:
0610: /**
0611: * Client property name for specifying that a single control / all
0612: * application controls should always be painted in active color (unless a
0613: * control is disabled). This property can be set either as a client
0614: * property on a specific control or as a global setting on
0615: * {@link UIManager}. The value should be either {@link Boolean#TRUE} or
0616: * {@link Boolean#FALSE}.
0617: *
0618: * <p>
0619: * Example of marking a button to be painted active:
0620: * </p>
0621: * <code>
0622: * JButton button = new JButton("text");<br>
0623: * button.putClientProperty(SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY, <br>
0624: * Boolean.TRUE);
0625: * </code>
0626: * <p>
0627: * Example of marking all application controls to be painted active:
0628: * </p>
0629: * <code>
0630: * UIManager.put(SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY, <br>
0631: * Boolean.TRUE);
0632: * </code>
0633: *
0634: * @since version 3.0
0635: */
0636: public static final String PAINT_ACTIVE_PROPERTY = "substancelaf.paintactive";
0637:
0638: /**
0639: * Client property name for specifying that a single button / all
0640: * application buttons should never paint the background. This property can
0641: * be set either as a client property on a specific button or as a global
0642: * setting on {@link UIManager}. The value should be either
0643: * {@link Boolean#TRUE} or {@link Boolean#FALSE}. Note that unlike the
0644: * {@link #FLAT_PROPERTY}, a button marked with this property will <b>never</b>
0645: * show the background (will always be painted flat).
0646: *
0647: * <p>
0648: * Example of marking a button to never paint background:
0649: * </p>
0650: * <code>
0651: * JButton button = new JButton("text");<br>
0652: * button.putClientProperty(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, <br>
0653: * Boolean.TRUE);
0654: * </code>
0655: *
0656: * <p>
0657: * Example of marking all application buttons to never paint background:
0658: * </p>
0659: * <code>
0660: * UIManager.put(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, <br>
0661: * Boolean.TRUE);
0662: * </code>
0663: *
0664: * @since version 2.3
0665: * @see #FLAT_PROPERTY
0666: */
0667: public static final String BUTTON_PAINT_NEVER_PROPERTY = "substancelaf.buttonpaintnever";
0668:
0669: /**
0670: * Client property name for specifying a straight side for a single button.
0671: * This property must be set as a client property on a specific button. The
0672: * value can be:
0673: *
0674: * <p>
0675: * <ul>
0676: * <li>The name of one of the values in {@link SubstanceConstants.Side}
0677: * enum.
0678: * <li>Array of names of the values in {@link SubstanceConstants.Side}
0679: * enum.
0680: * <li>A value in {@link SubstanceConstants.Side} enum.
0681: * <li>Array of values in {@link SubstanceConstants.Side} enum.
0682: * </ul>
0683: *
0684: * <p>
0685: * Note that not all {@link SubstanceButtonShaper} implementations are
0686: * required to respect this property. The default
0687: * {@link StandardButtonShaper} and {@link ClassicButtonShaper} respect this
0688: * property.
0689: * </p>
0690: *
0691: * <p>
0692: * Example of marking a button to have straight north side:
0693: * </p>
0694: * <code>
0695: * JButton button = new JButton("text");<br>
0696: * button.putClientProperty(SubstanceLookAndFeel.BUTTON_SIDE_PROPERTY,<br>
0697: * SubstanceConstants.Side.RIGHT.name());
0698: * </code>
0699: *
0700: * @since version 2.1
0701: * @see #BUTTON_OPEN_SIDE_PROPERTY
0702: */
0703: public static final String BUTTON_SIDE_PROPERTY = "substancelaf.buttonside";
0704:
0705: /**
0706: * Client property name for specifying an open side for a single button.
0707: * This property must be set as a client property on a specific button. The
0708: * value can be:
0709: *
0710: * <p>
0711: * <ul>
0712: * <li>The name of one of the values in {@link SubstanceConstants.Side}
0713: * enum.
0714: * <li>Array of names of the values in {@link SubstanceConstants.Side}
0715: * enum.
0716: * <li>A value in {@link SubstanceConstants.Side} enum.
0717: * <li>Array of values in {@link SubstanceConstants.Side} enum.
0718: * </ul>
0719: * </p>
0720: * <p>
0721: * Example of marking a button to have open north side:
0722: * </p>
0723: * <code>
0724: * JButton button = new JButton("text");<br>
0725: * Set<Side> openSides = new HashSet<Side>();<br>
0726: * openSides.put(Side.TOP);<br>
0727: * button.putClientProperty(SubstanceLookAndFeel.BUTTON_OPEN_SIDE_PROPERTY, <br>
0728: * openSides);
0729: * </code>
0730: *
0731: * @since version 3.1
0732: * @see #BUTTON_SIDE_PROPERTY
0733: */
0734: public static final String BUTTON_OPEN_SIDE_PROPERTY = "substancelaf.buttonopenSide";
0735:
0736: /**
0737: * Property name for specifying button shaper. This property is used both as
0738: * a JVM flag and as a client property that can be set on a specific button.
0739: *
0740: * <p>
0741: * If this property is used as a JVM flag, the value should be a
0742: * fully-qualified name of the button shaper class. This class must have a
0743: * default (no-argument) constructor.
0744: * </p>
0745: *
0746: * <p>
0747: * If this property is used as a client property, the value can be one of:
0748: * <ul>
0749: * <li>{@link String} - fully-qualified name of the button shaper class.</li>
0750: * <li>{@link SubstanceButtonShaper} object itself.</li>
0751: * </ul>
0752: * </p>
0753: *
0754: * <p>
0755: * Example of specifying a custom default button shaper as a VM flag:
0756: * </p>
0757: * <code>
0758: * -Dsubstancelaf.buttonShaper=org.jvnet.substance.button.ClassicButtonShaper
0759: * </code>
0760: *
0761: * <p>
0762: * Example of using a shaper class name as client property value:
0763: * </p>
0764: * <code>
0765: * JButton b = new JButton("text");<br>
0766: * b.putClientProperty(SubstanceLookAndFeel.BUTTON_SHAPER_PROPERTY, <br>
0767: * "org.jvnet.substance.button.ClassicButtonShaper");
0768: * </code>
0769: *
0770: * <p>
0771: * Example of using a {@link SubstanceButtonShaper} object as client
0772: * property value:
0773: * </p>
0774: * <code>
0775: * JButton b = new JButton("text");<br>
0776: * b.putClientProperty(SubstanceLookAndFeel.BUTTON_SHAPER_PROPERTY, <br>
0777: * new ClassicButtonShaper());
0778: * </code>
0779: *
0780: * @since version 2.1
0781: * @see #getCurrentButtonShaper()
0782: * @see #getCurrentButtonShaperName()
0783: * @see #setCurrentButtonShaper(String)
0784: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
0785: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
0786: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
0787: */
0788: public static final String BUTTON_SHAPER_PROPERTY = "substancelaf.buttonShaper";
0789:
0790: /**
0791: * Client property name for specifying the corner radius for buttons.
0792: * Currently, this property is respected only on toolbar buttons. This
0793: * property can be set either as a client property on a specific toolbar
0794: * button, a client property on a specific toolbar (will hold for all
0795: * buttons in the toolbar) or as a global setting on {@link UIManager}. The
0796: * value should be a {@link Float} instance.
0797: *
0798: * <p>
0799: * Example of specifying a (toolbar) button to have corner radius of 5
0800: * pixels:
0801: * </p>
0802: * <code>
0803: * JButton button = new JButton("text");<br>
0804: * button.putClientProperty(SubstanceLookAndFeel.CORNER_RADIUS, <br>
0805: * Float.valueOf(5.0f));
0806: * </code>
0807: *
0808: * <p>
0809: * Example of specifying all buttons of a toolbar to have corner radius of 3
0810: * pixels:
0811: * </p>
0812: * <code>
0813: * JToolBar toolbar = new JToolBar("toolbar");<br>
0814: * toolbar.putClientProperty(SubstanceLookAndFeel.CORNER_RADIUS, <br>
0815: * Float.valueOf(3.0f));
0816: * </code>
0817: *
0818: * <p>
0819: * Example of specifying all toolbar buttons to have corner radius of 0
0820: * pixels:
0821: * </p>
0822: * <code>
0823: * UIManager.put(SubstanceLookAndFeel.CORNER_RADIUS, Float.valueOf(0.0f));
0824: * </code>
0825: *
0826: * @since version 3.0
0827: */
0828: public static final String CORNER_RADIUS = "substancelaf.cornerRadius";
0829:
0830: /**
0831: * Property name for specifying that the component should be painted flat
0832: * (no background / border) when it's inactive. This property should be
0833: * specified on a specific component or its parent and must have either
0834: * {@link Boolean#TRUE} or {@link Boolean#FALSE} value. For example, this is
0835: * how to mark a button to appear flat:
0836: * <p>
0837: * <code>
0838: * JButton button = new JButton("text");<br>
0839: * button.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, <br>
0840: * Boolean.TRUE);
0841: * </code>
0842: *
0843: * @since version 3.0
0844: * @see #BUTTON_PAINT_NEVER_PROPERTY
0845: */
0846: public static final String FLAT_PROPERTY = "substancelaf.componentFlat";
0847:
0848: /**
0849: * Client property name for specifying that a single control / all
0850: * application controls have overlay functionality. This property can be set
0851: * either as a client property on a specific control or as a global setting
0852: * on {@link UIManager}. The value should be either {@link Boolean#TRUE} or
0853: * {@link Boolean#FALSE}.
0854: *
0855: * <p>
0856: * Example of marking a scroll pane to have overlays on the scroll bars:
0857: * </p>
0858: * <code>
0859: * JPanel myPanel = new JPanel();<br>
0860: * JScrollPane jsp = new JScrollPane(myPanel);<br>
0861: * myPanel.putClientProperty(SubstanceLookAndFeel.OVERLAY_PROPERTY, <br>
0862: * Boolean.TRUE);
0863: * </code>
0864: *
0865: * <p>
0866: * Example of marking all application controls to have overlays:
0867: * </p>
0868: * <code>
0869: * UIManager.put(SubstanceLookAndFeel.OVERLAY_PROPERTY, <br>
0870: * Boolean.TRUE);
0871: * </code>
0872: *
0873: * @since version 3.2
0874: */
0875: public static final String OVERLAY_PROPERTY = "substancelaf.overlay";
0876:
0877: /**
0878: * Property name for specifying custom grip handles. This applies to scroll
0879: * bars, split pane dividers and other relevant controls. The value should
0880: * be an instance of {@link GripPainter} interface.
0881: *
0882: * <p>
0883: * Example of marking a scroll pane to have custom grip handles on its
0884: * scroll bars:
0885: * </p>
0886: * <code>
0887: * JPanel myPanel = new JPanel();<br>
0888: * JScrollPane jsp = new JScrollPane(myPanel);<br>
0889: * myPanel.putClientProperty(SubstanceLookAndFeel.GRIP_PAINTER, <br>
0890: * new DragBumpsGripPainter());
0891: * </code>
0892: *
0893: * @since version 3.2
0894: * @deprecated Will be removed in version 5.0
0895: */
0896: public static final String GRIP_PAINTER = "substancelaf.gripPainter";
0897:
0898: /**
0899: * Property name for specifying gradient painter. This property is used both
0900: * as a JVM flag and as a client property that can be set on a specific
0901: * button.
0902: *
0903: * <p>
0904: * For the JVM flag, the value should be fully-qualified name of the
0905: * gradient painter class. This class must have a default (no-argument)
0906: * constructor. For the client property, the value can be either a
0907: * fully-qualified class name as above or an instance of
0908: * {@link SubstanceGradientPainter}.
0909: * </p>
0910: *
0911: * <p>
0912: * Example of specifying a custom default gradient painter as a VM flag:
0913: * </p>
0914: * <code>
0915: * -Dsubstancelaf.gradientPainter=org.jvnet.substance.painter.SpecularGradientPainter
0916: * </code>
0917: *
0918: * <p>
0919: * Example of using a painter class name as client property value:
0920: * </p>
0921: * <code>
0922: * JButton b = new JButton("text");<br>
0923: * b.putClientProperty(SubstanceLookAndFeel.GRADIENT_PAINTER_PROPERTY, <br>
0924: * "org.jvnet.substance.painter.SpecularGradientPainter");
0925: * </code>
0926: *
0927: * <p>
0928: * Example of using a painter instance as client property value:
0929: * </p>
0930: * <code>
0931: * JButton b = new JButton("text");<br>
0932: * b.putClientProperty(SubstanceLookAndFeel.GRADIENT_PAINTER_PROPERTY,<br>
0933: * new SpecularGradientPainter());
0934: * </code>
0935: *
0936: * @since version 2.1
0937: * @see #getCurrentGradientPainter()
0938: * @see #getCurrentGradientPainterName()
0939: * @see #setCurrentGradientPainter(String)
0940: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
0941: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
0942: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
0943: */
0944: public static final String GRADIENT_PAINTER_PROPERTY = "substancelaf.gradientPainter";
0945:
0946: /**
0947: * Property name for specifying title painter. This property is used both as
0948: * a JVM flag and as a client property that can be set on a specific root
0949: * pane / internal frame.
0950: *
0951: * <p>
0952: * For JVM flag, the value should be a fully-qualified name of the title
0953: * painter class. This class must have a default (no-argument) constructor.
0954: * For client property, the value should be either a fully-qualified class
0955: * name as above or an instance of {@link SubstanceTitlePainter}.
0956: * </p>
0957: *
0958: * <p>
0959: * Example of specifying a custom default title painter as a VM flag:
0960: * </p>
0961: * <code>
0962: * -Dsubstancelaf.titlePainter=org.jvnet.substance.title.ClassicTitlePainter
0963: * </code>
0964: *
0965: * <p>
0966: * Example of using a painter class name as client property value:
0967: * </p>
0968: * <code>
0969: * JFrame fr = new JFrame("text");<br>
0970: * fr.getRootPane().putClientProperty(SubstanceLookAndFeel.TITLE_PAINTER_PROPERTY,<br>
0971: * "org.jvnet.substance.title.ClassicTitlePainter");
0972: * </code>
0973: *
0974: * @since version 3.0
0975: * @see #getCurrentTitlePainter()
0976: * @see #getCurrentTitlePainterName()
0977: * @see #setCurrentTitlePainter(String)
0978: * @see #setCurrentTitlePainter(SubstanceTitlePainter)
0979: * @see #registerTitlePainterChangeListener(TitlePainterChangeListener)
0980: * @see #unregisterTitlePainterChangeListener(TitlePainterChangeListener)
0981: */
0982: public static final String TITLE_PAINTER_PROPERTY = "substancelaf.titlePainter";
0983:
0984: /**
0985: * Property name for specifying border painter. This property is used both
0986: * as a JVM flag and as a client property that can be set on a specific
0987: * component.
0988: *
0989: * <p>
0990: * For JVM flag, the value should be a fully-qualified name of the border
0991: * painter class. This class must have a default (no-argument) constructor.
0992: * For client property, the value should be either a fully-qualified class
0993: * name as above or an instance of {@link SubstanceBorderPainter}.
0994: * </p>
0995: *
0996: * <p>
0997: * Example of specifying a custom default border painter as a VM flag:
0998: * </p>
0999: * <code>
1000: * -Dsubstancelaf.borderPainter=org.jvnet.substance.border.ClassicBorderPainter
1001: * </code>
1002: *
1003: * <p>
1004: * Example of using a painter class name as client property value:
1005: * </p>
1006: * <code>
1007: * JButton button = new JButton("text");<br>
1008: * button.putClientProperty(SubstanceLookAndFeel.BORDER_PAINTER_PROPERTY,<br>
1009: * "org.jvnet.substance.border.ClassicBorderPainter");
1010: * </code>
1011: *
1012: * @since version 4.0
1013: * @see #getCurrentBorderPainter()
1014: * @see #getCurrentBorderPainterName()
1015: * @see #setCurrentBorderPainter(String)
1016: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
1017: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
1018: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
1019: */
1020: public static final String BORDER_PAINTER_PROPERTY = "substancelaf.borderPainter";
1021:
1022: /**
1023: * Property name for specifying that custom frame title panes should show
1024: * the heap status panel. Can be used as a VM flag.
1025: *
1026: * <p>
1027: * When this VM flag is set (no need to specify a value), the system menu on
1028: * decorated title panes will have a check box menu item that controls the
1029: * visibility of the heap status panel. The
1030: * {@link #permanentlyShowHeapStatusPanel(JRootPane)} (can be called <b>only</b>
1031: * when the VM flag is set) removes the above check box menu item and adds
1032: * the heap status panel to the title pane (if it wasn't shown prior to
1033: * calling that method). The
1034: * {@link #permanentlyHideHeapStatusPanel(JRootPane)} (can be called <b>only</b>
1035: * when the VM flag is set) removes the above check box menu item and
1036: * removes the heap status panel to the title pane (if it was shown prior to
1037: * calling that method).
1038: * </p>
1039: *
1040: * <code>
1041: * -Dsubstancelaf.heapStatusPanel
1042: * </code>
1043: *
1044: * @since version 2.1
1045: * @see #permanentlyHideHeapStatusPanel(JRootPane)
1046: * @see #permanentlyShowHeapStatusPanel(JRootPane)
1047: */
1048: public static final String HEAP_STATUS_PANEL = "substancelaf.heapStatusPanel";
1049:
1050: /**
1051: * Client property name for specifying that contents of some frame, dialog,
1052: * internal frame, desktop icon or tab have been modified and not saved. The
1053: * property can be set on:
1054: * <p>
1055: * <ul>
1056: * <li>{@link JInternalFrame} - the <b>close</b> button of the specific
1057: * internal frame will be animated (in case that the internal frame has
1058: * decorated title pane). In addition, once such internal frame is iconified
1059: * (to a {@link JInternalFrame.JDesktopIcon}), the close button of the
1060: * matching desktop icon is animated as well.</li>
1061: * <li>{@link JRootPane} - the <b>close</b> button of the title pane of
1062: * the matching frame / dialog will be animated (in case that the frame /
1063: * dialog have decorated title pane).</li>
1064: * <li>{@link JComponent} in a {@link JTabbedPane}. Based on the
1065: * {@link #TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION} property presence,
1066: * either the entire tab or its close button area is animated. In this case,
1067: * this property must be set on the tab component itself, <b>not</b> on one
1068: * of its child components.</li>
1069: * </ul>
1070: * </p>
1071: * <p>
1072: * The animation cycles between red, orange and yellow themes. In most cases
1073: * (all but tabs not marked with
1074: * {@link #TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION} property), the
1075: * animation will be visible only when the mouse hovers over the close
1076: * button of the matching container (frame, dialog, internal frame, desktop
1077: * icon, tab). The tooltip of the close button is changed as well to reflect
1078: * that the container contents are marked as modified.
1079: * </p>
1080: *
1081: * <p>
1082: * Here is a sample text editing application that illustrates the use of
1083: * this property. Once the contents of the text pane are changed, the frame
1084: * is marked as modified. The <b>Save</b> button marks the frame as
1085: * not-modified. In the real application, the listener on this button will
1086: * need to persist the changes as well.
1087: * </p>
1088: *
1089: * <code>
1090: * public class Changer extends JFrame {<br>
1091: * public Changer() {<br>
1092: * super("Changer");<br>
1093: * <br>
1094: * this.setLayout(new BorderLayout());<br>
1095: * JTextPane textArea = new JTextPane();<br>
1096: * this.add(textArea, BorderLayout.CENTER);<br>
1097: * textArea.getDocument().addDocumentListener(new
1098: * DocumentListener() {<br>
1099: * private void handleChange() {<br>
1100: * getRootPane().putClientProperty(<br>
1101: * SubstanceLookAndFeel.WINDOW_MODIFIED,
1102: * Boolean.TRUE);<br>
1103: * }<br>
1104: * <br>
1105: * public void
1106: * changedUpdate(DocumentEvent e) {<br>
1107: * handleChange();<br>
1108: * }<br>
1109: * <br>
1110: * public void
1111: * insertUpdate(DocumentEvent e) {<br>
1112: * handleChange();<br>
1113: * }<br>
1114: * <br>
1115: * public void
1116: * removeUpdate(DocumentEvent e) {<br>
1117: * handleChange();<br>
1118: * }<br>
1119: * });<br>
1120: * <br>
1121: * JPanel buttons = new JPanel(new
1122: * FlowLayout(FlowLayout.RIGHT));<br>
1123: * JButton saveButton = new JButton("Save");<br>
1124: * saveButton.addActionListener(new ActionListener() {<br>
1125: * public void
1126: * actionPerformed(ActionEvent e) {<br>
1127: * getRootPane().putClientProperty(<br>
1128: * SubstanceLookAndFeel.WINDOW_MODIFIED,
1129: * Boolean.FALSE);<br>
1130: * }<br>
1131: * });<br>
1132: * <br>
1133: * buttons.add(saveButton);<br>
1134: * this.add(buttons, BorderLayout.SOUTH);<br>
1135: * <br>
1136: * this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br>
1137: * }<br>
1138: * <br>
1139: * public static void main(String ... args) {<br>
1140: * try {<br>
1141: * UIManager.setLookAndFeel(new
1142: * SubstanceLookAndFeel());<br>
1143: * }<br>
1144: * catch (Exception exc) {}<br>
1145: * JFrame.setDefaultLookAndFeelDecorated(true);<br>
1146: * Changer ch = new Changer();<br>
1147: * ch.setPreferredSize(new Dimension(200, 200));<br>
1148: * ch.setSize(ch.getPreferredSize());<br>
1149: * ch.setLocationRelativeTo(null);<br>
1150: * ch.setVisible(true);<br>
1151: * }<br> }
1152: * </code>
1153: *
1154: * @since version 2.1
1155: */
1156: public final static String WINDOW_MODIFIED = "windowModified";
1157:
1158: /**
1159: * Client property name for specifying the background composite for various
1160: * translucency effects. This property can be set either as a client
1161: * property on a specific control or as a global setting on
1162: * {@link UIManager}. The value should be an instance of
1163: * {@link ControlBackgroundComposite}. Available core implementations
1164: * include {@link AlphaControlBackgroundComposite},
1165: * {@link DefaultControlBackgroundComposite} and
1166: * {@link DecayControlBackgroundComposite}.
1167: * </p>
1168: *
1169: * <p>
1170: * Note that setting this property on a container (such as
1171: * {@link JScrollPane}) will affect all its children (recursively) unless
1172: * they set this property.
1173: * </p>
1174: *
1175: * <p>
1176: * Example of setting a custom background composite on a scroll pane (will
1177: * affect the painting of the scroll bars and all its children):
1178: * </p>
1179: * <code>
1180: * JPanel myPanel = new JPanel();<br>
1181: * JScrollPane jsp = new JScrollPane(myPanel);<br>
1182: * myPanel.putClientProperty(SubstanceLookAndFeel.BACKGROUND_COMPOSITE,<br>
1183: * new AlphaControlBackgroundComposite(0.4f, 0.7f));
1184: * </code>
1185: *
1186: * <p>
1187: * Example of marking all application controls with the same background
1188: * composite:
1189: * </p>
1190: * <code>
1191: * UIManager.put(SubstanceLookAndFeel.BACKGROUND_COMPOSITE, <br>
1192: * new AlphaControlBackgroundComposite(0.6f));
1193: * </code>
1194: *
1195: * @since version 3.1
1196: */
1197: public final static String BACKGROUND_COMPOSITE = "substancelaf.backgroundComposite";
1198:
1199: /**
1200: * Client property name for specifying that a single tab / all tabs of a
1201: * single tabbed pane / all tabs of all tabbed panes should have close
1202: * buttons. This property can be specified on a single tab component, on a
1203: * {@link JTabbedPane} itself (will hold for all tab components that don't
1204: * define this property) or on {@link UIManager}. The value should be
1205: * either {@link Boolean#TRUE} or {@link Boolean#FALSE}. By default, the
1206: * close buttons are not displayed.
1207: *
1208: * <p>
1209: * Example of setting that all tabs in the application will have close
1210: * buttons:
1211: * </p>
1212: * <code>
1213: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, <br>
1214: * Boolean.TRUE);
1215: * </code>
1216: *
1217: * <p>
1218: * A more complex example:
1219: * </p>
1220: * <code>
1221: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, <br>
1222: * Boolean.TRUE);<br>
1223: * JTabbedPane jtpMain = new JTabbedPane();<br>
1224: * JTabbedPane jtpSecondary = new JTabbedPane();<br>
1225: * jtpSecondary.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, <br>
1226: * Boolean.FALSE);<br>
1227: * JPanel panelSecondary = new JPanel();<br>
1228: * jtpMain.addTab(jtpSecondary);<br>
1229: * jtpMain.addTab(panelSecondary);<br>
1230: * JPanel tab1 = new JPanel();<br>
1231: * JPanel tab2 = new JPanel();<br>
1232: * tab2.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, <br>
1233: * Boolean.TRUE);<br>
1234: * jtpSecondary.addTab(tab1);<br>
1235: * jtpSecondary.addTab(tab2);
1236: * </code>
1237: *
1238: * <p>
1239: * In the example above, the first first-level child (<b>jtpSecondary</b>)
1240: * doesn't have the close button (since it overrides the global setting).
1241: * The second first-level child tab (<b>panelSecondary</b>) has close
1242: * button (from the global <b>UIManager</b> setting). The first
1243: * second-level tab doesn't have the close button (setting inherited from
1244: * the parent <b>jtpSecondary</b> tab that overrides the global setting).
1245: * The second second-level tab has the close button (since its setting
1246: * overrides the parent setting).
1247: * </p>
1248: *
1249: * @since version 2.1
1250: * @see #TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION
1251: * @see #TABBED_PANE_CLOSE_CALLBACK
1252: */
1253: public final static String TABBED_PANE_CLOSE_BUTTONS_PROPERTY = "substancelaf.tabbedpanehasclosebuttons";
1254:
1255: /**
1256: * Client property name for specifying that a single tabbed pane / all
1257: * tabbed panes should have vertical layout (rotated tabs) on
1258: * {@link SwingConstants#LEFT} and {@link SwingConstants#RIGHT} tab
1259: * placements. This property can be specified either on a single
1260: * {@link JTabbedPane} or on {@link UIManager}. The value should be either
1261: * {@link Boolean#TRUE} or {@link Boolean#FALSE}. By default, the tab
1262: * orientation on all placements is horizontal.
1263: *
1264: * <p>
1265: * Example of setting that all tabbed panes in the application will be
1266: * vertically oriented:
1267: * </p>
1268: * <code>
1269: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION, <br>
1270: * Boolean.TRUE);
1271: * </code>
1272: *
1273: * <p>
1274: * Example of specifying that the specific tabbed pane will be vertically
1275: * oriented:
1276: * </p>
1277: * <code>
1278: * JTabbedPane jtpMain = new JTabbedPane();<br>
1279: * jtpMain.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION, <br>
1280: * Boolean.TRUE);
1281: * </code>
1282: *
1283: * @since version 2.2
1284: * @see #TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS
1285: */
1286: public final static String TABBED_PANE_VERTICAL_ORIENTATION = "substancelaf.tabbedpaneverticalOrientation";
1287:
1288: /**
1289: * Client property name for specifying that when a single tabbed pane / all
1290: * tabbed panes is layed-out vertically, the tab icons remain unrotated.This
1291: * property can be specified on a single tab component, on a
1292: * {@link JTabbedPane} itself (will hold for all tab components that don't
1293: * define this property) or on {@link UIManager}. The value should be
1294: * either {@link Boolean#TRUE} or {@link Boolean#FALSE}. By default, the
1295: * vertically oriented tabs will have the rotated icons. In case the icon
1296: * internal layout has horizontal / vertical meaning, using this property
1297: * with value {@link Boolean#TRUE} will preserve the icon orientation. Note
1298: * that this setting is only relevant for tabs marked with
1299: * {@link #TABBED_PANE_VERTICAL_ORIENTATION} property.
1300: *
1301: * <p>
1302: * Example of setting that all vertically-oriented tabs in the application
1303: * will have unrotated icons:
1304: * </p>
1305: * <code>
1306: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS, <br>
1307: * Boolean.TRUE);
1308: * </code>
1309: *
1310: * <p>
1311: * An example of tabbed pane with two different kinds of icon orientation:
1312: * </p>
1313: * <code>
1314: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS, <br>
1315: * Boolean.TRUE);<br>
1316: * JTabbedPane jtp = new JTabbedPane();<br>
1317: * jtp.setTabPlacement(SwingConstants.LEFT);<br>
1318: * JPanel tab1 = new JPanel();<br>
1319: * JPanel tab2 = new JPanel();<br>
1320: * tab2.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS, <br>
1321: * Boolean.FALSE);<br>
1322: * jtp.addTab(tab1);<br>
1323: * jtp.addTab(tab2);
1324: * </code>
1325: *
1326: * <p>
1327: * In the example above, the first tab (<b>tab1</b>) has the
1328: * horizontally-oriented icon (the same as with {@link SwingConstants#TOP}
1329: * or {@link SwingConstants#BOTTOM}) , while the second tab (<b>tab2</b>)
1330: * has the rotated icon (oriented along the tab text).
1331: * </p>
1332: *
1333: * @since version 2.2
1334: * @see #TABBED_PANE_VERTICAL_ORIENTATION
1335: */
1336: public final static String TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS = "substancelaf.tabbedpaneverticalOrientationRotateIcons";
1337:
1338: /**
1339: * Client property name for specifying that only the close button of a
1340: * marked-as-modified tab component should pulsate. This property can be
1341: * specified on a single tab component, on a {@link JTabbedPane} itself
1342: * (will hold for all tab components that don't define this property) or on
1343: * {@link UIManager}. The value should be either {@link Boolean#TRUE} or
1344: * {@link Boolean#FALSE}. By default, the animation on modified tabs is on
1345: * the entire tab rectangle. Note that this setting is only relevant for
1346: * tabs marked with {@link #WINDOW_MODIFIED} property.
1347: *
1348: * <p>
1349: * Example of setting that all tabs in the application will have modified
1350: * animation on close button:
1351: * </p>
1352: * <code>
1353: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION, <br>
1354: * Boolean.TRUE);
1355: * </code>
1356: *
1357: * <p>
1358: * A more complex example:
1359: * </p>
1360: * <code>
1361: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION, <br>
1362: * Boolean.TRUE);<br>
1363: * JTabbedPane jtpMain = new JTabbedPane();<br>
1364: * JTabbedPane jtpSecondary = new JTabbedPane();<br>
1365: * jtpSecondary.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION, <br>
1366: * Boolean.FALSE);<br>
1367: * JPanel panelSecondary = new JPanel();<br>
1368: * jtpMain.addTab(jtpSecondary);<br>
1369: * jtpMain.addTab(panelSecondary);<br>
1370: * JPanel tab1 = new JPanel();<br>
1371: * JPanel tab2 = new JPanel();<br>
1372: * tab2.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION, <br>
1373: * Boolean.TRUE);<br>
1374: * jtpSecondary.addTab(tab1);<br>
1375: * jtpSecondary.addTab(tab2);
1376: * </code>
1377: *
1378: * <p>
1379: * In the example above, the first first-level child (<b>jtpSecondary</b>)
1380: * has the animation on the entire tab (since it overrides the global
1381: * setting). The second first-level child tab (<b>panelSecondary</b>) has
1382: * animation on the close button (from the global <b>UIManager</b>
1383: * setting). The first second-level tab has the animation on the entire tab
1384: * (setting inherited from the parent <b>jtpSecondary</b> tab that
1385: * overrides the global setting). The second second-level tab has animation
1386: * on the close button (since its setting overrides the parent setting).
1387: * </p>
1388: *
1389: * @since version 2.2
1390: * @see #TABBED_PANE_CLOSE_BUTTONS_PROPERTY
1391: * @see #TABBED_PANE_CLOSE_CALLBACK
1392: */
1393: public final static String TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION = "substancelaf.tabbedpaneclosebuttonsmodifiedanimation";
1394:
1395: /**
1396: * Client property name for specifying the callback for deciding on the tab
1397: * close type. This property can be specified on a single tab component, on
1398: * a {@link JTabbedPane} itself (will hold for all tab components that don't
1399: * define this property) or on {@link UIManager}. The value should be an
1400: * instance of {@link TabCloseCallback}. Note that this setting is only
1401: * relevant for tabs marked with {@link #TABBED_PANE_CLOSE_BUTTONS_PROPERTY}
1402: * property.
1403: *
1404: * <p>
1405: * Example of custom tab close callback set on a tabbed pane:
1406: * </p>
1407: * <code>
1408: * TabCloseCallback closeCallback = new TabCloseCallback() {<br>
1409: * public TabCloseKind onAreaClick(JTabbedPane tabbedPane,<br>
1410: * int tabIndex, MouseEvent mouseEvent) {<br>
1411: * if (mouseEvent.getButton() != MouseEvent.BUTTON3)<br>
1412: * return TabCloseKind.NONE;<br>
1413: * if (mouseEvent.isShiftDown()) {<br>
1414: * return TabCloseKind.ALL;<br>
1415: * }<br>
1416: * return TabCloseKind.THIS;<br>
1417: * }<br>
1418: * <br>
1419: * public TabCloseKind onCloseButtonClick(JTabbedPane tabbedPane,<br>
1420: * int tabIndex, MouseEvent mouseEvent) {<br>
1421: * if (mouseEvent.isAltDown()) {<br>
1422: * return TabCloseKind.ALL_BUT_THIS;<br>
1423: * }<br>
1424: * if (mouseEvent.isShiftDown()) {<br>
1425: * return TabCloseKind.ALL;<br>
1426: * }<br>
1427: * return TabCloseKind.THIS;<br>
1428: * }<br>
1429: * <br>
1430: * public String getAreaTooltip(JTabbedPane tabbedPane, int tabIndex) {<br>
1431: * return null;<br>
1432: * }<br>
1433: * <br>
1434: * public String getCloseButtonTooltip(JTabbedPane tabbedPane,<br>
1435: * int tabIndex) {<br>
1436: * StringBuffer result = new StringBuffer();<br>
1437: * result.append("<html><body>");<br>
1438: * result.append("Mouse click closes <b>"<br>
1439: * + tabbedPane.getTitleAt(tabIndex) + "</b> tab");<br>
1440: * result.append("<br><b>Alt</b>-Mouse click closes all tabs but <b>"<br>
1441: * + tabbedPane.getTitleAt(tabIndex) + "</b> tab");<br>
1442: * result.append("<br><b>Shift</b>-Mouse click closes all tabs");<br>
1443: * result.append("</body></html>");<br>
1444: * return result.toString();<br>
1445: * }<br>
1446: * };<br>
1447: *
1448: * JTabbedPane jtp = new JTabbedPane();<br>
1449: * jtp.putClientProperty(<br>
1450: * SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK, <br>
1451: * closeCallback);
1452: * </code>
1453: *
1454: * @since version 2.3
1455: */
1456: public final static String TABBED_PANE_CLOSE_CALLBACK = "substancelaf.tabbedpanecloseCallback";
1457:
1458: /**
1459: * Client property name for specifying the text alignment kind for on
1460: * {@link SwingConstants#LEFT} and {@link SwingConstants#RIGHT} tab
1461: * placements. This property can be specified either on a single
1462: * {@link JTabbedPane} or on {@link UIManager}. The value should be one of
1463: * {@link SubstanceConstants.TabTextAlignmentKind} enum. By default, the
1464: * text alignment is {@link SubstanceConstants.TabTextAlignmentKind#DEFAULT}
1465: * (centered).
1466: *
1467: * <p>
1468: * Example of setting that all tabbed panes in the application will follow
1469: * placement for the text alignment:
1470: * </p>
1471: * <code>
1472: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_TEXT_ALIGNMENT_KIND, <br>
1473: * TabTextAlignmentKind.FOLLOW_PLACEMENT);
1474: * </code>
1475: *
1476: * <p>
1477: * Example of specifying that the specific tabbed pane will follow placement
1478: * for the text alignment:
1479: * </p>
1480: * <code>
1481: * JTabbedPane jtpMain = new JTabbedPane();<br>
1482: * jtpMain.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_TEXT_ALIGNMENT_KIND, <br>
1483: * TabTextAlignmentKind.FOLLOW_PLACEMENT);
1484: * </code>
1485: *
1486: * @since version 2.3
1487: */
1488: public final static String TABBED_PANE_TEXT_ALIGNMENT_KIND = "substancelaf.tabbedpanetextAlignmentKind";
1489:
1490: /**
1491: * Client property name for specifying the content pane border kind. This
1492: * property can be specified either on a single {@link JTabbedPane} or on
1493: * {@link UIManager}. The value should be one of
1494: * {@link SubstanceConstants.TabContentPaneBorderKind} enum. By default, the
1495: * border kind is
1496: * {@link SubstanceConstants.TabContentPaneBorderKind#DOUBLE_FULL}.
1497: *
1498: * <p>
1499: * Example of setting that all tabbed panes in the application have single
1500: * full border (default setting prior to version 4.1):
1501: * </p>
1502: * <code>
1503: * UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, <br>
1504: * TabContentPaneBorderKind.SINGLE_FULL);
1505: * </code>
1506: *
1507: * <p>
1508: * Example of specifying that the specific tabbed pane has single full
1509: * border (default setting prior to version 4.1):
1510: * </p>
1511: * <code>
1512: * JTabbedPane jtpMain = new JTabbedPane();<br>
1513: * jtpMain.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, <br>
1514: * TabContentPaneBorderKind.SINGLE_FULL);
1515: * </code>
1516: *
1517: * @since version 4.1
1518: */
1519: public final static String TABBED_PANE_CONTENT_BORDER_KIND = "substancelaf.tabbedPaneContentBorderKind";
1520:
1521: /**
1522: * Client property name for specifying combo popup flyout orientation. This
1523: * property can be set on either a specific {@link JComboBox} or globally on
1524: * {@link UIManager}. The value should be one of the {@link Integer}s
1525: * below:
1526: *
1527: * <p>
1528: * <ul>
1529: * <li>The default {@link SwingConstants#SOUTH} - the popup is displayed
1530: * directly below the combo aligned to the left.
1531: * <li>{@link SwingConstants#NORTH} - the popup is displayed directly above
1532: * the combo aligned to the left.
1533: * <li>{@link SwingConstants#EAST} - the popup is displayed to the left of
1534: * the combo aligned to the top.
1535: * <li>{@link SwingConstants#WEST} - the popup is displayed to the right of
1536: * the combo aligned to the top.
1537: * <li>{@link SwingConstants#CENTER} - the popup is displayed centered
1538: * vertically over the combo aligned to the left.
1539: * </ul>
1540: * </p>
1541: *
1542: * <p>
1543: * Note that the combo arrow changes in accordance with the combo popup
1544: * flyout orientation. Example of setting a combobox with a custom flyout
1545: * orientation:
1546: * </p>
1547: * <code>
1548: * JComboBox cb = new JComboBox(<br>
1549: * new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });<br>
1550: * cb.putClientProperty(SubstanceLookAndFeel.COMBO_BOX_POPUP_FLYOUT_ORIENTATION, <br>
1551: * SwingConstants.CENTER);
1552: * </code>
1553: *
1554: * @since version 2.3
1555: * @see #COMBO_POPUP_PROTOTYPE
1556: */
1557: public final static String COMBO_BOX_POPUP_FLYOUT_ORIENTATION = "substancelaf.comboboxpopupFlyoutOrientation";
1558:
1559: /**
1560: * Client property name for specifying scroll pane button policy. This
1561: * property can be set on either a specific {@link JScrollPane} or globally
1562: * on {@link UIManager}. The value should be one of the
1563: * {@link SubstanceConstants.ScrollPaneButtonPolicyKind} enum. Example of
1564: * setting a scroll pane with a custom button policy:
1565: *
1566: * <p>
1567: * <code>
1568: * JScrollPane jsp = new JScrollPane(new JPanel());<br>
1569: * jsp.putClientProperty(SubstanceLookAndFeel.SCROLL_PANE_BUTTONS_POLICY,<br>
1570: * ScrollPaneButtonPolicyKind.MULTIPLE);
1571: * </code>
1572: *
1573: * @since version 3.1
1574: */
1575: public final static String SCROLL_PANE_BUTTONS_POLICY = "substancelaf.scrollPaneButtonsPolicy";
1576:
1577: /**
1578: * Property name for specifying that no extra UI elements (such as menu
1579: * items in system menu or menu search panel) should be shown. This property
1580: * can be set as either VM flag (no value needed) or as a global setting on
1581: * {@link UIManager}. In the latter case, the value should be either
1582: * {@link Boolean#TRUE} or {@link Boolean#FALSE}. Partial list of UI
1583: * elements that will not be present when this property is specified:
1584: *
1585: * <p>
1586: * <ul>
1587: * <li>System menu items
1588: * <li>Menu search panel
1589: * <li>Lock icon on non-editable text components
1590: * </ul>
1591: * </p>
1592: *
1593: * <p>
1594: * Example of setting this property via VM flag:
1595: * </p>
1596: * <code>
1597: * -Dsubstancelaf.noExtraElements
1598: * </code>
1599: *
1600: * <p>
1601: * Example of setting this property on {@link UIManager}:
1602: * </p>
1603: * <code>
1604: * UIManager.put(SubstanceLookAndFeel.NO_EXTRA_ELEMENTS, Boolean.TRUE);
1605: * SwingUtilities.updateComponentTree(myFrame);
1606: * </code>
1607: *
1608: * @see #toShowExtraElements
1609: * @since version 2.1
1610: */
1611: public final static String NO_EXTRA_ELEMENTS = "substancelaf.noExtraElements";
1612:
1613: /**
1614: * Property name for specifying menu gutter fill kind. Menu gutter is the
1615: * part of the menu where checkmarks and icons are painted. The value should
1616: * be one of {@link MenuGutterFillKind} enum. This property can be set
1617: * globally on the {@link UIManager}. The default value is
1618: * {@link MenuGutterFillKind#HARD}.
1619: *
1620: * <p>
1621: * Example of setting soft fill kind:
1622: * </p>
1623: * <code>
1624: * UIManager.put(SubstanceLookAndFeel.MENU_GUTTER_FILL_KIND, MenuGutterFillKind.SOFT);
1625: * </code>
1626: *
1627: * @since version 3.2
1628: */
1629: public final static String MENU_GUTTER_FILL_KIND = "substancelaf.menuGutterFillKind";
1630:
1631: /**
1632: * Client property name for specifying the kind of focus indication on
1633: * buttons, check boxes and radio buttons. The value should be one of
1634: * {@link SubstanceConstants.FocusKind} enum. This property can be set
1635: * either as client property on some component or as global property on
1636: * {@link UIManager}.
1637: *
1638: * <p>
1639: * In order to compute the kind of focus indication for some component, the
1640: * component's hierarchy is traversed bottom up. The first component that
1641: * has this property set, defines the focus indication kind. Finally, if
1642: * neither component not its ancestors define this property, the global
1643: * setting on {@link UIManager} is checked. If there is no global setting,
1644: * the default {@link SubstanceConstants.FocusKind#ALL_INNER} is used. Here
1645: * is an example to illustrate the above:
1646: * </p>
1647: *
1648: * <code>
1649: * JPanel topPanel = new JPanel();<br>
1650: * topPanel.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.UNDERLINE);<br>
1651: * JPanel panel1 = new JPanel();<br>
1652: * JButton b1 = new JButton("button1");<br>
1653: * b1.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.TEXT);<br>
1654: * JButton b2 = new JButton("button2");<br>
1655: * JButton b3 = new JButton("button3");<br>
1656: * b3.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.ALL_INNER);<br>
1657: * panel1.add(b1);<br>
1658: * panel1.add(b2);<br>
1659: * topPanel.add(panel1);<br>
1660: * topPanel.add(b3);<br>
1661: * </code>
1662: *
1663: * <p>
1664: * In the code above:
1665: * </p>
1666: * <ul>
1667: * <li>Button <b>b1</b> will have
1668: * {@link SubstanceConstants.FocusKind#NONE} focus kind which is set
1669: * directly on the button.
1670: * <li>Button <b>b2</b> will have
1671: * {@link SubstanceConstants.FocusKind#UNDERLINE} focus kind which is
1672: * inherited from its <b>topPanel</b> parent.
1673: * <li>Button <b>b3</b> will have
1674: * {@link SubstanceConstants.FocusKind#ALL_INNER} focus kind which is set
1675: * directly on the button.
1676: * </ul>
1677: *
1678: * @since 2.2
1679: * @see SubstanceConstants.FocusKind
1680: */
1681: public final static String FOCUS_KIND = "substancelaf.focusKind";
1682:
1683: /**
1684: * Property name for specifying the combobox popup prototype display value
1685: * which is used to compute the width of the popup at runtime. The property
1686: * value should be one of:
1687: *
1688: * <p>
1689: * <ul>
1690: * <li>{@link ComboPopupPrototypeCallback} - will provide
1691: * application-specific logic at runtime.
1692: * <li>{@link Object} - will point to the prototype entry itself.
1693: * </ul>
1694: * </p>
1695: *
1696: * <p>
1697: * This property can be set either on a specific {@link JComboBox} or
1698: * globally on {@link UIManager}.
1699: * </p>
1700: *
1701: * <p>
1702: * Here is an example of combo popup prototype set to a model element:
1703: * </p>
1704: * <code>
1705: * JComboBox comboProto1 = new JComboBox(new Object[] { "aa", "aaaaa",<br>
1706: * "aaaaaaaaaa", "this one is the one", "aaaaaaaaaaaaaaaaaaaaa" });<br>
1707: * comboProto1.setPrototypeDisplayValue("aaaaa");<br>
1708: * comboProto1.putClientProperty(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE,<br>
1709: * "this one is the one");
1710: * </code>
1711: *
1712: * <p>
1713: * Here is an example of combo popup prototype set to a dynamic callback.
1714: * This callback always returns the last model element:
1715: * </p>
1716: * <code>
1717: * JComboBox comboProto3 = new JComboBox(new Object[] { "aa", "aaaaa",<br>
1718: * "this is not", "this one is not it",<br>
1719: * "this one is it that is for the popup" });<br>
1720: * comboProto3.setPrototypeDisplayValue("aaaaa");<br>
1721: * comboProto3.putClientProperty(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE,<br>
1722: * new ComboPopupPrototypeCallback() {<br>
1723: * public Object getPopupPrototypeDisplayValue(JComboBox jc) {<br>
1724: * return jc.getModel().getElementAt(<br>
1725: * jc.getModel().getSize() - 1);<br>
1726: * }<br>
1727: * });
1728: * </code>
1729: *
1730: * @since version 3.0
1731: * @see #COMBO_BOX_POPUP_FLYOUT_ORIENTATION
1732: */
1733: public final static String COMBO_POPUP_PROTOTYPE = "substancelaf.comboPopupPrototype";
1734:
1735: /**
1736: * VM property name for specifying the trace file. The trace file will
1737: * contain output of the memory analyser which can be used to pinpoint the
1738: * memory leaks. The property value is used as a filename for tracing the
1739: * memory allocations. Example for specifying the trace file name:
1740: *
1741: * <p>
1742: * <code>
1743: * -Dsubstancelaf.traceFile=C:/temp/myApp.substance.log
1744: * </code>
1745: * </p>
1746: *
1747: * @see MemoryAnalyzer
1748: * @since version 2.0
1749: */
1750: public final static String TRACE_FILE = "substancelaf.traceFile";
1751:
1752: /**
1753: * VM property name for the configuration file. If this property is
1754: * specified in the VM flags, all other global VM Substance-specific
1755: * settings are ignored and are read instead from the (local) configuration
1756: * file. The property value should point to a file in the regular
1757: * {@link Properties} format. Example of specifying configuration file:
1758: *
1759: * <p>
1760: * <code>
1761: * -Dsubstancelaf.configFile=C:/myConfigSubstance.properties
1762: * </code>
1763: * </p>
1764: *
1765: * @since version 2.2
1766: */
1767: public final static String CONFIG_FILE = "substancelaf.configFile";
1768:
1769: /**
1770: * Property name for enabling inverted themes. This property can be set as
1771: * either VM flag (no value needed) or as a global setting on
1772: * {@link UIManager}. In the latter case, the value should be either
1773: * {@link Boolean#TRUE} or {@link Boolean#FALSE}. When this property is
1774: * set, the {@link #getAllThemes()} method will return entries for all
1775: * {@link SubstanceTheme.ThemeKind#BRIGHT} and
1776: * {@link SubstanceTheme.ThemeKind#COLD} themes. All these entries will be
1777: * marked with {@link SubstanceTheme.ThemeKind#INVERTED} kind.
1778: *
1779: * <p>
1780: * Example of setting this property via VM flag:
1781: * </p>
1782: * <code>
1783: * -Dsubstancelaf.enableInvertedThemes
1784: * </code>
1785: *
1786: * <p>
1787: * Example of setting this property on {@link UIManager}:
1788: * </p>
1789: * <code>
1790: * UIManager.put(SubstanceLookAndFeel.ENABLE_INVERTED_THEMES, <br>
1791: * Boolean.TRUE);
1792: * </code>
1793: *
1794: * @since version 2.3
1795: * @see #ENABLE_NEGATED_THEMES
1796: */
1797: public final static String ENABLE_INVERTED_THEMES = "substancelaf.enableInvertedThemes";
1798:
1799: /**
1800: * Property name for enabling negated themes. This property can be set as
1801: * either VM flag (no value needed) or as a global setting on
1802: * {@link UIManager}. In the latter case, the value should be either
1803: * {@link Boolean#TRUE} or {@link Boolean#FALSE}. When this property is
1804: * set, the {@link #getAllThemes()} method will return entries for all
1805: * {@link SubstanceTheme.ThemeKind#BRIGHT} and
1806: * {@link SubstanceTheme.ThemeKind#COLD} themes. All these entries will be
1807: * marked with {@link SubstanceTheme.ThemeKind#NEGATED} kind.
1808: *
1809: * <p>
1810: * Example of setting this property via VM flag:
1811: * </p>
1812: * <code>
1813: * -Dsubstancelaf.enableNegatedThemes
1814: * </code>
1815: *
1816: * <p>
1817: * Example of setting this property on {@link UIManager}:
1818: * </p>
1819: * <code>
1820: * UIManager.put(SubstanceLookAndFeel.ENABLE_NEGATED_THEMES, <br>
1821: * Boolean.TRUE);
1822: * </code>
1823: *
1824: * @since version 3.1
1825: * @see #ENABLE_INVERTED_THEMES
1826: */
1827: public final static String ENABLE_NEGATED_THEMES = "substancelaf.enableNegatedThemes";
1828:
1829: /**
1830: * Client property name for specifying the number of echo characters for
1831: * each password character. The value should be an instance of
1832: * {@link Integer}, otherwise will be ignored. This property can be set
1833: * either on a specific {@link JPasswordField} or globally on
1834: * {@link UIManager}.
1835: *
1836: * <p>
1837: * Example of having all password fields echo 3 characters per each typed
1838: * user character:
1839: * </p>
1840: * <code>
1841: * UIManager.put(SubstanceLookAndFeel.PASSWORD_ECHO_PER_CHAR, <br>
1842: * new Integer(3));
1843: * </code>
1844: *
1845: * <p>
1846: * Example of having a specific password field echo 2 characters per each
1847: * typed user character:
1848: * </p>
1849: * <code>
1850: * JPasswordField jpf = new JPasswordField();<br>
1851: * jpf.putClientProperty(SubstanceLookAndFeel.PASSWORD_ECHO_PER_CHAR, <br>
1852: * new Integer(2));
1853: * </code>
1854: *
1855: * @since version 2.2
1856: */
1857: public final static String PASSWORD_ECHO_PER_CHAR = "substancelaf.passwordEchoPerChar";
1858:
1859: // /**
1860: // * Client property name for specifying that the toolbar buttons should be
1861: // * flat (no background when non-selected and non-rollover). The value
1862: // should
1863: // * be an instance of {@link Boolean}. The default value is
1864: // * <code>true</code>. This property can be specified on a single button,
1865: // * on a single {@link JToolBar} or globally on {@link UIManager}.
1866: // *
1867: // * <p>
1868: // * Example of specifying that a specific toolbar button should not appear
1869: // * flat:
1870: // * </p>
1871: // * <code>
1872: // * JToolBar tb = new JToolBar("Toolbar");<br>
1873: // * JButton b = new JButton("Button");<br>
1874: // * b.putClientProperty(SubstanceLookAndFeel.TOOLBAR_BUTTON_FLAT, <br>
1875: // * Boolean.FALSE);<br>
1876: // * tb.add(b);
1877: // * </code>
1878: // *
1879: // * <p>
1880: // * Example of specifying that all toolbar buttons of the specific toolbar
1881: // * (except those that specify their own property) should not appear flat:
1882: // * </p>
1883: // * <code>
1884: // * JToolBar tb = new JToolBar("Toolbar");<br>
1885: // * tb.putClientProperty(SubstanceLookAndFeel.TOOLBAR_BUTTON_FLAT, <br>
1886: // * Boolean.FALSE);<br>
1887: // * </code>
1888: // *
1889: // * @since version 2.3
1890: // * @see #BUTTON_PAINT_NEVER_PROPERTY
1891: // * @see #FLAT_PROPERTY
1892: // */
1893: // public final static String TOOLBAR_BUTTON_FLAT =
1894: // "substancelaf.toolbarButtonFlat";
1895:
1896: /**
1897: * <p>
1898: * Client property name for specifying that icons on buttons and toggle
1899: * buttons should match the color of the current theme when they are in
1900: * default state. The button is in default state when it's not pressed, not
1901: * selected, not armed and not rolled over. The value should be an instance
1902: * of {@link Boolean}. By default, all buttons show regular (full-color
1903: * original) icons. The value can be set on the specific button or globally
1904: * on {@link UIManager}.
1905: * </p>
1906: *
1907: * <p>
1908: * Example of marking a button to have theme-matching icon in default state:
1909: * </p>
1910: * <code>
1911: * JButton jb = new JButton("sample", myIcon);<br>
1912: * jb.putClientProperty(SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS, <br>
1913: * Boolean.TRUE);
1914: * </code>
1915: *
1916: * @since version 3.3
1917: */
1918: public final static String USE_THEMED_DEFAULT_ICONS = "substancelaf.useThemedDefaultIcons";
1919:
1920: /**
1921: * <p>
1922: * Client property name for specifying that the colorization amount applied
1923: * to the background and foreground of the current theme and the specific
1924: * control. By default, when the application does not use any custom colors,
1925: * all the controls are painted with the colors of the current theme / skin.
1926: * The colors coming from the look-and-feel implement the marker
1927: * {@link UIResource} interface which allows the UI delegates to
1928: * differentiate between application-specific colors which are not changed,
1929: * and the LAF-provide colors that are changed on LAF switch.
1930: * </p>
1931: *
1932: * <p>
1933: * Up until version 4.2, the support for custom background and foreground
1934: * colors in Substance was not very consistent. On some controls, such as
1935: * buttons, the background color was ignored completely (in favour of the
1936: * current theme), while on others it was used to color the entire bounds of
1937: * the control (such as check box). This new client property installs the
1938: * "smart colorization" mode which uses the colors of the current theme
1939: * <b>and</b> the custom background and foreground colors (where installed
1940: * by application) to colorize the relevant portions of the control. For
1941: * example, on checkbox the custom background color will be used to colorize
1942: * the check box itself, while the custom foreground color will be applied
1943: * to the check box text and the check mark.
1944: * </p>
1945: *
1946: * <p>
1947: * The value of this property specifies the actual colorization amount.
1948: * Value of 0.0 results in no colorization at all. Values closer to 1.0
1949: * result in controls being colorized in almost full amount of the custom
1950: * colors. Note that in order to maintain the gradients (fill, border, etc),
1951: * even value of 1.0 does not result in full custom color being applied to
1952: * the relevant visuals of the control.
1953: * </p>
1954: *
1955: * <p>
1956: * This property can be specified globally on {@link UIManager}, applying
1957: * on all controls, or on the specific component / container. In the later
1958: * case, the value will be applied to the component / container itself and
1959: * all its children that do not specify a custom value for this property.
1960: * </p>
1961: *
1962: * <p>
1963: * The value should be an instance of {@link Double} in 0.0-1.0 range.
1964: * </p>
1965: *
1966: * <p>
1967: * Example of marking a button to have custom background color and
1968: * colorizing it with 50%:
1969: * </p>
1970: * <code>
1971: * JButton jb = new JButton("sample", myIcon);<br>
1972: * jb.setBackground(Color.red);<br>
1973: * jb.putClientProperty(SubstanceLookAndFeel.COLORIZATION_FACTOR, <br>
1974: * new Double(0.5));
1975: * </code>
1976: *
1977: * @since version 4.2
1978: * @see Component#setBackground(Color)
1979: * @see Component#setForeground(Color)
1980: */
1981: public final static String COLORIZATION_FACTOR = "substancelaf.colorizationFactor";
1982:
1983: /**
1984: * Internal client property name for storing application-specific font
1985: * policy.
1986: *
1987: * @since version 3.3
1988: * @see #setFontPolicy(FontPolicy)
1989: * @see #getFontPolicy()
1990: */
1991: protected final static String SUBSTANCE_FONT_POLICY_KEY = "substancelaf.fontPolicyKey";
1992:
1993: /**
1994: * The parameter reader.
1995: */
1996: protected static ParamReader paramReader;
1997:
1998: /**
1999: * Resource bundle for <b>Substance</b> labels.
2000: */
2001: private static ResourceBundle LABEL_BUNDLE = null;
2002:
2003: /**
2004: * Class loader for {@link #LABEL_BUNDLE}.
2005: */
2006: private static ClassLoader labelBundleClassLoader;
2007:
2008: /**
2009: * Retrieves the current label bundle.
2010: *
2011: * @return The current label bundle.
2012: * @see #resetLabelBundle()
2013: */
2014: public static synchronized ResourceBundle getLabelBundle() {
2015: if (SubstanceLookAndFeel.LABEL_BUNDLE == null) {
2016: // fix for RFE 157 (allowing custom class loader for
2017: // resource bundles which can remove server calls
2018: // in applets)
2019: if (SubstanceLookAndFeel.labelBundleClassLoader == null) {
2020: SubstanceLookAndFeel.LABEL_BUNDLE = ResourceBundle
2021: .getBundle(
2022: "org.jvnet.substance.resources.Labels",
2023: Locale.getDefault());
2024: } else {
2025: SubstanceLookAndFeel.LABEL_BUNDLE = ResourceBundle
2026: .getBundle(
2027: "org.jvnet.substance.resources.Labels",
2028: Locale.getDefault(),
2029: SubstanceLookAndFeel.labelBundleClassLoader);
2030: }
2031: for (LocaleChangeListener lcl : SubstanceLookAndFeel.localeChangeListeners)
2032: lcl.localeChanged();
2033: }
2034: return SubstanceLookAndFeel.LABEL_BUNDLE;
2035: }
2036:
2037: /**
2038: * Retrieves the label bundle for the specified locale.
2039: *
2040: * @param locale
2041: * Locale.
2042: * @return The label bundle for the specified locale.
2043: */
2044: public static synchronized ResourceBundle getLabelBundle(
2045: Locale locale) {
2046: // fix for RFE 157 (allowing custom class loader for
2047: // resource bundles which can remove server calls
2048: // in applets)
2049: if (SubstanceLookAndFeel.labelBundleClassLoader == null) {
2050: return ResourceBundle.getBundle(
2051: "org.jvnet.substance.resources.Labels", locale);
2052: } else {
2053: return ResourceBundle.getBundle(
2054: "org.jvnet.substance.resources.Labels", locale,
2055: SubstanceLookAndFeel.labelBundleClassLoader);
2056: }
2057: }
2058:
2059: /**
2060: * Resets the current label bundle. Useful when the application changes
2061: * Locale at runtime.
2062: *
2063: * @see #getLabelBundle()
2064: */
2065: public static synchronized void resetLabelBundle() {
2066: SubstanceLookAndFeel.LABEL_BUNDLE = null;
2067: LafWidgetRepository.resetLabelBundle();
2068: }
2069:
2070: /**
2071: * Creates new instance of <b>Substance</b> look and feel.
2072: */
2073: public SubstanceLookAndFeel() {
2074: SubstanceLookAndFeel.componentPlugins = new ComponentPluginManager(
2075: SubstanceLookAndFeel.PLUGIN_XML);
2076:
2077: SubstanceLookAndFeel.themePlugins = new PluginManager(
2078: SubstanceLookAndFeel.PLUGIN_XML, LafPlugin.TAG_MAIN,
2079: SubstanceThemePlugin.TAG_THEME_PLUGIN_CLASS);
2080:
2081: SubstanceLookAndFeel.skinPlugins = new PluginManager(
2082: SubstanceLookAndFeel.PLUGIN_XML, LafPlugin.TAG_MAIN,
2083: SubstanceSkinPlugin.TAG_SKIN_PLUGIN_CLASS);
2084:
2085: SubstanceLookAndFeel.watermarkPlugins = new PluginManager(
2086: SubstanceLookAndFeel.PLUGIN_XML, LafPlugin.TAG_MAIN,
2087: SubstanceWatermarkPlugin.TAG_WATERMARK_PLUGIN_CLASS);
2088:
2089: SubstanceLookAndFeel.shaperPlugins = new PluginManager(
2090: SubstanceLookAndFeel.PLUGIN_XML,
2091: LafPlugin.TAG_MAIN,
2092: SubstanceButtonShaperPlugin.TAG_BUTTON_SHAPER_PLUGIN_CLASS);
2093:
2094: SubstanceLookAndFeel.painterPlugins = new PluginManager(
2095: SubstanceLookAndFeel.PLUGIN_XML,
2096: LafPlugin.TAG_MAIN,
2097: SubstanceGradientPainterPlugin.TAG_GRADIENT_PAINTER_PLUGIN_CLASS);
2098:
2099: SubstanceLookAndFeel.borderPainterPlugins = new PluginManager(
2100: SubstanceLookAndFeel.PLUGIN_XML,
2101: LafPlugin.TAG_MAIN,
2102: SubstanceBorderPainterPlugin.TAG_BORDER_PAINTER_PLUGIN_CLASS);
2103:
2104: // Bootstrap reader - for reading (possible) configuration file location
2105: JvmFlagsParamReader bootstrapReader = new JvmFlagsParamReader();
2106:
2107: String configFileName = bootstrapReader.getConfigFileName();
2108:
2109: // Choose actual reader (continue working with bootstrap VM reader
2110: // or switch to file-based reader)
2111: SubstanceLookAndFeel.paramReader = bootstrapReader;
2112: if (configFileName != null)
2113: SubstanceLookAndFeel.paramReader = new PropertiesFileParamReader(
2114: configFileName);
2115: }
2116:
2117: /**
2118: * The current theme.
2119: */
2120: private static SubstanceTheme currentTheme = null;
2121:
2122: /**
2123: * Returns the current theme.
2124: *
2125: * @return The current theme.
2126: * @see #getCurrentThemeName()
2127: * @see #setCurrentTheme(String)
2128: * @see #setCurrentTheme(SubstanceTheme)
2129: * @see #setCurrentTheme(ThemeInfo)
2130: * @see #registerThemeChangeListener(ThemeChangeListener)
2131: * @see #unregisterThemeChangeListener(ThemeChangeListener)
2132: * @see #THEME_PROPERTY
2133: */
2134: public static SubstanceTheme getTheme() {
2135: if (currentTheme == null) {
2136: return new SubstanceAquaTheme();
2137: }
2138: return currentTheme;
2139: }
2140:
2141: /**
2142: * Returns the current color scheme for components in active visual state.
2143: *
2144: * @return Current color scheme for components in active visual state.
2145: * @see #getDefaultColorScheme()
2146: * @see #getDisabledColorScheme()
2147: */
2148: public static ColorScheme getActiveColorScheme() {
2149: return SubstanceThemeUtilities.getTheme(null,
2150: ComponentState.ACTIVE).getColorScheme();
2151: }
2152:
2153: /**
2154: * Returns the current color scheme for components in default visual state.
2155: *
2156: * @return Current color scheme for components in default visual state.
2157: * @see #getActiveColorScheme()
2158: * @see #getDisabledColorScheme()
2159: */
2160: public static ColorScheme getDefaultColorScheme() {
2161: return SubstanceThemeUtilities.getTheme(null,
2162: ComponentState.DEFAULT).getColorScheme();
2163: }
2164:
2165: /**
2166: * Returns the current color scheme for components in disabled visual state.
2167: *
2168: * @return Current color scheme for components in disabled visual state.
2169: * @see #getActiveColorScheme()
2170: * @see #getDefaultColorScheme()
2171: */
2172: public static ColorScheme getDisabledColorScheme() {
2173: return SubstanceThemeUtilities.getTheme(null,
2174: ComponentState.DISABLED_UNSELECTED).getColorScheme();
2175: }
2176:
2177: /**
2178: * Sets new theme. In order for the theme to be correctly set, you need to
2179: * call {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)} on
2180: * all open frames (call {@link Frame#getFrames()} to get a list of all open
2181: * frames).
2182: *
2183: * @param themeClassName
2184: * Theme class name (full qualified).
2185: * @return The status of the theme change.
2186: * @see #getCurrentThemeName()
2187: * @see #getTheme()
2188: * @see #setCurrentTheme(SubstanceTheme)
2189: * @see #setCurrentTheme(ThemeInfo)
2190: * @see #registerThemeChangeListener(ThemeChangeListener)
2191: * @see #unregisterThemeChangeListener(ThemeChangeListener)
2192: * @see #THEME_PROPERTY
2193: */
2194: public static boolean setCurrentTheme(String themeClassName) {
2195: return setCurrentTheme(themeClassName, true);
2196: }
2197:
2198: /**
2199: * Sets new theme. In order for the theme to be correctly set, you need to
2200: * call {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)} on
2201: * all open frames (call {@link Frame#getFrames()} to get a list of all open
2202: * frames).
2203: *
2204: * @param themeClassName
2205: * Theme class name (full qualified).
2206: * @param toUpdateUiTable
2207: * Indicates whether the UI table needs to be updated.
2208: * @return The status of the theme change.
2209: */
2210: private static boolean setCurrentTheme(String themeClassName,
2211: boolean toUpdateUiTable) {
2212: try {
2213: Class<?> themeClass = Class.forName(themeClassName);
2214: if (themeClass == null) {
2215: return false;
2216: }
2217: Object obj = themeClass.newInstance();
2218: if (obj == null) {
2219: return false;
2220: }
2221: if (!(obj instanceof SubstanceTheme)) {
2222: return false;
2223: }
2224: return SubstanceLookAndFeel.setCurrentTheme(
2225: (SubstanceTheme) obj, toUpdateUiTable);
2226: } catch (Exception exc) {
2227: return false;
2228: }
2229: }
2230:
2231: /**
2232: * Sets new theme. In order for the theme to be correctly set, you need to
2233: * call {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)} on
2234: * all open frames (call {@link Frame#getFrames()} to get a list of all open
2235: * frames).
2236: *
2237: * @param themeInfo
2238: * Theme information.
2239: * @return The status of the theme change.
2240: * @see #getCurrentThemeName()
2241: * @see #getTheme()
2242: * @see #setCurrentTheme(String)
2243: * @see #setCurrentTheme(SubstanceTheme)
2244: * @see #registerThemeChangeListener(ThemeChangeListener)
2245: * @see #unregisterThemeChangeListener(ThemeChangeListener)
2246: * @see #THEME_PROPERTY
2247: */
2248: public static boolean setCurrentTheme(ThemeInfo themeInfo) {
2249: return setCurrentTheme(themeInfo, true);
2250: }
2251:
2252: /**
2253: * Sets new theme. In order for the theme to be correctly set, you need to
2254: * call {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)} on
2255: * all open frames (call {@link Frame#getFrames()} to get a list of all open
2256: * frames).
2257: *
2258: * @param themeInfo
2259: * Theme information.
2260: * @param toUpdateUiTable
2261: * Indicates whether the UI table needs to be updated.
2262: * @return The status of the theme change.
2263: */
2264: private static boolean setCurrentTheme(ThemeInfo themeInfo,
2265: boolean toUpdateUiTable) {
2266: try {
2267: SubstanceTheme theme = SubstanceTheme
2268: .createInstance(themeInfo);
2269: if (theme == null)
2270: return false;
2271: return SubstanceLookAndFeel.setCurrentTheme(theme,
2272: toUpdateUiTable);
2273: } catch (Exception exc) {
2274: return false;
2275: }
2276: }
2277:
2278: /**
2279: * Sets new theme. In order for the theme to be correctly set, you need to
2280: * call {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)} on
2281: * all open frames (call {@link Frame#getFrames()} to get a list of all open
2282: * frames).
2283: *
2284: * @param theme
2285: * Theme object.
2286: * @return The status of the theme change.
2287: * @see #getCurrentThemeName()
2288: * @see #getTheme()
2289: * @see #setCurrentTheme(String)
2290: * @see #setCurrentTheme(ThemeInfo)
2291: * @see #registerThemeChangeListener(ThemeChangeListener)
2292: * @see #unregisterThemeChangeListener(ThemeChangeListener)
2293: * @see #THEME_PROPERTY
2294: */
2295: public static boolean setCurrentTheme(SubstanceTheme theme) {
2296: return SubstanceLookAndFeel.setCurrentTheme(theme, true);
2297: }
2298:
2299: /**
2300: * Sets new theme.
2301: *
2302: * @param theme
2303: * Theme object.
2304: * @param toUpdateUiTable
2305: * Indicates whether the UI table needs to be updated.
2306: * @return The status of the theme change.
2307: */
2308: private static boolean setCurrentTheme(SubstanceTheme theme,
2309: boolean toUpdateUiTable) {
2310: SubstanceLookAndFeel.currentTheme = theme;
2311: if (toUpdateUiTable) {
2312: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
2313: // The table will be null when the skin is set using a custom
2314: // LAF
2315: if (defaults != null) {
2316: SubstanceLookAndFeel.currentTheme
2317: .addCustomEntriesToTable(UIManager
2318: .getLookAndFeelDefaults());
2319: SubstanceLookAndFeel.componentPlugins
2320: .processAllDefaultsEntries(UIManager
2321: .getLookAndFeelDefaults(),
2322: SubstanceLookAndFeel.currentTheme);
2323: }
2324: }
2325:
2326: SubstanceCoreUtilities.resetCaches();
2327:
2328: if (SubstanceLookAndFeel.currentWatermark != null) {
2329: if (SubstanceLookAndFeel.currentWatermark
2330: .isDependingOnTheme())
2331: SubstanceLookAndFeel.currentWatermark
2332: .updateWatermarkImage();
2333: }
2334:
2335: for (ThemeChangeListener themeChangeListener : SubstanceLookAndFeel.themeChangeListeners)
2336: themeChangeListener.themeChanged();
2337:
2338: return true;
2339: }
2340:
2341: /**
2342: * Returns the current color theme name.
2343: *
2344: * @return Current color theme name.
2345: * @see #getTheme()
2346: * @see #setCurrentTheme(String)
2347: * @see #setCurrentTheme(SubstanceTheme)
2348: * @see #setCurrentTheme(ThemeInfo)
2349: * @see #registerThemeChangeListener(ThemeChangeListener)
2350: * @see #unregisterThemeChangeListener(ThemeChangeListener)
2351: * @see #THEME_PROPERTY
2352: */
2353: public static String getCurrentThemeName() {
2354: if (SubstanceLookAndFeel.getTheme() == null)
2355: return null;
2356: return SubstanceLookAndFeel.getTheme().getDisplayName();
2357: }
2358:
2359: /**
2360: * Returns all available themes.
2361: *
2362: * @return All available color themes. Key - theme name, value - theme
2363: * information.
2364: */
2365: public static Map<String, ThemeInfo> getAllThemes() {
2366: Map<String, ThemeInfo> result = new TreeMap<String, ThemeInfo>();
2367: for (Object themePlugin : SubstanceLookAndFeel.themePlugins
2368: .getAvailablePlugins(true)) {
2369: for (ThemeInfo themeInfo : ((SubstanceThemePlugin) themePlugin)
2370: .getThemes()) {
2371: result.put(themeInfo.getDisplayName(), themeInfo);
2372: if (SubstanceLookAndFeel.toEnableInvertedThemes()) {
2373: if ((themeInfo.getThemeKind() == ThemeKind.BRIGHT)
2374: || (themeInfo.getThemeKind() == ThemeKind.COLD)) {
2375: ThemeInfo invertedInfo = new ThemeInfo(
2376: "Inverted "
2377: + themeInfo.getDisplayName(),
2378: themeInfo.getClassName(),
2379: ThemeKind.INVERTED);
2380: result.put(invertedInfo.getDisplayName(),
2381: invertedInfo);
2382: }
2383: }
2384: if (SubstanceLookAndFeel.toEnableNegatedThemes()) {
2385: if ((themeInfo.getThemeKind() == ThemeKind.BRIGHT)
2386: || (themeInfo.getThemeKind() == ThemeKind.COLD)) {
2387: ThemeInfo negatedInfo = new ThemeInfo(
2388: "Negated " + themeInfo.getDisplayName(),
2389: themeInfo.getClassName(),
2390: ThemeKind.NEGATED);
2391: result.put(negatedInfo.getDisplayName(),
2392: negatedInfo);
2393: }
2394: }
2395: }
2396: }
2397: for (SubstanceMixTheme mixedTheme : SubstanceLookAndFeel.mixedThemes
2398: .values()) {
2399: SubstanceTheme[] origThemes = (mixedTheme)
2400: .getOriginalThemes();
2401: String[] origThemeClassNames = new String[origThemes.length];
2402: for (int i = 0; i < origThemes.length; i++)
2403: origThemeClassNames[i] = origThemes[i].getClass()
2404: .getName();
2405:
2406: ThemeInfo mixedInfo = new MixedThemeInfo(mixedTheme
2407: .getDisplayName(), origThemeClassNames);
2408: result.put(mixedInfo.getDisplayName(), mixedInfo);
2409: }
2410:
2411: return result;
2412: }
2413:
2414: /**
2415: * The current watermark.
2416: */
2417: private static SubstanceWatermark currentWatermark = null;
2418:
2419: /**
2420: * Returns the current watermark name.
2421: *
2422: * @return Current watermark name.
2423: * @see #getCurrentWatermark()
2424: * @see #setCurrentWatermark(String)
2425: * @see #setCurrentWatermark(SubstanceWatermark)
2426: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
2427: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
2428: * @see #WATERMARK_PROPERTY
2429: */
2430: public static String getCurrentWatermarkName() {
2431: if (SubstanceLookAndFeel.currentWatermark == null)
2432: return null;
2433: return SubstanceLookAndFeel.currentWatermark.getDisplayName();
2434: }
2435:
2436: /**
2437: * Returns all available watermarks.
2438: *
2439: * @return All available watermarks. Key - watermark name, value - watermark
2440: * information.
2441: */
2442: public static Map<String, WatermarkInfo> getAllWatermarks() {
2443: Map<String, WatermarkInfo> result = new TreeMap<String, WatermarkInfo>();
2444: for (Object watermarkPlugin : SubstanceLookAndFeel.watermarkPlugins
2445: .getAvailablePlugins(true)) {
2446: for (WatermarkInfo watermarkInfo : ((SubstanceWatermarkPlugin) watermarkPlugin)
2447: .getWatermarks()) {
2448: result.put(watermarkInfo.getDisplayName(),
2449: watermarkInfo);
2450: }
2451: }
2452: return result;
2453: }
2454:
2455: /**
2456: * Returns the current watermark.
2457: *
2458: * @return The current watermark.
2459: * @see #getCurrentWatermarkName()
2460: * @see #setCurrentWatermark(String)
2461: * @see #setCurrentWatermark(SubstanceWatermark)
2462: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
2463: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
2464: * @see #WATERMARK_PROPERTY
2465: */
2466: public static SubstanceWatermark getCurrentWatermark() {
2467: return SubstanceLookAndFeel.currentWatermark;
2468: }
2469:
2470: /**
2471: * Sets new watermark.
2472: *
2473: * @param watermarkClassName
2474: * Watermark class name (full qualified).
2475: * @return The status of the watermark change.
2476: * @see #getCurrentWatermark()
2477: * @see #getCurrentWatermarkName()
2478: * @see #setCurrentWatermark(SubstanceWatermark)
2479: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
2480: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
2481: * @see #WATERMARK_PROPERTY
2482: */
2483: public static boolean setCurrentWatermark(String watermarkClassName) {
2484: try {
2485: Class<?> watermarkClass = Class.forName(watermarkClassName);
2486: if (watermarkClass == null) {
2487: return false;
2488: }
2489: Object obj = null;
2490: // see if has constructor that gets a ParamReader class
2491: Constructor<?> paramCtr = null;
2492:
2493: try {
2494: paramCtr = watermarkClass
2495: .getConstructor(new Class[] { ParamReader.class });
2496: } catch (NoSuchMethodException nsme) {
2497: // no biggie - doesn't exist
2498: paramCtr = null;
2499: }
2500: if (paramCtr != null) {
2501: obj = paramCtr.newInstance(new Object[] { null });
2502: } else {
2503: obj = watermarkClass.newInstance();
2504: }
2505: if (obj == null) {
2506: return false;
2507: }
2508: if (!(obj instanceof SubstanceWatermark)) {
2509: return false;
2510: }
2511: return SubstanceLookAndFeel
2512: .setCurrentWatermark((SubstanceWatermark) obj);
2513: } catch (Exception exc) {
2514: return false;
2515: }
2516: }
2517:
2518: /**
2519: * Sets new watermark.
2520: *
2521: * @param watermarkClassName
2522: * Watermark class name (full qualified).
2523: * @param paramReader
2524: * Parameter reader. Is here for the
2525: * {@link SubstanceImageWatermark}.
2526: * @return The status of the watermark change.
2527: */
2528: private static boolean setCurrentWatermark(
2529: String watermarkClassName, ParamReader paramReader) {
2530: try {
2531: Class<?> watermarkClass = Class.forName(watermarkClassName);
2532: if (watermarkClass == null) {
2533: return false;
2534: }
2535: Object obj = null;
2536: // see if has constructor that gets a ParamReader class
2537: Constructor<?> paramCtr = null;
2538: try {
2539: paramCtr = watermarkClass
2540: .getConstructor(new Class[] { ParamReader.class });
2541: } catch (NoSuchMethodException nsme) {
2542: paramCtr = null;
2543: }
2544: if (paramCtr != null) {
2545: obj = paramCtr
2546: .newInstance(new Object[] { paramReader });
2547: } else {
2548: obj = watermarkClass.newInstance();
2549: }
2550: if (obj == null) {
2551: return false;
2552: }
2553: if (!(obj instanceof SubstanceWatermark)) {
2554: return false;
2555: }
2556: return SubstanceLookAndFeel
2557: .setCurrentWatermark((SubstanceWatermark) obj);
2558: } catch (Exception exc) {
2559: return false;
2560: }
2561: }
2562:
2563: /**
2564: * Sets new watermark.
2565: *
2566: * @param currentWatermark
2567: * Watermark object.
2568: * @return The status of the watermark change.
2569: * @see #getCurrentWatermark()
2570: * @see #getCurrentWatermarkName()
2571: * @see #setCurrentWatermark(String)
2572: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
2573: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
2574: * @see #WATERMARK_PROPERTY
2575: */
2576: public static boolean setCurrentWatermark(
2577: SubstanceWatermark currentWatermark) {
2578: // fix for defect 109 - memory leak on watermark switch
2579: if (SubstanceLookAndFeel.currentWatermark != null)
2580: SubstanceLookAndFeel.currentWatermark.dispose();
2581: SubstanceLookAndFeel.currentWatermark = currentWatermark;
2582: boolean status = currentWatermark.updateWatermarkImage();
2583: if (status == true) {
2584: for (WatermarkChangeListener watermarkChangeListener : SubstanceLookAndFeel.watermarkChangeListeners)
2585: watermarkChangeListener.watermarkChanged();
2586: }
2587: return status;
2588: }
2589:
2590: /**
2591: * The current button shaper.
2592: */
2593: private static SubstanceButtonShaper currentButtonShaper = null;
2594:
2595: /**
2596: * Returns the current button shaper name.
2597: *
2598: * @return Current button shaper name.
2599: * @see #getCurrentButtonShaperName()
2600: * @see #setCurrentButtonShaper(String)
2601: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
2602: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
2603: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
2604: * @see #BUTTON_SHAPER_PROPERTY
2605: */
2606: public static String getCurrentButtonShaperName() {
2607: if (SubstanceLookAndFeel.currentButtonShaper == null)
2608: return null;
2609: return SubstanceLookAndFeel.currentButtonShaper
2610: .getDisplayName();
2611: }
2612:
2613: /**
2614: * Returns all available button shapers.
2615: *
2616: * @return All available button shapers. Key - button shaper name, value -
2617: * button shaper information.
2618: */
2619: public static Map<String, ButtonShaperInfo> getAllButtonShapers() {
2620: Map<String, ButtonShaperInfo> result = new TreeMap<String, ButtonShaperInfo>();
2621: for (Object buttonShaperPlugin : SubstanceLookAndFeel.shaperPlugins
2622: .getAvailablePlugins(true)) {
2623: for (ButtonShaperInfo buttonShaperInfo : ((SubstanceButtonShaperPlugin) buttonShaperPlugin)
2624: .getButtonShapers()) {
2625: result.put(buttonShaperInfo.getDisplayName(),
2626: buttonShaperInfo);
2627: }
2628: }
2629: return result;
2630: }
2631:
2632: /**
2633: * Returns the current button shaper.
2634: *
2635: * @return The current button shaper.
2636: * @see #getCurrentButtonShaperName()
2637: * @see #setCurrentButtonShaper(String)
2638: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
2639: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
2640: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
2641: * @see #BUTTON_SHAPER_PROPERTY
2642: */
2643: public static SubstanceButtonShaper getCurrentButtonShaper() {
2644: return SubstanceLookAndFeel.currentButtonShaper;
2645: }
2646:
2647: /**
2648: * Sets new button shaper.
2649: *
2650: * @param buttonShaperClassName
2651: * Button shaper class name (full qualified).
2652: * @return The status of the button shaper change.
2653: * @see #getCurrentButtonShaper()
2654: * @see #getCurrentButtonShaperName()
2655: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
2656: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
2657: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
2658: * @see #BUTTON_SHAPER_PROPERTY
2659: */
2660: public static boolean setCurrentButtonShaper(
2661: String buttonShaperClassName) {
2662: return SubstanceLookAndFeel.setCurrentButtonShaper(
2663: buttonShaperClassName, true);
2664: }
2665:
2666: /**
2667: * Sets new button shaper.
2668: *
2669: * @param buttonShaperClassName
2670: * Button shaper class name (full qualified).
2671: * @param toEnsureAccess
2672: * If <code>true</code>, an exception will be thrown when this
2673: * function is called and the current LAF (as returned by
2674: * {@link UIManager#getLookAndFeel()}) is not <b>Substance</b>.
2675: * @return The status of the button shaper change.
2676: */
2677: private static boolean setCurrentButtonShaper(
2678: String buttonShaperClassName, boolean toEnsureAccess) {
2679: try {
2680: Class<?> buttonShaperClass = Class
2681: .forName(buttonShaperClassName);
2682: if (buttonShaperClass == null) {
2683: return false;
2684: }
2685: Object obj = buttonShaperClass.newInstance();
2686: if (obj == null) {
2687: return false;
2688: }
2689: if (!(obj instanceof SubstanceButtonShaper)) {
2690: return false;
2691: }
2692: return SubstanceLookAndFeel
2693: .setCurrentButtonShaper((SubstanceButtonShaper) obj);
2694: } catch (Exception exc) {
2695: return false;
2696: }
2697: }
2698:
2699: /**
2700: * Sets new button shaper.
2701: *
2702: * @param currentButtonShaper
2703: * Button shaper object.
2704: * @return The status of the button shaper change.
2705: * @see #getCurrentButtonShaper()
2706: * @see #getCurrentButtonShaperName()
2707: * @see #setCurrentButtonShaper(String)
2708: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
2709: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
2710: * @see #BUTTON_SHAPER_PROPERTY
2711: */
2712: public static boolean setCurrentButtonShaper(
2713: SubstanceButtonShaper currentButtonShaper) {
2714: return SubstanceLookAndFeel.setCurrentButtonShaper(
2715: currentButtonShaper, true);
2716: }
2717:
2718: /**
2719: * Sets new button shaper.
2720: *
2721: * @param currentButtonShaper
2722: * Button shaper object.
2723: * @param toReset
2724: * If <code>true</code>, relevant caches will be reset.
2725: * @return The status of the button shaper change.
2726: */
2727: private static boolean setCurrentButtonShaper(
2728: SubstanceButtonShaper currentButtonShaper, boolean toReset) {
2729: SubstanceLookAndFeel.currentButtonShaper = currentButtonShaper;
2730: if (toReset) {
2731: SubstanceCoreUtilities.resetCaches();
2732: }
2733:
2734: for (ButtonShaperChangeListener buttonShaperChangeListener : SubstanceLookAndFeel.buttonShaperChangeListeners)
2735: buttonShaperChangeListener.buttonShaperChanged();
2736:
2737: return true;
2738: }
2739:
2740: /**
2741: * The current gradient painter.
2742: */
2743: private static SubstanceGradientPainter currentGradientPainter = null;
2744:
2745: /**
2746: * Returns the current gradient painter name.
2747: *
2748: * @return Current gradient painter name.
2749: * @see #getCurrentGradientPainter()
2750: * @see #setCurrentGradientPainter(String)
2751: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
2752: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
2753: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
2754: * @see #GRADIENT_PAINTER_PROPERTY
2755: */
2756: public static String getCurrentGradientPainterName() {
2757: if (SubstanceLookAndFeel.currentGradientPainter == null)
2758: return null;
2759: return SubstanceLookAndFeel.currentGradientPainter
2760: .getDisplayName();
2761: }
2762:
2763: /**
2764: * Returns all available gradient painters.
2765: *
2766: * @return All available gradient painters. Key - gradient painter name,
2767: * value - gradient painter information.
2768: */
2769: public static Map<String, GradientPainterInfo> getAllGradientPainters() {
2770: Map<String, GradientPainterInfo> result = new TreeMap<String, GradientPainterInfo>();
2771: for (Object gradientPainterPlugin : SubstanceLookAndFeel.painterPlugins
2772: .getAvailablePlugins(true)) {
2773: for (GradientPainterInfo gradientPainterInfo : ((SubstanceGradientPainterPlugin) gradientPainterPlugin)
2774: .getGradientPainters()) {
2775: result.put(gradientPainterInfo.getDisplayName(),
2776: gradientPainterInfo);
2777: }
2778: }
2779: return result;
2780: }
2781:
2782: /**
2783: * Returns the current gradient painter.
2784: *
2785: * @return The current gradient painter.
2786: * @see #getCurrentGradientPainterName()
2787: * @see #setCurrentGradientPainter(String)
2788: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
2789: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
2790: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
2791: * @see #GRADIENT_PAINTER_PROPERTY
2792: */
2793: public static SubstanceGradientPainter getCurrentGradientPainter() {
2794: return SubstanceLookAndFeel.currentGradientPainter;
2795: }
2796:
2797: /**
2798: * Sets new gradient painter.
2799: *
2800: * @param gradientPainterClassName
2801: * Gradient painter class name (full qualified).
2802: * @return The status of the gradient painter change.
2803: * @see #getCurrentGradientPainter()
2804: * @see #getCurrentGradientPainterName()
2805: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
2806: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
2807: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
2808: * @see #GRADIENT_PAINTER_PROPERTY
2809: */
2810: public static boolean setCurrentGradientPainter(
2811: String gradientPainterClassName) {
2812: try {
2813: Class<?> gradientPainterClass = Class
2814: .forName(gradientPainterClassName);
2815: if (gradientPainterClass == null) {
2816: return false;
2817: }
2818: Object obj = gradientPainterClass.newInstance();
2819: if (obj == null) {
2820: return false;
2821: }
2822: if (!(obj instanceof SubstanceGradientPainter)) {
2823: return false;
2824: }
2825: return SubstanceLookAndFeel.setCurrentGradientPainter(
2826: (SubstanceGradientPainter) obj, true);
2827: } catch (Exception exc) {
2828: return false;
2829: }
2830: }
2831:
2832: /**
2833: * Sets new gradient painter.
2834: *
2835: * @param currentGradientPainter
2836: * Gradient painter object.
2837: * @return The status of the gradient painter change.
2838: * @see #getCurrentGradientPainter()
2839: * @see #getCurrentGradientPainterName()
2840: * @see #setCurrentGradientPainter(String)
2841: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
2842: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
2843: * @see #GRADIENT_PAINTER_PROPERTY
2844: */
2845: public static boolean setCurrentGradientPainter(
2846: SubstanceGradientPainter currentGradientPainter) {
2847: return SubstanceLookAndFeel.setCurrentGradientPainter(
2848: currentGradientPainter, true);
2849: }
2850:
2851: /**
2852: * Sets new gradient painter.
2853: *
2854: * @param currentGradientPainter
2855: * Gradient painter object.
2856: * @param toReset
2857: * If <code>true</code>, internal image caches are reset.
2858: * @return The status of the gradient painter change.
2859: */
2860: private static boolean setCurrentGradientPainter(
2861: SubstanceGradientPainter currentGradientPainter,
2862: boolean toReset) {
2863: SubstanceLookAndFeel.currentGradientPainter = currentGradientPainter;
2864: if (toReset) {
2865: ButtonBackgroundDelegate.reset();
2866: SubstanceCheckBoxUI.reset();
2867: SubstanceRadioButtonUI.reset();
2868: }
2869:
2870: for (GradientPainterChangeListener gradientPainterChangeListener : SubstanceLookAndFeel.gradientPainterChangeListeners)
2871: gradientPainterChangeListener.gradientPainterChanged();
2872:
2873: return true;
2874: }
2875:
2876: /**
2877: * The current border painter.
2878: */
2879: private static SubstanceBorderPainter currentBorderPainter = null;
2880:
2881: /**
2882: * Returns the current border painter name.
2883: *
2884: * @return Current border painter name.
2885: * @since version 4.0
2886: * @see #getCurrentBorderPainter()
2887: * @see #setCurrentBorderPainter(String)
2888: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
2889: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
2890: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
2891: * @see #BORDER_PAINTER_PROPERTY
2892: */
2893: public static String getCurrentBorderPainterName() {
2894: if (SubstanceLookAndFeel.currentBorderPainter == null)
2895: return null;
2896: return SubstanceLookAndFeel.currentBorderPainter
2897: .getDisplayName();
2898: }
2899:
2900: /**
2901: * Returns all available border painters.
2902: *
2903: * @return All available border painters. Key - border painter name, value -
2904: * border painter information.
2905: * @since version 4.0
2906: */
2907: public static Map<String, BorderPainterInfo> getAllBorderPainters() {
2908: Map<String, BorderPainterInfo> result = new TreeMap<String, BorderPainterInfo>();
2909: for (Object BorderPainterPlugin : SubstanceLookAndFeel.borderPainterPlugins
2910: .getAvailablePlugins(true)) {
2911: for (BorderPainterInfo BorderPainterInfo : ((SubstanceBorderPainterPlugin) BorderPainterPlugin)
2912: .getBorderPainters()) {
2913: result.put(BorderPainterInfo.getDisplayName(),
2914: BorderPainterInfo);
2915: }
2916: }
2917: return result;
2918: }
2919:
2920: /**
2921: * Returns the current Border painter.
2922: *
2923: * @return The current Border painter.
2924: * @since version 4.0
2925: * @see #getCurrentBorderPainterName()
2926: * @see #setCurrentBorderPainter(String)
2927: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
2928: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
2929: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
2930: * @see #BORDER_PAINTER_PROPERTY
2931: */
2932: public static SubstanceBorderPainter getCurrentBorderPainter() {
2933: return SubstanceLookAndFeel.currentBorderPainter;
2934: }
2935:
2936: /**
2937: * Sets new border painter.
2938: *
2939: * @param borderPainterClassName
2940: * Border painter class name (full qualified).
2941: * @return The status of the border painter change.
2942: * @since version 4.0
2943: * @see #getCurrentBorderPainter()
2944: * @see #getCurrentBorderPainterName()
2945: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
2946: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
2947: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
2948: * @see #BORDER_PAINTER_PROPERTY
2949: */
2950: public static boolean setCurrentBorderPainter(
2951: String borderPainterClassName) {
2952: try {
2953: Class<?> BorderPainterClass = Class
2954: .forName(borderPainterClassName);
2955: if (BorderPainterClass == null) {
2956: return false;
2957: }
2958: Object obj = BorderPainterClass.newInstance();
2959: if (obj == null) {
2960: return false;
2961: }
2962: if (!(obj instanceof SubstanceBorderPainter)) {
2963: return false;
2964: }
2965: return SubstanceLookAndFeel.setCurrentBorderPainter(
2966: (SubstanceBorderPainter) obj, true);
2967: } catch (Exception exc) {
2968: return false;
2969: }
2970: }
2971:
2972: /**
2973: * Sets new border painter.
2974: *
2975: * @param currentBorderPainter
2976: * Border painter object.
2977: * @return The status of the border painter change.
2978: * @since version 4.0
2979: * @see #getCurrentBorderPainter()
2980: * @see #getCurrentBorderPainterName()
2981: * @see #setCurrentBorderPainter(String)
2982: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
2983: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
2984: * @see #BORDER_PAINTER_PROPERTY
2985: */
2986: public static boolean setCurrentBorderPainter(
2987: SubstanceBorderPainter currentBorderPainter) {
2988: return SubstanceLookAndFeel.setCurrentBorderPainter(
2989: currentBorderPainter, true);
2990: }
2991:
2992: /**
2993: * Sets new border painter.
2994: *
2995: * @param newBorderPainter
2996: * Border painter object.
2997: * @param toReset
2998: * If <code>true</code>, internal image caches are reset.
2999: * @return The status of the border painter change.
3000: */
3001: private static boolean setCurrentBorderPainter(
3002: SubstanceBorderPainter newBorderPainter, boolean toReset) {
3003: SubstanceLookAndFeel.currentBorderPainter = newBorderPainter;
3004:
3005: if (toReset) {
3006: ButtonBackgroundDelegate.reset();
3007: SubstanceCheckBoxUI.reset();
3008: SubstanceRadioButtonUI.reset();
3009: }
3010:
3011: for (BorderPainterChangeListener borderPainterChangeListener : SubstanceLookAndFeel.borderPainterChangeListeners)
3012: borderPainterChangeListener.borderPainterChanged();
3013:
3014: return true;
3015: }
3016:
3017: /**
3018: * The current text painter.
3019: */
3020: private static SubstanceTextPainter currentTextPainter = new DefaultTextPainter();
3021:
3022: public static SubstanceTextPainter getCurrentTextPainter() {
3023: return SubstanceLookAndFeel.currentTextPainter;
3024: }
3025:
3026: public static boolean setCurrentTextPainter(
3027: SubstanceTextPainter newTextPainter) {
3028: SubstanceLookAndFeel.currentTextPainter = newTextPainter;
3029: return true;
3030: }
3031:
3032: private static SubstanceHighlightPainter currentHighlightPainter = new ClassicHighlightPainter();
3033:
3034: public static SubstanceHighlightPainter getCurrentHighlightPainter() {
3035: return SubstanceLookAndFeel.currentHighlightPainter;
3036: }
3037:
3038: public static boolean setCurrentHighlightPainter(
3039: SubstanceHighlightPainter newHighlightPainter) {
3040: SubstanceLookAndFeel.currentHighlightPainter = newHighlightPainter;
3041: return true;
3042: }
3043:
3044: private static SubstanceDecorationPainter currentDecorationPainter = new Glass3DDecorationPainter();
3045:
3046: public static SubstanceDecorationPainter getCurrentDecorationPainter() {
3047: return SubstanceLookAndFeel.currentDecorationPainter;
3048: }
3049:
3050: public static boolean setCurrentDecorationPainter(
3051: SubstanceDecorationPainter newDecorationPainter) {
3052: SubstanceLookAndFeel.currentDecorationPainter = newDecorationPainter;
3053: return true;
3054: }
3055:
3056: /*
3057: * (non-Javadoc)
3058: *
3059: * @see javax.swing.LookAndFeel#getDescription()
3060: */
3061: @Override
3062: public String getDescription() {
3063: return "Substance Look and Feel by Kirill Grouchnikov";
3064: }
3065:
3066: /*
3067: * (non-Javadoc)
3068: *
3069: * @see javax.swing.LookAndFeel#getID()
3070: */
3071: @Override
3072: public String getID() {
3073: return "Substance";
3074: }
3075:
3076: /*
3077: * (non-Javadoc)
3078: *
3079: * @see javax.swing.LookAndFeel#getName()
3080: */
3081: @Override
3082: public String getName() {
3083: return "Substance";
3084: }
3085:
3086: /*
3087: * (non-Javadoc)
3088: *
3089: * @see javax.swing.LookAndFeel#isNativeLookAndFeel()
3090: */
3091: @Override
3092: public boolean isNativeLookAndFeel() {
3093: return false;
3094: }
3095:
3096: /*
3097: * (non-Javadoc)
3098: *
3099: * @see javax.swing.LookAndFeel#isSupportedLookAndFeel()
3100: */
3101: @Override
3102: public boolean isSupportedLookAndFeel() {
3103: return true;
3104: }
3105:
3106: /*
3107: * (non-Javadoc)
3108: *
3109: * @see javax.swing.plaf.basic.BasicLookAndFeel#initClassDefaults(javax.swing.UIDefaults)
3110: */
3111: @Override
3112: protected void initClassDefaults(UIDefaults table) {
3113: super .initClassDefaults(table);
3114:
3115: String UI_CLASSNAME_PREFIX = "org.jvnet.substance.Substance";
3116: Object[] uiDefaults = {
3117:
3118: "ButtonUI", UI_CLASSNAME_PREFIX + "ButtonUI",
3119:
3120: "CheckBoxUI", UI_CLASSNAME_PREFIX + "CheckBoxUI",
3121:
3122: "ComboBoxUI", UI_CLASSNAME_PREFIX + "ComboBoxUI",
3123:
3124: "CheckBoxMenuItemUI",
3125: UI_CLASSNAME_PREFIX + "CheckBoxMenuItemUI",
3126:
3127: "DesktopIconUI", UI_CLASSNAME_PREFIX + "DesktopIconUI",
3128:
3129: "DesktopPaneUI",
3130: UI_CLASSNAME_PREFIX + "DesktopPaneUI",
3131:
3132: "EditorPaneUI",
3133: UI_CLASSNAME_PREFIX + "EditorPaneUI",
3134:
3135: "FileChooserUI",
3136: UI_CLASSNAME_PREFIX + "FileChooserUI",
3137:
3138: // "FileChooserUI", "javax.swing.plaf.metal.MetalFileChooserUI",
3139:
3140: "FormattedTextFieldUI",
3141: UI_CLASSNAME_PREFIX + "FormattedTextFieldUI",
3142:
3143: "InternalFrameUI",
3144: UI_CLASSNAME_PREFIX + "InternalFrameUI",
3145:
3146: "LabelUI", UI_CLASSNAME_PREFIX + "LabelUI",
3147:
3148: "ListUI", UI_CLASSNAME_PREFIX + "ListUI",
3149:
3150: "MenuUI", UI_CLASSNAME_PREFIX + "MenuUI",
3151:
3152: "MenuBarUI", UI_CLASSNAME_PREFIX + "MenuBarUI",
3153:
3154: "MenuItemUI", UI_CLASSNAME_PREFIX + "MenuItemUI",
3155:
3156: "OptionPaneUI", UI_CLASSNAME_PREFIX + "OptionPaneUI",
3157:
3158: "PanelUI", UI_CLASSNAME_PREFIX + "PanelUI",
3159:
3160: "PasswordFieldUI",
3161: UI_CLASSNAME_PREFIX + "PasswordFieldUI",
3162:
3163: "PopupMenuUI", UI_CLASSNAME_PREFIX + "PopupMenuUI",
3164:
3165: "PopupMenuSeparatorUI",
3166: UI_CLASSNAME_PREFIX + "PopupMenuSeparatorUI",
3167:
3168: "ProgressBarUI", UI_CLASSNAME_PREFIX + "ProgressBarUI",
3169:
3170: "RadioButtonUI", UI_CLASSNAME_PREFIX + "RadioButtonUI",
3171:
3172: "RadioButtonMenuItemUI",
3173: UI_CLASSNAME_PREFIX + "RadioButtonMenuItemUI",
3174:
3175: "RootPaneUI", UI_CLASSNAME_PREFIX + "RootPaneUI",
3176:
3177: "ScrollBarUI", UI_CLASSNAME_PREFIX + "ScrollBarUI",
3178:
3179: "ScrollPaneUI", UI_CLASSNAME_PREFIX + "ScrollPaneUI",
3180:
3181: "SeparatorUI", UI_CLASSNAME_PREFIX + "SeparatorUI",
3182:
3183: "SliderUI", UI_CLASSNAME_PREFIX + "SliderUI",
3184:
3185: "SpinnerUI", UI_CLASSNAME_PREFIX + "SpinnerUI",
3186:
3187: "SplitPaneUI", UI_CLASSNAME_PREFIX + "SplitPaneUI",
3188:
3189: "TabbedPaneUI", UI_CLASSNAME_PREFIX + "TabbedPaneUI",
3190:
3191: "TableUI", UI_CLASSNAME_PREFIX + "TableUI",
3192:
3193: "TableHeaderUI", UI_CLASSNAME_PREFIX + "TableHeaderUI",
3194:
3195: "TextAreaUI", UI_CLASSNAME_PREFIX + "TextAreaUI",
3196:
3197: "TextFieldUI", UI_CLASSNAME_PREFIX + "TextFieldUI",
3198:
3199: "TextPaneUI", UI_CLASSNAME_PREFIX + "TextPaneUI",
3200:
3201: "ToggleButtonUI",
3202: UI_CLASSNAME_PREFIX + "ToggleButtonUI",
3203:
3204: "ToolBarUI", UI_CLASSNAME_PREFIX + "ToolBarUI",
3205:
3206: "ToolBarSeparatorUI",
3207: UI_CLASSNAME_PREFIX + "ToolBarSeparatorUI",
3208:
3209: "ToolTipUI", UI_CLASSNAME_PREFIX + "ToolTipUI",
3210:
3211: "TreeUI", UI_CLASSNAME_PREFIX + "TreeUI",
3212:
3213: };
3214: table.putDefaults(uiDefaults);
3215: }
3216:
3217: /*
3218: * (non-Javadoc)
3219: *
3220: * @see javax.swing.plaf.basic.BasicLookAndFeel#initComponentDefaults(javax.swing.UIDefaults)
3221: */
3222: @Override
3223: protected void initComponentDefaults(UIDefaults table) {
3224: super .initComponentDefaults(table);
3225:
3226: // if (LookUtils.IS_OS_WINDOWS) {
3227: initFontDefaults(table);
3228: // } else {
3229: // String fontFamilyName = SubstanceLookAndFeel.getFontFamilyName();
3230: // int regKind = SubstanceLookAndFeel.isBasicFontBold() ? Font.BOLD
3231: // : Font.PLAIN;
3232: // int baseFontSize = SubstanceLookAndFeel.getBasicFontSize();
3233: // Font fontPlainBase = new FontUIResource(new Font(fontFamilyName,
3234: // regKind, baseFontSize));
3235: // Font fontBoldBase = new FontUIResource(new Font(fontFamilyName,
3236: // Font.BOLD, baseFontSize));
3237: // Font fontBoldBaseP1 = new FontUIResource(new Font(fontFamilyName,
3238: // Font.BOLD, baseFontSize + 1));
3239: // Object[] fontDefaults = {
3240: //
3241: // "Button.font", fontPlainBase,
3242: //
3243: // "CheckBox.font", fontPlainBase,
3244: //
3245: // "CheckBoxMenuItem.font", fontPlainBase,
3246: //
3247: // "CheckBoxMenuItem.acceleratorFont", fontPlainBase,
3248: //
3249: // "ComboBox.font", fontPlainBase,
3250: //
3251: // "DesktopIcon.font", fontBoldBaseP1,
3252: //
3253: // "EditorPane.font", fontPlainBase,
3254: //
3255: // "FormattedTextField.font", fontPlainBase,
3256: //
3257: // "InternalFrame.titleFont", fontBoldBaseP1,
3258: //
3259: // "Label.font", fontPlainBase,
3260: //
3261: // "List.font", fontPlainBase,
3262: //
3263: // "Menu.font", fontPlainBase,
3264: //
3265: // "Menu.acceleratorFont", fontPlainBase,
3266: //
3267: // "MenuBar.font", fontPlainBase,
3268: //
3269: // "MenuItem.font", fontPlainBase,
3270: //
3271: // "MenuItem.acceleratorFont", fontPlainBase,
3272: //
3273: // "OptionPane.font", fontPlainBase,
3274: //
3275: // "OptionPane.messageFont", fontPlainBase,
3276: //
3277: // "OptionPane.buttonFont", fontPlainBase,
3278: //
3279: // "Panel.font", fontPlainBase,
3280: //
3281: // "PasswordField.font", fontPlainBase,
3282: //
3283: // "PopupMenu.font", fontPlainBase,
3284: //
3285: // "ProgressBar.font", fontPlainBase,
3286: //
3287: // "RadioButton.font", fontPlainBase,
3288: //
3289: // "RadioButtonMenuItem.font", fontPlainBase,
3290: //
3291: // "RadioButtonMenuItem.acceleratorFont", fontPlainBase,
3292: //
3293: // "ScrollPane.font", fontPlainBase,
3294: //
3295: // "Spinner.font", fontPlainBase,
3296: //
3297: // "TabbedPane.font", fontPlainBase,
3298: //
3299: // "Table.font", fontPlainBase,
3300: //
3301: // "TableHeader.font", fontPlainBase,
3302: //
3303: // "TextField.font", fontPlainBase,
3304: //
3305: // "TextPane.font", fontPlainBase,
3306: //
3307: // "ToolBar.font", fontPlainBase,
3308: //
3309: // "ToggleButton.font", fontPlainBase,
3310: //
3311: // "Tree.font", fontPlainBase,
3312: //
3313: // "Viewport.font", fontPlainBase,
3314: //
3315: // "Spinner.font", fontPlainBase,
3316: //
3317: // "TextArea.font", fontPlainBase,
3318: //
3319: // "TitledBorder.font", fontBoldBase,
3320: //
3321: // "ToolTip.font", fontPlainBase,
3322: //
3323: // };
3324: // table.putDefaults(fontDefaults);
3325: // }
3326: SubstanceLookAndFeel.getTheme().addCustomEntriesToTable(table);
3327: }
3328:
3329: /**
3330: * Sets the {@link FontPolicy} to be used with Substance family. If the
3331: * specified policy is <code>null</code>, the default will be reset. Note
3332: * that after calling this method you need to call
3333: * {@link UIManager#setLookAndFeel(LookAndFeel)} with Substance and
3334: * {@link SwingUtilities#updateComponentTreeUI(Component)} to have the new
3335: * font policy applied to your windows.
3336: *
3337: * @param fontPolicy
3338: * The {@link FontPolicy} to be used with Substance family, or
3339: * <code>null</code> to reset to the default
3340: *
3341: * @see #getFontPolicy()
3342: * @see SubstanceLookAndFeel#SUBSTANCE_FONT_POLICY_KEY
3343: */
3344: public static void setFontPolicy(FontPolicy fontPolicy) {
3345: UIManager.put(SUBSTANCE_FONT_POLICY_KEY, fontPolicy);
3346: SubstanceSizeUtils.setControlFontSize(-1);
3347: SubstanceSizeUtils.resetPointsToPixelsRatio(fontPolicy);
3348: }
3349:
3350: /**
3351: * Looks up and retrieves the {@link FontPolicy} used by the Substance
3352: * family. If a {@link FontPolicy} has been set, it'll be returned.
3353: * Otherwise, this method checks if a {@link FontPolicy} or {@link FontSet}
3354: * is defined in the system properties or UIDefaults. If so, it is returned.
3355: * If no {@link FontPolicy} has been set for this look, in the system
3356: * properties or {@link UIDefaults}, the default Substance font policy will
3357: * be returned.
3358: *
3359: * @return the {@link FontPolicy} set for this Look&feel - if any, the
3360: * {@link FontPolicy} specified in the system properties or
3361: * {@link UIDefaults} - if any, or the default Substance font
3362: * policy.
3363: *
3364: * @see #setFontPolicy
3365: * @see FontPolicies
3366: * @see FontPolicies#customSettingsPolicy(FontPolicy)
3367: */
3368: public static FontPolicy getFontPolicy() {
3369: FontPolicy policy = (FontPolicy) UIManager
3370: .get(SUBSTANCE_FONT_POLICY_KEY);
3371: if (policy != null)
3372: return policy;
3373:
3374: // return default policy
3375: return SubstanceFontUtilities.getDefaultFontPolicy();
3376: }
3377:
3378: /**
3379: * Looks up the correct control font and sets it for all controls.
3380: *
3381: * @param table
3382: * The UI defaults table.
3383: */
3384: private void initFontDefaults(UIDefaults table) {
3385: FontSet substanceFontSet = getFontPolicy().getFontSet(
3386: "Substance", null);
3387: initFontDefaults(table, substanceFontSet);
3388: }
3389:
3390: // public static FontSet getFontSet() {
3391: // FontPolicy fontChoicePolicy = getFontPolicy();
3392: // FontSet fontSet = fontChoicePolicy.getFontSet("Substance", null);
3393: // FontSet substanceFontSet = new SubstanceFontSet(fontSet);
3394: // return substanceFontSet;
3395: // }
3396: //
3397: /**
3398: * Sets Fonts in the given FontSet as defaults for all known component types
3399: * in the given UIDefaults table.
3400: *
3401: * @param table
3402: * the UIDefaults table used to set fonts
3403: * @param fontSet
3404: * describes the set of Fonts to be installed
3405: */
3406: private static void initFontDefaults(UIDefaults table,
3407: FontSet fontSet) {
3408: Font controlFont = fontSet.getControlFont();
3409: Font menuFont = fontSet.getMenuFont();
3410: Font messageFont = fontSet.getMessageFont();
3411: Font toolTipFont = fontSet.getSmallFont();
3412: Font titleFont = fontSet.getTitleFont();
3413: Font windowFont = fontSet.getWindowTitleFont();
3414:
3415: // System.out.println("Control: " + fontSet.getControlFont());
3416: // System.out.println("Menu: " + fontSet.getMenuFont());
3417: // System.out.println("Message: " + fontSet.getMessageFont());
3418: // System.out.println("Small: " + fontSet.getSmallFont());
3419: // System.out.println("Title: " + fontSet.getTitleFont());
3420: // System.out.println("Window title: " + fontSet.getWindowTitleFont());
3421:
3422: Object[] defaults = {
3423:
3424: "Button.font", controlFont,
3425:
3426: "CheckBox.font", controlFont,
3427:
3428: "ColorChooser.font", controlFont,
3429:
3430: "ComboBox.font", controlFont,
3431:
3432: "EditorPane.font", controlFont,
3433:
3434: "FormattedTextField.font", controlFont,
3435:
3436: "Label.font", controlFont,
3437:
3438: "List.font", controlFont,
3439:
3440: "Panel.font", controlFont,
3441:
3442: "PasswordField.font", controlFont,
3443:
3444: "ProgressBar.font", controlFont,
3445:
3446: "RadioButton.font", controlFont,
3447:
3448: "ScrollPane.font", controlFont,
3449:
3450: "Spinner.font", controlFont,
3451:
3452: "TabbedPane.font", controlFont,
3453:
3454: "Table.font", controlFont,
3455:
3456: "TableHeader.font", controlFont,
3457:
3458: "TextArea.font", controlFont,
3459:
3460: "TextField.font", controlFont,
3461:
3462: "TextPane.font", controlFont,
3463:
3464: "ToolBar.font", controlFont,
3465:
3466: "ToggleButton.font", controlFont,
3467:
3468: "Tree.font", controlFont,
3469:
3470: "Viewport.font", controlFont,
3471:
3472: "InternalFrame.titleFont", windowFont,
3473:
3474: "DesktopIcon.titleFont", windowFont,
3475:
3476: "OptionPane.font", messageFont,
3477:
3478: "OptionPane.messageFont", messageFont,
3479:
3480: "OptionPane.buttonFont", messageFont,
3481:
3482: "TitledBorder.font", titleFont,
3483:
3484: "ToolTip.font", toolTipFont,
3485:
3486: "CheckBoxMenuItem.font", menuFont,
3487:
3488: "CheckBoxMenuItem.acceleratorFont", menuFont,
3489:
3490: "Menu.font", menuFont,
3491:
3492: "Menu.acceleratorFont", menuFont,
3493:
3494: "MenuBar.font", menuFont,
3495:
3496: "MenuItem.font", menuFont,
3497:
3498: "MenuItem.acceleratorFont", menuFont,
3499:
3500: "PopupMenu.font", menuFont,
3501:
3502: "RadioButtonMenuItem.font", menuFont,
3503:
3504: "RadioButtonMenuItem.acceleratorFont", menuFont,
3505: // ?
3506: };
3507: table.putDefaults(defaults);
3508: }
3509:
3510: /*
3511: * (non-Javadoc)
3512: *
3513: * @see javax.swing.plaf.basic.BasicLookAndFeel#getDefaults()
3514: */
3515: @Override
3516: public UIDefaults getDefaults() {
3517: UIDefaults table = super .getDefaults();
3518:
3519: SubstanceLookAndFeel.componentPlugins
3520: .processAllDefaultsEntries(table,
3521: SubstanceLookAndFeel.currentTheme);
3522: return table;
3523: }
3524:
3525: /*
3526: * (non-Javadoc)
3527: *
3528: * @see javax.swing.plaf.basic.BasicLookAndFeel#initialize()
3529: */
3530: @Override
3531: public void initialize() {
3532: super .initialize();
3533: ShadowPopupFactory.install();
3534: if (SubstanceLookAndFeel.currentTheme == null) {
3535: // set theme
3536: String paramTheme = SubstanceLookAndFeel.paramReader
3537: .getThemeProperty();
3538: boolean isSetTheme = false;
3539: if (paramTheme != null) {
3540: isSetTheme = SubstanceLookAndFeel.setCurrentTheme(
3541: paramTheme, false);
3542: }
3543: if (!isSetTheme) {
3544: try {
3545: for (Object themePlugin : SubstanceLookAndFeel.themePlugins
3546: .getAvailablePlugins(true)) {
3547: String defaultThemeClassName = ((SubstanceThemePlugin) themePlugin)
3548: .getDefaultThemeClassName();
3549: if (defaultThemeClassName == null)
3550: continue;
3551: isSetTheme = SubstanceLookAndFeel
3552: .setCurrentTheme(defaultThemeClassName,
3553: false);
3554: if (isSetTheme)
3555: break;
3556: }
3557: if (!isSetTheme)
3558: SubstanceLookAndFeel.setCurrentTheme(
3559: new SubstanceAquaTheme(), false);
3560: } catch (Exception exc) {
3561: exc.printStackTrace();
3562: }
3563: }
3564: } else {
3565: SubstanceLookAndFeel.setCurrentTheme(
3566: SubstanceLookAndFeel.currentTheme, false);
3567: }
3568:
3569: ImageWatermarkKind imageWatermarkKind = SubstanceLookAndFeel.paramReader
3570: .getWatermarkImageKindProperty();
3571: if (imageWatermarkKind != null)
3572: SubstanceLookAndFeel
3573: .setImageWatermarkKind(imageWatermarkKind);
3574:
3575: Float imageWatermarkOpacity = SubstanceLookAndFeel.paramReader
3576: .getWatermarkImageOpacityProperty();
3577: if (imageWatermarkOpacity != null)
3578: SubstanceLookAndFeel
3579: .setImageWatermarkOpacity(imageWatermarkOpacity);
3580:
3581: if (SubstanceLookAndFeel.currentWatermark == null) {
3582: // set watermark
3583: String paramWatermark = SubstanceLookAndFeel.paramReader
3584: .getWatermarkProperty();
3585: boolean isSetWatermark = false;
3586: if (paramWatermark != null) {
3587: isSetWatermark = SubstanceLookAndFeel
3588: .setCurrentWatermark(paramWatermark,
3589: SubstanceLookAndFeel.paramReader);
3590: }
3591: if (!isSetWatermark) {
3592: try {
3593: for (Object watermarkPlugin : SubstanceLookAndFeel.watermarkPlugins
3594: .getAvailablePlugins(true)) {
3595: String defaultWatermarkClassName = ((SubstanceWatermarkPlugin) watermarkPlugin)
3596: .getDefaultWatermarkClassName();
3597: if (defaultWatermarkClassName == null)
3598: continue;
3599: isSetWatermark = SubstanceLookAndFeel
3600: .setCurrentWatermark(
3601: defaultWatermarkClassName,
3602: SubstanceLookAndFeel.paramReader);
3603: if (isSetWatermark)
3604: break;
3605: }
3606: if (!isSetWatermark)
3607: SubstanceLookAndFeel
3608: .setCurrentWatermark(new SubstanceStripeWatermark());
3609: } catch (Exception exc) {
3610: exc.printStackTrace();
3611: }
3612: }
3613: }
3614:
3615: if (SubstanceLookAndFeel.currentButtonShaper == null) {
3616: // set button shaper
3617: String paramButtonShaper = SubstanceLookAndFeel.paramReader
3618: .getButtonShaperProperty();
3619: boolean isSetButtonShaper = false;
3620: if (paramButtonShaper != null) {
3621: isSetButtonShaper = SubstanceLookAndFeel
3622: .setCurrentButtonShaper(paramButtonShaper,
3623: false);
3624: }
3625: if (!isSetButtonShaper) {
3626: try {
3627: for (Object buttonShaperPlugin : SubstanceLookAndFeel.shaperPlugins
3628: .getAvailablePlugins(true)) {
3629: for (ButtonShaperInfo buttonShaperInfo : ((SubstanceButtonShaperPlugin) buttonShaperPlugin)
3630: .getButtonShapers()) {
3631: if (buttonShaperInfo.isDefault()) {
3632: isSetButtonShaper = SubstanceLookAndFeel
3633: .setCurrentButtonShaper(
3634: buttonShaperInfo
3635: .getClassName(),
3636: false);
3637: }
3638: }
3639: }
3640: if (!isSetButtonShaper)
3641: SubstanceLookAndFeel.setCurrentButtonShaper(
3642: new StandardButtonShaper(), false);
3643: } catch (Exception exc) {
3644: exc.printStackTrace();
3645: }
3646: }
3647: }
3648:
3649: if (SubstanceLookAndFeel.currentGradientPainter == null) {
3650: // set gradient painter
3651: String paramGradientPainter = SubstanceLookAndFeel.paramReader
3652: .getGradientPainterProperty();
3653: boolean isSetGradientPainter = false;
3654: if (paramGradientPainter != null) {
3655: isSetGradientPainter = SubstanceLookAndFeel
3656: .setCurrentGradientPainter(paramGradientPainter);
3657: }
3658: if (!isSetGradientPainter) {
3659: try {
3660: for (Object gradientPainterPlugin : SubstanceLookAndFeel.painterPlugins
3661: .getAvailablePlugins(true)) {
3662: for (GradientPainterInfo gradientPainterInfo : ((SubstanceGradientPainterPlugin) gradientPainterPlugin)
3663: .getGradientPainters()) {
3664: if (gradientPainterInfo.isDefault()) {
3665: isSetGradientPainter = SubstanceLookAndFeel
3666: .setCurrentGradientPainter(gradientPainterInfo
3667: .getClassName());
3668: }
3669: }
3670: }
3671: if (!isSetGradientPainter)
3672: SubstanceLookAndFeel.setCurrentGradientPainter(
3673: new StandardGradientPainter(), false);
3674: } catch (Exception exc) {
3675: exc.printStackTrace();
3676: }
3677: }
3678: }
3679:
3680: if (SubstanceLookAndFeel.currentBorderPainter == null) {
3681: // set border painter
3682: String paramBorderPainter = SubstanceLookAndFeel.paramReader
3683: .getBorderPainterProperty();
3684: boolean isSetBorderPainter = false;
3685: if (paramBorderPainter != null) {
3686: isSetBorderPainter = SubstanceLookAndFeel
3687: .setCurrentBorderPainter(paramBorderPainter);
3688: }
3689: if (!isSetBorderPainter) {
3690: try {
3691: for (Object borderPainterPlugin : SubstanceLookAndFeel.borderPainterPlugins
3692: .getAvailablePlugins(true)) {
3693: for (BorderPainterInfo borderPainterInfo : ((SubstanceBorderPainterPlugin) borderPainterPlugin)
3694: .getBorderPainters()) {
3695: if (borderPainterInfo.isDefault()) {
3696: isSetBorderPainter = SubstanceLookAndFeel
3697: .setCurrentBorderPainter(borderPainterInfo
3698: .getClassName());
3699: }
3700: }
3701: }
3702: if (!isSetBorderPainter)
3703: SubstanceLookAndFeel.setCurrentBorderPainter(
3704: new StandardBorderPainter(), false);
3705: } catch (Exception exc) {
3706: exc.printStackTrace();
3707: }
3708: }
3709: }
3710:
3711: // tracer for memory analysis
3712: String paramTraceFile = SubstanceLookAndFeel.paramReader
3713: .getTraceFileNameProperty();
3714: if (paramTraceFile != null) {
3715: MemoryAnalyzer.commence(1000, paramTraceFile);
3716: for (Object plugin : SubstanceLookAndFeel.componentPlugins
3717: .getAvailablePlugins(true))
3718: MemoryAnalyzer.enqueueUsage("Has plugin '"
3719: + plugin.getClass().getName() + "'");
3720: for (Object plugin : SubstanceLookAndFeel.themePlugins
3721: .getAvailablePlugins(true))
3722: MemoryAnalyzer.enqueueUsage("Has theme plugin '"
3723: + plugin.getClass().getName() + "'");
3724: for (Object plugin : SubstanceLookAndFeel.watermarkPlugins
3725: .getAvailablePlugins(true))
3726: MemoryAnalyzer.enqueueUsage("Has watermark plugin '"
3727: + plugin.getClass().getName() + "'");
3728: for (Object plugin : SubstanceLookAndFeel.shaperPlugins
3729: .getAvailablePlugins(true))
3730: MemoryAnalyzer
3731: .enqueueUsage("Has button shaper plugin '"
3732: + plugin.getClass().getName() + "'");
3733:
3734: }
3735:
3736: // to show heap status panel in title pane?
3737: String heapStatusPanelParam = SubstanceLookAndFeel.paramReader
3738: .toShowHeapStatusPanelProperty();
3739: SubstanceTitlePane
3740: .setCanHaveHeapStatusPanel(heapStatusPanelParam != null);
3741: SubstanceTitlePane
3742: .setHeapStatusLogfileName(heapStatusPanelParam);
3743:
3744: // to show extra UI elements?
3745: SubstanceLookAndFeel.toShowExtraElements = SubstanceLookAndFeel.paramReader
3746: .toShowExtraElementProperty();
3747:
3748: // to enable inverted themes?
3749: SubstanceLookAndFeel.toEnableInvertedThemes = SubstanceLookAndFeel.paramReader
3750: .toEnableInvertedThemes();
3751:
3752: // to enable inverted themes?
3753: SubstanceLookAndFeel.toEnableNegatedThemes = SubstanceLookAndFeel.paramReader
3754: .toEnableNegatedThemes();
3755:
3756: // to bleed watermark?
3757: SubstanceLookAndFeel.toBleedWatermark = SubstanceLookAndFeel.paramReader
3758: .toBleedWatermark();
3759:
3760: // is debug UI mode?
3761: SubstanceLookAndFeel.isDebugUiMode = SubstanceLookAndFeel.paramReader
3762: .isDebugUiMode();
3763:
3764: try {
3765: Class.forName("org.jvnet.lafwidget.menu.MenuSearchWidget");
3766: SubstanceMenuBarUI.showSearchPanels();
3767: } catch (ClassNotFoundException cnfe) {
3768: }
3769:
3770: // initialize component plugins
3771: SubstanceLookAndFeel.componentPlugins.initializeAll();
3772:
3773: // initialize widget support
3774: LafWidgetRepository.getRepository().setLafSupport(
3775: new SubstanceWidgetSupport());
3776:
3777: // fix for defect 208 - tracking changes to focus owner
3778: // and repainting the default button
3779: this .focusOwnerChangeListener = new PropertyChangeListener() {
3780: public void propertyChange(PropertyChangeEvent evt) {
3781: if ("focusOwner".equals(evt.getPropertyName())) {
3782: Component newFocusOwner = (Component) evt
3783: .getNewValue();
3784: if (newFocusOwner != null) {
3785: JRootPane rootPane = SwingUtilities
3786: .getRootPane(newFocusOwner);
3787: if (rootPane == null)
3788: return;
3789: JButton defaultButton = rootPane
3790: .getDefaultButton();
3791: if (defaultButton == null)
3792: return;
3793: defaultButton.repaint();
3794: }
3795: }
3796: if ("managingFocus".equals(evt.getPropertyName())) {
3797: if (Boolean.FALSE.equals(evt.getNewValue())) {
3798: // new keyboard focus manager has been installed
3799: currentKeyboardFocusManager
3800: .removePropertyChangeListener(focusOwnerChangeListener);
3801: currentKeyboardFocusManager = KeyboardFocusManager
3802: .getCurrentKeyboardFocusManager();
3803: currentKeyboardFocusManager
3804: .addPropertyChangeListener(focusOwnerChangeListener);
3805: }
3806: }
3807: }
3808: };
3809: this .currentKeyboardFocusManager = KeyboardFocusManager
3810: .getCurrentKeyboardFocusManager();
3811: this .currentKeyboardFocusManager
3812: .addPropertyChangeListener(this .focusOwnerChangeListener);
3813:
3814: // TitleButtonManager.getManager().configure();
3815: }
3816:
3817: /*
3818: * (non-Javadoc)
3819: *
3820: * @see javax.swing.plaf.basic.BasicLookAndFeel#uninitialize()
3821: */
3822: @Override
3823: public void uninitialize() {
3824: super .uninitialize();
3825: ShadowPopupFactory.uninstall();
3826:
3827: SubstanceLookAndFeel.stopThreads();
3828: // if (MemoryAnalyzer.isRunning())
3829: // MemoryAnalyzer.requestStop();
3830:
3831: try {
3832: Class.forName("org.jvnet.lafwidget.menu.MenuSearchWidget");
3833: SubstanceMenuBarUI.hideSearchPanels(false);
3834: } catch (ClassNotFoundException cnfe) {
3835: }
3836:
3837: // fix for defect 109 - memory leak on watermarks
3838: SubstanceLookAndFeel.currentWatermark.dispose();
3839:
3840: // uninitialize component plugins
3841: SubstanceLookAndFeel.componentPlugins.uninitializeAll();
3842:
3843: // reset widget support
3844: LafWidgetRepository.getRepository().unsetLafSupport();
3845:
3846: // dispose the current text painter
3847: SubstanceLookAndFeel.currentTextPainter.dispose();
3848:
3849: this .currentKeyboardFocusManager
3850: .removePropertyChangeListener(this .focusOwnerChangeListener);
3851: this .focusOwnerChangeListener = null;
3852: this .currentKeyboardFocusManager = null;
3853:
3854: // TitleButtonManager.getManager().clean();
3855: }
3856:
3857: /**
3858: * Stops all Substance threads. Use with extreme caution - improper use may
3859: * result in UI artifacts and runtime exceptions. In general, this method is
3860: * for internal use only.
3861: */
3862: public static void stopThreads() {
3863: PulseTracker.stopAllTimers();
3864: // TabPulseTracker.stopAllTimers();
3865: // TabAnimationTracker.stopAllTimers();
3866: FadeTracker.getInstance().stopAllTimers();
3867: TrackableThread.requestStopAllThreads();
3868: }
3869:
3870: /**
3871: * Returns all available plugins. Each entry is {@link LafPlugin}.
3872: *
3873: * @return All available plugins.
3874: */
3875: @SuppressWarnings("unchecked")
3876: public static Set getPlugins() {
3877: return Collections
3878: .unmodifiableSet(SubstanceLookAndFeel.componentPlugins
3879: .getAvailablePlugins(true));
3880: }
3881:
3882: /**
3883: * Registers a new listener on skin change.
3884: *
3885: * @param skinChangeListener
3886: * New listener on skin change.
3887: * @see #setSkin(String)
3888: * @see #setSkin(SubstanceSkin)
3889: * @see #unregisterSkinChangeListener(SkinChangeListener)
3890: */
3891: public static void registerSkinChangeListener(
3892: SkinChangeListener skinChangeListener) {
3893: SubstanceLookAndFeel.skinChangeListeners
3894: .add(skinChangeListener);
3895: }
3896:
3897: /**
3898: * Unregisters a listener on skin change.
3899: *
3900: * @param skinChangeListener
3901: * The listener to unregister.
3902: * @see #setSkin(String)
3903: * @see #setSkin(SubstanceSkin)
3904: * @see #registerSkinChangeListener(SkinChangeListener)
3905: */
3906: public static void unregisterSkinChangeListener(
3907: SkinChangeListener skinChangeListener) {
3908: SubstanceLookAndFeel.skinChangeListeners
3909: .remove(skinChangeListener);
3910: }
3911:
3912: /**
3913: * Registers a new listener on theme change.
3914: *
3915: * @param themeChangeListener
3916: * New listener on theme change.
3917: * @see #getCurrentThemeName()
3918: * @see #getTheme()
3919: * @see #setCurrentTheme(String)
3920: * @see #setCurrentTheme(SubstanceTheme)
3921: * @see #setCurrentTheme(ThemeInfo)
3922: * @see #unregisterThemeChangeListener(ThemeChangeListener)
3923: * @see #THEME_PROPERTY
3924: */
3925: public static void registerThemeChangeListener(
3926: ThemeChangeListener themeChangeListener) {
3927: SubstanceLookAndFeel.themeChangeListeners
3928: .add(themeChangeListener);
3929: }
3930:
3931: /**
3932: * Unregisters a listener on theme change.
3933: *
3934: * @param themeChangeListener
3935: * The listener to unregister.
3936: * @see #getCurrentThemeName()
3937: * @see #getTheme()
3938: * @see #setCurrentTheme(String)
3939: * @see #setCurrentTheme(SubstanceTheme)
3940: * @see #setCurrentTheme(ThemeInfo)
3941: * @see #registerThemeChangeListener(ThemeChangeListener)
3942: * @see #THEME_PROPERTY
3943: */
3944: public static void unregisterThemeChangeListener(
3945: ThemeChangeListener themeChangeListener) {
3946: SubstanceLookAndFeel.themeChangeListeners
3947: .remove(themeChangeListener);
3948: }
3949:
3950: /**
3951: * Registers a new listener on watermark change.
3952: *
3953: * @param watermarkChangeListener
3954: * New listener on watermark change.
3955: * @see #getCurrentWatermark()
3956: * @see #getCurrentWatermarkName()
3957: * @see #setCurrentWatermark(String)
3958: * @see #setCurrentWatermark(SubstanceWatermark)
3959: * @see #unregisterWatermarkChangeListener(WatermarkChangeListener)
3960: * @see #WATERMARK_PROPERTY
3961: */
3962: public static void registerWatermarkChangeListener(
3963: WatermarkChangeListener watermarkChangeListener) {
3964: SubstanceLookAndFeel.watermarkChangeListeners
3965: .add(watermarkChangeListener);
3966: }
3967:
3968: /**
3969: * Unregisters a listener on watermark change.
3970: *
3971: * @param watermarkChangeListener
3972: * The listener to unregister.
3973: * @see #getCurrentWatermark()
3974: * @see #getCurrentWatermarkName()
3975: * @see #setCurrentWatermark(String)
3976: * @see #setCurrentWatermark(SubstanceWatermark)
3977: * @see #registerWatermarkChangeListener(WatermarkChangeListener)
3978: * @see #WATERMARK_PROPERTY
3979: */
3980: public static void unregisterWatermarkChangeListener(
3981: WatermarkChangeListener watermarkChangeListener) {
3982: SubstanceLookAndFeel.watermarkChangeListeners
3983: .remove(watermarkChangeListener);
3984: }
3985:
3986: /**
3987: * Registers a new listener on button shaper change.
3988: *
3989: * @param buttonShaperChangeListener
3990: * New listener on button shaper change.
3991: * @see #getCurrentButtonShaper()
3992: * @see #getCurrentButtonShaperName()
3993: * @see #setCurrentButtonShaper(String)
3994: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
3995: * @see #unregisterButtonShaperChangeListener(ButtonShaperChangeListener)
3996: * @see #BUTTON_SHAPER_PROPERTY
3997: */
3998: public static void registerButtonShaperChangeListener(
3999: ButtonShaperChangeListener buttonShaperChangeListener) {
4000: SubstanceLookAndFeel.buttonShaperChangeListeners
4001: .add(buttonShaperChangeListener);
4002: }
4003:
4004: /**
4005: * Unregisters a listener on button shaper change.
4006: *
4007: * @param buttonShaperChangeListener
4008: * The listener to unregister.
4009: * @see #getCurrentButtonShaper()
4010: * @see #getCurrentButtonShaperName()
4011: * @see #setCurrentButtonShaper(String)
4012: * @see #setCurrentButtonShaper(SubstanceButtonShaper)
4013: * @see #registerButtonShaperChangeListener(ButtonShaperChangeListener)
4014: * @see #BUTTON_SHAPER_PROPERTY
4015: */
4016: public static void unregisterButtonShaperChangeListener(
4017: ButtonShaperChangeListener buttonShaperChangeListener) {
4018: SubstanceLookAndFeel.buttonShaperChangeListeners
4019: .remove(buttonShaperChangeListener);
4020: }
4021:
4022: /**
4023: * Registers a new listener on gradient painter change.
4024: *
4025: * @param gradientPainterChangeListener
4026: * New listener on gradient painter change.
4027: * @see #getCurrentGradientPainter()
4028: * @see #getCurrentGradientPainterName()
4029: * @see #setCurrentGradientPainter(String)
4030: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
4031: * @see #unregisterGradientPainterChangeListener(GradientPainterChangeListener)
4032: * @see #GRADIENT_PAINTER_PROPERTY
4033: */
4034: public static void registerGradientPainterChangeListener(
4035: GradientPainterChangeListener gradientPainterChangeListener) {
4036: SubstanceLookAndFeel.gradientPainterChangeListeners
4037: .add(gradientPainterChangeListener);
4038: }
4039:
4040: /**
4041: * Unregisters a listener on gradient painter change.
4042: *
4043: * @param gradientPainterChangeListener
4044: * The listener to unregister.
4045: * @see #getCurrentGradientPainter()
4046: * @see #getCurrentGradientPainterName()
4047: * @see #setCurrentGradientPainter(String)
4048: * @see #setCurrentGradientPainter(SubstanceGradientPainter)
4049: * @see #registerGradientPainterChangeListener(GradientPainterChangeListener)
4050: * @see #GRADIENT_PAINTER_PROPERTY
4051: */
4052: public static void unregisterGradientPainterChangeListener(
4053: GradientPainterChangeListener gradientPainterChangeListener) {
4054: SubstanceLookAndFeel.gradientPainterChangeListeners
4055: .remove(gradientPainterChangeListener);
4056: }
4057:
4058: /**
4059: * Registers a new listener on border painter change.
4060: *
4061: * @param borderPainterChangeListener
4062: * New listener on border painter change.
4063: * @see #getCurrentBorderPainter()
4064: * @see #getCurrentBorderPainterName()
4065: * @see #setCurrentBorderPainter(String)
4066: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
4067: * @see #unregisterBorderPainterChangeListener(BorderPainterChangeListener)
4068: * @see #BORDER_PAINTER_PROPERTY
4069: */
4070: public static void registerBorderPainterChangeListener(
4071: BorderPainterChangeListener borderPainterChangeListener) {
4072: SubstanceLookAndFeel.borderPainterChangeListeners
4073: .add(borderPainterChangeListener);
4074: }
4075:
4076: /**
4077: * Unregisters a listener on border painter change.
4078: *
4079: * @param borderPainterChangeListener
4080: * The listener to unregister.
4081: * @see #getCurrentBorderPainter()
4082: * @see #getCurrentBorderPainterName()
4083: * @see #setCurrentBorderPainter(String)
4084: * @see #setCurrentBorderPainter(SubstanceBorderPainter)
4085: * @see #registerBorderPainterChangeListener(BorderPainterChangeListener)
4086: * @see #BORDER_PAINTER_PROPERTY
4087: */
4088: public static void unregisterBorderPainterChangeListener(
4089: BorderPainterChangeListener borderPainterChangeListener) {
4090: SubstanceLookAndFeel.borderPainterChangeListeners
4091: .remove(borderPainterChangeListener);
4092: }
4093:
4094: /**
4095: * Registers the specified listener on tab-close events on <b>all</b>
4096: * tabbed panes.
4097: *
4098: * @param tabCloseListener
4099: * Listener to register.
4100: * @see #registerTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4101: * @see #unregisterTabCloseChangeListener(BaseTabCloseListener)
4102: * @see #unregisterTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4103: */
4104: public static void registerTabCloseChangeListener(
4105: BaseTabCloseListener tabCloseListener) {
4106: TabCloseListenerManager.getInstance().registerListener(
4107: tabCloseListener);
4108: }
4109:
4110: /**
4111: * Registers the specified listener on tab-close events on <b>the specified</b>
4112: * tabbed pane.
4113: *
4114: * @param tabbedPane
4115: * Tabbed pane. If <code>null</code>, the tab close listener
4116: * is registered globally (for all tabbed panes).
4117: * @param tabCloseListener
4118: * Listener to register.
4119: * @see #registerTabCloseChangeListener(BaseTabCloseListener)
4120: * @see #unregisterTabCloseChangeListener(BaseTabCloseListener)
4121: * @see #unregisterTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4122: */
4123: public static void registerTabCloseChangeListener(
4124: JTabbedPane tabbedPane,
4125: BaseTabCloseListener tabCloseListener) {
4126: TabCloseListenerManager.getInstance().registerListener(
4127: tabbedPane, tabCloseListener);
4128: }
4129:
4130: /**
4131: * Unregisters the specified listener on tab-close events on <b>all</b>
4132: * tabbed panes.
4133: *
4134: * @param tabCloseListener
4135: * Listener to unregister.
4136: * @see #registerTabCloseChangeListener(BaseTabCloseListener)
4137: * @see #registerTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4138: * @see #unregisterTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4139: */
4140: public static void unregisterTabCloseChangeListener(
4141: BaseTabCloseListener tabCloseListener) {
4142: TabCloseListenerManager.getInstance().unregisterListener(
4143: tabCloseListener);
4144: }
4145:
4146: /**
4147: * Unregisters the specified listener on tab-close events on <b>the
4148: * specified</b> tabbed pane.
4149: *
4150: * @param tabbedPane
4151: * Tabbed pane. If <code>null</code>, the tab close listener
4152: * is unregistered globally (for all tabbed panes).
4153: * @param tabCloseListener
4154: * Listener to unregister.
4155: * @see #registerTabCloseChangeListener(BaseTabCloseListener)
4156: * @see #registerTabCloseChangeListener(JTabbedPane, BaseTabCloseListener)
4157: * @see #unregisterTabCloseChangeListener(BaseTabCloseListener)
4158: */
4159: public static void unregisterTabCloseChangeListener(
4160: JTabbedPane tabbedPane,
4161: BaseTabCloseListener tabCloseListener) {
4162: TabCloseListenerManager.getInstance().unregisterListener(
4163: tabbedPane, tabCloseListener);
4164: }
4165:
4166: /**
4167: * Returns the set of all listeners registered on tab-close events on <b>all</b>
4168: * tabbed panes.
4169: *
4170: * @return Set of all listeners registered on tab-close events on <b>all</b>
4171: * tabbed panes.
4172: */
4173: public static Set<BaseTabCloseListener> getAllTabCloseListeners() {
4174: return TabCloseListenerManager.getInstance().getListeners();
4175: }
4176:
4177: /**
4178: * Returns all listeners registered on tab closing of the specified tabbed
4179: * pane.
4180: *
4181: * @param tabbedPane
4182: * A tabbed pane. If <code>null</code>, all globally
4183: * registered tab close listeners are returned.
4184: * @return All listeners registered on tab closing of the specified tabbed
4185: * pane.
4186: */
4187: public static Set<BaseTabCloseListener> getAllTabCloseListeners(
4188: JTabbedPane tabbedPane) {
4189: return TabCloseListenerManager.getInstance().getListeners(
4190: tabbedPane);
4191: }
4192:
4193: /**
4194: * Registers a new listener on locale change.
4195: *
4196: * @param localeListener
4197: * New listener on locale change.
4198: */
4199: public static void registerLocaleChangeListener(
4200: LocaleChangeListener localeListener) {
4201: SubstanceLookAndFeel.localeChangeListeners.add(localeListener);
4202: }
4203:
4204: /**
4205: * Unregisters a listener on locale change.
4206: *
4207: * @param localeListener
4208: * The listener to unregister.
4209: */
4210: public static void unregisterLocaleChangeListener(
4211: LocaleChangeListener localeListener) {
4212: SubstanceLookAndFeel.localeChangeListeners
4213: .remove(localeListener);
4214: }
4215:
4216: /**
4217: * Returns all listeners registered on locale change.
4218: *
4219: * @return All listeners registered on locale change.
4220: */
4221: public static Set<LocaleChangeListener> getLocaleListeners() {
4222: return Collections
4223: .unmodifiableSet(SubstanceLookAndFeel.localeChangeListeners);
4224: }
4225:
4226: /**
4227: * Returns indication whether extra UI elements (such as menu items in
4228: * system menu or menu search panel) should be shown.
4229: *
4230: * @return <code>true</code> if extra UI elements (such as menu items in
4231: * system menu or menu search panel) should be shown,
4232: * <code>false</code> otherwise.
4233: */
4234: public static boolean toShowExtraElements() {
4235: if (!SubstanceLookAndFeel.toShowExtraElements)
4236: return false;
4237: return !Boolean.TRUE.equals(UIManager
4238: .get(SubstanceLookAndFeel.NO_EXTRA_ELEMENTS));
4239: }
4240:
4241: /**
4242: * Returns indication whether inverted themes should be enabled.
4243: *
4244: * @return <code>true</code> if inverted themes should be enabled,
4245: * <code>false</code> otherwise.
4246: */
4247: public static boolean toEnableInvertedThemes() {
4248: if (SubstanceLookAndFeel.toEnableInvertedThemes)
4249: return true;
4250: return Boolean.TRUE.equals(UIManager
4251: .get(SubstanceLookAndFeel.ENABLE_INVERTED_THEMES));
4252: }
4253:
4254: /**
4255: * Returns indication whether negated themes should be enabled.
4256: *
4257: * @return <code>true</code> if negated themes should be enabled,
4258: * <code>false</code> otherwise.
4259: */
4260: public static boolean toEnableNegatedThemes() {
4261: if (SubstanceLookAndFeel.toEnableNegatedThemes)
4262: return true;
4263: return Boolean.TRUE.equals(UIManager
4264: .get(SubstanceLookAndFeel.ENABLE_NEGATED_THEMES));
4265: }
4266:
4267: /**
4268: * Returns indication whether the watermark should "bleed" through list,
4269: * table and tree renderers (where possible).
4270: *
4271: * @return <code>true</code> if the watermark should "bleed" through list,
4272: * table and tree renderers (where possible), <code>false</code>
4273: * otherwise.
4274: */
4275: public static boolean toBleedWatermark() {
4276: if (SubstanceLookAndFeel.toBleedWatermark)
4277: return true;
4278: return Boolean.TRUE.equals(UIManager
4279: .get(SubstanceLookAndFeel.WATERMARK_TO_BLEED));
4280: }
4281:
4282: /**
4283: * Returns indication whether the application is in debug UI mode.
4284: *
4285: * @return <code>true</code> if the application is in debug UI mode,
4286: * <code>false</code> otherwise.
4287: * @since version 3.1
4288: */
4289: public static boolean isDebugUiMode() {
4290: if (SubstanceLookAndFeel.isDebugUiMode)
4291: return true;
4292: return Boolean.TRUE.equals(UIManager
4293: .get(SubstanceLookAndFeel.DEBUG_UI_MODE));
4294: }
4295:
4296: /**
4297: * Returns the parameter reader.
4298: *
4299: * @return Parameter reader.
4300: */
4301: public static ParamReader getParamReader() {
4302: return SubstanceLookAndFeel.paramReader;
4303: }
4304:
4305: /**
4306: * Hides menu search panels on all open frames.
4307: *
4308: * @see #showMenuSearchPanels()
4309: */
4310: public static void hideMenuSearchPanels() {
4311: SubstanceMenuBarUI.hideSearchPanels(true);
4312: }
4313:
4314: /**
4315: * Shows menu search panels on all open frames. For each panel, the menu
4316: * search panel will be shown only if the corresponding settings allow it.
4317: *
4318: * @see #hideMenuSearchPanels()
4319: */
4320: public static void showMenuSearchPanels() {
4321: SubstanceMenuBarUI.showSearchPanels();
4322: }
4323:
4324: /**
4325: * Requests that animations be ignored on all instances of the specified
4326: * class.
4327: *
4328: * @param componentClazz
4329: * Component class.
4330: */
4331: public static void ignoreAnimationsOnClass(Class<?> componentClazz) {
4332: SubstanceLookAndFeel.ignoreAnimationsSet.add(componentClazz
4333: .getName());
4334: }
4335:
4336: /**
4337: * Requests that animations be ignored on all instances of the specified
4338: * class.
4339: *
4340: * @param componentClazzName
4341: * Component class name.
4342: */
4343: public static void ignoreAnimationsOnClass(String componentClazzName) {
4344: SubstanceLookAndFeel.ignoreAnimationsSet
4345: .add(componentClazzName);
4346: }
4347:
4348: /**
4349: * Checks whether animations should be ignored on instances of the specified
4350: * class.
4351: *
4352: * @param componentClazz
4353: * Component class.
4354: * @return <code>true</code> if animations should be ignored on instances
4355: * of the specified class, <code>false</code> otherwise.
4356: */
4357: public static boolean toIgnoreAnimation(Class<?> componentClazz) {
4358: return SubstanceLookAndFeel.ignoreAnimationsSet
4359: .contains(componentClazz.getName());
4360: }
4361:
4362: /**
4363: * Makes the heap status panels appear permanently on the specified title
4364: * pane and removes the corresponding check box menu items from the system
4365: * menu. Note that heap status panel can be shown only on custom decorated
4366: * frames / dialogs. Use
4367: * {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} with
4368: * <code>true</code> or -Dsubstancelaf.useDecorations VM flag to run your
4369: * app in custom decoration mode.
4370: *
4371: * @param pane
4372: * The root pane.
4373: * @throws IllegalArgumentException
4374: * if the heap status panel functionality is not available (was
4375: * not enabled).
4376: * @see #permanentlyHideHeapStatusPanel(JRootPane)
4377: * @see #HEAP_STATUS_PANEL
4378: */
4379: public static void permanentlyShowHeapStatusPanel(JRootPane pane) {
4380: if (!SubstanceTitlePane.getCanHaveHeapStatusPanel())
4381: throw new IllegalArgumentException(
4382: "This function can only be called when heap status panel functionality is enabled");
4383: ((SubstanceRootPaneUI) pane.getUI())
4384: .setHeapStatusPanePermanentVisibility(true);
4385: }
4386:
4387: /**
4388: * Makes the heap status panels disappear permanently on the specified title
4389: * pane and removes the corresponding check box menu items from the system
4390: * menu.
4391: *
4392: * @param pane
4393: * The root pane.
4394: * @throws IllegalArgumentException
4395: * if the heap status panel functionality is not available (was
4396: * not enabled).
4397: * @see #permanentlyShowHeapStatusPanel(JRootPane)
4398: * @see #HEAP_STATUS_PANEL
4399: */
4400: public static void permanentlyHideHeapStatusPanel(JRootPane pane) {
4401: if (!SubstanceTitlePane.getCanHaveHeapStatusPanel())
4402: throw new IllegalArgumentException(
4403: "This function can only be called when heap status panel functionality is enabled");
4404: ((SubstanceRootPaneUI) pane.getUI())
4405: .setHeapStatusPanePermanentVisibility(false);
4406: }
4407:
4408: /**
4409: * Sets the global kind for image-based watermarks.
4410: *
4411: * @param kind
4412: * New value for the global kind for image-based watermarks.
4413: * @see #getImageWatermarkKind()
4414: * @see #getImageWatermarkOpacity()
4415: * @see #setImageWatermarkOpacity(float)
4416: * @see #WATERMARK_IMAGE_KIND
4417: * @see #WATERMARK_IMAGE_OPACITY
4418: * @see #WATERMARK_IMAGE_PROPERTY
4419: */
4420: public static void setImageWatermarkKind(ImageWatermarkKind kind) {
4421: SubstanceImageWatermark.setKind(kind);
4422: if (SubstanceLookAndFeel.currentWatermark instanceof SubstanceImageWatermark)
4423: SubstanceLookAndFeel.currentWatermark
4424: .updateWatermarkImage();
4425: }
4426:
4427: /**
4428: * Returns the global kind for image-based watermarks.
4429: *
4430: * @return The global kind for image-based watermarks.
4431: * @see #getImageWatermarkOpacity()
4432: * @see #setImageWatermarkKind(ImageWatermarkKind)
4433: * @see #setImageWatermarkOpacity(float)
4434: * @see #WATERMARK_IMAGE_KIND
4435: * @see #WATERMARK_IMAGE_OPACITY
4436: * @see #WATERMARK_IMAGE_PROPERTY
4437: */
4438: public static ImageWatermarkKind getImageWatermarkKind() {
4439: return SubstanceImageWatermark.getKind();
4440: }
4441:
4442: /**
4443: * Sets the global opacity for image-based watermarks.
4444: *
4445: * @param opacity
4446: * New value for the global opacity for image-based watermarks.
4447: * Should be in 0.0-1.0 range.
4448: * @throws IllegalArgumentException
4449: * If the value is not in 0.0-1.0 range.
4450: * @see #getImageWatermarkKind()
4451: * @see #getImageWatermarkOpacity()
4452: * @see #setImageWatermarkKind(ImageWatermarkKind)
4453: * @see #WATERMARK_IMAGE_KIND
4454: * @see #WATERMARK_IMAGE_OPACITY
4455: * @see #WATERMARK_IMAGE_PROPERTY
4456: */
4457: public static void setImageWatermarkOpacity(float opacity) {
4458: SubstanceImageWatermark.setOpacity(opacity);
4459: if (SubstanceLookAndFeel.currentWatermark instanceof SubstanceImageWatermark)
4460: SubstanceLookAndFeel.currentWatermark
4461: .updateWatermarkImage();
4462: }
4463:
4464: /**
4465: * Returns the global opacity for image-based watermarks.
4466: *
4467: * @return The global opacity for image-based watermarks. The value is in
4468: * 0.0-1.0 range.
4469: * @see #getImageWatermarkKind()
4470: * @see #setImageWatermarkKind(ImageWatermarkKind)
4471: * @see #setImageWatermarkOpacity(float)
4472: * @see #WATERMARK_IMAGE_KIND
4473: * @see #WATERMARK_IMAGE_OPACITY
4474: * @see #WATERMARK_IMAGE_PROPERTY
4475: */
4476: public static float getImageWatermarkOpacity() {
4477: return SubstanceImageWatermark.getOpacity();
4478: }
4479:
4480: /**
4481: * Globally registers a new <code>mixed</code> theme.
4482: *
4483: * @param mixedTheme
4484: * A <code>mixed</code> theme to register.
4485: * @see #addMixedTheme(SubstanceTheme...)
4486: * @see #addMixedThemeBy(SubstanceTheme)
4487: * @see #hasMixedThemes()
4488: * @see #removeMixedTheme(SubstanceMixTheme)
4489: * @see #removeMixedThemeBy(SubstanceTheme)
4490: */
4491: public static void addMixedTheme(SubstanceMixTheme mixedTheme) {
4492: if (SubstanceLookAndFeel.mixedThemes.containsKey(mixedTheme
4493: .getDisplayName()))
4494: return;
4495: SubstanceLookAndFeel.mixedThemes.put(mixedTheme
4496: .getDisplayName(), mixedTheme);
4497: }
4498:
4499: /**
4500: * Globally registers a new <code>mixed</code> theme.
4501: *
4502: * @param themes
4503: * The base themes for the new <code>mixed</code> theme.
4504: * @see #addMixedTheme(SubstanceMixTheme)
4505: * @see #addMixedThemeBy(SubstanceTheme)
4506: * @see #hasMixedThemes()
4507: * @see #removeMixedTheme(SubstanceMixTheme)
4508: * @see #removeMixedThemeBy(SubstanceTheme)
4509: */
4510: public static void addMixedTheme(SubstanceTheme... themes) {
4511: SubstanceLookAndFeel
4512: .addMixedTheme(new SubstanceMixTheme(themes));
4513: }
4514:
4515: /**
4516: * Globally registers a collection of <code>mixed</code> themes such as:
4517: * <ul>
4518: * <li>The specified theme is the main theme for a new <code>mixed</code>
4519: * theme.</li>
4520: * <li>The secondary theme is of the same kind.</li>
4521: * </ul>
4522: *
4523: * @param mainTheme
4524: * The main theme for the new <code>mixed</code> themes.
4525: * @see #addMixedTheme(SubstanceMixTheme)
4526: * @see #addMixedTheme(SubstanceTheme...)
4527: * @see #hasMixedThemes()
4528: * @see #removeMixedTheme(SubstanceMixTheme)
4529: * @see #removeMixedThemeBy(SubstanceTheme)
4530: */
4531: public static void addMixedThemeBy(SubstanceTheme mainTheme) {
4532: ThemeKind mainThemeKind = mainTheme.getKind();
4533: if ((mainThemeKind == ThemeKind.BRIGHT)
4534: || (mainThemeKind == ThemeKind.COLD)) {
4535: for (ThemeInfo themeInfo : SubstanceLookAndFeel
4536: .getAllThemes().values()) {
4537: ThemeKind themeKind = themeInfo.getThemeKind();
4538: if (themeKind != mainTheme.getKind())
4539: continue;
4540: if (themeInfo.getDisplayName().equals(
4541: mainTheme.getDisplayName()))
4542: continue;
4543:
4544: try {
4545: Class<?> themeClass = Class.forName(themeInfo
4546: .getClassName());
4547: if (themeClass == null) {
4548: continue;
4549: }
4550: Object obj = themeClass.newInstance();
4551: if (obj == null) {
4552: continue;
4553: }
4554: if (!(obj instanceof SubstanceTheme)) {
4555: continue;
4556: }
4557: SubstanceLookAndFeel
4558: .addMixedTheme(new SubstanceMixTheme(
4559: mainTheme, (SubstanceTheme) obj));
4560: } catch (Exception exc) {
4561: }
4562: }
4563: }
4564: }
4565:
4566: /**
4567: * Globally unregisters the specified <code>mixed</code> theme.
4568: *
4569: * @param mixedTheme
4570: * The <code>mixed</code> theme to unregister.
4571: * @see #addMixedTheme(SubstanceMixTheme)
4572: * @see #addMixedTheme(SubstanceTheme...)
4573: * @see #addMixedThemeBy(SubstanceTheme)
4574: * @see #hasMixedThemes()
4575: * @see #removeMixedThemeBy(SubstanceTheme)
4576: */
4577: public static void removeMixedTheme(SubstanceMixTheme mixedTheme) {
4578: SubstanceLookAndFeel.mixedThemes.remove(mixedTheme
4579: .getDisplayName());
4580: }
4581:
4582: /**
4583: * Globally unregisters a collection of <code>mixed</code> themes such
4584: * that the specified theme is the main theme.
4585: *
4586: * @param mainTheme
4587: * The main theme for the <code>mixed</code> themes to be
4588: * unregistered.
4589: * @see #addMixedTheme(SubstanceMixTheme)
4590: * @see #addMixedTheme(SubstanceTheme...)
4591: * @see #addMixedThemeBy(SubstanceTheme)
4592: * @see #hasMixedThemes()
4593: * @see #removeMixedTheme(SubstanceMixTheme)
4594: */
4595: public static void removeMixedThemeBy(SubstanceTheme mainTheme) {
4596: for (Iterator<Map.Entry<String, SubstanceMixTheme>> it = SubstanceLookAndFeel.mixedThemes
4597: .entrySet().iterator(); it.hasNext();) {
4598: Map.Entry<String, SubstanceMixTheme> entry = it.next();
4599: if (entry.getValue().getOriginalThemes()[0]
4600: .getDisplayName()
4601: .equals(mainTheme.getDisplayName()))
4602: it.remove();
4603: }
4604: }
4605:
4606: /**
4607: * Checks whether there are any <code>mixed</code> themes registered
4608: * globally.
4609: *
4610: * @return <code>true</code> if there is at least one <code>mixed</code>
4611: * theme registered globally, <code>false</code> otherwise.
4612: * @see #addMixedTheme(SubstanceMixTheme)
4613: * @see #addMixedTheme(SubstanceTheme...)
4614: * @see #addMixedThemeBy(SubstanceTheme)
4615: * @see #removeMixedTheme(SubstanceMixTheme)
4616: * @see #removeMixedThemeBy(SubstanceTheme)
4617: */
4618: public static boolean hasMixedThemes() {
4619: return SubstanceLookAndFeel.mixedThemes.size() > 0;
4620: }
4621:
4622: /**
4623: * Checks whether the <code>JOptionPane</code>s created with predefined
4624: * message types should use constant themes for the icons.
4625: *
4626: * @return <code>true</code> if the <code>JOptionPane</code>s created
4627: * with predefined message types should use constant themes for the
4628: * icons, <code>false</code> otherwise.
4629: * @see #setToUseConstantThemesOnDialogs(boolean)
4630: */
4631: public static boolean isToUseConstantThemesOnDialogs() {
4632: return SubstanceLookAndFeel.toUseConstantThemesOnDialogs;
4633: }
4634:
4635: /**
4636: * Sets the new setting for the icons of the <code>JOptionPane</code>s
4637: * created with predefined message types.
4638: *
4639: * @param toUseConstantThemesOnDialogs
4640: * if <code>true</code>, the <code>JOptionPane</code>s
4641: * created with predefined message types should use constant
4642: * themes for the icons.
4643: * @see #isToUseConstantThemesOnDialogs()
4644: */
4645: public static void setToUseConstantThemesOnDialogs(
4646: boolean toUseConstantThemesOnDialogs) {
4647: SubstanceLookAndFeel.toUseConstantThemesOnDialogs = toUseConstantThemesOnDialogs;
4648: }
4649:
4650: /**
4651: * Sets the specified skin.
4652: *
4653: * @param skin
4654: * Skin to set.
4655: * @return <code>true</code> if the specified skin has been set
4656: * successfully, <code>false</code> otherwise.
4657: * @since version 3.1
4658: * @see #setSkin(SubstanceSkin)
4659: * @see #registerSkinChangeListener(SkinChangeListener)
4660: * @see #unregisterSkinChangeListener(SkinChangeListener)
4661: */
4662: public static boolean setSkin(SubstanceSkin skin) {
4663: try {
4664: if (!(UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel)) {
4665: UIManager.setLookAndFeel(new SubstanceLookAndFeel());
4666: }
4667: if (!skin.set())
4668: return false;
4669: SwingUtilities.invokeLater(new Runnable() {
4670: public void run() {
4671: for (Frame frame : Frame.getFrames()) {
4672: SwingUtilities.updateComponentTreeUI(frame);
4673: for (Window window : frame.getOwnedWindows()) {
4674: SwingUtilities
4675: .updateComponentTreeUI(window);
4676: }
4677: }
4678:
4679: for (SkinChangeListener skinChangeListener : SubstanceLookAndFeel.skinChangeListeners)
4680: skinChangeListener.skinChanged();
4681: }
4682: });
4683: return true;
4684: } catch (NoClassDefFoundError ncdfe) {
4685: // this may happen when a skin references some class
4686: // that can't be found in the classpath.
4687: return false;
4688: } catch (Exception e) {
4689: return false;
4690: }
4691: }
4692:
4693: /**
4694: * Sets the specified skin.
4695: *
4696: * @param skinClassName
4697: * Skin to set.
4698: * @return <code>true</code> if the specified skin has been set
4699: * successfully, <code>false</code> otherwise.
4700: * @since version 3.1
4701: * @see #setSkin(SubstanceSkin)
4702: * @see #registerSkinChangeListener(SkinChangeListener)
4703: * @see #unregisterSkinChangeListener(SkinChangeListener)
4704: */
4705: public static boolean setSkin(String skinClassName) {
4706: try {
4707: Class<?> skinClass = Class.forName(skinClassName);
4708: if (skinClass == null) {
4709: return false;
4710: }
4711: Object obj = skinClass.newInstance();
4712: if (obj == null) {
4713: return false;
4714: }
4715: if (!(obj instanceof SubstanceSkin)) {
4716: return false;
4717: }
4718: return SubstanceLookAndFeel.setSkin((SubstanceSkin) obj);
4719: } catch (Exception exc) {
4720: return false;
4721: }
4722: }
4723:
4724: /**
4725: * Returns all available skins.
4726: *
4727: * @return All available skins. Key - skin display name, value - skin
4728: * information.
4729: */
4730: public static Map<String, SkinInfo> getAllSkins() {
4731: Map<String, SkinInfo> result = new TreeMap<String, SkinInfo>();
4732: for (Object skinPlugin : SubstanceLookAndFeel.skinPlugins
4733: .getAvailablePlugins(true)) {
4734: for (SkinInfo skinInfo : ((SubstanceSkinPlugin) skinPlugin)
4735: .getSkins()) {
4736: result.put(skinInfo.getDisplayName(), skinInfo);
4737: }
4738: }
4739: return result;
4740: }
4741:
4742: /*
4743: * (non-Javadoc)
4744: *
4745: * @see javax.swing.LookAndFeel#getSupportsWindowDecorations()
4746: */
4747: @Override
4748: public boolean getSupportsWindowDecorations() {
4749: return true;
4750: }
4751:
4752: /**
4753: * Sets the class loader for {@link #LABEL_BUNDLE}.
4754: *
4755: * @param labelBundleClassLoader
4756: * Class loader for {@link #LABEL_BUNDLE}.
4757: * @since version 3.1
4758: */
4759: public static void setLabelBundleClassLoader(
4760: ClassLoader labelBundleClassLoader) {
4761: SubstanceLookAndFeel.labelBundleClassLoader = labelBundleClassLoader;
4762: LafWidgetRepository
4763: .setLabelBundleClassLoader(labelBundleClassLoader);
4764: }
4765:
4766: /**
4767: * Returns the title pane of the specified top-level window.
4768: *
4769: * @param window
4770: * Top-level window.
4771: * @return If the parameter is either {@link JFrame} or {@link JDialog} and
4772: * has custom decorations, the result is the title pane,
4773: * <code>null</code> otherwise.
4774: * @since version 3.1
4775: */
4776: public static JComponent getTitlePaneComponent(Window window) {
4777: JRootPane rootPane = null;
4778: if (window instanceof JFrame) {
4779: JFrame f = (JFrame) window;
4780: rootPane = f.getRootPane();
4781: }
4782: if (window instanceof JDialog) {
4783: JDialog d = (JDialog) window;
4784: rootPane = d.getRootPane();
4785: }
4786: if (rootPane != null) {
4787: SubstanceRootPaneUI ui = (SubstanceRootPaneUI) rootPane
4788: .getUI();
4789: return ui.getTitlePane();
4790: }
4791: return null;
4792: }
4793:
4794: /**
4795: * Specifies that a control of some class should use the specified
4796: * background composite when it (the control) doesn't define the
4797: * {@link #BACKGROUND_COMPOSITE} client property.
4798: *
4799: * @param clazz
4800: * Component class.
4801: * @param composite
4802: * Default background composite for controls of the specified
4803: * class.
4804: */
4805: public static synchronized void setBackgroundComposite(
4806: Class<?> clazz, ControlBackgroundComposite composite) {
4807: backgroundComposites.put(clazz, composite);
4808: }
4809:
4810: /**
4811: * Returns the default background composite for the specified component.
4812: *
4813: * @param component
4814: * Component.
4815: * @return The default background composite for the specified component.
4816: */
4817: public static synchronized ControlBackgroundComposite getBackgroundComposite(
4818: Component component) {
4819: ControlBackgroundComposite result = backgroundComposites
4820: .get(component.getClass());
4821: if (result == null)
4822: result = new DefaultControlBackgroundComposite();
4823: return result;
4824: }
4825:
4826: public static void setDecorationType(JComponent comp,
4827: DecorationAreaType type) {
4828: SubstanceDecorationUtilities.setDecorationType(comp, type);
4829: }
4830: }
|