Source Code Cross Referenced for SubstanceCoreUtilities.java in  » Swing-Library » substance-look-feel » org » jvnet » substance » utils » 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.utils 
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.utils;
0031:
0032:        import java.awt.*;
0033:        import java.awt.event.ActionListener;
0034:        import java.awt.event.MouseEvent;
0035:        import java.awt.image.*;
0036:        import java.net.URL;
0037:        import java.util.*;
0038:
0039:        import javax.swing.*;
0040:        import javax.swing.border.Border;
0041:        import javax.swing.border.CompoundBorder;
0042:        import javax.swing.plaf.*;
0043:        import javax.swing.text.*;
0044:
0045:        import org.jvnet.lafwidget.*;
0046:        import org.jvnet.lafwidget.animation.*;
0047:        import org.jvnet.lafwidget.layout.TransitionLayout;
0048:        import org.jvnet.substance.*;
0049:        import org.jvnet.substance.border.SubstanceBorderPainter;
0050:        import org.jvnet.substance.button.BaseButtonShaper;
0051:        import org.jvnet.substance.button.SubstanceButtonShaper;
0052:        import org.jvnet.substance.color.*;
0053:        import org.jvnet.substance.combo.ComboPopupPrototypeCallback;
0054:        import org.jvnet.substance.combo.SubstanceComboBoxButton;
0055:        import org.jvnet.substance.painter.ControlBackgroundComposite;
0056:        import org.jvnet.substance.painter.SubstanceGradientPainter;
0057:        import org.jvnet.substance.painter.decoration.*;
0058:        import org.jvnet.substance.painter.text.SubstanceTextPainter;
0059:        import org.jvnet.substance.scroll.SubstanceScrollButton;
0060:        import org.jvnet.substance.skin.AutumnSkin;
0061:        import org.jvnet.substance.skin.MagmaSkin;
0062:        import org.jvnet.substance.tabbed.TabCloseCallback;
0063:        import org.jvnet.substance.theme.*;
0064:        import org.jvnet.substance.theme.SubstanceTheme.ThemeKind;
0065:        import org.jvnet.substance.utils.SubstanceConstants.*;
0066:        import org.jvnet.substance.utils.icon.SubstanceIconFactory;
0067:        import org.jvnet.substance.utils.icon.TransitionAwareIcon;
0068:
0069:        /**
0070:         * Various utility functions. This class is <b>for internal use only</b>.
0071:         * 
0072:         * @author Kirill Grouchnikov
0073:         * @author Romain Guy
0074:         */
0075:        public class SubstanceCoreUtilities {
0076:            /**
0077:             * Client property name for the previous component state. The client
0078:             * property value should be an instance of {@link ComponentState}.
0079:             */
0080:            private static final String PREV_COMPONENT_STATE = "substancelaf.internal.prevComponentState";
0081:
0082:            /**
0083:             * Client property name for the previous component state. The client
0084:             * property value should be an instance of {@link ComponentState}.
0085:             */
0086:            private static final String PREV_SEL_COMPONENT_STATE = "substancelaf.internal.prevSelComponentState";
0087:
0088:            /**
0089:             * Client property name for the next component state. The client property
0090:             * value should be an instance of {@link ComponentState}.
0091:             */
0092:            private static final String NEXT_COMPONENT_STATE = "substancelaf.internal.nextComponentState";
0093:
0094:            /**
0095:             * Client property name for the next component state. The client property
0096:             * value should be an instance of {@link ComponentState}.
0097:             */
0098:            private static final String NEXT_SEL_COMPONENT_STATE = "substancelaf.internal.nextSelComponentState";
0099:
0100:            /**
0101:             * Client property name to mark a component as skipping the background fill
0102:             * during the painting sequence that involves text painters.
0103:             */
0104:            public static final String DO_NOT_FILL_BACKGROUND = "substancelaf.internal.textPainter.doNotFillBackground";
0105:
0106:            public static final String HAS_CUSTOM_BACKGROUND_FILL = "substancelaf.internal.textPainter.hasCustomBackgroundFill";
0107:
0108:            public static final String IS_COVERED_BY_LIGHTWEIGHT_POPUPS = "substancelaf.internal.paint.isCoveredByLightweightPopups";
0109:
0110:            // public static final String IS_WINDOW_DECORATION_AREA =
0111:            // "substancelaf.internal.headerPainter.isDecorationArea";
0112:
0113:            /**
0114:             * Private constructor. Is here to enforce using static methods only.
0115:             */
0116:            private SubstanceCoreUtilities() {
0117:            }
0118:
0119:            /**
0120:             * Clips string based on specified font metrics and available width (in
0121:             * pixels). Returns the clipped string, which contains the beginning and the
0122:             * end of the input string separated by ellipses (...) in case the string is
0123:             * too long to fit into the specified width, and the origianl string
0124:             * otherwise.
0125:             * 
0126:             * @param metrics
0127:             *            Font metrics.
0128:             * @param availableWidth
0129:             *            Available width in pixels.
0130:             * @param fullText
0131:             *            String to clip.
0132:             * @return The clipped string, which contains the beginning and the end of
0133:             *         the input string separated by ellipses (...) in case the string
0134:             *         is too long to fit into the specified width, and the origianl
0135:             *         string otherwise.
0136:             */
0137:            public static String clipString(FontMetrics metrics,
0138:                    int availableWidth, String fullText) {
0139:
0140:                if (metrics.stringWidth(fullText) <= availableWidth)
0141:                    return fullText;
0142:
0143:                String ellipses = "...";
0144:                int ellipsesWidth = metrics.stringWidth(ellipses);
0145:                if (ellipsesWidth > availableWidth)
0146:                    return "";
0147:
0148:                String starter = "";
0149:                String ender = "";
0150:
0151:                int w = fullText.length();
0152:                int w2 = (w / 2) + (w % 2);
0153:                String prevTitle = "";
0154:                for (int i = 0; i < w2; i++) {
0155:                    String newStarter = starter + fullText.charAt(i);
0156:                    String newEnder = ender;
0157:                    if ((w - i) > w2)
0158:                        newEnder = fullText.charAt(w - i - 1) + newEnder;
0159:                    String newTitle = newStarter + ellipses + newEnder;
0160:                    if (metrics.stringWidth(newTitle) <= availableWidth) {
0161:                        starter = newStarter;
0162:                        ender = newEnder;
0163:                        prevTitle = newTitle;
0164:                        continue;
0165:                    }
0166:                    return prevTitle;
0167:                }
0168:                return fullText;
0169:            }
0170:
0171:            /**
0172:             * Checks whether the specified button has associated icon.
0173:             * 
0174:             * @param button
0175:             *            Button.
0176:             * @return If the button has associated icon, <code>true</code> is
0177:             *         returned, otherwise <code>false</code>.
0178:             */
0179:            public static boolean hasIcon(AbstractButton button) {
0180:                return (button.getIcon() != null);
0181:            }
0182:
0183:            /**
0184:             * Checks whether the specified button has associated text.
0185:             * 
0186:             * @param button
0187:             *            Button.
0188:             * @return If the button has associated text, <code>true</code> is
0189:             *         returned, otherwise <code>false</code>.
0190:             */
0191:            public static boolean hasText(AbstractButton button) {
0192:                String text = button.getText();
0193:                if ((text != null) && (text.length() > 0)) {
0194:                    return true;
0195:                }
0196:                return false;
0197:            }
0198:
0199:            /**
0200:             * Checks and answers if the specified button is in a combo box.
0201:             * 
0202:             * @param button
0203:             *            the button to check
0204:             * @return <code>true</code> if in combo box, <code>false</code>
0205:             *         otherwise
0206:             */
0207:            public static boolean isComboBoxButton(AbstractButton button) {
0208:                Container parent = button.getParent();
0209:                return (parent != null)
0210:                        && ((parent instanceof  JComboBox) || (parent
0211:                                .getParent() instanceof  JComboBox));
0212:            }
0213:
0214:            /**
0215:             * Checks and answers if the specified button is in a scroll bar.
0216:             * 
0217:             * @param button
0218:             *            the button to check
0219:             * @return <code>true</code> if in scroll bar, <code>false</code>
0220:             *         otherwise
0221:             */
0222:            public static boolean isScrollBarButton(AbstractButton button) {
0223:                Container parent = button.getParent();
0224:                return (parent != null)
0225:                        && ((parent instanceof  JScrollBar) || (parent
0226:                                .getParent() instanceof  JScrollBar));
0227:            }
0228:
0229:            /**
0230:             * Checks and answers if the specified button is in a spinner.
0231:             * 
0232:             * @param button
0233:             *            the button to check
0234:             * @return <code>true</code> if in spinner, <code>false</code> otherwise
0235:             */
0236:            public static boolean isSpinnerButton(AbstractButton button) {
0237:                Container parent = button.getParent();
0238:                if (!(button instanceof  SubstanceSpinnerButton))
0239:                    return false;
0240:                return (parent != null)
0241:                        && ((parent instanceof  JSpinner) || (parent.getParent() instanceof  JSpinner));
0242:            }
0243:
0244:            /**
0245:             * Checks and answers if the specified button is in a toolbar.
0246:             * 
0247:             * @param button
0248:             *            the button to check
0249:             * @return <code>true</code> if in toolbar, <code>false</code> otherwise
0250:             */
0251:            public static boolean isToolBarButton(AbstractButton button) {
0252:                if (button instanceof  SubstanceComboBoxButton)
0253:                    return false;
0254:                if (button instanceof  SubstanceSpinnerButton)
0255:                    return false;
0256:                Container parent = button.getParent();
0257:                return (parent != null)
0258:                        && ((parent instanceof  JToolBar) || (parent.getParent() instanceof  JToolBar));
0259:            }
0260:
0261:            /**
0262:             * Checks answers if the specified component is a button in a scroll
0263:             * control, such as scroll bar or tabbed pane (as tab scroller).
0264:             * 
0265:             * @param comp
0266:             *            The component to check
0267:             * @return <code>true</code> if the specified component is a button in a
0268:             *         scroll control, <code>false</code> otherwise
0269:             */
0270:            public static boolean isScrollButton(JComponent comp) {
0271:                return (comp instanceof  SubstanceScrollButton);
0272:            }
0273:
0274:            /**
0275:             * Checks whether the specified control is always painted in currently
0276:             * active color (ignoring the transition states that normally result in
0277:             * default appearance).
0278:             * 
0279:             * @param comp
0280:             *            Control.
0281:             * @return <code>true</code> if the specified control is always painted in
0282:             *         currently active color (ignoring the transition states that
0283:             *         normally result in default appearance), <code>false</code>
0284:             *         otherwise.
0285:             */
0286:            public static boolean isControlAlwaysPaintedActive(Component comp) {
0287:                return isControlAlwaysPaintedActive(comp, false);
0288:            }
0289:
0290:            /**
0291:             * Checks whether the specified control is always painted in currently
0292:             * active color (ignoring the transition states that normally result in
0293:             * default appearance).
0294:             * 
0295:             * @param comp
0296:             *            Control.
0297:             * @param checkHierarchy
0298:             *            If <code>true</code>, the entire component hierarchy will
0299:             *            be scanned for the
0300:             *            {@link SubstanceLookAndFeel#PAINT_ACTIVE_PROPERTY}.
0301:             * @return <code>true</code> if the specified control is always painted in
0302:             *         currently active color (ignoring the transition states that
0303:             *         normally result in default appearance), <code>false</code>
0304:             *         otherwise.
0305:             */
0306:            public static boolean isControlAlwaysPaintedActive(Component comp,
0307:                    boolean checkHierarchy) {
0308:                if (!checkHierarchy) {
0309:                    if (comp instanceof  JComponent) {
0310:                        JComponent jcomp = (JComponent) comp;
0311:                        Object componentProp = jcomp
0312:                                .getClientProperty(SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY);
0313:                        if (componentProp != null) {
0314:                            if (Boolean.TRUE.equals(componentProp))
0315:                                return true;
0316:                            if (Boolean.FALSE.equals(componentProp))
0317:                                return false;
0318:                        }
0319:                    }
0320:                } else {
0321:                    Component c = comp;
0322:                    while (c != null) {
0323:                        if (c instanceof  JComponent) {
0324:                            JComponent jcomp = (JComponent) c;
0325:                            Object componentProp = jcomp
0326:                                    .getClientProperty(SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY);
0327:                            if (componentProp != null) {
0328:                                if (Boolean.TRUE.equals(componentProp))
0329:                                    return true;
0330:                                if (Boolean.FALSE.equals(componentProp))
0331:                                    return false;
0332:                            }
0333:                        }
0334:                        c = c.getParent();
0335:                    }
0336:                }
0337:                return Boolean.TRUE.equals(UIManager
0338:                        .get(SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY));
0339:            }
0340:
0341:            /**
0342:             * Checks whether the specified button never paints its background.
0343:             * 
0344:             * @param button
0345:             *            Button.
0346:             * @return <code>true</code> if the specified button never paints its
0347:             *         background, <code>false</code> otherwise.
0348:             */
0349:            public static boolean isButtonNeverPainted(AbstractButton button) {
0350:                Component c = button;
0351:                while (c != null) {
0352:                    if (c instanceof  JComponent) {
0353:                        JComponent jc = (JComponent) c;
0354:                        Object prop = jc
0355:                                .getClientProperty(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY);
0356:                        if (prop != null) {
0357:                            if (Boolean.TRUE.equals(prop))
0358:                                return true;
0359:                            if (Boolean.FALSE.equals(prop))
0360:                                return false;
0361:                        }
0362:                    }
0363:                    c = c.getParent();
0364:                }
0365:
0366:                return Boolean.TRUE.equals(UIManager
0367:                        .get(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY));
0368:            }
0369:
0370:            /**
0371:             * Returns the focus ring kind of the specified component.
0372:             * 
0373:             * @param component
0374:             *            Component.
0375:             * @return The focus ring kind of the specified component.
0376:             */
0377:            public static FocusKind getFocusKind(Component component) {
0378:                while (component != null) {
0379:                    if (component instanceof  JComponent) {
0380:                        JComponent jcomp = (JComponent) component;
0381:                        Object jcompFocusKind = jcomp
0382:                                .getClientProperty(SubstanceLookAndFeel.FOCUS_KIND);
0383:                        if (jcompFocusKind instanceof  FocusKind)
0384:                            return (FocusKind) jcompFocusKind;
0385:                    }
0386:                    component = component.getParent();
0387:                }
0388:                Object globalFocusKind = UIManager
0389:                        .get(SubstanceLookAndFeel.FOCUS_KIND);
0390:                if (globalFocusKind instanceof  FocusKind)
0391:                    return (FocusKind) globalFocusKind;
0392:                return FocusKind.ALL_INNER;
0393:            }
0394:
0395:            /**
0396:             * Returns the text alignment kind of the specified tabbed pane.
0397:             * 
0398:             * @param tabPane
0399:             *            Tabbed pane.
0400:             * @return The text alignment kind of the specified tabbed pane.
0401:             */
0402:            public static TabTextAlignmentKind getTabTextAlignmentKind(
0403:                    JTabbedPane tabPane) {
0404:                Object jcompAlignmentKind = tabPane
0405:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_TEXT_ALIGNMENT_KIND);
0406:                if (jcompAlignmentKind instanceof  TabTextAlignmentKind)
0407:                    return (TabTextAlignmentKind) jcompAlignmentKind;
0408:
0409:                Object globalAlignmentKind = UIManager
0410:                        .get(SubstanceLookAndFeel.TABBED_PANE_TEXT_ALIGNMENT_KIND);
0411:                if (globalAlignmentKind instanceof  TabTextAlignmentKind)
0412:                    return (TabTextAlignmentKind) globalAlignmentKind;
0413:                return TabTextAlignmentKind.DEFAULT;
0414:            }
0415:
0416:            /**
0417:             * Returns indication whether the watermark should be drawn on the specified
0418:             * component.
0419:             * 
0420:             * @param component
0421:             *            Component.
0422:             * @return <code>true</code> if the watermark should be drawn on the
0423:             *         specified component, <code>false</code> otherwise.
0424:             */
0425:            public static boolean toDrawWatermark(Component component) {
0426:                Component c = component;
0427:                while (c != null) {
0428:                    if (c instanceof  JComponent) {
0429:                        JComponent jcomp = (JComponent) component;
0430:                        Object obj = jcomp
0431:                                .getClientProperty(SubstanceLookAndFeel.WATERMARK_IGNORE);
0432:                        if (Boolean.TRUE.equals(obj))
0433:                            return false;
0434:                        if (Boolean.FALSE.equals(obj))
0435:                            return true;
0436:                    }
0437:                    c = c.getParent();
0438:                }
0439:                Object obj = UIManager
0440:                        .get(SubstanceLookAndFeel.WATERMARK_IGNORE);
0441:                if (Boolean.TRUE.equals(obj))
0442:                    return false;
0443:
0444:                // special cases - lists, tables and trees that show watermarks only
0445:                // when the WATERMARK_BLEED is set to Boolean.TRUE
0446:                if (component instanceof  JList)
0447:                    return false;
0448:                if (component instanceof  JTree)
0449:                    return false;
0450:                if (component instanceof  JTable)
0451:                    return false;
0452:                if (component instanceof  JTextComponent)
0453:                    return false;
0454:                return true;
0455:            }
0456:
0457:            /**
0458:             * Returns indication whether the watermark should "bleed" through the
0459:             * specified component.
0460:             * 
0461:             * @param component
0462:             *            Component.
0463:             * @return <code>true</code> if the watermark should "bleed" through the
0464:             *         specified component, <code>false</code> otherwise.
0465:             */
0466:            public static boolean toBleedWatermark(Component component) {
0467:                if (component instanceof  JComponent) {
0468:                    JComponent jcomp = (JComponent) component;
0469:                    Object obj = jcomp
0470:                            .getClientProperty(SubstanceLookAndFeel.WATERMARK_TO_BLEED);
0471:                    if (Boolean.TRUE.equals(obj))
0472:                        return true;
0473:                    if (Boolean.FALSE.equals(obj))
0474:                        return false;
0475:                }
0476:
0477:                return SubstanceLookAndFeel.toBleedWatermark();
0478:            }
0479:
0480:            /**
0481:             * Returns the button shaper of the specified button.
0482:             * 
0483:             * @param button
0484:             *            The button.
0485:             * @return The button shaper of the specified button.
0486:             */
0487:            public static SubstanceButtonShaper getButtonShaper(Component button) {
0488:                SubstanceButtonShaper shaper = null;
0489:                Component c = button;
0490:                while (c != null) {
0491:                    if (c instanceof  JComponent) {
0492:                        JComponent jcomp = (JComponent) c;
0493:                        Object customShaper = jcomp
0494:                                .getClientProperty(SubstanceLookAndFeel.BUTTON_SHAPER_PROPERTY);
0495:                        if (customShaper != null) {
0496:                            if (customShaper instanceof  SubstanceButtonShaper)
0497:                                return (SubstanceButtonShaper) customShaper;
0498:                            if (customShaper instanceof  String) {
0499:                                try {
0500:                                    shaper = (SubstanceButtonShaper) Class
0501:                                            .forName((String) customShaper)
0502:                                            .newInstance();
0503:                                } catch (Exception exc) {
0504:                                    shaper = null;
0505:                                }
0506:
0507:                                if (shaper != null)
0508:                                    return shaper;
0509:                            }
0510:                        }
0511:                    }
0512:                    c = c.getParent();
0513:                }
0514:                if (shaper == null) {
0515:                    shaper = SubstanceLookAndFeel.getCurrentButtonShaper();
0516:                }
0517:                return shaper;
0518:            }
0519:
0520:            /**
0521:             * Returns the gradient painter of the specified component.
0522:             * 
0523:             * @param comp
0524:             *            Component.
0525:             * @return The gradient painter of the specified component.
0526:             */
0527:            public static SubstanceGradientPainter getGradientPainter(
0528:                    JComponent comp) {
0529:                SubstanceGradientPainter painter = SubstanceLookAndFeel
0530:                        .getCurrentGradientPainter();
0531:                Object customPainter = comp
0532:                        .getClientProperty(SubstanceLookAndFeel.GRADIENT_PAINTER_PROPERTY);
0533:                if (customPainter != null) {
0534:                    if (customPainter instanceof  SubstanceGradientPainter)
0535:                        return (SubstanceGradientPainter) customPainter;
0536:                    try {
0537:                        painter = (SubstanceGradientPainter) Class.forName(
0538:                                (String) customPainter).newInstance();
0539:                    } catch (Exception exc) {
0540:                        painter = SubstanceLookAndFeel
0541:                                .getCurrentGradientPainter();
0542:                    }
0543:                }
0544:                return painter;
0545:            }
0546:
0547:            /**
0548:             * Retrieves the <code>modified</code> state for the specified component
0549:             * in a tabbed pane.
0550:             * 
0551:             * @param tabComponent
0552:             *            The associated tab component.
0553:             * @return <code>true</code> if the specified component in a tabbed pane
0554:             *         is marked as modified, <code>false</code> otherwise.
0555:             * @see SubstanceLookAndFeel#WINDOW_MODIFIED
0556:             */
0557:            public static boolean isTabModified(Component tabComponent) {
0558:                boolean isWindowModified = false;
0559:                // boolean toEnd = (tabComponent == null);
0560:                Component comp = tabComponent;
0561:                // while (!toEnd) {
0562:                if (comp instanceof  JComponent) {
0563:                    JComponent jc = (JComponent) comp;
0564:
0565:                    isWindowModified = Boolean.TRUE
0566:                            .equals(jc
0567:                                    .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED));
0568:                    // if (isWindowModified)
0569:                    // break;
0570:                }
0571:                // if (comp instanceof JTabbedPane)
0572:                // toEnd = true;
0573:                // comp = comp.getParent();
0574:                // if (comp == null)
0575:                // toEnd = true;
0576:                // }
0577:                return isWindowModified;
0578:            }
0579:
0580:            /**
0581:             * Retrieves the <code>modified</code> state for the specified root pane.
0582:             * 
0583:             * @param rootPane
0584:             *            The root pane.
0585:             * @return <code>true</code> if the specified root pane is marked as
0586:             *         modified, <code>false</code> otherwise.
0587:             * @see SubstanceLookAndFeel#WINDOW_MODIFIED
0588:             */
0589:            public static boolean isRootPaneModified(JRootPane rootPane) {
0590:                return Boolean.TRUE
0591:                        .equals(rootPane
0592:                                .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED));
0593:            }
0594:
0595:            /**
0596:             * Retrieves the <code>modified</code> state for the specified internal
0597:             * frame.
0598:             * 
0599:             * @param internalFrame
0600:             *            The internal frame.
0601:             * @return <code>true</code> if the specified internal frame is marked as
0602:             *         modified, <code>false</code> otherwise.
0603:             * @see SubstanceLookAndFeel#WINDOW_MODIFIED
0604:             */
0605:            public static boolean isInternalFrameModified(
0606:                    JInternalFrame internalFrame) {
0607:                Object frameProp = internalFrame
0608:                        .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED);
0609:                if (Boolean.TRUE.equals(frameProp))
0610:                    return true;
0611:                if (Boolean.FALSE.equals(frameProp))
0612:                    return false;
0613:                return Boolean.TRUE
0614:                        .equals(internalFrame.getRootPane().getClientProperty(
0615:                                SubstanceLookAndFeel.WINDOW_MODIFIED));
0616:            }
0617:
0618:            // /**
0619:            // * Returns the tab animation kind of the specified tab component.
0620:            // *
0621:            // * @param tabComponent
0622:            // * Tab component.
0623:            // * @return Tab animation kind of the specified tab component.
0624:            // */
0625:            // public static TabAnimationKind getTabAnimationKind(Component
0626:            // tabComponent) {
0627:            // Component comp = tabComponent;
0628:            // // while (!toEnd) {
0629:            // if (comp instanceof JComponent) {
0630:            // JComponent jc = (JComponent) comp;
0631:            //
0632:            // Object animObj = jc
0633:            // .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_TAB_ANIMATION_KIND);
0634:            // if (animObj instanceof TabAnimationKind)
0635:            // return (TabAnimationKind) animObj;
0636:            // }
0637:            // return null;
0638:            // }
0639:            //
0640:            /**
0641:             * Returns the tab background composite of the specified tabbed pane.
0642:             * 
0643:             * @param component
0644:             *            Tabbed pane.
0645:             * @return Tab background composite of the specified tabbed pane.
0646:             */
0647:            public static ControlBackgroundComposite getControlBackgroundComposite(
0648:                    Component component) {
0649:                Component c = component;
0650:                while (c != null) {
0651:                    if (c instanceof  JComponent) {
0652:                        JComponent jc = (JComponent) c;
0653:                        Object objProp = jc
0654:                                .getClientProperty(SubstanceLookAndFeel.BACKGROUND_COMPOSITE);
0655:                        if (objProp instanceof  ControlBackgroundComposite)
0656:                            return (ControlBackgroundComposite) objProp;
0657:                    }
0658:                    c = c.getParent();
0659:                }
0660:                Object globalProp = UIManager
0661:                        .get(SubstanceLookAndFeel.BACKGROUND_COMPOSITE);
0662:                if (globalProp instanceof  ControlBackgroundComposite)
0663:                    return (ControlBackgroundComposite) globalProp;
0664:
0665:                return SubstanceLookAndFeel.getBackgroundComposite(component);
0666:            }
0667:
0668:            /**
0669:             * Checks whether the specified tab has a close button.
0670:             * 
0671:             * @param tabbedPane
0672:             *            Tabbed pane.
0673:             * @param tabIndex
0674:             *            Tab index.
0675:             * @return <code>true</code> if the specified tab has a close button,
0676:             *         <code>false</code> otherwise.
0677:             */
0678:            public static boolean hasCloseButton(JTabbedPane tabbedPane,
0679:                    int tabIndex) {
0680:                int tabCount = tabbedPane.getTabCount();
0681:                if ((tabIndex < 0) || (tabIndex >= tabCount))
0682:                    return false;
0683:
0684:                // if tab is disabled, it doesn't have a close button
0685:                if (!tabbedPane.isEnabledAt(tabIndex))
0686:                    return false;
0687:
0688:                // check property on tab component
0689:                Component tabComponent = tabbedPane.getComponentAt(tabIndex);
0690:                if (tabComponent instanceof  JComponent) {
0691:                    Object compProp = ((JComponent) tabComponent)
0692:                            .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY);
0693:                    if (Boolean.TRUE.equals(compProp))
0694:                        return true;
0695:                    if (Boolean.FALSE.equals(compProp))
0696:                        return false;
0697:                }
0698:                // check property on tabbed pane
0699:                Object tabProp = tabbedPane
0700:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY);
0701:                if (Boolean.TRUE.equals(tabProp))
0702:                    return true;
0703:                if (Boolean.FALSE.equals(tabProp))
0704:                    return false;
0705:                // check property in UIManager
0706:                return UIManager
0707:                        .getBoolean(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY);
0708:            }
0709:
0710:            /**
0711:             * Returns the size of the close button for a tab in the specified tabbed
0712:             * pane.
0713:             * 
0714:             * @param tabbedPane
0715:             *            Tabbed pane.
0716:             * @param tabIndex
0717:             *            Tab index.
0718:             * @return The size of the close button for a tab in the specified tabbed
0719:             *         pane.
0720:             */
0721:            public static int getCloseButtonSize(JTabbedPane tabbedPane,
0722:                    int tabIndex) {
0723:                if (!SubstanceCoreUtilities
0724:                        .hasCloseButton(tabbedPane, tabIndex))
0725:                    return 0;
0726:                return SubstanceSizeUtils
0727:                        .getTabCloseIconSize(SubstanceSizeUtils
0728:                                .getComponentFontSize(tabbedPane));
0729:            }
0730:
0731:            /**
0732:             * Checks whether the specified tab should show vertically-aligned (rotated)
0733:             * components.
0734:             * 
0735:             * @param tabbedPane
0736:             *            Tabbed pane.
0737:             * @return <code>true</code> if the specified tab should show
0738:             *         vertically-aligned (rotated) components, <code>false</code>
0739:             *         otherwise.
0740:             */
0741:            public static boolean toLayoutVertically(JTabbedPane tabbedPane) {
0742:                int tabPlacement = tabbedPane.getTabPlacement();
0743:                if ((tabPlacement == SwingConstants.TOP)
0744:                        || (tabPlacement == SwingConstants.BOTTOM))
0745:                    return false;
0746:
0747:                // check property on tabbed pane
0748:                Object tabProp = tabbedPane
0749:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION);
0750:                if (Boolean.TRUE.equals(tabProp))
0751:                    return true;
0752:                if (Boolean.FALSE.equals(tabProp))
0753:                    return false;
0754:                // check property in UIManager
0755:                return UIManager
0756:                        .getBoolean(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION);
0757:            }
0758:
0759:            /**
0760:             * Checks whether the specified tab should show unrotated icon when the tab
0761:             * itself is layed-out vertically.
0762:             * 
0763:             * @param tabbedPane
0764:             *            Tabbed pane.
0765:             * @param tabIndex
0766:             *            Tab index.
0767:             * @return <code>true</code> if the specified tab should show unrotated
0768:             *         icon when the tab itself is layed-out vertically,
0769:             *         <code>false</code> otherwise.
0770:             */
0771:            public static boolean toShowIconUnrotated(JTabbedPane tabbedPane,
0772:                    int tabIndex) {
0773:                int tabCount = tabbedPane.getTabCount();
0774:                if ((tabIndex < 0) || (tabIndex >= tabCount))
0775:                    return false;
0776:                // check property on tab component
0777:                Component tabComponent = tabbedPane.getComponentAt(tabIndex);
0778:                if (tabComponent instanceof  JComponent) {
0779:                    Object compProp = ((JComponent) tabComponent)
0780:                            .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS);
0781:                    if (Boolean.TRUE.equals(compProp))
0782:                        return true;
0783:                    if (Boolean.FALSE.equals(compProp))
0784:                        return false;
0785:                }
0786:                // check property on tabbed pane
0787:                Object tabProp = tabbedPane
0788:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS);
0789:                if (Boolean.TRUE.equals(tabProp))
0790:                    return true;
0791:                if (Boolean.FALSE.equals(tabProp))
0792:                    return false;
0793:                // check property in UIManager
0794:                return UIManager
0795:                        .getBoolean(SubstanceLookAndFeel.TABBED_PANE_VERTICAL_ORIENTATION_ROTATE_ICONS);
0796:            }
0797:
0798:            /**
0799:             * Returns the content border kind of the specified tabbed pane.
0800:             * 
0801:             * @param tabbedPane
0802:             *            Tabbed pane.
0803:             * @return Content border kind of the specified tabbed pane.
0804:             */
0805:            public static TabContentPaneBorderKind getContentBorderKind(
0806:                    JTabbedPane tabbedPane) {
0807:                // check property on tabbed pane
0808:                Object tabProp = tabbedPane
0809:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND);
0810:                if (tabProp instanceof  TabContentPaneBorderKind)
0811:                    return (TabContentPaneBorderKind) tabProp;
0812:                // check property in UIManager
0813:                Object globalProp = UIManager
0814:                        .get(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND);
0815:                if (globalProp instanceof  TabContentPaneBorderKind)
0816:                    return (TabContentPaneBorderKind) globalProp;
0817:                return TabContentPaneBorderKind.DOUBLE_FULL;
0818:            }
0819:
0820:            /**
0821:             * Checks whether the specified tab should show modified animation only on
0822:             * its close button.
0823:             * 
0824:             * @param tabbedPane
0825:             *            Tabbed pane.
0826:             * @param tabIndex
0827:             *            Tab index.
0828:             * @return <code>true</code> if the specified tab should show modified
0829:             *         animation only on its close button, <code>false</code>
0830:             *         otherwise.
0831:             */
0832:            public static boolean toAnimateCloseIconOfModifiedTab(
0833:                    JTabbedPane tabbedPane, int tabIndex) {
0834:                int tabCount = tabbedPane.getTabCount();
0835:                if ((tabIndex < 0) || (tabIndex >= tabCount))
0836:                    return false;
0837:
0838:                if (!hasCloseButton(tabbedPane, tabIndex))
0839:                    return false;
0840:
0841:                // check property on tab component
0842:                Component tabComponent = tabbedPane.getComponentAt(tabIndex);
0843:                if (tabComponent instanceof  JComponent) {
0844:                    Object compProp = ((JComponent) tabComponent)
0845:                            .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION);
0846:                    if (Boolean.TRUE.equals(compProp))
0847:                        return true;
0848:                    if (Boolean.FALSE.equals(compProp))
0849:                        return false;
0850:                }
0851:                // check property on tabbed pane
0852:                Object tabProp = tabbedPane
0853:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION);
0854:                if (Boolean.TRUE.equals(tabProp))
0855:                    return true;
0856:                if (Boolean.FALSE.equals(tabProp))
0857:                    return false;
0858:                // check property in UIManager
0859:                return UIManager
0860:                        .getBoolean(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION);
0861:            }
0862:
0863:            /**
0864:             * Retrieves transparent image of specified dimension.
0865:             * 
0866:             * @param width
0867:             *            Image width.
0868:             * @param height
0869:             *            Image height.
0870:             * @return Transparent image of specified dimension.
0871:             */
0872:            public static BufferedImage getBlankImage(int width, int height) {
0873:                if (MemoryAnalyzer.isRunning()) {
0874:                    // see if the request is unusual
0875:                    if ((width >= 100) || (height >= 100)) {
0876:                        // throw an Exception and then analyze it
0877:                        try {
0878:                            throw new Exception();
0879:                        } catch (Exception exc) {
0880:                            StringBuffer sb = new StringBuffer();
0881:                            StackTraceElement[] stack = exc.getStackTrace();
0882:                            int count = 0;
0883:                            for (StackTraceElement stackEntry : stack) {
0884:                                if (count++ > 8)
0885:                                    break;
0886:                                sb.append(stackEntry.getClassName() + ".");
0887:                                sb.append(stackEntry.getMethodName() + " [");
0888:                                sb.append(stackEntry.getLineNumber() + "]");
0889:                                sb.append("\n");
0890:                            }
0891:                            MemoryAnalyzer.enqueueUsage("Blank " + width + "*"
0892:                                    + height + "\n" + sb.toString());
0893:
0894:                        }
0895:                    }
0896:                }
0897:
0898:                BufferedImage image = new BufferedImage(width, height,
0899:                        BufferedImage.TYPE_INT_ARGB);
0900:
0901:                // get graphics and set hints
0902:                Graphics2D graphics = (Graphics2D) image.getGraphics().create();
0903:                graphics.setColor(new Color(0, 0, 0, 0));
0904:                graphics.setComposite(AlphaComposite.Src);
0905:                graphics.fillRect(0, 0, width, height);
0906:                graphics.dispose();
0907:
0908:                return image;
0909:            }
0910:
0911:            /**
0912:             * Checks whether the specified button should have minimal size.
0913:             * 
0914:             * @param button
0915:             *            Button.
0916:             * @return <code>false</code> if the specified button should have minimal
0917:             *         size, <code>true</code> otherwise.
0918:             */
0919:            public static boolean hasNoMinSizeProperty(AbstractButton button) {
0920:                Object noMinSizeProperty = button
0921:                        .getClientProperty(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY);
0922:                if (Boolean.TRUE.equals(noMinSizeProperty))
0923:                    return true;
0924:                if (Boolean.FALSE.equals(noMinSizeProperty))
0925:                    return false;
0926:                Container parent = button.getParent();
0927:                if (parent instanceof  JComponent) {
0928:                    noMinSizeProperty = ((JComponent) parent)
0929:                            .getClientProperty(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY);
0930:                    if (Boolean.TRUE.equals(noMinSizeProperty))
0931:                        return true;
0932:                    if (Boolean.FALSE.equals(noMinSizeProperty))
0933:                        return false;
0934:                }
0935:                return (Boolean.TRUE.equals(UIManager
0936:                        .get(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY)));
0937:            }
0938:
0939:            /**
0940:             * Checks whether the specified component is flat.
0941:             * 
0942:             * @param comp
0943:             *            Component.
0944:             * @param defaultValue
0945:             *            The value to return if there is no
0946:             *            {@link SubstanceLookAndFeel#FLAT_PROPERTY} defined on button
0947:             *            hierarchy or {@link UIManager}.
0948:             * @return <code>false</code> if the specified button is flat,
0949:             *         <code>true</code> otherwise.
0950:             */
0951:            public static boolean hasFlatAppearance(Component comp,
0952:                    boolean defaultValue) {
0953:                Component c = comp;
0954:                while (c != null) {
0955:                    if (c instanceof  JComponent) {
0956:                        JComponent jcomp = (JComponent) c;
0957:                        Object flatProperty = jcomp
0958:                                .getClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY);
0959:                        if (Boolean.TRUE.equals(flatProperty))
0960:                            return true;
0961:                        if (Boolean.FALSE.equals(flatProperty))
0962:                            return false;
0963:                    }
0964:                    c = c.getParent();
0965:                }
0966:                Object flatProperty = UIManager
0967:                        .get(SubstanceLookAndFeel.FLAT_PROPERTY);
0968:                if (Boolean.TRUE.equals(flatProperty))
0969:                    return true;
0970:                if (Boolean.FALSE.equals(flatProperty))
0971:                    return false;
0972:                return defaultValue;
0973:            }
0974:
0975:            /**
0976:             * Computes whether the specified button has flat appearance.
0977:             * 
0978:             * @param button
0979:             *            Button.
0980:             * @return <code>true</code> if the button has flat appearance,
0981:             *         <code>false</code> otherwise.
0982:             */
0983:            public static boolean hasFlatAppearance(AbstractButton button) {
0984:                return ((SubstanceCoreUtilities.isToolBarButton(button) && SubstanceCoreUtilities
0985:                        .hasFlatAppearance(button, true)) || SubstanceCoreUtilities
0986:                        .hasFlatAppearance(button, false));
0987:            }
0988:
0989:            /**
0990:             * Returns the popup flyout orientation for the specified combobox.
0991:             * 
0992:             * @param combobox
0993:             *            Combobox.
0994:             * @return The popup flyout orientation for the specified combobox.
0995:             */
0996:            public static int getPopupFlyoutOrientation(JComboBox combobox) {
0997:                Object comboProperty = combobox
0998:                        .getClientProperty(SubstanceLookAndFeel.COMBO_BOX_POPUP_FLYOUT_ORIENTATION);
0999:                if (comboProperty instanceof  Integer)
1000:                    return (Integer) comboProperty;
1001:                Object globalProperty = UIManager
1002:                        .get(SubstanceLookAndFeel.COMBO_BOX_POPUP_FLYOUT_ORIENTATION);
1003:                if (globalProperty instanceof  Integer)
1004:                    return (Integer) globalProperty;
1005:                return SwingConstants.SOUTH;
1006:            }
1007:
1008:            /**
1009:             * Makes the specified component and all its descendants non-opaque.
1010:             * 
1011:             * @param comp
1012:             *            Component.
1013:             * @param opacitySnapshot
1014:             *            The "snapshot" map that will contain the original opacity
1015:             *            status of the specified component and all its descendants.
1016:             */
1017:            public static void makeNonOpaque(Component comp,
1018:                    Map<Component, Boolean> opacitySnapshot) {
1019:                if (comp instanceof  JComponent) {
1020:                    JComponent jcomp = (JComponent) comp;
1021:                    opacitySnapshot.put(comp, jcomp.isOpaque());
1022:                    jcomp.setOpaque(false);
1023:                }
1024:                if (comp instanceof  Container) {
1025:                    Container cont = (Container) comp;
1026:                    for (int i = 0; i < cont.getComponentCount(); i++)
1027:                        makeNonOpaque(cont.getComponent(i), opacitySnapshot);
1028:                }
1029:            }
1030:
1031:            /**
1032:             * Restores the opacity of the specified component and all its descendants.
1033:             * 
1034:             * @param comp
1035:             *            Component.
1036:             * @param opacitySnapshot
1037:             *            The "snapshot" map that contains the original opacity status
1038:             *            of the specified component and all its descendants.
1039:             */
1040:            public static void restoreOpaque(Component comp,
1041:                    Map<Component, Boolean> opacitySnapshot) {
1042:                if (comp instanceof  JComponent) {
1043:                    JComponent jcomp = (JComponent) comp;
1044:                    // fix for defect 159 - snapshot may not contain
1045:                    // opacity for table header of a table when it's used
1046:                    // inside tree cell renderer (wrapper in a scroll pane).
1047:                    if (opacitySnapshot.containsKey(comp))
1048:                        jcomp.setOpaque(opacitySnapshot.get(comp));
1049:                    else
1050:                        jcomp.setOpaque(true);
1051:                }
1052:                if (comp instanceof  Container) {
1053:                    Container cont = (Container) comp;
1054:                    for (int i = 0; i < cont.getComponentCount(); i++)
1055:                        restoreOpaque(cont.getComponent(i), opacitySnapshot);
1056:                }
1057:            }
1058:
1059:            /**
1060:             * Makes the specified component and all its descendants non-double
1061:             * buffered.
1062:             * 
1063:             * @param comp
1064:             *            Component.
1065:             * @param dbSnapshot
1066:             *            The "snapshot" map that will contain the original double
1067:             *            buffer status of the specified component and all its
1068:             *            descendants.
1069:             */
1070:            public static void makeNonDoubleBuffered(Component comp,
1071:                    Map<Component, Boolean> dbSnapshot) {
1072:                if (comp instanceof  JComponent) {
1073:                    JComponent jcomp = (JComponent) comp;
1074:                    dbSnapshot.put(comp, jcomp.isDoubleBuffered());
1075:                    jcomp.setDoubleBuffered(false);
1076:                }
1077:                if (comp instanceof  Container) {
1078:                    Container cont = (Container) comp;
1079:                    for (int i = 0; i < cont.getComponentCount(); i++)
1080:                        makeNonDoubleBuffered(cont.getComponent(i), dbSnapshot);
1081:                }
1082:            }
1083:
1084:            /**
1085:             * Restores the double buffer of the specified component and all its
1086:             * descendants.
1087:             * 
1088:             * @param comp
1089:             *            Component.
1090:             * @param dbSnapshot
1091:             *            The "snapshot" map that contains the original double buffer
1092:             *            status of the specified component and all its descendants.
1093:             */
1094:            public static void restoreDoubleBuffered(Component comp,
1095:                    Map<Component, Boolean> dbSnapshot) {
1096:                if (comp instanceof  JComponent) {
1097:                    JComponent jcomp = (JComponent) comp;
1098:                    // fix for defect 159 - snapshot may not contain
1099:                    // opacity for table header of a table when it's used
1100:                    // inside tree cell renderer (wrapper in a scroll pane).
1101:                    if (dbSnapshot.containsKey(comp))
1102:                        jcomp.setDoubleBuffered(dbSnapshot.get(comp));
1103:                    else
1104:                        jcomp.setOpaque(true);
1105:                }
1106:                if (comp instanceof  Container) {
1107:                    Container cont = (Container) comp;
1108:                    for (int i = 0; i < cont.getComponentCount(); i++)
1109:                        restoreDoubleBuffered(cont.getComponent(i), dbSnapshot);
1110:                }
1111:            }
1112:
1113:            /**
1114:             * Creates a compatible image (for efficient processing and drawing).
1115:             * 
1116:             * @param image
1117:             *            The original image.
1118:             * @return Compatible version of the original image.
1119:             * @author Romain Guy
1120:             */
1121:            public static BufferedImage createCompatibleImage(
1122:                    BufferedImage image) {
1123:                GraphicsEnvironment e = GraphicsEnvironment
1124:                        .getLocalGraphicsEnvironment();
1125:                GraphicsDevice d = e.getDefaultScreenDevice();
1126:                GraphicsConfiguration c = d.getDefaultConfiguration();
1127:                BufferedImage compatibleImage = c.createCompatibleImage(image
1128:                        .getWidth(), image.getHeight());
1129:                Graphics g = compatibleImage.getGraphics();
1130:                g.drawImage(image, 0, 0, null);
1131:                g.dispose();
1132:                return compatibleImage;
1133:            }
1134:
1135:            // /**
1136:            // * Checks whether the specified button in a toolbar is flat.
1137:            // *
1138:            // * @param button
1139:            // * Button.
1140:            // * @return <code>true</code> if the specified button is flat in a toolbar,
1141:            // * <code>false</code> otherwise.
1142:            // */
1143:            // public static boolean isToolbarButtonFlat(AbstractButton button) {
1144:            // Component comp = button;
1145:            // JToolBar toolbar = null;
1146:            // while (comp != null) {
1147:            // if (comp instanceof JToolBar) {
1148:            // toolbar = (JToolBar) comp;
1149:            // break;
1150:            // }
1151:            // comp = comp.getParent();
1152:            // }
1153:            // if (toolbar == null)
1154:            // return false;
1155:            //
1156:            // return isToolbarButtonFlat(button, toolbar);
1157:            // }
1158:            //
1159:            // /**
1160:            // * Checks whether the specified button in the specified toolbar is flat.
1161:            // *
1162:            // * @param button
1163:            // * Button.
1164:            // * @param toolbar
1165:            // * Toolbar that contains the specified button.
1166:            // * @return <code>true</code> if the specified button is flat in the
1167:            // * specified toolbar, <code>false</code> otherwise.
1168:            // */
1169:            // public static boolean isToolbarButtonFlat(AbstractButton button,
1170:            // JToolBar toolbar) {
1171:            // Object isFlatProperty = button
1172:            // .getClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY);
1173:            // if (Boolean.TRUE.equals(isFlatProperty))
1174:            // return true;
1175:            // if (Boolean.FALSE.equals(isFlatProperty))
1176:            // return false;
1177:            // isFlatProperty = toolbar
1178:            // .getClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY);
1179:            // if (Boolean.TRUE.equals(isFlatProperty))
1180:            // return true;
1181:            // if (Boolean.FALSE.equals(isFlatProperty))
1182:            // return false;
1183:            // if (Boolean.FALSE.equals(UIManager
1184:            // .get(SubstanceLookAndFeel.FLAT_PROPERTY)))
1185:            // return false;
1186:            // return true;
1187:            // }
1188:
1189:            /**
1190:             * Checks whether the specified component will show theme-colorized icon in
1191:             * the default state.
1192:             * 
1193:             * @param comp
1194:             *            Component.
1195:             * @return <code>true</code> if the specified component will show
1196:             *         theme-colorized icon in the default state, <code>false</code>
1197:             *         otherwise.
1198:             */
1199:            public static boolean useThemedDefaultIcon(JComponent comp) {
1200:                if (comp != null) {
1201:                    Object useThemedDefaultIconProperty = comp
1202:                            .getClientProperty(SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS);
1203:                    if (Boolean.TRUE.equals(useThemedDefaultIconProperty))
1204:                        return true;
1205:                    if (Boolean.FALSE.equals(useThemedDefaultIconProperty))
1206:                        return false;
1207:                }
1208:                if (Boolean.TRUE.equals(UIManager
1209:                        .get(SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS)))
1210:                    return true;
1211:                return false;
1212:            }
1213:
1214:            /**
1215:             * Returns the callback to be called upon tab closing (using the tab close
1216:             * button).
1217:             * 
1218:             * @param me
1219:             *            Mouse event.
1220:             * @param tabbedPane
1221:             *            Tabbed pane.
1222:             * @param tabIndex
1223:             *            Tab index.
1224:             * @return Callback to be called upon tab closing (using the tab close
1225:             *         button).
1226:             */
1227:            public static TabCloseCallback getTabCloseCallback(MouseEvent me,
1228:                    JTabbedPane tabbedPane, int tabIndex) {
1229:                int tabCount = tabbedPane.getTabCount();
1230:                if ((tabIndex < 0) || (tabIndex >= tabCount))
1231:                    return null;
1232:
1233:                // check property on tab component
1234:                Component tabComponent = tabbedPane.getComponentAt(tabIndex);
1235:                if (tabComponent instanceof  JComponent) {
1236:                    Object compProp = ((JComponent) tabComponent)
1237:                            .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK);
1238:                    if (compProp instanceof  TabCloseCallback)
1239:                        return (TabCloseCallback) compProp;
1240:                }
1241:
1242:                // check property on tabbed pane
1243:                Object tabProp = tabbedPane
1244:                        .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK);
1245:                if (tabProp instanceof  TabCloseCallback)
1246:                    return (TabCloseCallback) tabProp;
1247:
1248:                Object globProp = UIManager
1249:                        .get(SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK);
1250:                if (globProp instanceof  TabCloseCallback)
1251:                    return (TabCloseCallback) globProp;
1252:
1253:                return null;
1254:            }
1255:
1256:            /**
1257:             * Blends two images along X-axis.
1258:             * 
1259:             * @param imageLeft
1260:             *            The left image.
1261:             * @param imageRight
1262:             *            The right image.
1263:             * @param start
1264:             *            Relative start of the blend area (in 0.0-1.0 range).
1265:             * @param end
1266:             *            Relative end of the blend area (in 0.0-1.0 range).
1267:             * @return Blended image.
1268:             */
1269:            public static BufferedImage blendImagesHorizontal(
1270:                    BufferedImage imageLeft, BufferedImage imageRight,
1271:                    double start, double end) {
1272:                int width = imageLeft.getWidth();
1273:                if (width != imageRight.getWidth())
1274:                    throw new IllegalArgumentException(
1275:                            "Widths are not the same: " + imageLeft.getWidth()
1276:                                    + " and " + imageRight.getWidth());
1277:                int height = imageLeft.getHeight();
1278:                if (height != imageRight.getHeight())
1279:                    throw new IllegalArgumentException(
1280:                            "Heights are not the same: "
1281:                                    + imageLeft.getHeight() + " and "
1282:                                    + imageRight.getHeight());
1283:
1284:                BufferedImage result = getBlankImage(width, height);
1285:                Graphics2D graphics = (Graphics2D) result.getGraphics()
1286:                        .create();
1287:
1288:                int startX = (int) (start * width);
1289:                int endX = (int) (end * width);
1290:                int rampWidth = endX - startX;
1291:
1292:                if (rampWidth == 0) {
1293:                    graphics.drawImage(imageLeft, 0, 0, startX, height, 0, 0,
1294:                            startX, height, null);
1295:                    graphics.drawImage(imageRight, startX, 0, width, height,
1296:                            startX, 0, width, height, null);
1297:                } else {
1298:                    BufferedImage rampRight = getBlankImage(rampWidth, height);
1299:                    Graphics2D rampRightG = (Graphics2D) rampRight
1300:                            .getGraphics();
1301:                    rampRightG.setPaint(new GradientPaint(new Point(0, 0),
1302:                            new Color(0, 0, 0, 255), new Point(rampWidth, 0),
1303:                            new Color(0, 0, 0, 0)));
1304:                    rampRightG.fillRect(0, 0, rampWidth, height);
1305:
1306:                    BufferedImage tempRight = getBlankImage(width - startX,
1307:                            height);
1308:                    Graphics2D tempRightG = (Graphics2D) tempRight
1309:                            .getGraphics();
1310:                    tempRightG.drawImage(imageRight, 0, 0, width - startX,
1311:                            height, startX, 0, width, height, null);
1312:                    tempRightG.setComposite(AlphaComposite.DstOut);
1313:                    tempRightG.drawImage(rampRight, 0, 0, null);
1314:
1315:                    tempRightG.setComposite(AlphaComposite.SrcOver);
1316:                    graphics.drawImage(imageLeft, 0, 0, null);
1317:                    graphics.drawImage(tempRight, startX, 0, null);
1318:                }
1319:                graphics.dispose();
1320:                return result;
1321:            }
1322:
1323:            /**
1324:             * Blends two images along Y-axis.
1325:             * 
1326:             * @param imageTop
1327:             *            The left image.
1328:             * @param imageBottom
1329:             *            The right image.
1330:             * @param start
1331:             *            Relative start of the blend area (in 0.0-1.0 range).
1332:             * @param end
1333:             *            Relative end of the blend area (in 0.0-1.0 range).
1334:             * @return Blended image.
1335:             */
1336:            public static BufferedImage blendImagesVertical(
1337:                    BufferedImage imageTop, BufferedImage imageBottom,
1338:                    double start, double end) {
1339:                int width = imageTop.getWidth();
1340:                if (width != imageBottom.getWidth())
1341:                    throw new IllegalArgumentException(
1342:                            "Widths are not the same: " + imageTop.getWidth()
1343:                                    + " and " + imageBottom.getWidth());
1344:                int height = imageTop.getHeight();
1345:                if (height != imageBottom.getHeight())
1346:                    throw new IllegalArgumentException(
1347:                            "Heights are not the same: " + imageTop.getHeight()
1348:                                    + " and " + imageBottom.getHeight());
1349:
1350:                BufferedImage result = getBlankImage(width, height);
1351:                Graphics2D graphics = (Graphics2D) result.getGraphics()
1352:                        .create();
1353:
1354:                int startY = (int) (start * height);
1355:                int endY = (int) (end * height);
1356:                int rampHeight = endY - startY;
1357:
1358:                if (rampHeight == 0) {
1359:                    graphics.drawImage(imageTop, 0, 0, width, startY, 0, 0,
1360:                            width, startY, null);
1361:                    graphics.drawImage(imageBottom, 0, startY, width, height,
1362:                            0, startY, width, height, null);
1363:                } else {
1364:                    BufferedImage rampBottom = getBlankImage(width, rampHeight);
1365:                    Graphics2D rampBottomG = (Graphics2D) rampBottom
1366:                            .getGraphics();
1367:                    rampBottomG.setPaint(new GradientPaint(new Point(0, 0),
1368:                            new Color(0, 0, 0, 255), new Point(0, rampHeight),
1369:                            new Color(0, 0, 0, 0)));
1370:                    rampBottomG.fillRect(0, 0, width, rampHeight);
1371:
1372:                    BufferedImage tempBottom = getBlankImage(width, height
1373:                            - startY);
1374:                    Graphics2D tempBottomG = (Graphics2D) tempBottom
1375:                            .getGraphics();
1376:                    tempBottomG.drawImage(imageBottom, 0, 0, width, height
1377:                            - startY, 0, startY, width, height, null);
1378:                    tempBottomG.setComposite(AlphaComposite.DstOut);
1379:                    tempBottomG.drawImage(rampBottom, 0, 0, null);
1380:
1381:                    tempBottomG.setComposite(AlphaComposite.SrcOver);
1382:                    graphics.drawImage(imageTop, 0, 0, null);
1383:                    graphics.drawImage(tempBottom, 0, startY, null);
1384:                }
1385:                graphics.dispose();
1386:                return result;
1387:            }
1388:
1389:            /**
1390:             * Retruns the unique ID for the specified color scheme.
1391:             * 
1392:             * @param colorScheme
1393:             *            Color scheme.
1394:             * @return Unique ID for the specified color scheme.
1395:             */
1396:            public static String getSchemeId(ColorScheme colorScheme) {
1397:                if (colorScheme instanceof  BaseColorScheme) {
1398:                    BaseColorScheme base = (BaseColorScheme) colorScheme;
1399:                    return base.getId();
1400:                }
1401:
1402:                return colorScheme.getClass().getName();
1403:            }
1404:
1405:            /**
1406:             * Returns the color scheme for the icon of option panes with the specified
1407:             * message type.
1408:             * 
1409:             * @param messageType
1410:             *            Option pane message type.
1411:             * @param mainScheme
1412:             *            Main color scheme.
1413:             * @return Color scheme for the icon of option panes with the specified
1414:             *         message type.
1415:             */
1416:            public static ColorScheme getOptionPaneColorScheme(int messageType,
1417:                    ColorScheme mainScheme) {
1418:                if (!SubstanceLookAndFeel.isToUseConstantThemesOnDialogs())
1419:                    return mainScheme;
1420:
1421:                switch (messageType) {
1422:                case JOptionPane.INFORMATION_MESSAGE:
1423:                    return new BottleGreenColorScheme();
1424:                case JOptionPane.QUESTION_MESSAGE:
1425:                    return new LightAquaColorScheme();
1426:                case JOptionPane.WARNING_MESSAGE:
1427:                    return new SunsetColorScheme();
1428:                case JOptionPane.ERROR_MESSAGE:
1429:                    return new SunfireRedColorScheme();
1430:                }
1431:                return null;
1432:            }
1433:
1434:            /**
1435:             * Checks whether the specified theme is dark.
1436:             * 
1437:             * @param theme
1438:             *            Theme.
1439:             * @return <code>true</code> if the specified theme is dark,
1440:             *         <code>false</code> otherwise.
1441:             */
1442:            public static boolean isThemeDark(SubstanceTheme theme) {
1443:                if (theme instanceof  SubstanceInvertedTheme) {
1444:                    return !isThemeDark(((SubstanceInvertedTheme) theme)
1445:                            .getOriginalTheme());
1446:                }
1447:                if (theme instanceof  SubstanceNegatedTheme) {
1448:                    return isThemeDark(((SubstanceNegatedTheme) theme)
1449:                            .getOriginalTheme());
1450:                }
1451:                if (theme instanceof  SubstanceMixTheme) {
1452:                    SubstanceMixTheme mix = (SubstanceMixTheme) theme;
1453:                    for (SubstanceTheme mixCompTheme : mix.getOriginalThemes())
1454:                        if (isThemeDark(mixCompTheme))
1455:                            return true;
1456:                    return false;
1457:                }
1458:                if (theme instanceof  SubstanceBlendBiTheme) {
1459:                    SubstanceBlendBiTheme blend = (SubstanceBlendBiTheme) theme;
1460:                    return isThemeDark(blend.getOriginalFirstTheme())
1461:                            || isThemeDark(blend.getOriginalSecondTheme());
1462:                }
1463:                return (theme.getKind() == ThemeKind.DARK);
1464:            }
1465:
1466:            /**
1467:             * Returns the popup prototype display value for the specified combo box.
1468:             * This value is used to compute the width of the combo popup.
1469:             * 
1470:             * @param combo
1471:             *            Combo box.
1472:             * @return The popup prototype display value for the specified combo box.
1473:             */
1474:            public static Object getComboPopupPrototypeDisplayValue(
1475:                    JComboBox combo) {
1476:                Object objProp = combo
1477:                        .getClientProperty(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE);
1478:                if (objProp == null)
1479:                    objProp = UIManager
1480:                            .get(SubstanceLookAndFeel.COMBO_POPUP_PROTOTYPE);
1481:                if (objProp == null)
1482:                    return null;
1483:
1484:                if (objProp instanceof  ComboPopupPrototypeCallback) {
1485:                    ComboPopupPrototypeCallback callback = (ComboPopupPrototypeCallback) objProp;
1486:                    return callback.getPopupPrototypeDisplayValue(combo);
1487:                }
1488:
1489:                // check if this object is in the model ???
1490:                return objProp;
1491:            }
1492:
1493:            /**
1494:             * Returns the scroll bar buttons kind of the specified scroll bar.
1495:             * 
1496:             * @param scrollBar
1497:             *            Scroll bar.
1498:             * @return The scroll bar buttons kind of the specified scroll bar.
1499:             */
1500:            public static ScrollPaneButtonPolicyKind getScrollPaneButtonsPolicyKind(
1501:                    JScrollBar scrollBar) {
1502:                Component parent = scrollBar.getParent();
1503:                if (parent instanceof  JScrollPane) {
1504:                    Object jspKind = ((JScrollPane) parent)
1505:                            .getClientProperty(SubstanceLookAndFeel.SCROLL_PANE_BUTTONS_POLICY);
1506:                    if (jspKind instanceof  ScrollPaneButtonPolicyKind)
1507:                        return (ScrollPaneButtonPolicyKind) jspKind;
1508:                }
1509:                Object globalJspKind = UIManager
1510:                        .get(SubstanceLookAndFeel.SCROLL_PANE_BUTTONS_POLICY);
1511:                if (globalJspKind instanceof  ScrollPaneButtonPolicyKind)
1512:                    return (ScrollPaneButtonPolicyKind) globalJspKind;
1513:                return ScrollPaneButtonPolicyKind.OPPOSITE;
1514:            }
1515:
1516:            /**
1517:             * Returns the set of sides registered on the specified button.
1518:             * 
1519:             * @param button
1520:             *            Button.
1521:             * @param propertyName
1522:             *            Client property name for retrieving the registered sides.
1523:             * @return Set of sides registered on the specified button.
1524:             */
1525:            @SuppressWarnings("unchecked")
1526:            public static Set<Side> getSides(AbstractButton button,
1527:                    String propertyName) {
1528:                Object prop = button.getClientProperty(propertyName);
1529:
1530:                if (prop instanceof  Set) {
1531:                    return (Set<Side>) prop;
1532:                }
1533:
1534:                Set<Side> result = new HashSet<Side>();
1535:                if (prop != null) {
1536:                    if (prop instanceof  String) {
1537:                        result.add(SubstanceConstants.Side
1538:                                .valueOf((String) prop));
1539:                    }
1540:                    if (prop instanceof  String[]) {
1541:                        String[] clientSides = (String[]) prop;
1542:                        for (String side : clientSides) {
1543:                            result.add(SubstanceConstants.Side.valueOf(side));
1544:                        }
1545:                    }
1546:                    if (prop instanceof  Side) {
1547:                        result.add((Side) prop);
1548:                    }
1549:                    if (prop instanceof  Side[]) {
1550:                        Side[] clientSides = (Side[]) prop;
1551:                        for (Side side : clientSides) {
1552:                            result.add(side);
1553:                        }
1554:                    }
1555:                }
1556:                return result;
1557:            }
1558:
1559:            /**
1560:             * Returns the corner radius of the specified toolbar button.
1561:             * 
1562:             * @param button
1563:             *            Toolbar button.
1564:             * @param insets
1565:             *            Button insets.
1566:             * @return Corner radius of the specified toolbar button.
1567:             */
1568:            public static float getToolbarButtonCornerRadius(
1569:                    AbstractButton button, Insets insets) {
1570:
1571:                JToolBar toolbar = null;
1572:                Component c = button.getParent();
1573:                while (c != null) {
1574:                    if (c instanceof  JToolBar) {
1575:                        toolbar = (JToolBar) c;
1576:                        break;
1577:                    }
1578:                    c = c.getParent();
1579:                }
1580:                if (toolbar == null)
1581:                    return 2.0f;
1582:
1583:                int width = button.getWidth();
1584:                int height = button.getHeight();
1585:
1586:                if (insets != null) {
1587:                    width -= (insets.left + insets.right);
1588:                    height -= (insets.top + insets.bottom);
1589:                }
1590:                float maxRadius = (width > height) ? (height) / 2.0f
1591:                        : (width) / 2.0f;
1592:
1593:                Object buttonProp = button
1594:                        .getClientProperty(SubstanceLookAndFeel.CORNER_RADIUS);
1595:                if (buttonProp instanceof  Float)
1596:                    return Math.min(maxRadius, ((Float) buttonProp)
1597:                            .floatValue());
1598:
1599:                Object toolbarProp = toolbar
1600:                        .getClientProperty(SubstanceLookAndFeel.CORNER_RADIUS);
1601:                if (toolbarProp instanceof  Float)
1602:                    return Math.min(maxRadius, ((Float) toolbarProp)
1603:                            .floatValue());
1604:
1605:                Object globalProp = UIManager
1606:                        .get(SubstanceLookAndFeel.CORNER_RADIUS);
1607:                if (globalProp instanceof  Float)
1608:                    return Math.min(maxRadius, ((Float) globalProp)
1609:                            .floatValue());
1610:
1611:                return 2.0f;
1612:            }
1613:
1614:            /**
1615:             * Returns the number of echo characters per each password chanaracter.
1616:             * 
1617:             * @param jpf
1618:             *            Password field.
1619:             * @return The number of echo characters per each password chanaracter.
1620:             */
1621:            public static int getEchoPerChar(JPasswordField jpf) {
1622:                Object obj = jpf
1623:                        .getClientProperty(SubstanceLookAndFeel.PASSWORD_ECHO_PER_CHAR);
1624:                if ((obj != null) && (obj instanceof  Integer)) {
1625:                    int result = (Integer) obj;
1626:                    if (result >= 1)
1627:                        return result;
1628:                }
1629:
1630:                obj = UIManager
1631:                        .get(SubstanceLookAndFeel.PASSWORD_ECHO_PER_CHAR);
1632:                if ((obj != null) && (obj instanceof  Integer)) {
1633:                    int result = (Integer) obj;
1634:                    if (result >= 1)
1635:                        return result;
1636:                }
1637:                return 1;
1638:            }
1639:
1640:            /**
1641:             * Creates a clip image for soft-clipping. Code taken from <a
1642:             * href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker_2.html">here</a>.
1643:             * 
1644:             * @param s
1645:             *            Clip shape.
1646:             * @param width
1647:             *            Image width.
1648:             * @param height
1649:             *            Image height.
1650:             * @return Clip image.
1651:             * @author Chris Campbell.
1652:             */
1653:            public static BufferedImage createClipImage(Shape s, int width,
1654:                    int height) {
1655:                // Create a translucent intermediate image in which we can perform
1656:                // the soft clipping
1657:                GraphicsEnvironment e = GraphicsEnvironment
1658:                        .getLocalGraphicsEnvironment();
1659:                GraphicsDevice d = e.getDefaultScreenDevice();
1660:                GraphicsConfiguration c = d.getDefaultConfiguration();
1661:
1662:                BufferedImage img = c.createCompatibleImage(width, height,
1663:                        Transparency.TRANSLUCENT);
1664:                Graphics2D g2 = img.createGraphics();
1665:
1666:                // Clear the image so all pixels have zero alpha
1667:                g2.setComposite(AlphaComposite.Clear);
1668:                g2.fillRect(0, 0, width, height);
1669:
1670:                // Render our clip shape into the image. Note that we enable
1671:                // antialiasing to achieve the soft clipping effect. Try
1672:                // commenting out the line that enables antialiasing, and
1673:                // you will see that you end up with the usual hard clipping.
1674:                g2.setComposite(AlphaComposite.Src);
1675:                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1676:                        RenderingHints.VALUE_ANTIALIAS_ON);
1677:                g2.setColor(Color.WHITE);
1678:                g2.fill(s);
1679:                g2.dispose();
1680:
1681:                return img;
1682:            }
1683:
1684:            /**
1685:             * Returns the color of mark icons (checkbox, radio button, scrollbar
1686:             * arrows, combo arrows, menu arrows etc) for the specified theme.
1687:             * 
1688:             * @param theme
1689:             *            Theme.
1690:             * @param isEnabled
1691:             *            If <code>true</code>, the mark should be painted in enabled
1692:             *            state.
1693:             * @return Color of mark icons.
1694:             */
1695:            public static Color getMarkColor(SubstanceTheme theme,
1696:                    boolean isEnabled) {
1697:                ColorScheme scheme = theme.getColorScheme();
1698:                if (SubstanceCoreUtilities.isThemeDark(theme)) {
1699:                    if (!isEnabled) {
1700:                        // return SubstanceColorUtilities.getInterpolatedColor(theme
1701:                        // .getBorderTheme().getColorScheme().getDarkColor(),
1702:                        // scheme.getForegroundColor(), 0.7);
1703:                        return theme.getBorderTheme().getColorScheme()
1704:                                .getDarkColor();
1705:
1706:                    } else {
1707:                        return SubstanceColorUtilities.getInterpolatedColor(
1708:                                scheme.getForegroundColor(), scheme
1709:                                        .getUltraLightColor(), 0.9);
1710:                    }
1711:                } else {
1712:                    Color color1 = isEnabled ? scheme.getUltraDarkColor()
1713:                            : scheme.getUltraDarkColor();
1714:                    Color color2 = isEnabled ? scheme.getDarkColor() : scheme
1715:                            .getLightColor();
1716:                    return SubstanceColorUtilities.getInterpolatedColor(color1,
1717:                            color2, 0.9);
1718:                }
1719:            }
1720:
1721:            /**
1722:             * Checks whether the specified component has overlay enabled.
1723:             * 
1724:             * @param component
1725:             *            Component.
1726:             * @return <code>true</code> if the specified component has overlay
1727:             *         enabled, <code>false</code> otherwise.
1728:             */
1729:            public static boolean hasOverlayProperty(Component component) {
1730:                if (component instanceof  JComponent) {
1731:                    Object flatProperty = ((JComponent) component)
1732:                            .getClientProperty(SubstanceLookAndFeel.OVERLAY_PROPERTY);
1733:                    if (Boolean.TRUE.equals(flatProperty))
1734:                        return true;
1735:                    if (Boolean.FALSE.equals(flatProperty))
1736:                        return false;
1737:                }
1738:
1739:                return Boolean.TRUE.equals(UIManager
1740:                        .get(SubstanceLookAndFeel.OVERLAY_PROPERTY));
1741:            }
1742:
1743:            /**
1744:             * Checks whether the specified component has extra Substance-specific UI
1745:             * elements.
1746:             * 
1747:             * @param component
1748:             *            Component.
1749:             * @return <code>true</code> if the specified component has extra
1750:             *         Substance-specific UI elements, <code>false</code> otherwise.
1751:             */
1752:            public static boolean toShowExtraElements(Component component) {
1753:                Component c = component;
1754:                while (c != null) {
1755:                    if (c instanceof  JComponent) {
1756:                        JComponent jcomp = (JComponent) c;
1757:                        Object componentProp = jcomp
1758:                                .getClientProperty(SubstanceLookAndFeel.NO_EXTRA_ELEMENTS);
1759:                        if (componentProp != null) {
1760:                            if (Boolean.TRUE.equals(componentProp))
1761:                                return false;
1762:                            if (Boolean.FALSE.equals(componentProp))
1763:                                return true;
1764:                        }
1765:                    }
1766:                    c = c.getParent();
1767:                }
1768:                return SubstanceLookAndFeel.toShowExtraElements();
1769:            }
1770:
1771:            // /**
1772:            // * Returns the grip painter for the specified component.
1773:            // *
1774:            // * @param component
1775:            // * Component.
1776:            // * @param defaultPainter
1777:            // * Default painter to use if no custom grip painter is specified.
1778:            // * @return The grip painter for the specified component.
1779:            // */
1780:            // public static GripPainter getGripPainter(JComponent component,
1781:            // GripPainter defaultPainter) {
1782:            // Component c = component;
1783:            // while (c != null) {
1784:            // if (c instanceof JComponent) {
1785:            // JComponent jcomp = (JComponent) c;
1786:            // Object jcompSetting = jcomp
1787:            // .getClientProperty(SubstanceLookAndFeel.GRIP_PAINTER);
1788:            // if (jcompSetting instanceof GripPainter)
1789:            // return (GripPainter) jcompSetting;
1790:            // }
1791:            // c = c.getParent();
1792:            // }
1793:            // Object globalSetting = UIManager.get(SubstanceLookAndFeel.GRIP_PAINTER);
1794:            // if (globalSetting instanceof GripPainter)
1795:            // return (GripPainter) globalSetting;
1796:            // return defaultPainter;
1797:            // }
1798:            //
1799:            /**
1800:             * Returns indication whether the specified component's border is a
1801:             * Substance-specific border.
1802:             * 
1803:             * @param c
1804:             *            Component.
1805:             * @return <code>true</code> if the specified component's border is a
1806:             *         Substance-specific border, <code>false</code> otherwise.
1807:             */
1808:            public static boolean hasSubstanceBorder(JComponent c) {
1809:                if (c == null)
1810:                    return false;
1811:
1812:                Border border = c.getBorder();
1813:                if (border instanceof  SubstanceBorder)
1814:                    return true;
1815:
1816:                if (border instanceof  CompoundBorder) {
1817:                    CompoundBorder cb = (CompoundBorder) border;
1818:                    if (cb.getOutsideBorder() instanceof  SubstanceBorder)
1819:                        return true;
1820:                }
1821:
1822:                return false;
1823:            }
1824:
1825:            public static Icon getActiveIcon(Icon origIcon, JComponent comp,
1826:                    ButtonModel model, Icon glowingIcon,
1827:                    boolean ignoreRolloverSetting) {
1828:                if (origIcon == null)
1829:                    return null;
1830:                Icon result = origIcon;
1831:                if (SubstanceCoreUtilities.useThemedDefaultIcon(comp)) {
1832:                    boolean useThemedVersion = !model.isArmed()
1833:                            && !model.isPressed() && !model.isSelected();
1834:                    if (!ignoreRolloverSetting)
1835:                        useThemedVersion = useThemedVersion
1836:                                && !model.isRollover();
1837:                    if (useThemedVersion) {
1838:                        result = new ImageIcon(SubstanceImageCreator
1839:                                .getThemeImage(comp, result,
1840:                                        SubstanceThemeUtilities.getTheme(comp,
1841:                                                ComponentState.DEFAULT), false));
1842:                    }
1843:                }
1844:                if (FadeConfigurationManager.getInstance().fadeAllowed(
1845:                        FadeKind.ICON_GLOW, comp)
1846:                        && model.isRollover() && (glowingIcon != null)) {
1847:                    result = glowingIcon;
1848:                }
1849:                return result;
1850:            }
1851:
1852:            /**
1853:             * Returns the current icon for the specified button. This method is <b>for
1854:             * internal use only</b>.
1855:             * 
1856:             * @param b
1857:             *            Button.
1858:             * @param glowingIcon
1859:             *            The glowing icon.
1860:             * @param ignoreRolloverSetting
1861:             *            If <code>true</code>, the rollover status of the specified
1862:             *            button is ignored.
1863:             * @return Icon for the specified button.
1864:             */
1865:            public static Icon getIcon(AbstractButton b, Icon defaultIcon,
1866:                    Icon glowingIcon, boolean ignoreRolloverSetting) {
1867:                ButtonModel model = b.getModel();
1868:                Icon icon = getActiveIcon(b.getIcon() == null ? defaultIcon : b
1869:                        .getIcon(), b, model, glowingIcon,
1870:                        ignoreRolloverSetting);
1871:                if (icon == null)
1872:                    return null;
1873:
1874:                Icon tmpIcon = null;
1875:
1876:                if (icon != null) {
1877:                    if (!model.isEnabled()) {
1878:                        if (model.isSelected()) {
1879:                            tmpIcon = b.getDisabledSelectedIcon();
1880:                        } else {
1881:                            tmpIcon = b.getDisabledIcon();
1882:                        }
1883:                    } else if (model.isPressed() && model.isArmed()) {
1884:                        tmpIcon = b.getPressedIcon();
1885:                    } else if (b.isRolloverEnabled() && model.isRollover()) {
1886:                        if (model.isSelected()) {
1887:                            tmpIcon = b.getRolloverSelectedIcon();
1888:                        } else {
1889:                            tmpIcon = b.getRolloverIcon();
1890:                        }
1891:                    } else if (model.isSelected()) {
1892:                        tmpIcon = b.getSelectedIcon();
1893:                    }
1894:
1895:                    if (tmpIcon != null) {
1896:                        icon = tmpIcon;
1897:                    }
1898:                }
1899:                return icon;
1900:            }
1901:
1902:            /**
1903:             * Returns the global menu gutter fill kind.
1904:             * 
1905:             * @return The global menu gutter fill kind.
1906:             */
1907:            public static MenuGutterFillKind getMenuGutterFillKind() {
1908:                Object globalSetting = UIManager
1909:                        .get(SubstanceLookAndFeel.MENU_GUTTER_FILL_KIND);
1910:                if (globalSetting instanceof  MenuGutterFillKind)
1911:                    return (MenuGutterFillKind) globalSetting;
1912:                return MenuGutterFillKind.HARD;
1913:            }
1914:
1915:            /**
1916:             * Given a component, returns the parent for computing the
1917:             * {@link SubstanceDecorationPainter}.
1918:             * 
1919:             * @param c
1920:             *            Component.
1921:             * @return The parent for computing the {@link SubstanceDecorationPainter}.
1922:             */
1923:            public static Container getHeaderParent(Component c) {
1924:                Component comp = c.getParent();
1925:                Container result = null;
1926:                while (comp != null) {
1927:                    // the second part fixes the incorrect alignments on
1928:                    // internal frames.
1929:                    if ((comp instanceof  JLayeredPane) && (result == null))
1930:                        result = (Container) comp;
1931:                    if ((result == null) && (comp instanceof  Window))
1932:                        result = (Container) comp;
1933:                    comp = comp.getParent();
1934:                }
1935:                return result;
1936:                //
1937:                // while (comp != null) {
1938:                // if (comp instanceof JToolBar)
1939:                // return (JToolBar) comp;
1940:                // if (comp instanceof JMenuBar)
1941:                // return (JMenuBar) comp;
1942:                // comp = comp.getParent();
1943:                // }
1944:                // return c.getParent();
1945:            }
1946:
1947:            // /**
1948:            // * Checks whether the specified component is inside a container painted by
1949:            // * {@link SubstanceHeaderPainter}.
1950:            // *
1951:            // * @param c
1952:            // * Component.
1953:            // * @return <code>true</code>, if the specified component is inside a
1954:            // * container painted by {@link SubstanceHeaderPainter},
1955:            // * <code>false</code> otherwise.
1956:            // */
1957:            // public static boolean isInHeader(Component c) {
1958:            // Component comp = c.getParent();
1959:            // while (comp != null) {
1960:            // if (comp instanceof JToolBar)
1961:            // return true;
1962:            // if (comp instanceof JMenuBar)
1963:            // return true;
1964:            // if (comp instanceof JComponent) {
1965:            // JComponent jcomp = (JComponent) comp;
1966:            // if (Boolean.TRUE
1967:            // .equals(jcomp
1968:            // .getClientProperty(SubstanceCoreUtilities.IS_WINDOW_DECORATION_AREA))) {
1969:            // return true;
1970:            // }
1971:            // }
1972:            // comp = comp.getParent();
1973:            // }
1974:            //
1975:            // return false;
1976:            // }
1977:
1978:            /**
1979:             * Paints the text.
1980:             * 
1981:             * @param button
1982:             *            Button
1983:             * @param textRect
1984:             *            Text rectangle
1985:             * @param text
1986:             *            Text to paint
1987:             * @param mnemonicIndex
1988:             *            Mnemonic index.
1989:             * @return Text alpha channel.
1990:             */
1991:            public static float paintText(AbstractButton button,
1992:                    Rectangle textRect, String text, int mnemonicIndex) {
1993:                ButtonModel model = button.getModel();
1994:
1995:                // Ignore the selection state of the menu item. This is especially
1996:                // relevant for dark themes.
1997:                ComponentState state = ComponentState.getState(model, button,
1998:                        button instanceof  JMenuItem);
1999:                ComponentState prevState = SubstanceCoreUtilities
2000:                        .getPrevComponentState(button);
2001:
2002:                // special case for enabled buttons with no background -
2003:                // always use the theme for the default state.
2004:                if (SubstanceCoreUtilities.isButtonNeverPainted(button)
2005:                        || !button.isContentAreaFilled()
2006:                        || (button instanceof  JRadioButton)
2007:                        || (button instanceof  JCheckBox)) {
2008:                    if (state.isKindActive(FadeKind.ENABLE)) {
2009:                        state = ComponentState.DEFAULT;
2010:                        prevState = ComponentState.DEFAULT;
2011:                    }
2012:                }
2013:
2014:                return paintText(button, textRect, text, mnemonicIndex, state,
2015:                        prevState);
2016:                // graphics.dispose();
2017:            }
2018:
2019:            public static float paintText(JComponent component,
2020:                    Rectangle textRect, String text, int mnemonicIndex,
2021:                    ComponentState state, ComponentState prevState) {
2022:
2023:                float themeAlpha = SubstanceThemeUtilities.getTheme(component)
2024:                        .getThemeAlpha(component, state);
2025:
2026:                Color fgColor = getForegroundColor(component, state, prevState);
2027:
2028:                boolean isColorized = SubstanceCoreUtilities
2029:                        .hasColorization(component);
2030:                boolean isForegroundUiResource = component.getForeground() instanceof  UIResource;
2031:                if (!isForegroundUiResource && !component.isEnabled()
2032:                        && (themeAlpha == 1.0)) {
2033:                    // Application-specific color on disabled buttons should be "dimmed"
2034:                    // a little. The higher the colorization factor, the more dimming
2035:                    // should be.
2036:                    double colorizationFactor = isColorized ? SubstanceCoreUtilities
2037:                            .getColorizationFactor(component)
2038:                            : 1.0;
2039:                    themeAlpha /= (1.0 + colorizationFactor);
2040:                }
2041:
2042:                // Graphics2D graphics = (Graphics2D) g.create();
2043:
2044:                SubstanceTextPainter textPainter = SubstanceLookAndFeel
2045:                        .getCurrentTextPainter();
2046:
2047:                textPainter.attachText(component, textRect, text,
2048:                        mnemonicIndex, component.getFont(), fgColor, null);
2049:
2050:                return themeAlpha;
2051:            }
2052:
2053:            public static Color getForegroundColor(Component component,
2054:                    ComponentState state, ComponentState prevState) {
2055:                // Three cases:
2056:                // 1. No colorization and the foreground color is UIResource.
2057:                // Interpolate the color based on the button states.
2058:                // 2. No colorization and the foreground color is not a UIResource.
2059:                // Use the button foreground color.
2060:                // 3. Colorization. If the foreground color is not a UIResource,
2061:                // colorize the button theme. Then, interpolate the color based on the
2062:                // button states.
2063:                // compute unshifted theme
2064:                SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
2065:                        component, state);
2066:                boolean isColorized = SubstanceCoreUtilities
2067:                        .hasColorization(component);
2068:                Color buttonFgColor = component.getForeground();
2069:                boolean isForegroundUiResource = buttonFgColor instanceof  UIResource;
2070:                if (isColorized && !isForegroundUiResource) {
2071:                    // case 3
2072:                    double colorizationFactor = SubstanceCoreUtilities
2073:                            .getColorizationFactor(component);
2074:                    theme = SubstanceShiftTheme.getShiftedTheme(theme,
2075:                            buttonFgColor, colorizationFactor, buttonFgColor,
2076:                            colorizationFactor);
2077:                }
2078:                Color fgColor = buttonFgColor;
2079:                if (isColorized || (!isColorized && isForegroundUiResource)) {
2080:                    if (component instanceof  JMenuItem) {
2081:                        fgColor = SubstanceCoreUtilities
2082:                                .getInterpolatedForegroundColor(component,
2083:                                        null, theme, state, prevState,
2084:                                        FadeKind.ROLLOVER, FadeKind.SELECTION,
2085:                                        FadeKind.PRESS, FadeKind.ARM);
2086:                    } else {
2087:                        // if (SwingUtilities
2088:                        // .getAncestorOfClass(JMenuBar.class, component) == null) {
2089:                        fgColor = SubstanceCoreUtilities
2090:                                .getInterpolatedForegroundColor(component,
2091:                                        null, theme, state, prevState,
2092:                                        FadeKind.ROLLOVER, FadeKind.SELECTION,
2093:                                        FadeKind.PRESS);
2094:                        // }
2095:                    }
2096:                }
2097:                return fgColor;
2098:            }
2099:
2100:            // /**
2101:            // * Paints menu text.
2102:            // *
2103:            // * @param menuItem
2104:            // * Menu item.
2105:            // * @param g
2106:            // * Graphics context.
2107:            // * @param text
2108:            // * Text to paint.
2109:            // * @param textRect
2110:            // * Text rectangle.
2111:            // */
2112:            // public static void paintMenuText(JMenuItem menuItem, Graphics g,
2113:            // String text, Rectangle textRect) {
2114:            // int mnemIndex = menuItem.getDisplayedMnemonicIndex();
2115:            //
2116:            // ComponentState state = ComponentState.getState(menuItem.getModel(),
2117:            // menuItem, true);
2118:            // Graphics2D graphics = (Graphics2D) g.create();
2119:            // graphics.setComposite(TransitionLayout.getAlphaComposite(menuItem,
2120:            // SubstanceCoreUtilities.getTheme(menuItem, true).getThemeAlpha(
2121:            // menuItem, state), g));
2122:            //
2123:            // // System.out.println(menuItem.getText() + "->" + graphics.getFont());
2124:            // SubstanceTextPainter textPainter = SubstanceLookAndFeel
2125:            // .getCurrentTextPainter();
2126:            // if (!state.isKindActive(FadeKind.ENABLE)) {
2127:            // graphics
2128:            // .setColor(UIManager.getColor("MenuItem.disabledForeground"));
2129:            // textPainter
2130:            // .paintText(graphics, menuItem, textRect, text, mnemIndex);
2131:            // } else {
2132:            // // Ignore the selection state of the menu item. This is especially
2133:            // // relevant for dark themes.
2134:            // ComponentState prevState = SubstanceCoreUtilities
2135:            // .getPrevComponentState(menuItem);
2136:            // // fix for defect 232 - respect the application menu color
2137:            // Color fg = menuItem.getForeground();
2138:            // if (fg instanceof UIResource) {
2139:            // fg = SubstanceCoreUtilities.getInterpolatedForegroundColor(
2140:            // menuItem, null, SubstanceCoreUtilities
2141:            // .getHighlightTheme(menuItem, menuItem
2142:            // .getParent(), state, true), state,
2143:            // prevState, FadeKind.ROLLOVER, FadeKind.PRESS,
2144:            // FadeKind.ARM, FadeKind.SELECTION);
2145:            // }
2146:            //
2147:            // graphics.setColor(fg);
2148:            // textPainter
2149:            // .paintText(graphics, menuItem, textRect, text, mnemIndex);
2150:            // }
2151:            // graphics.dispose();
2152:            // }
2153:
2154:            /**
2155:             * Paints the focus ring on the specified component.
2156:             * 
2157:             * @param g
2158:             *            Graphics context.
2159:             * @param mainComp
2160:             *            The main component for the focus painting.
2161:             * @param focusedComp
2162:             *            The actual component that has the focus. For example, the main
2163:             *            component can be a {@link JSpinner}, while the focused
2164:             *            component is a text field inside the the spinner editor.
2165:             * @param focusShape
2166:             *            Focus shape. May be <code>null</code> - in this case, the
2167:             *            bounds of <code>mainComp</code> will be used.
2168:             * @param textRect
2169:             *            Text rectangle (if relevant).
2170:             * @param maxAlphaCoef
2171:             *            Maximum alhpa coefficient for painting the focus. Values lower
2172:             *            than 1.0 will result in a translucent focus ring (can be used
2173:             *            to paint a focus ring that doesn't draw too much attention
2174:             *            away from the content, for example on text components).
2175:             * @param extraPadding
2176:             *            Extra padding between the component bounds and the focus ring
2177:             *            painting.
2178:             */
2179:            public static void paintFocus(Graphics g, Component mainComp,
2180:                    Component focusedComp, Shape focusShape,
2181:                    Rectangle textRect, float maxAlphaCoef, int extraPadding) {
2182:                FadeTracker fadeTracker = FadeTracker.getInstance();
2183:                FocusKind focusKind = SubstanceCoreUtilities
2184:                        .getFocusKind(mainComp);
2185:                if ((focusKind == FocusKind.NONE)
2186:                        && (!fadeTracker.isTracked(focusedComp, FadeKind.FOCUS)))
2187:                    return;
2188:
2189:                Graphics2D graphics = (Graphics2D) g.create();
2190:                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
2191:                        RenderingHints.VALUE_ANTIALIAS_ON);
2192:
2193:                float alpha = 1.0f;
2194:                if (fadeTracker.isTracked(focusedComp, FadeKind.FOCUS)) {
2195:                    alpha = fadeTracker.getFade10(focusedComp, FadeKind.FOCUS) / 10.f;
2196:                }
2197:                alpha *= maxAlphaCoef;
2198:                graphics.setComposite(TransitionLayout.getAlphaComposite(
2199:                        mainComp, alpha, g));
2200:
2201:                Color color = SubstanceColorUtilities.getFocusColor(mainComp);
2202:                graphics.setColor(color);
2203:                focusKind.paintFocus(mainComp, focusedComp, graphics,
2204:                        focusShape, textRect, extraPadding);
2205:                graphics.dispose();
2206:            }
2207:
2208:            /**
2209:             * Paints the focus ring on the specified component.
2210:             * 
2211:             * @param g
2212:             *            Graphics context.
2213:             * @param mainComp
2214:             *            The main component for the focus painting.
2215:             * @param focusedComp
2216:             *            The actual component that has the focus. For example, the main
2217:             *            component can be a {@link JSpinner}, while the focused
2218:             *            component is a text field inside the the spinner editor.
2219:             * @param textRect
2220:             *            Text rectangle (if relevant).
2221:             */
2222:            public static void paintFocus(Graphics g, Component mainComp,
2223:                    Component focusedComp, Rectangle textRect) {
2224:                paintFocus(g, mainComp, focusedComp, null, textRect, 1.0f, 0);
2225:            }
2226:
2227:            /**
2228:             * Paints a separator.
2229:             * 
2230:             * @param c
2231:             *            Component.
2232:             * @param graphics
2233:             *            Graphics context.
2234:             * @param colorScheme
2235:             *            Color scheme.
2236:             * @param isDark
2237:             *            Indication whether the color scheme is dark.
2238:             * @param width
2239:             *            Separator width.
2240:             * @param height
2241:             *            Separator height.
2242:             * @param orientation
2243:             *            Separator orientation.
2244:             */
2245:            public static void paintSeparator(Component c, Graphics2D graphics,
2246:                    ColorScheme colorScheme, boolean isDark, int width,
2247:                    int height, int orientation) {
2248:                SubstanceCoreUtilities.paintSeparator(c, graphics, colorScheme,
2249:                        isDark, width, height, orientation, true, 10);
2250:            }
2251:
2252:            /**
2253:             * Paints a separator.
2254:             * 
2255:             * @param c
2256:             *            Component.
2257:             * @param graphics
2258:             *            Graphics context.
2259:             * @param colorScheme
2260:             *            Color scheme.
2261:             * @param isDark
2262:             *            Indication whether the color scheme is dark.
2263:             * @param width
2264:             *            Separator width.
2265:             * @param height
2266:             *            Separator height.
2267:             * @param orientation
2268:             *            Separator orientation.
2269:             * @param hasShadow
2270:             *            If <code>true</code>, the separator painting will have
2271:             *            shadow.
2272:             * @param maxGradLength
2273:             *            Specifies the maximum pixel length of "ramp" portions of the
2274:             *            separator. The ramp portions are located on separator ends and
2275:             *            allow providing a faded appearance on those ends.
2276:             */
2277:            public static void paintSeparator(Component c, Graphics2D graphics,
2278:                    ColorScheme colorScheme, boolean isDark, int width,
2279:                    int height, int orientation, boolean hasShadow,
2280:                    int maxGradLength) {
2281:                paintSeparator(c, graphics, colorScheme, isDark, width, height,
2282:                        orientation, hasShadow, maxGradLength, maxGradLength);
2283:            }
2284:
2285:            /**
2286:             * Paints a separator.
2287:             * 
2288:             * @param c
2289:             *            Component.
2290:             * @param graphics
2291:             *            Graphics context.
2292:             * @param colorScheme
2293:             *            Color scheme.
2294:             * @param isDark
2295:             *            Indication whether the color scheme is dark.
2296:             * @param width
2297:             *            Separator width.
2298:             * @param height
2299:             *            Separator height.
2300:             * @param orientation
2301:             *            Separator orientation.
2302:             * @param hasShadow
2303:             *            If <code>true</code>, the separator painting will have
2304:             *            shadow.
2305:             * @param maxGradLengthStart
2306:             *            Specifies the maximum pixel length of the starting "ramp"
2307:             *            portion of the separator. The starting ramp portion is located
2308:             *            on top / left separator end and allows providing a faded
2309:             *            appearance on that end.
2310:             * @param maxGradLengthEnd
2311:             *            Specifies the maximum pixel length of the ending "ramp"
2312:             *            portion of the separator. The ending ramp portion is located
2313:             *            on bottom / right separator end and allows providing a faded
2314:             *            appearance on that end.
2315:             */
2316:            public static void paintSeparator(Component c, Graphics2D graphics,
2317:                    ColorScheme colorScheme, boolean isDark, int width,
2318:                    int height, int orientation, boolean hasShadow,
2319:                    int maxGradLengthStart, int maxGradLengthEnd) {
2320:                Color foreLight = isDark ? colorScheme.getLightColor()
2321:                        : SubstanceColorUtilities.getInterpolatedColor(
2322:                                colorScheme.getLightColor(), colorScheme
2323:                                        .getDarkColor(), 0.8);
2324:                Color foreDark = isDark ? colorScheme.getExtraLightColor()
2325:                        : SubstanceColorUtilities.getInterpolatedColor(
2326:                                colorScheme.getMidColor(), colorScheme
2327:                                        .getDarkColor(), 0.4);
2328:                Color back = isDark ? colorScheme.getDarkColor() : colorScheme
2329:                        .getUltraLightColor();
2330:
2331:                float borderStrokeWidth = SubstanceSizeUtils
2332:                        .getBorderStrokeWidth(SubstanceSizeUtils
2333:                                .getComponentFontSize(c));
2334:                graphics.setStroke(new BasicStroke(borderStrokeWidth,
2335:                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
2336:                if (orientation == JSeparator.VERTICAL) {
2337:                    int gradStart = Math.min(maxGradLengthStart, height / 2);
2338:                    int gradEnd = Math.min(maxGradLengthEnd, height / 2);
2339:                    graphics.translate(Math.max(0, width / 2 - 1), 0);
2340:                    graphics.setPaint(new GradientPaint(0, 0,
2341:                            SubstanceColorUtilities
2342:                                    .getAlphaColor(foreLight, 32), 0,
2343:                            gradStart, SubstanceColorUtilities.getAlphaColor(
2344:                                    foreDark, 240)));
2345:                    graphics.drawLine(0, 0, 0, gradStart);
2346:                    if (height / 2 > gradStart) {
2347:                        graphics.setColor(SubstanceColorUtilities
2348:                                .getAlphaColor(foreDark, 240));
2349:                        graphics.drawLine(0, gradStart, 0, height - gradEnd);
2350:                    }
2351:                    graphics.setPaint(new GradientPaint(0, height - gradEnd,
2352:                            SubstanceColorUtilities
2353:                                    .getAlphaColor(foreDark, 240), 0, height,
2354:                            SubstanceColorUtilities
2355:                                    .getAlphaColor(foreLight, 32)));
2356:                    graphics.drawLine(0, height - gradEnd, 0, height);
2357:
2358:                    if (hasShadow) {
2359:                        int offset = (int) borderStrokeWidth;
2360:                        graphics
2361:                                .setPaint(new GradientPaint(offset, 0,
2362:                                        SubstanceColorUtilities.getAlphaColor(
2363:                                                back, 32), offset, gradStart,
2364:                                        SubstanceColorUtilities.getAlphaColor(
2365:                                                back, 196)));
2366:                        graphics.drawLine(offset, 0, offset, gradStart);
2367:                        if (height / 2 > gradStart) {
2368:                            graphics.setColor(SubstanceColorUtilities
2369:                                    .getAlphaColor(back, 196));
2370:                            graphics.drawLine(offset, gradStart, offset, height
2371:                                    - gradEnd);
2372:                        }
2373:                        graphics
2374:                                .setPaint(new GradientPaint(offset, height
2375:                                        - gradEnd, SubstanceColorUtilities
2376:                                        .getAlphaColor(back, 196), offset,
2377:                                        height, SubstanceColorUtilities
2378:                                                .getAlphaColor(back, 32)));
2379:                        graphics.drawLine(offset, height - gradEnd, offset,
2380:                                height);
2381:                    }
2382:                } else {
2383:                    // HORIZONTAL
2384:                    int gradStart = Math.min(maxGradLengthStart, width / 2);
2385:                    int gradEnd = Math.min(maxGradLengthEnd, width / 2);
2386:                    graphics.translate(0, Math.max(0, height / 2 - 1));
2387:                    graphics.setPaint(new GradientPaint(0, 0,
2388:                            SubstanceColorUtilities
2389:                                    .getAlphaColor(foreLight, 32), gradStart,
2390:                            0, SubstanceColorUtilities.getAlphaColor(foreDark,
2391:                                    240)));
2392:                    graphics.drawLine(0, 0, gradStart, 0);
2393:                    // if (width / 2 > gradStart) {
2394:                    graphics.setColor(SubstanceColorUtilities.getAlphaColor(
2395:                            foreDark, 240));
2396:                    graphics.drawLine(gradStart, 0, width - gradEnd, 0);
2397:                    // }
2398:                    graphics.setPaint(new GradientPaint(width - gradEnd, 0,
2399:                            SubstanceColorUtilities
2400:                                    .getAlphaColor(foreDark, 240), width, 0,
2401:                            SubstanceColorUtilities
2402:                                    .getAlphaColor(foreLight, 32)));
2403:                    graphics.drawLine(width - gradEnd, 0, width, 0);
2404:
2405:                    if (hasShadow) {
2406:                        int offset = (int) borderStrokeWidth;
2407:                        graphics
2408:                                .setPaint(new GradientPaint(0, offset,
2409:                                        SubstanceColorUtilities.getAlphaColor(
2410:                                                back, 32), gradStart, offset,
2411:                                        SubstanceColorUtilities.getAlphaColor(
2412:                                                back, 196)));
2413:                        graphics.drawLine(0, offset, gradStart, offset);
2414:                        // if (width / 2 > gradStart) {
2415:                        graphics.setColor(SubstanceColorUtilities
2416:                                .getAlphaColor(back, 196));
2417:                        graphics.drawLine(gradStart, offset, width - gradEnd,
2418:                                offset);
2419:                        // }
2420:                        graphics
2421:                                .setPaint(new GradientPaint(width - gradEnd,
2422:                                        offset, SubstanceColorUtilities
2423:                                                .getAlphaColor(back, 196),
2424:                                        width, offset, SubstanceColorUtilities
2425:                                                .getAlphaColor(back, 32)));
2426:                        graphics.drawLine(width - gradEnd, offset, width,
2427:                                offset);
2428:                    }
2429:                }
2430:
2431:            }
2432:
2433:            /**
2434:             * Returns indication whether the specified button is a close button on some
2435:             * title pane.
2436:             * 
2437:             * @param ab
2438:             *            Button.
2439:             * @return <code>true</code> if the specified button is a close button on
2440:             *         some title pane, <code>false</code> otherwise.
2441:             */
2442:            public static boolean isTitleCloseButton(AbstractButton ab) {
2443:                if ((ab instanceof  SubstanceTitleButton)
2444:                        && Boolean.TRUE
2445:                                .equals(ab
2446:                                        .getClientProperty(SubstanceButtonUI.IS_TITLE_CLOSE_BUTTON)))
2447:                    return true;
2448:                return false;
2449:            }
2450:
2451:            /**
2452:             * Uninstalls the specified menu item.
2453:             * 
2454:             * @param menuItem
2455:             *            Menu item.
2456:             */
2457:            public static void uninstallMenu(JMenuItem menuItem) {
2458:                if (menuItem instanceof  JMenu) {
2459:                    JMenu menu = (JMenu) menuItem;
2460:                    for (Component comp : menu.getMenuComponents())
2461:                        if (comp instanceof  JMenuItem)
2462:                            SubstanceCoreUtilities
2463:                                    .uninstallMenu((JMenuItem) comp);
2464:                }
2465:
2466:                ButtonUI menuItemUI = menuItem.getUI();
2467:                if (menuItemUI instanceof  SubstanceMenu) {
2468:                    SubstanceMenu sMenu = (SubstanceMenu) menuItemUI;
2469:                    if (sMenu.getAssociatedMenuItem() != null) {
2470:                        menuItemUI.uninstallUI(menuItem);
2471:                    }
2472:                }
2473:
2474:                for (ActionListener actionListener : menuItem
2475:                        .getActionListeners())
2476:                    menuItem.removeActionListener(actionListener);
2477:
2478:                menuItem.removeAll();
2479:            }
2480:
2481:            /**
2482:             * Returns an icon pointed to by the specified string.
2483:             * 
2484:             * @param iconResource
2485:             *            Resource location string.
2486:             * @return Icon.
2487:             */
2488:            public static Icon getIcon(String iconResource) {
2489:                ClassLoader cl = getClassLoaderForResources();
2490:                URL iconUrl = cl.getResource(iconResource);
2491:                if (iconUrl == null)
2492:                    return null;
2493:                return new IconUIResource(new ImageIcon(iconUrl));
2494:            }
2495:
2496:            public static ClassLoader getClassLoaderForResources() {
2497:                // the following is fix by Dag Joar and Christian Schlichtherle
2498:                // for application running with -Xbootclasspath VM flag. In this case,
2499:                // the using MyClass.class.getClassLoader() would return null,
2500:                // but the context class loader will function properly that classes will
2501:                // be properly loaded regardless of whether the lib is added to the
2502:                // system class path, the extension class path and regardless of the
2503:                // class loader architecture set up by some frameworks.
2504:                ClassLoader cl = (ClassLoader) UIManager.get("ClassLoader");
2505:                if (cl == null)
2506:                    cl = Thread.currentThread().getContextClassLoader();
2507:                return cl;
2508:            }
2509:
2510:            /**
2511:             * Returns the fade callback for the specified button.
2512:             * 
2513:             * @param button
2514:             *            Button.
2515:             * @return Fade callback for the specified button.
2516:             */
2517:            public static FadeTrackerCallback getFadeCallback(
2518:                    final AbstractButton button, boolean toRepaintParent) {
2519:                return getFadeCallback(button, button.getModel(), false,
2520:                        toRepaintParent, button);
2521:            }
2522:
2523:            /**
2524:             * Returns the fade callback for the specified component.
2525:             * 
2526:             * @param component
2527:             *            Component.
2528:             * @param model
2529:             *            Model for tracking the transitions. For button components,
2530:             *            pass the {@link AbstractButton#getModel()}, for other
2531:             *            controls pass a dummy (synthesized) model.
2532:             * @param toIgnoreSelection
2533:             *            If <code>true</code>, the {@link ButtonModel#isSelected()}
2534:             *            will not be checked. This can be used for tracking transitions
2535:             *            on menu items that use <code>armed</code> state instead,
2536:             *            when we don't want to use different rollover themes for
2537:             *            selected and unselected checkbox and radio button menu items
2538:             *            (to preserve consistent visual appearence of highlights).
2539:             * @return Fade callback for the specified component.
2540:             */
2541:            public static FadeTrackerCallback getFadeCallback(
2542:                    final JComponent component, final ButtonModel model,
2543:                    final boolean toIgnoreSelection,
2544:                    final boolean toRepaintParent,
2545:                    final Component componentToRepaint) {
2546:                if (isScrollButton(component))
2547:                    return null;
2548:                FadeTrackerCallback callback = new FadeTrackerAdapter() {
2549:                    @Override
2550:                    public void fadeReversed(FadeKind fadeKind,
2551:                            boolean isFadingIn, float fadeCycle10) {
2552:                        component
2553:                                .putClientProperty(
2554:                                        SubstanceCoreUtilities.PREV_COMPONENT_STATE,
2555:                                        component
2556:                                                .getClientProperty(SubstanceCoreUtilities.NEXT_COMPONENT_STATE));
2557:                        component
2558:                                .putClientProperty(
2559:                                        SubstanceCoreUtilities.PREV_SEL_COMPONENT_STATE,
2560:                                        component
2561:                                                .getClientProperty(SubstanceCoreUtilities.NEXT_SEL_COMPONENT_STATE));
2562:                        // String text = (component instanceof AbstractButton) ?
2563:                        // ((AbstractButton)
2564:                        // component)
2565:                        // .getText()
2566:                        // : "";
2567:                        // System.out.println(component.getClass().getSimpleName()
2568:                        // + "["
2569:                        // + text
2570:                        // + "]"
2571:                        // + " : "
2572:                        // + fadeKind.toString()
2573:                        // + " - tracking prev as "
2574:                        // + ((ComponentState) component
2575:                        // .getClientProperty(PREV_COMPONENT_STATE))
2576:                        // .name());
2577:                        if (!toRepaintParent) {
2578:                            componentToRepaint.repaint();
2579:                        } else {
2580:                            Container parent = component.getParent();
2581:                            if (parent != null) {
2582:                                parent.repaint();
2583:                            }
2584:                        }
2585:                    }
2586:
2587:                    /*
2588:                     * (non-Javadoc)
2589:                     * 
2590:                     * @see org.jvnet.lafwidget.animation.FadeTrackerAdapter#fadeEnded(org.jvnet.lafwidget.animation.FadeKind)
2591:                     */
2592:                    @Override
2593:                    public void fadeEnded(FadeKind fadeKind) {
2594:                        // System.out.println(toIgnoreSelection);
2595:                        component.putClientProperty(
2596:                                SubstanceCoreUtilities.PREV_COMPONENT_STATE,
2597:                                ComponentState.getState(model, component,
2598:                                        toIgnoreSelection));
2599:                        component
2600:                                .putClientProperty(
2601:                                        SubstanceCoreUtilities.PREV_SEL_COMPONENT_STATE,
2602:                                        ComponentState.getState(model,
2603:                                                component, false));
2604:                        component.putClientProperty(
2605:                                SubstanceCoreUtilities.NEXT_COMPONENT_STATE,
2606:                                null);
2607:                        component
2608:                                .putClientProperty(
2609:                                        SubstanceCoreUtilities.NEXT_SEL_COMPONENT_STATE,
2610:                                        null);
2611:                        // String text = (component instanceof AbstractButton) ?
2612:                        // ((AbstractButton)
2613:                        // component)
2614:                        // .getText()
2615:                        // : "";
2616:                        // ComponentState prevState = (ComponentState) component
2617:                        // .getClientProperty(PREV_COMPONENT_STATE);
2618:                        // System.out.println(component.getClass().getSimpleName() + "["
2619:                        // + text + "]" + " : " + fadeKind.toString()
2620:                        // + " - tracking prev as " + prevState.name());
2621:                        if (!toRepaintParent) {
2622:                            SwingUtilities.invokeLater(new Runnable() {
2623:                                public void run() {
2624:                                    if (component instanceof  JMenuItem) {
2625:                                        if (isCoveredByLightweightPopups(component)) {
2626:                                            component
2627:                                                    .putClientProperty(
2628:                                                            SubstanceCoreUtilities.IS_COVERED_BY_LIGHTWEIGHT_POPUPS,
2629:                                                            Boolean.TRUE);
2630:                                        } else {
2631:                                            component
2632:                                                    .putClientProperty(
2633:                                                            SubstanceCoreUtilities.IS_COVERED_BY_LIGHTWEIGHT_POPUPS,
2634:                                                            null);
2635:                                        }
2636:                                    }
2637:                                    componentToRepaint.repaint();
2638:                                }
2639:                            });
2640:                        } else {
2641:                            Container parent = component.getParent();
2642:                            if (parent != null) {
2643:                                parent.repaint();
2644:                            }
2645:                        }
2646:                    }
2647:
2648:                    @Override
2649:                    public void fadePerformed(FadeKind fadeKind,
2650:                            float fadeCycle10) {
2651:                        component.putClientProperty(
2652:                                SubstanceCoreUtilities.NEXT_COMPONENT_STATE,
2653:                                ComponentState.getState(model, component,
2654:                                        toIgnoreSelection));
2655:                        component
2656:                                .putClientProperty(
2657:                                        SubstanceCoreUtilities.NEXT_SEL_COMPONENT_STATE,
2658:                                        ComponentState.getState(model,
2659:                                                component, false));
2660:                        if (!toRepaintParent) {
2661:                            SwingUtilities.invokeLater(new Runnable() {
2662:                                public void run() {
2663:                                    if (component instanceof  JMenuItem) {
2664:                                        if (isCoveredByLightweightPopups(component)) {
2665:                                            component
2666:                                                    .putClientProperty(
2667:                                                            SubstanceCoreUtilities.IS_COVERED_BY_LIGHTWEIGHT_POPUPS,
2668:                                                            Boolean.TRUE);
2669:                                        } else {
2670:                                            component
2671:                                                    .putClientProperty(
2672:                                                            SubstanceCoreUtilities.IS_COVERED_BY_LIGHTWEIGHT_POPUPS,
2673:                                                            null);
2674:                                        }
2675:                                    }
2676:                                    componentToRepaint.repaint();
2677:                                }
2678:                            });
2679:                        } else {
2680:                            Container parent = component.getParent();
2681:                            if (parent != null) {
2682:                                parent.repaint();
2683:                            }
2684:                        }
2685:                    }
2686:
2687:                    private boolean isCoveredByLightweightPopups(
2688:                            final Component comp) {
2689:                        JRootPane rootPane = SwingUtilities.getRootPane(comp);
2690:                        if (rootPane == null)
2691:                            return false;
2692:                        Component[] popups = rootPane.getLayeredPane()
2693:                                .getComponentsInLayer(JLayeredPane.POPUP_LAYER);
2694:                        if (popups == null)
2695:                            return false;
2696:
2697:                        // System.out.println("Has " + popups.length + " popups");
2698:
2699:                        // Convert the component bounds to the layered pane.
2700:                        // Can't use the SwingUtilities.convertRectangle() as that
2701:                        // eventually will try to acquire the lock on the container
2702:                        Rectangle compBoundsConverted = SwingUtilities
2703:                                .convertRectangle(comp.getParent(), comp
2704:                                        .getBounds(), rootPane.getLayeredPane());
2705:
2706:                        // System.out.println("Bounds : \n\torig : " + comp.getBounds()
2707:                        // + "\n\ttrans:" + compBoundsConverted);
2708:
2709:                        int popupIndexToStartWith = getPopupParentIndexOf(comp,
2710:                                popups) - 1;
2711:                        // String txt = (comp instanceof JMenuItem) ? ((JMenuItem) comp)
2712:                        // .getText() : "";
2713:                        // System.out.println("Starting scan from popup "
2714:                        // + popupIndexToStartWith + " for " + txt);
2715:                        for (int i = popupIndexToStartWith; i >= 0; i--) {
2716:                            Component popup = popups[i];
2717:                            // System.out.println("Popup " +
2718:                            // popup.getClass().getName());
2719:                            // System.out.println("Popup bounds " + popup.getBounds());
2720:                            if (compBoundsConverted.intersects(popup
2721:                                    .getBounds())) {
2722:                                return true;
2723:                            }
2724:                        }
2725:                        return false;
2726:                    }
2727:                };
2728:                return callback;
2729:            }
2730:
2731:            public static int getPopupParentIndexOf(Component comp,
2732:                    Component[] popups) {
2733:                for (int i = 0; i < popups.length; i++) {
2734:                    Component popup = popups[i];
2735:
2736:                    Component currComp = comp;
2737:                    while (currComp != null) {
2738:                        if (currComp == popup) {
2739:                            return i;
2740:                        }
2741:                        currComp = currComp.getParent();
2742:                    }
2743:                }
2744:                return popups.length;
2745:            }
2746:
2747:            /**
2748:             * Returns the previous state of the specified component.
2749:             * 
2750:             * @param comp
2751:             *            Component.
2752:             * @return The previous state of the specified component.
2753:             */
2754:            public static ComponentState getPrevComponentState(JComponent comp) {
2755:                ComponentState result = (ComponentState) comp
2756:                        .getClientProperty(PREV_COMPONENT_STATE);
2757:                if (result == null) {
2758:                    result = ComponentState.DEFAULT;
2759:                }
2760:                return result;
2761:            }
2762:
2763:            /**
2764:             * Returns the previous state of the specified component.
2765:             * 
2766:             * @param comp
2767:             *            Component.
2768:             * @return The previous state of the specified component.
2769:             */
2770:            public static ComponentState getPrevSelComponentState(
2771:                    JComponent comp) {
2772:                ComponentState result = (ComponentState) comp
2773:                        .getClientProperty(PREV_SEL_COMPONENT_STATE);
2774:                if (result == null) {
2775:                    result = ComponentState.DEFAULT;
2776:                }
2777:                return result;
2778:            }
2779:
2780:            /**
2781:             * Checks whether a component has the specified client property set to the
2782:             * specified value.
2783:             * 
2784:             * @param comp
2785:             *            Component.
2786:             * @param propertyName
2787:             *            Client property name.
2788:             * @param expectedValue
2789:             *            Expected value.
2790:             * @param checkHierarchy
2791:             *            if <code>true</code>, the entire component hierarchy is
2792:             *            traversed.
2793:             * @return <code>true</code> if the component has the specified client
2794:             *         property set to the specified value, <code>false</code>
2795:             *         otherwise.
2796:             */
2797:            public static boolean hasPropertySetTo(Component comp,
2798:                    String propertyName, boolean expectedValue,
2799:                    boolean checkHierarchy) {
2800:                if (!checkHierarchy) {
2801:                    if (comp instanceof  JComponent) {
2802:                        JComponent jcomp = (JComponent) comp;
2803:                        Object componentProp = jcomp
2804:                                .getClientProperty(propertyName);
2805:                        if (componentProp != null) {
2806:                            if (componentProp.equals(expectedValue))
2807:                                return true;
2808:                        }
2809:                    }
2810:                } else {
2811:                    Component c = comp;
2812:                    while (c != null) {
2813:                        if (c instanceof  JComponent) {
2814:                            JComponent jcomp = (JComponent) c;
2815:                            Object componentProp = jcomp
2816:                                    .getClientProperty(propertyName);
2817:                            if (componentProp != null) {
2818:                                if (componentProp.equals(expectedValue))
2819:                                    return true;
2820:                            }
2821:                        }
2822:                        c = c.getParent();
2823:                    }
2824:                }
2825:                Object globalProp = UIManager.get(propertyName);
2826:                if (globalProp != null) {
2827:                    return globalProp.equals(expectedValue);
2828:                }
2829:                return false;
2830:            }
2831:
2832:            /**
2833:             * Returns the resource bundle for the specified component.
2834:             * 
2835:             * @param jcomp
2836:             *            Component.
2837:             * @return Resource bundle for the specified component.
2838:             */
2839:            public static ResourceBundle getResourceBundle(JComponent jcomp) {
2840:                if (LafWidgetUtilities.toIgnoreGlobalLocale(jcomp)) {
2841:                    return SubstanceLookAndFeel.getLabelBundle(jcomp
2842:                            .getLocale());
2843:                } else {
2844:                    return SubstanceLookAndFeel.getLabelBundle();
2845:                }
2846:            }
2847:
2848:            /**
2849:             * Returns the border painter for the specified component.
2850:             * 
2851:             * @param comp
2852:             *            Component.
2853:             * @return Border painter for the specified component.
2854:             */
2855:            public static SubstanceBorderPainter getBorderPainter(Component comp) {
2856:                // check the client property on component hierarchy
2857:                while (comp != null) {
2858:                    if (comp instanceof  JComponent) {
2859:                        Object clientProp = ((JComponent) comp)
2860:                                .getClientProperty(SubstanceLookAndFeel.BORDER_PAINTER_PROPERTY);
2861:                        if (clientProp instanceof  SubstanceBorderPainter)
2862:                            return (SubstanceBorderPainter) clientProp;
2863:                        if (clientProp instanceof  String) {
2864:                            try {
2865:                                return (SubstanceBorderPainter) Class.forName(
2866:                                        (String) clientProp).newInstance();
2867:                            } catch (Exception exc) {
2868:                            }
2869:                        }
2870:                    }
2871:                    comp = comp.getParent();
2872:                }
2873:                // check property on UIManager
2874:                Object globalProp = UIManager
2875:                        .get(SubstanceLookAndFeel.BORDER_PAINTER_PROPERTY);
2876:                if (globalProp instanceof  SubstanceBorderPainter)
2877:                    return (SubstanceBorderPainter) globalProp;
2878:                if (globalProp instanceof  String) {
2879:                    try {
2880:                        return (SubstanceBorderPainter) Class.forName(
2881:                                (String) globalProp).newInstance();
2882:                    } catch (Exception exc) {
2883:                    }
2884:                }
2885:                // return currently installed global border painter
2886:                return SubstanceLookAndFeel.getCurrentBorderPainter();
2887:            }
2888:
2889:            /**
2890:             * Resets the menu bars on the specified component.
2891:             * 
2892:             * @param component
2893:             *            Component.
2894:             */
2895:            public static void resetMenuBars(Component component) {
2896:                if (component instanceof  JRootPane) {
2897:                    JRootPane jrp = (JRootPane) component;
2898:                    JMenuBar jmb = jrp.getJMenuBar();
2899:                    if (jmb != null) {
2900:                        MenuBarUI ui = jmb.getUI();
2901:                        if (ui instanceof  SubstanceMenuBarUI) {
2902:                            Set<?> lafWidgets = ((SubstanceMenuBarUI) ui)
2903:                                    .getLafWidgets();
2904:                            for (Iterator<?> it = lafWidgets.iterator(); it
2905:                                    .hasNext();) {
2906:                                LafWidget lw = (LafWidget) it.next();
2907:                                if (lw instanceof  Resettable) {
2908:                                    ((Resettable) lw).reset();
2909:                                }
2910:                            }
2911:                        }
2912:                    }
2913:                }
2914:                if (component instanceof  Container) {
2915:                    Container cont = (Container) component;
2916:                    for (int i = 0; i < cont.getComponentCount(); i++) {
2917:                        Component child = cont.getComponent(i);
2918:                        resetMenuBars(child);
2919:                    }
2920:                }
2921:            }
2922:
2923:            /**
2924:             * Returns the foreground color for the specified component.
2925:             * 
2926:             * @param comp
2927:             *            Component.
2928:             * @param componentId
2929:             *            Optional component ID. Can be used to differentiate sub-parts
2930:             *            of the component, such as tabs in tabbed pane, cells in list
2931:             *            etc.
2932:             * @param theme
2933:             *            Component theme.
2934:             * @param state
2935:             *            Component current state.
2936:             * @param prevState
2937:             *            Component previous state.
2938:             * @param kinds
2939:             *            Animation kinds to consult for computing the foreground color.
2940:             * @return Foreground color.
2941:             */
2942:            public static Color getInterpolatedForegroundColor(Component comp,
2943:                    Comparable<?> componentId, SubstanceTheme theme,
2944:                    ComponentState state, ComponentState prevState,
2945:                    FadeKind... kinds) {
2946:                ColorScheme colorScheme = theme.getColorScheme();
2947:                ColorScheme colorScheme2 = colorScheme;
2948:                float cyclePos = state.getCycleCount();
2949:
2950:                FadeState fadeState = SubstanceFadeUtilities.getFadeState(comp,
2951:                        componentId, kinds);
2952:                if (fadeState != null) {
2953:                    colorScheme = SubstanceThemeUtilities.getTheme(comp, state)
2954:                            .getColorScheme();
2955:                    colorScheme2 = SubstanceThemeUtilities.getTheme(comp,
2956:                            prevState).getColorScheme();
2957:                    cyclePos = fadeState.getFadePosition();
2958:                    if (!fadeState.isFadingIn())
2959:                        cyclePos = 10 - cyclePos;
2960:                }
2961:
2962:                Color c1 = colorScheme.getForegroundColor();
2963:                Color c2 = colorScheme2.getForegroundColor();
2964:
2965:                // // special case for components in default state on menu bar
2966:                // if (comp.getParent() instanceof JMenuBar) {
2967:                // Color menuBarForegr = UIManager.getColor("MenuBar.foreground");
2968:                // if (SubstanceCoreUtilities.hasColorization(comp)) {
2969:                // Color fore = comp.getForeground();
2970:                // if (!(fore instanceof UIResource)) {
2971:                // double colorizationFactor = SubstanceCoreUtilities
2972:                // .getColorizationFactor(comp);
2973:                // if (!comp.isEnabled())
2974:                // colorizationFactor /= 2.0;
2975:                // Color toShiftTo = SubstanceColorUtilities
2976:                // .deriveByBrightness(fore, menuBarForegr);
2977:                // menuBarForegr = SubstanceColorUtilities
2978:                // .getInterpolatedColor(toShiftTo, menuBarForegr,
2979:                // colorizationFactor);
2980:                // }
2981:                // }
2982:                // if (state == ComponentState.DEFAULT)
2983:                // c1 = menuBarForegr;
2984:                // if (prevState == ComponentState.DEFAULT)
2985:                // c2 = menuBarForegr;
2986:                // }
2987:
2988:                return SubstanceColorUtilities.getInterpolatedColor(c1, c2,
2989:                        cyclePos / 10.);
2990:            }
2991:
2992:            /**
2993:             * Paints text with drop shadow.
2994:             * 
2995:             * @param c
2996:             *            Component.
2997:             * @param g
2998:             *            Graphics context.
2999:             * @param foregroundColor
3000:             *            Foreground color.
3001:             * @param text
3002:             *            Text to paint.
3003:             * @param width
3004:             *            Text rectangle width.
3005:             * @param height
3006:             *            Text rectangle height.
3007:             * @param xOffset
3008:             *            Text rectangle X offset.
3009:             * @param yOffset
3010:             *            Text rectangle Y offset.
3011:             */
3012:            public static void paintTextWithDropShadow(final JComponent c,
3013:                    Graphics g, Color foregroundColor, String text, int width,
3014:                    int height, int xOffset, int yOffset) {
3015:                Graphics2D graphics = (Graphics2D) g.create();
3016:
3017:                // blur the text shadow
3018:                BufferedImage blurred = SubstanceCoreUtilities.getBlankImage(
3019:                        width, height);
3020:                Graphics2D gBlurred = (Graphics2D) blurred.getGraphics();
3021:                gBlurred.setFont(graphics.getFont());
3022:                gBlurred.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
3023:                        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
3024:                // Color neg =
3025:                // SubstanceColorUtilities.getNegativeColor(foregroundColor);
3026:                final float luminFactor = SubstanceColorUtilities
3027:                        .getColorStrength(foregroundColor);
3028:                gBlurred.setColor(SubstanceColorUtilities
3029:                        .getNegativeColor(foregroundColor));
3030:                ConvolveOp convolve = new ConvolveOp(new Kernel(3, 3,
3031:                        new float[] { .0f, .05f, .1f, .05f, .0f, .1f, .1f, .1f,
3032:                                .1f }), ConvolveOp.EDGE_NO_OP, null);
3033:                gBlurred.drawString(text, xOffset + 1, yOffset + 1);
3034:                blurred = convolve.filter(blurred, null);
3035:
3036:                SubstanceTextPainter textPainter = SubstanceLookAndFeel
3037:                        .getCurrentTextPainter();
3038:                if (textPainter.needsBackgroundImage()) {
3039:                    final BufferedImage finalBlurred = blurred;
3040:                    textPainter
3041:                            .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
3042:                                public void paintBackground(Graphics g) {
3043:                                    Graphics2D graphics = (Graphics2D) g
3044:                                            .create();
3045:                                    graphics.setComposite(TransitionLayout
3046:                                            .getAlphaComposite(c, luminFactor,
3047:                                                    g));
3048:                                    graphics
3049:                                            .drawImage(finalBlurred, 0, 0, null);
3050:                                    graphics.setComposite(TransitionLayout
3051:                                            .getAlphaComposite(c, g));
3052:                                    graphics.dispose();
3053:                                }
3054:                            });
3055:                } else {
3056:                    graphics.setComposite(TransitionLayout.getAlphaComposite(c,
3057:                            luminFactor, g));
3058:                    graphics.drawImage(blurred, 0, 0, null);
3059:                    graphics.setComposite(TransitionLayout.getAlphaComposite(c,
3060:                            g));
3061:                }
3062:
3063:                // graphics.setColor(foregroundColor);
3064:                // RenderingUtils.installDesktopHints(graphics);
3065:                FontMetrics fm = graphics.getFontMetrics();
3066:                textPainter.attachText(c, new Rectangle(xOffset, yOffset
3067:                        - fm.getAscent(), width - xOffset, fm.getHeight()),
3068:                        text, -1, graphics.getFont(), foregroundColor, graphics
3069:                                .getClipBounds());
3070:                // textPainter.paint(graphics);
3071:                // graphics.drawString(text, xOffset, yOffset);
3072:
3073:                graphics.dispose();
3074:            }
3075:
3076:            /**
3077:             * Provides workaround for <a
3078:             * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6576507">bug
3079:             * 6576507</a>. This is especially relevant for skins that use translucent
3080:             * themes, such as {@link AutumnSkin} and {@link MagmaSkin}.
3081:             * 
3082:             * @param graphics
3083:             *            Graphics context.
3084:             */
3085:            public static void workaroundBug6576507(Graphics graphics) {
3086:                Font font = graphics.getFont();
3087:                font = font.deriveFont(font.getStyle(), font.getSize2D());
3088:                graphics.setFont(font);
3089:            }
3090:
3091:            /**
3092:             * Returns the component hierarchy.
3093:             * 
3094:             * @param comp
3095:             *            Component.
3096:             * @return Component hierarchy string.
3097:             */
3098:            public static String getHierarchy(Component comp) {
3099:                StringBuffer buffer = new StringBuffer();
3100:                getHierarchy(comp, buffer, 0);
3101:                while (true) {
3102:                    if (comp instanceof  Window) {
3103:                        Window w = (Window) comp;
3104:                        comp = w.getOwner();
3105:                        if (comp != null) {
3106:                            buffer.append("Owner --->\n");
3107:                            getHierarchy(comp, buffer, 0);
3108:                        }
3109:                    } else {
3110:                        break;
3111:                    }
3112:                }
3113:                return buffer.toString();
3114:            }
3115:
3116:            /**
3117:             * Computes the component hierarchy.
3118:             * 
3119:             * @param comp
3120:             *            Component.
3121:             * @param buffer
3122:             *            Hierarchy representation buffer.
3123:             * @param level
3124:             *            Hierarchy level.
3125:             */
3126:            public static void getHierarchy(Component comp,
3127:                    StringBuffer buffer, int level) {
3128:                for (int i = 0; i < level; i++)
3129:                    buffer.append("   ");
3130:                String name = comp.getName();
3131:                if (comp instanceof  Dialog)
3132:                    name = ((Dialog) comp).getTitle();
3133:                if (comp instanceof  Frame)
3134:                    name = ((Frame) comp).getTitle();
3135:                buffer.append(comp.getClass().getName() + "[" + name + "]\n");
3136:                if (comp instanceof  Container) {
3137:                    Container cont = (Container) comp;
3138:                    for (int i = 0; i < cont.getComponentCount(); i++)
3139:                        getHierarchy(cont.getComponent(i), buffer, level + 1);
3140:                }
3141:            }
3142:
3143:            /**
3144:             * Returns the title pane of the specified root pane.
3145:             * 
3146:             * @param rootPane
3147:             *            Root pane.
3148:             * @return The title pane of the specified root pane.
3149:             */
3150:            public static JComponent getTitlePane(JRootPane rootPane) {
3151:                JInternalFrame jif = (JInternalFrame) SwingUtilities
3152:                        .getAncestorOfClass(JInternalFrame.class, rootPane);
3153:                if (jif != null) {
3154:                    SubstanceInternalFrameUI ui = (SubstanceInternalFrameUI) jif
3155:                            .getUI();
3156:                    return ui.getTitlePane();
3157:                }
3158:                SubstanceRootPaneUI ui = (SubstanceRootPaneUI) rootPane.getUI();
3159:                return ui.getTitlePane();
3160:            }
3161:
3162:            public static void resetCaches() {
3163:                SubstanceIconFactory.reset();
3164:                ButtonBackgroundDelegate.reset();
3165:                SubstanceCheckBoxUI.reset();
3166:                SubstanceProgressBarUI.reset();
3167:                SubstanceRadioButtonUI.reset();
3168:                SubstanceScrollBarUI.reset();
3169:                SubstanceTabbedPaneUI.reset();
3170:                // SubstanceComboBoxUI.reset();
3171:                SubstanceScrollBarUI.reset();
3172:                ClassicDecorationPainter.reset();
3173:            }
3174:
3175:            /**
3176:             * Returns the arrow icon.
3177:             * 
3178:             * @param comp
3179:             *            Component.
3180:             * @param button
3181:             *            Button.
3182:             * @param orientation
3183:             *            Arrow orientation.
3184:             * @return Arrow icon.
3185:             */
3186:            public static Icon getArrowIcon(final Component comp,
3187:                    final AbstractButton button, final int orientation) {
3188:                Icon result = new TransitionAwareIcon(button,
3189:                        new TransitionAwareIcon.Delegate() {
3190:                            public Icon getThemeIcon(SubstanceTheme theme) {
3191:                                int fontSize = SubstanceSizeUtils
3192:                                        .getComponentFontSize(comp);
3193:                                return SubstanceImageCreator
3194:                                        .getArrowIcon(
3195:                                                SubstanceSizeUtils
3196:                                                        .getArrowIconWidth(fontSize),
3197:                                                (orientation == SwingConstants.CENTER) ? 2 * SubstanceSizeUtils
3198:                                                        .getArrowIconHeight(fontSize)
3199:                                                        : SubstanceSizeUtils
3200:                                                                .getArrowIconHeight(fontSize),
3201:                                                SubstanceSizeUtils
3202:                                                        .getArrowStrokeWidth(fontSize),
3203:                                                orientation, theme);
3204:                            }
3205:                        });
3206:                return result;
3207:            }
3208:
3209:            /**
3210:             * Returns the arrow icon.
3211:             * 
3212:             * @param comp
3213:             *            Component.
3214:             * @param button
3215:             *            Button.
3216:             * @param orientation
3217:             *            Arrow orientation.
3218:             * @return Arrow icon.
3219:             */
3220:            public static Icon getDoubleArrowIcon(final Component comp,
3221:                    final AbstractButton button, final int orientation) {
3222:                Icon result = new TransitionAwareIcon(button,
3223:                        new TransitionAwareIcon.Delegate() {
3224:                            public Icon getThemeIcon(SubstanceTheme theme) {
3225:                                int fontSize = SubstanceSizeUtils
3226:                                        .getComponentFontSize(comp);
3227:                                return SubstanceImageCreator
3228:                                        .getDoubleArrowIcon(
3229:                                                SubstanceSizeUtils
3230:                                                        .getArrowIconWidth(fontSize),
3231:                                                SubstanceSizeUtils
3232:                                                        .getArrowIconHeight(fontSize) + 2,
3233:                                                SubstanceSizeUtils
3234:                                                        .getDoubleArrowStrokeWidth(fontSize),
3235:                                                orientation, theme);
3236:                            }
3237:                        });
3238:                return result;
3239:            }
3240:
3241:            public static double getColorizationFactor(Component c) {
3242:                JPopupMenu popupMenu = null;
3243:                while (c != null) {
3244:                    if (c instanceof  JComponent) {
3245:                        JComponent jcomp = (JComponent) c;
3246:                        Object compProp = jcomp
3247:                                .getClientProperty(SubstanceLookAndFeel.COLORIZATION_FACTOR);
3248:                        if (compProp instanceof  Double)
3249:                            return (Double) compProp;
3250:                    }
3251:                    if (c instanceof  JPopupMenu) {
3252:                        popupMenu = (JPopupMenu) c;
3253:                    }
3254:                    c = c.getParent();
3255:                }
3256:
3257:                if (popupMenu != null) {
3258:                    Component invoker = popupMenu.getInvoker();
3259:                    if (popupMenu != invoker)
3260:                        return getColorizationFactor(popupMenu.getInvoker());
3261:                }
3262:
3263:                Object globalProp = UIManager
3264:                        .get(SubstanceLookAndFeel.COLORIZATION_FACTOR);
3265:                if (globalProp instanceof  Double) {
3266:                    return (Double) globalProp;
3267:                }
3268:
3269:                return 0.0;
3270:            }
3271:
3272:            public static boolean hasColorization(Component c) {
3273:                JPopupMenu popupMenu = null;
3274:                while (c != null) {
3275:                    if (c instanceof  JComponent) {
3276:                        JComponent jcomp = (JComponent) c;
3277:                        Object compProp = jcomp
3278:                                .getClientProperty(SubstanceLookAndFeel.COLORIZATION_FACTOR);
3279:                        if (compProp instanceof  Double)
3280:                            return true;
3281:                    }
3282:                    if (c instanceof  JPopupMenu) {
3283:                        popupMenu = (JPopupMenu) c;
3284:                    }
3285:                    c = c.getParent();
3286:                }
3287:
3288:                if (popupMenu != null) {
3289:                    Component invoker = popupMenu.getInvoker();
3290:                    if (popupMenu != invoker)
3291:                        return hasColorization(popupMenu.getInvoker());
3292:                }
3293:
3294:                Object globalProp = UIManager
3295:                        .get(SubstanceLookAndFeel.COLORIZATION_FACTOR);
3296:                if (globalProp instanceof  Double) {
3297:                    return true;
3298:                }
3299:                return false;
3300:            }
3301:
3302:            public static Color getBackgroundFillColor(Component component) {
3303:                // special case - sliders, check boxes and radio buttons. For this,
3304:                // switch to component parent
3305:                boolean isColorized = hasColorization(component);
3306:                if (isColorized
3307:                        && ((component instanceof  JCheckBox)
3308:                                || (component instanceof  JRadioButton) || (component instanceof  JSlider))) {
3309:                    component = component.getParent();
3310:                } else {
3311:                    // Fix for 325 - respect the opacity setting of the text
3312:                    // component
3313:                    if (component instanceof  JTextComponent
3314:                            && !component.isOpaque())
3315:                        component = component.getParent();
3316:                }
3317:
3318:                Color backgr = component.getBackground();
3319:                boolean isBackgroundUiResource = backgr instanceof  UIResource;
3320:
3321:                if (!isBackgroundUiResource) {
3322:                    // custom background color set on component
3323:                    if (isColorized) {
3324:                        // colorized - shift the theme
3325:                        SubstanceTheme theme = SubstanceThemeUtilities
3326:                                .getTheme(
3327:                                        component,
3328:                                        component.isEnabled() ? ComponentState.DEFAULT
3329:                                                : ComponentState.DISABLED_UNSELECTED);
3330:
3331:                        // double colorizationFactor = getColorizationFactor(component);
3332:                        // if (!component.isEnabled())
3333:                        // colorizationFactor /= 2.0;
3334:                        // theme = SubstanceShiftTheme.getShiftedTheme(theme, backgr,
3335:                        // colorizationFactor, null, 0.0);
3336:                        backgr = theme.getBackgroundColor();
3337:                    } else {
3338:                        if (!component.isEnabled()) {
3339:                            SubstanceTheme theme = SubstanceThemeUtilities
3340:                                    .getTheme(component,
3341:                                            ComponentState.DISABLED_UNSELECTED);
3342:                            // theme = SubstanceShiftTheme.getShiftedTheme(theme,
3343:                            // backgr,
3344:                            // 0.5, null, 0.0);
3345:                            backgr = theme.getBackgroundColor();
3346:                        }
3347:                    }
3348:                } else {
3349:                    DecorationAreaType decorationType = SubstanceDecorationUtilities
3350:                            .getDecorationType(component);
3351:                    if (decorationType != null) {
3352:                        // Component is in the decoration area. Check if the current
3353:                        // theme is actively decorating it
3354:                        SubstanceTheme theme = SubstanceThemeUtilities
3355:                                .getNonColorizedTheme(component, true);
3356:                        if (theme.toUseDecorationPainter(decorationType)) {
3357:                            ComponentState state = component.isEnabled() ? ComponentState.DEFAULT
3358:                                    : ComponentState.DISABLED_UNSELECTED;
3359:                            if (component instanceof  JTextComponent) {
3360:                                if (!((JTextComponent) component).isEditable()) {
3361:                                    state = ComponentState.DISABLED_UNSELECTED;
3362:                                }
3363:                            }
3364:                            backgr = getDefaultBackgroundColor(component
3365:                                    .getClass(), SubstanceThemeUtilities
3366:                                    .getTheme(component, state));
3367:                        }
3368:                    }
3369:                }
3370:                return backgr;
3371:            }
3372:
3373:            public static ColorUIResource getDefaultBackgroundColor(
3374:                    Class componentClass, SubstanceTheme componentTheme) {
3375:                boolean useLightBackgroundColor = (JTextComponent.class
3376:                        .isAssignableFrom(componentClass))
3377:                        || (JComboBox.class.isAssignableFrom(componentClass))
3378:                        || (JSpinner.class.isAssignableFrom(componentClass));
3379:                if (useLightBackgroundColor)
3380:                    return new ColorUIResource(componentTheme
3381:                            .getLightBackgroundColor());
3382:                return new ColorUIResource(componentTheme.getBackgroundColor());
3383:            }
3384:
3385:            public static Color getStripedBackground(JComponent component,
3386:                    int index) {
3387:                Color backgr = getBackgroundFillColor(component);
3388:                if (backgr == null)
3389:                    return null;
3390:
3391:                if (index % 2 == 0)
3392:                    return backgr;
3393:                int r = backgr.getRed();
3394:                int g = backgr.getGreen();
3395:                int b = backgr.getBlue();
3396:                double coef = 0.96;
3397:                if (!component.isEnabled())
3398:                    coef = 1.0 - (1.0 - coef) / 2.0;
3399:                Color darkerColor = new ColorUIResource((int) (coef * r),
3400:                        (int) (coef * g), (int) (coef * b));
3401:
3402:                return darkerColor;
3403:            }
3404:
3405:            public static void applyStripedBackground(JComponent component,
3406:                    int index, JComponent renderer) {
3407:                Color backgr = getStripedBackground(component, index);
3408:                if (backgr == null)
3409:                    return;
3410:
3411:                // System.out.println(index + ":" + backgr);
3412:                renderer.setBackground(backgr);
3413:            }
3414:
3415:            public static void paintTextCompBackground(Graphics g,
3416:                    JComponent comp) {
3417:                Graphics2D g2d = (Graphics2D) g.create();
3418:                Color backgr = SubstanceCoreUtilities
3419:                        .getBackgroundFillColor(comp);
3420:
3421:                int borderDelta = (int) Math.floor(SubstanceSizeUtils
3422:                        .getBorderStrokeWidth(SubstanceSizeUtils
3423:                                .getComponentFontSize(comp)) / 2.0);
3424:                Border compBorder = comp.getBorder();
3425:                boolean isSubstanceBorder = compBorder instanceof  SubstanceBorder;
3426:                if (compBorder instanceof  CompoundBorder) {
3427:                    isSubstanceBorder = isSubstanceBorder
3428:                            || (((CompoundBorder) compBorder)
3429:                                    .getOutsideBorder() instanceof  SubstanceBorder);
3430:                }
3431:                Shape contour = isSubstanceBorder ? BaseButtonShaper
3432:                        .getBaseOutline(
3433:                                comp.getWidth(),
3434:                                comp.getHeight(),
3435:                                SubstanceSizeUtils
3436:                                        .getClassicButtonCornerRadius(SubstanceSizeUtils
3437:                                                .getComponentFontSize(comp)),
3438:                                null, borderDelta)
3439:                        : new Rectangle(0, 0, comp.getWidth(), comp.getHeight());
3440:
3441:                g2d.setColor(backgr);
3442:                g2d.fill(contour);
3443:
3444:                if (SubstanceCoreUtilities.toBleedWatermark(comp)
3445:                        || !comp.isOpaque()) {
3446:                    // g2d.clip(contour);
3447:                    SubstanceLookAndFeel.getCurrentWatermark()
3448:                            .drawWatermarkImage(g2d, comp, 0, 0,
3449:                                    comp.getWidth(), comp.getHeight());
3450:                }
3451:
3452:                g2d.dispose();
3453:            }
3454:
3455:            public static Container getSpecialBackgroundFillContainer(
3456:                    JComponent comp) {
3457:                Component c = comp;
3458:                while (c != null) {
3459:                    if (c instanceof  JComponent) {
3460:                        JComponent jc = (JComponent) c;
3461:                        if (Boolean.TRUE.equals(jc
3462:                                .getClientProperty(HAS_CUSTOM_BACKGROUND_FILL)))
3463:                            return jc;
3464:                    }
3465:                    c = c.getParent();
3466:                }
3467:                return null;
3468:            }
3469:
3470:            public static void paintTextComponent(Graphics g,
3471:                    final JTextComponent textComponent, View rootView,
3472:                    Rectangle visibleEditorRect) {
3473:                final SubstanceTextPainter textPainter = SubstanceLookAndFeel
3474:                        .getCurrentTextPainter();
3475:
3476:                Graphics2D g2d = (Graphics2D) g.create();
3477:                if (textComponent.isOpaque()
3478:                        || textPainter.needsBackgroundImage()) {
3479:                    SubstanceFillBackgroundDelegate.GLOBAL_INSTANCE.update(g2d,
3480:                            textComponent, false);
3481:                }
3482:
3483:                ComponentState currState = textComponent.isEnabled() ? ComponentState.DEFAULT
3484:                        : ComponentState.DISABLED_UNSELECTED;
3485:                float alpha = SubstanceThemeUtilities.getTheme(textComponent)
3486:                        .getThemeAlpha(textComponent, currState);
3487:                g2d.setComposite(TransitionLayout.getAlphaComposite(
3488:                        textComponent, alpha, g));
3489:
3490:                SubstanceTextPainter.BackgroundPaintingCallback callback = new SubstanceTextPainter.BackgroundPaintingCallback() {
3491:                    public void paintBackground(Graphics g) {
3492:                        Highlighter highlighter = textComponent
3493:                                .getHighlighter();
3494:
3495:                        // paint the background
3496:                        // if (textComponent.isOpaque()) {
3497:                        if (textPainter.needsBackgroundImage())
3498:                            paintTextCompBackground(g, textComponent);
3499:                        // }
3500:
3501:                        // paint the highlights
3502:                        if (highlighter != null) {
3503:                            highlighter.paint(g);
3504:                        }
3505:                    }
3506:                };
3507:
3508:                textPainter.init(textComponent, null, true);
3509:                if (textPainter.needsBackgroundImage()) {
3510:                    // Fix for 325 - respect the opacity setting of the text
3511:                    // component
3512:                    textPainter.setBackgroundFill(textComponent,
3513:                            SubstanceCoreUtilities
3514:                                    .getBackgroundFillColor(textComponent),
3515:                            false, 0, 0);
3516:                    textPainter.attachCallback(callback);
3517:                } else {
3518:                    callback.paintBackground(g2d);
3519:                }
3520:
3521:                // paint the view hierarchy
3522:                if (visibleEditorRect != null) {
3523:                    rootView.paint(g2d, visibleEditorRect);
3524:                }
3525:                textPainter.renderSurface(g2d);
3526:
3527:                // paint the caret
3528:                Caret caret = textComponent.getCaret();
3529:                if (caret != null) {
3530:                    caret.paint(g2d);
3531:                }
3532:
3533:                g2d.dispose();
3534:            }
3535:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.