Source Code Cross Referenced for SubstanceLookAndFeel.java in  » Swing-Library » substance-look-feel » org » jvnet » substance » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » substance look feel » org.jvnet.substance 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;Boolean.TRUE);<br>
0506:             * JPanel panel1 = new JPanel();<br>
0507:             * JPanel panel2 = new JPanel();<br>
0508:             * panel2.putClientProperty(SubstanceLookAndFeel.WATERMARK_IGNORE, <br>
0509:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;"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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;"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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;"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:             * &nbsp;&nbsp;"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:             * &nbsp;&nbsp;public Changer() {<br>
1092:             * &nbsp;&nbsp;&nbsp;&nbsp;super("Changer");<br>
1093:             * <br>
1094:             * &nbsp;&nbsp;&nbsp;&nbsp;this.setLayout(new BorderLayout());<br>
1095:             * &nbsp;&nbsp;&nbsp;&nbsp;JTextPane textArea = new JTextPane();<br>
1096:             * &nbsp;&nbsp;&nbsp;&nbsp;this.add(textArea, BorderLayout.CENTER);<br>
1097:             * &nbsp;&nbsp;&nbsp;&nbsp;textArea.getDocument().addDocumentListener(new
1098:             * DocumentListener() {<br>
1099:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private void handleChange() {<br>
1100:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getRootPane().putClientProperty(<br>
1101:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SubstanceLookAndFeel.WINDOW_MODIFIED,
1102:             * Boolean.TRUE);<br>
1103:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1104:             * <br>
1105:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void
1106:             * changedUpdate(DocumentEvent e) {<br>
1107:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleChange();<br>
1108:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1109:             * <br>
1110:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void
1111:             * insertUpdate(DocumentEvent e) {<br>
1112:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleChange();<br>
1113:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1114:             * <br>
1115:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void
1116:             * removeUpdate(DocumentEvent e) {<br>
1117:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleChange();<br>
1118:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1119:             * &nbsp;&nbsp;&nbsp;&nbsp;});<br>
1120:             * &nbsp;&nbsp;&nbsp;&nbsp;<br>
1121:             * &nbsp;&nbsp;&nbsp;&nbsp;JPanel buttons = new JPanel(new
1122:             * FlowLayout(FlowLayout.RIGHT));<br>
1123:             * &nbsp;&nbsp;&nbsp;&nbsp;JButton saveButton = new JButton("Save");<br>
1124:             * &nbsp;&nbsp;&nbsp;&nbsp;saveButton.addActionListener(new ActionListener() {<br>
1125:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void
1126:             * actionPerformed(ActionEvent e) {<br>
1127:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getRootPane().putClientProperty(<br>
1128:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SubstanceLookAndFeel.WINDOW_MODIFIED,
1129:             * Boolean.FALSE);<br>
1130:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1131:             * &nbsp;&nbsp;&nbsp;&nbsp;});<br>
1132:             * &nbsp;&nbsp;&nbsp;&nbsp;<br>
1133:             * &nbsp;&nbsp;&nbsp;&nbsp;buttons.add(saveButton);<br>
1134:             * &nbsp;&nbsp;&nbsp;&nbsp;this.add(buttons, BorderLayout.SOUTH);<br>
1135:             * &nbsp;&nbsp;&nbsp;&nbsp;<br>
1136:             * &nbsp;&nbsp;&nbsp;&nbsp;this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br>
1137:             * &nbsp;&nbsp;}<br>
1138:             * <br>
1139:             * &nbsp;&nbsp;public static void main(String ... args) {<br>
1140:             * &nbsp;&nbsp;&nbsp;&nbsp;try {<br>
1141:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UIManager.setLookAndFeel(new
1142:             * SubstanceLookAndFeel());<br>
1143:             * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
1144:             * &nbsp;&nbsp;&nbsp;&nbsp;catch (Exception exc) {}<br>
1145:             * &nbsp;&nbsp;&nbsp;&nbsp;JFrame.setDefaultLookAndFeelDecorated(true);<br>
1146:             * &nbsp;&nbsp;&nbsp;&nbsp;Changer ch = new Changer();<br>
1147:             * &nbsp;&nbsp;&nbsp;&nbsp;ch.setPreferredSize(new Dimension(200, 200));<br>
1148:             * &nbsp;&nbsp;&nbsp;&nbsp;ch.setSize(ch.getPreferredSize());<br>
1149:             * &nbsp;&nbsp;&nbsp;&nbsp;ch.setLocationRelativeTo(null);<br>
1150:             * &nbsp;&nbsp;&nbsp;&nbsp;ch.setVisible(true);<br>
1151:             * &nbsp;&nbsp;}<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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;public TabCloseKind onAreaClick(JTabbedPane tabbedPane,<br>
1410:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int tabIndex, MouseEvent mouseEvent) {<br>
1411:             * &nbsp;&nbsp;&nbsp;&nbsp;if (mouseEvent.getButton() != MouseEvent.BUTTON3)<br>
1412:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.NONE;<br>
1413:             * &nbsp;&nbsp;&nbsp;&nbsp;if (mouseEvent.isShiftDown()) {<br>
1414:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.ALL;<br>
1415:             * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
1416:             * &nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.THIS;<br>
1417:             * &nbsp;&nbsp;}<br>
1418:             * <br>
1419:             * &nbsp;&nbsp;public TabCloseKind onCloseButtonClick(JTabbedPane tabbedPane,<br>
1420:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int tabIndex, MouseEvent mouseEvent) {<br>
1421:             * &nbsp;&nbsp;&nbsp;&nbsp;if (mouseEvent.isAltDown()) {<br>
1422:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.ALL_BUT_THIS;<br>
1423:             * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
1424:             * &nbsp;&nbsp;&nbsp;&nbsp;if (mouseEvent.isShiftDown()) {<br>
1425:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.ALL;<br>
1426:             * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
1427:             * &nbsp;&nbsp;&nbsp;&nbsp;return TabCloseKind.THIS;<br>
1428:             * &nbsp;&nbsp;}<br>
1429:             * <br>
1430:             * &nbsp;&nbsp;public String getAreaTooltip(JTabbedPane tabbedPane, int tabIndex) {<br>
1431:             * &nbsp;&nbsp;&nbsp;&nbsp;return null;<br>
1432:             * &nbsp;&nbsp;}<br>
1433:             * <br>
1434:             * &nbsp;&nbsp;public String getCloseButtonTooltip(JTabbedPane tabbedPane,<br>
1435:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int tabIndex) {<br>
1436:             * &nbsp;&nbsp;&nbsp;&nbsp;StringBuffer result = new StringBuffer();<br>
1437:             * &nbsp;&nbsp;&nbsp;&nbsp;result.append("&lt;html&gt;&lt;body&gt;");<br>
1438:             * &nbsp;&nbsp;&nbsp;&nbsp;result.append("Mouse click closes &lt;b&gt;"<br>
1439:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ tabbedPane.getTitleAt(tabIndex) + "&lt;/b&gt; tab");<br>
1440:             * &nbsp;&nbsp;&nbsp;&nbsp;result.append("&lt;br&gt;&lt;b&gt;Alt&lt;/b&gt;-Mouse click closes all tabs but &lt;b&gt;"<br>
1441:             * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ tabbedPane.getTitleAt(tabIndex) + "&lt;/b&gt; tab");<br>
1442:             * &nbsp;&nbsp;&nbsp;&nbsp;result.append("&lt;br&gt;&lt;b&gt;Shift&lt;/b&gt;-Mouse click closes all tabs");<br>
1443:             * &nbsp;&nbsp;&nbsp;&nbsp;result.append("&lt;/body&gt;&lt;/html&gt;");<br>
1444:             * &nbsp;&nbsp;&nbsp;&nbsp;return result.toString();<br>
1445:             * &nbsp;&nbsp;}<br>
1446:             * };<br>
1447:             *
1448:             * JTabbedPane jtp = new JTabbedPane();<br>
1449:             * jtp.putClientProperty(<br>
1450:             * &nbsp;&nbsp;&nbsp;&nbsp;SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK, <br>
1451:             * &nbsp;&nbsp;&nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });<br>
1550:             * cb.putClientProperty(SubstanceLookAndFeel.COMBO_BOX_POPUP_FLYOUT_ORIENTATION, <br>
1551:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;JPanel topPanel = new JPanel();<br>
1650:             * &nbsp;&nbsp;topPanel.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.UNDERLINE);<br>
1651:             * &nbsp;&nbsp;JPanel panel1 = new JPanel();<br>
1652:             * &nbsp;&nbsp;JButton b1 = new JButton("button1");<br>
1653:             * &nbsp;&nbsp;b1.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.TEXT);<br>
1654:             * &nbsp;&nbsp;JButton b2 = new JButton("button2");<br>
1655:             * &nbsp;&nbsp;JButton b3 = new JButton("button3");<br>
1656:             * &nbsp;&nbsp;b3.putClientProperty(SubstanceLookAndFeel.FOCUS_KIND, FocusKind.ALL_INNER);<br>
1657:             * &nbsp;&nbsp;panel1.add(b1);<br>
1658:             * &nbsp;&nbsp;panel1.add(b2);<br>
1659:             * &nbsp;&nbsp;topPanel.add(panel1);<br>
1660:             * &nbsp;&nbsp;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:             *	&nbsp;&nbsp;"aaaaaaaaaa", "this one is the one", "aaaaaaaaaaaaaaaaaaaaa" });<br>
1707:             *	comboProto1.setPrototypeDisplayValue("aaaaa");<br>
1708:             *	comboProto1.putClientProperty(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE,<br>
1709:             *	&nbsp;&nbsp;"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:             *	&nbsp;&nbsp;"this is not", "this one is not it",<br>
1719:             *	&nbsp;&nbsp;"this one is it that is for the popup" });<br>
1720:             *	comboProto3.setPrototypeDisplayValue("aaaaa");<br>
1721:             *	comboProto3.putClientProperty(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE,<br>
1722:             *	&nbsp;&nbsp;new ComboPopupPrototypeCallback() {<br>
1723:             *	&nbsp;&nbsp;&nbsp;&nbsp;public Object getPopupPrototypeDisplayValue(JComboBox jc) {<br>
1724:             *	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return jc.getModel().getElementAt(<br>
1725:             *	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jc.getModel().getSize() - 1);<br>
1726:             *	&nbsp;&nbsp;&nbsp;&nbsp;}<br>
1727:             *	&nbsp;&nbsp;});
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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:            // * &nbsp;&nbsp;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:            // * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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:             * &nbsp;&nbsp;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&amp;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:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.