Source Code Cross Referenced for SubstanceTitlePane.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.*;
0034:        import java.awt.image.BufferedImage;
0035:        import java.beans.PropertyChangeEvent;
0036:        import java.beans.PropertyChangeListener;
0037:        import java.io.*;
0038:        import java.lang.ref.WeakReference;
0039:        import java.text.SimpleDateFormat;
0040:        import java.util.*;
0041:
0042:        import javax.swing.*;
0043:        import javax.swing.plaf.UIResource;
0044:
0045:        import org.jvnet.lafwidget.LafWidget;
0046:        import org.jvnet.lafwidget.LafWidgetUtilities;
0047:        import org.jvnet.lafwidget.animation.effects.GhostPaintingUtils;
0048:        import org.jvnet.lafwidget.utils.TrackableThread;
0049:        import org.jvnet.lafwidget.utils.LafConstants.AnimationKind;
0050:        import org.jvnet.substance.*;
0051:        import org.jvnet.substance.border.BorderPainterChangeListener;
0052:        import org.jvnet.substance.border.BorderPainterInfo;
0053:        import org.jvnet.substance.button.ButtonShaperChangeListener;
0054:        import org.jvnet.substance.button.ButtonShaperInfo;
0055:        import org.jvnet.substance.color.ColorScheme;
0056:        import org.jvnet.substance.painter.GradientPainterChangeListener;
0057:        import org.jvnet.substance.painter.GradientPainterInfo;
0058:        import org.jvnet.substance.painter.decoration.DecorationAreaType;
0059:        import org.jvnet.substance.painter.decoration.SubstanceDecorationUtilities;
0060:        import org.jvnet.substance.painter.text.SubstanceTextPainter;
0061:        import org.jvnet.substance.skin.SkinInfo;
0062:        import org.jvnet.substance.theme.*;
0063:        import org.jvnet.substance.theme.SubstanceTheme.ThemeKind;
0064:        import org.jvnet.substance.utils.SubstanceConstants.FocusKind;
0065:        import org.jvnet.substance.utils.icon.SubstanceIconFactory;
0066:        import org.jvnet.substance.utils.icon.TransitionAwareIcon;
0067:        import org.jvnet.substance.utils.menu.TraitMenuHandler;
0068:        import org.jvnet.substance.watermark.*;
0069:
0070:        /**
0071:         * Title pane for <b>Substance</b> look and feel.
0072:         * 
0073:         * @author Kirill Grouchnikov
0074:         */
0075:        public class SubstanceTitlePane extends JComponent {
0076:            /**
0077:             * Name for the client property that is set on a root pane to specify that
0078:             * the heap status panel should be displayed permanently.
0079:             */
0080:            public static final String HEAP_STATUS_PANEL_PERMANENT = "substancelaf.internal.heapStatusPanelPermanent";
0081:
0082:            // /**
0083:            // * Max icon height for the title icon.
0084:            // */
0085:            // public static final int IMAGE_HEIGHT = 16;
0086:            //
0087:            // /**
0088:            // * Max icon width for the title icon.
0089:            // */
0090:            // public static final int IMAGE_WIDTH = 16;
0091:            //
0092:            /**
0093:             * PropertyChangeListener added to the JRootPane.
0094:             */
0095:            private PropertyChangeListener propertyChangeListener;
0096:
0097:            /**
0098:             * JMenuBar, typically renders the system menu items.
0099:             */
0100:            private JMenuBar menuBar;
0101:
0102:            /**
0103:             * Action used to close the Window.
0104:             */
0105:            private Action closeAction;
0106:
0107:            /**
0108:             * Action used to iconify the Frame.
0109:             */
0110:            private Action iconifyAction;
0111:
0112:            /**
0113:             * Action to restore the Frame size.
0114:             */
0115:            private Action restoreAction;
0116:
0117:            /**
0118:             * Action to restore the Frame size.
0119:             */
0120:            private Action maximizeAction;
0121:
0122:            /**
0123:             * Button used to maximize or restore the frame.
0124:             */
0125:            private JButton toggleButton;
0126:
0127:            /**
0128:             * Button used to minimize the frame
0129:             */
0130:            private JButton minimizeButton;
0131:
0132:            /**
0133:             * Button used to close the frame.
0134:             */
0135:            private JButton closeButton;
0136:
0137:            /**
0138:             * Listens for changes in the state of the Window listener to update the
0139:             * state of the widgets.
0140:             */
0141:            private WindowListener windowListener;
0142:
0143:            /**
0144:             * Window we're currently in.
0145:             */
0146:            private Window window;
0147:
0148:            /**
0149:             * JRootPane rendering for.
0150:             */
0151:            private JRootPane rootPane;
0152:
0153:            /**
0154:             * Buffered Frame.state property. As state isn't bound, this is kept to
0155:             * determine when to avoid updating widgets.
0156:             */
0157:            private int state;
0158:
0159:            /**
0160:             * SubstanceRootPaneUI that created us.
0161:             */
0162:            private SubstanceRootPaneUI rootPaneUI;
0163:
0164:            /**
0165:             * Indication whether any title pane can have heap status panel.
0166:             */
0167:            protected static boolean canHaveHeapStatusPanel;
0168:
0169:            /**
0170:             * The logfile name for the heap status panel. Can be <code>null</code> -
0171:             * in this case the {@link HeapStatusThread} will not write heap
0172:             * information.
0173:             */
0174:            protected static String heapStatusLogfileName;
0175:
0176:            /**
0177:             * The heap status panel of <code>this</code> title pane.
0178:             */
0179:            protected HeapStatusPanel heapStatusPanel;
0180:
0181:            /**
0182:             * The heap status toggle menu item of <code>this</code> title pane.
0183:             */
0184:            protected JCheckBoxMenuItem heapStatusMenuItem;
0185:
0186:            /**
0187:             * Listens on changes to <code>componentOrientation</code> and
0188:             * {@link SubstanceLookAndFeel#WINDOW_MODIFIED} properties.
0189:             */
0190:            protected PropertyChangeListener propertyListener;
0191:
0192:            protected TraitMenuHandler themeMenuHandler;
0193:
0194:            protected ThemeChangeListener themeChangeListener;
0195:
0196:            protected TraitMenuHandler watermarkMenuHandler;
0197:
0198:            protected WatermarkChangeListener watermarkChangeListener;
0199:
0200:            protected TraitMenuHandler buttonShaperMenuHandler;
0201:
0202:            protected ButtonShaperChangeListener buttonShaperChangeListener;
0203:
0204:            protected TraitMenuHandler gradientPainterMenuHandler;
0205:
0206:            protected GradientPainterChangeListener gradientPainterChangeListener;
0207:
0208:            protected TraitMenuHandler titlePainterMenuHandler;
0209:
0210:            protected TraitMenuHandler borderPainterMenuHandler;
0211:
0212:            protected BorderPainterChangeListener borderPainterChangeListener;
0213:
0214:            protected MouseListener substanceDebugUiListener;
0215:
0216:            public static final String HAS_BEEN_UNINSTALLED = "substancelaf.internal.titlePane.hasBeenUninstalled";
0217:
0218:            /**
0219:             * Panel that shows heap status and allows running the garbage collector.
0220:             * 
0221:             * @author Kirill Grouchnikov
0222:             */
0223:            public static class HeapStatusPanel extends JPanel {
0224:                /**
0225:                 * The current heap size in kilobytes.
0226:                 */
0227:                private int currHeapSizeKB;
0228:
0229:                /**
0230:                 * The current used portion of heap in kilobytes.
0231:                 */
0232:                private int currTakenHeapSizeKB;
0233:
0234:                /**
0235:                 * History of used heap portion (in percents). Each value is in 0.0-1.0
0236:                 * range.
0237:                 */
0238:                private LinkedList<Double> graphValues;
0239:
0240:                private SubstanceTitlePane titlePane;
0241:
0242:                /**
0243:                 * Creates new heap status panel.
0244:                 */
0245:                public HeapStatusPanel(SubstanceTitlePane titlePane) {
0246:                    this .graphValues = new LinkedList<Double>();
0247:                    this .titlePane = titlePane;
0248:                    HeapStatusThread.getInstance();
0249:                }
0250:
0251:                /**
0252:                 * Updates the values for <code>this</code> heap status panel.
0253:                 * 
0254:                 * @param currHeapSizeKB
0255:                 *            The current heap size in kilobytes.
0256:                 * @param currTakenHeapSizeKB
0257:                 *            The current used portion of heap in kilobytes.
0258:                 */
0259:                public synchronized void updateStatus(int currHeapSizeKB,
0260:                        int currTakenHeapSizeKB) {
0261:                    this .currHeapSizeKB = currHeapSizeKB;
0262:                    this .currTakenHeapSizeKB = currTakenHeapSizeKB;
0263:                    double newGraphValue = (double) currTakenHeapSizeKB
0264:                            / (double) currHeapSizeKB;
0265:                    this .graphValues.addLast(newGraphValue);
0266:                    this .repaint();
0267:                }
0268:
0269:                /*
0270:                 * (non-Javadoc)
0271:                 * 
0272:                 * @see javax.swing.JComponent#paint(java.awt.Graphics)
0273:                 */
0274:                @Override
0275:                public synchronized void paint(Graphics g) {
0276:                    Graphics2D graphics = (Graphics2D) g.create();
0277:
0278:                    Window window = this .titlePane.getWindow();
0279:                    boolean isSelected = (window == null) ? true : window
0280:                            .isActive();
0281:                    final SubstanceTheme theme = isSelected ? SubstanceLookAndFeel
0282:                            .getTheme().getActiveTitlePaneTheme()
0283:                            : SubstanceLookAndFeel.getTheme()
0284:                                    .getDefaultTitlePaneTheme();
0285:                    ColorScheme scheme = theme.getColorScheme();
0286:
0287:                    graphics.setColor(scheme.getDarkColor());
0288:                    int w = this .getWidth();
0289:                    int h = this .getHeight();
0290:
0291:                    graphics.drawRect(0, 0, w - 1, h - 1);
0292:
0293:                    graphics.setColor(scheme.getExtraLightColor());
0294:                    graphics.fillRect(1, 1, w - 2, h - 2);
0295:
0296:                    while (this .graphValues.size() > (w - 2))
0297:                        this .graphValues.removeFirst();
0298:
0299:                    int xOff = w - this .graphValues.size() - 1;
0300:                    graphics.setColor(scheme.getMidColor());
0301:                    int count = 0;
0302:                    for (double value : this .graphValues) {
0303:                        int valueH = (int) (value * (h - 2));
0304:                        graphics.drawLine(xOff + count, h - 1 - valueH, xOff
0305:                                + count, h - 2);
0306:                        count++;
0307:                    }
0308:
0309:                    graphics.setFont(UIManager.getFont("Panel.font"));
0310:                    FontMetrics fm = graphics.getFontMetrics();
0311:
0312:                    StringBuffer longFormat = new StringBuffer();
0313:                    Formatter longFormatter = new Formatter(longFormat);
0314:                    longFormatter.format("%.1fMB / %.1fMB",
0315:                            this .currTakenHeapSizeKB / 1024.f,
0316:                            this .currHeapSizeKB / 1024.f);
0317:                    int strW = fm.stringWidth(longFormat.toString());
0318:                    int strH = fm.getAscent() + fm.getDescent();
0319:
0320:                    graphics.setColor(scheme.getForegroundColor());
0321:                    if (strW < (w - 5)) {
0322:                        graphics.drawString(longFormat.toString(),
0323:                                (w - strW) / 2, (h + strH) / 2 - 2);
0324:                    } else {
0325:                        String shortFormat = (this .currTakenHeapSizeKB / 1024)
0326:                                + "MB / " + (this .currHeapSizeKB / 1024) + "MB";
0327:                        strW = fm.stringWidth(shortFormat);
0328:                        graphics.drawString(shortFormat, (w - strW) / 2,
0329:                                (h + strH) / 2 - 2);
0330:                    }
0331:
0332:                    graphics.dispose();
0333:                }
0334:            }
0335:
0336:            /**
0337:             * Thread for heap status panel.
0338:             */
0339:            public static class HeapStatusThread extends TrackableThread {
0340:                /**
0341:                 * Current heap size in kilobytes.
0342:                 */
0343:                private int heapSizeKB;
0344:
0345:                /**
0346:                 * Current used portion of heap in kilobytes.
0347:                 */
0348:                private int takenHeapSizeKB;
0349:
0350:                /**
0351:                 * All heap status panels.
0352:                 */
0353:                private static Set<WeakReference<HeapStatusPanel>> panels = new HashSet<WeakReference<HeapStatusPanel>>();
0354:
0355:                /**
0356:                 * Single instance of <code>this</code> thread.
0357:                 */
0358:                private static HeapStatusThread instance;
0359:
0360:                /**
0361:                 * Formatter object (for logfile).
0362:                 */
0363:                private SimpleDateFormat format;
0364:
0365:                /**
0366:                 * Signifies whether a stop request has been issued on <code>this</code>
0367:                 * thread using the {@link #requestStop()} call.
0368:                 */
0369:                private boolean isStopRequested;
0370:
0371:                /**
0372:                 * Simple constructor. Defined private for singleton.
0373:                 * 
0374:                 * @see #getInstance()
0375:                 */
0376:                private HeapStatusThread() {
0377:                    this .format = new SimpleDateFormat(
0378:                            "dd/MM/yyyy HH:mm:ss.SSS");
0379:                    this .isStopRequested = false;
0380:                    this .setName("Substance heap status");
0381:                }
0382:
0383:                /**
0384:                 * Gets singleton instance of <code>this</code> thread.
0385:                 * 
0386:                 * @return Singleton instance of <code>this</code> thread.
0387:                 */
0388:                public synchronized static HeapStatusThread getInstance() {
0389:                    if (HeapStatusThread.instance == null) {
0390:                        HeapStatusThread.instance = new HeapStatusThread();
0391:                        HeapStatusThread.instance.start();
0392:                    }
0393:                    return HeapStatusThread.instance;
0394:                }
0395:
0396:                /**
0397:                 * Registers new heap status panel with <code>this</code> thread.
0398:                 * 
0399:                 * @param panel
0400:                 *            Heap statuc panel.
0401:                 */
0402:                public static synchronized void registerPanel(
0403:                        HeapStatusPanel panel) {
0404:                    panels.add(new WeakReference<HeapStatusPanel>(panel));
0405:                }
0406:
0407:                /**
0408:                 * Unregisters new heap status panel from <code>this</code> thread.
0409:                 * 
0410:                 * @param panel
0411:                 *            Heap statuc panel.
0412:                 */
0413:                public static synchronized void unregisterPanel(
0414:                        HeapStatusPanel panel) {
0415:                    for (Iterator<WeakReference<HeapStatusPanel>> it = panels
0416:                            .iterator(); it.hasNext();) {
0417:                        WeakReference<HeapStatusPanel> ref = it.next();
0418:                        HeapStatusPanel currPanel = ref.get();
0419:                        if (panel == currPanel) {
0420:                            it.remove();
0421:                            return;
0422:                        }
0423:                    }
0424:                }
0425:
0426:                /**
0427:                 * Updates the values of heap status.
0428:                 */
0429:                private synchronized void updateHeapCounts() {
0430:                    long heapSize = Runtime.getRuntime().totalMemory();
0431:                    long heapFreeSize = Runtime.getRuntime().freeMemory();
0432:
0433:                    this .heapSizeKB = (int) (heapSize / 1024);
0434:                    this .takenHeapSizeKB = (int) ((heapSize - heapFreeSize) / 1024);
0435:                }
0436:
0437:                /*
0438:                 * (non-Javadoc)
0439:                 * 
0440:                 * @see java.lang.Thread#run()
0441:                 */
0442:                @Override
0443:                public void run() {
0444:                    while (!this .isStopRequested) {
0445:                        try {
0446:                            // update every 0.5 seconds
0447:                            Thread.sleep(500);
0448:                        } catch (InterruptedException ie) {
0449:                        }
0450:                        this .updateHeapCounts();
0451:                        for (Iterator<WeakReference<HeapStatusPanel>> it = panels
0452:                                .iterator(); it.hasNext();) {
0453:                            WeakReference<HeapStatusPanel> refPanel = it.next();
0454:                            HeapStatusPanel panel = refPanel.get();
0455:                            if (panel == null) {
0456:                                // prune
0457:                                panels.remove(it);
0458:                                continue;
0459:                            }
0460:
0461:                            panel.updateStatus(this .heapSizeKB,
0462:                                    this .takenHeapSizeKB);
0463:                        }
0464:                        // see if need to put info in log file
0465:                        if (SubstanceTitlePane.heapStatusLogfileName != null) {
0466:                            PrintWriter pw = null;
0467:                            try {
0468:                                pw = new PrintWriter(
0469:                                        new FileWriter(
0470:                                                SubstanceTitlePane.heapStatusLogfileName,
0471:                                                true));
0472:                                pw.println(this .format.format(new Date()) + " "
0473:                                        + this .takenHeapSizeKB + "KB / "
0474:                                        + this .heapSizeKB + "KB");
0475:                            } catch (IOException ioe) {
0476:
0477:                            } finally {
0478:                                if (pw != null) {
0479:                                    pw.close();
0480:                                }
0481:                            }
0482:                        }
0483:                    }
0484:                }
0485:
0486:                @Override
0487:                protected void requestStop() {
0488:                    this .isStopRequested = true;
0489:                    HeapStatusThread.instance = null;
0490:                }
0491:            }
0492:
0493:            /**
0494:             * Creates a new title pane.
0495:             * 
0496:             * @param root
0497:             *            Root pane.
0498:             * @param ui
0499:             *            Root pane UI.
0500:             */
0501:            public SubstanceTitlePane(JRootPane root, SubstanceRootPaneUI ui) {
0502:                this .rootPane = root;
0503:                this .rootPaneUI = ui;
0504:
0505:                this .state = -1;
0506:
0507:                this .installSubcomponents();
0508:                this .installDefaults();
0509:
0510:                this .setLayout(this .createLayout());
0511:
0512:                this .setToolTipText(this .getTitle());
0513:
0514:                SubstanceDecorationUtilities.setDecorationType(this ,
0515:                        DecorationAreaType.PRIMARY_TITLE_PANE);
0516:            }
0517:
0518:            /**
0519:             * Uninstalls the necessary state.
0520:             */
0521:            public void uninstall() {
0522:                this .uninstallListeners();
0523:                this .window = null;
0524:                // Swing bug (?) - the updateComponentTree never gets to the
0525:                // system menu (and in our case we have radio menu items with
0526:                // rollover listeners). Fix for defect 109 - memory leak on theme
0527:                // switch
0528:                if ((this .menuBar != null) && (this .menuBar.getMenuCount() > 0)) {
0529:                    this .menuBar.getUI().uninstallUI(this .menuBar);
0530:                    SubstanceCoreUtilities.uninstallMenu(this .menuBar
0531:                            .getMenu(0));
0532:                }
0533:
0534:                if (SubstanceTitlePane.canHaveHeapStatusPanel) {
0535:                    if (this .heapStatusPanel != null) {
0536:                        for (MouseListener listener : this .heapStatusPanel
0537:                                .getMouseListeners())
0538:                            this .heapStatusPanel.removeMouseListener(listener);
0539:                        HeapStatusThread.unregisterPanel(this .heapStatusPanel);
0540:                        this .remove(this .heapStatusPanel);
0541:                    }
0542:                }
0543:
0544:                if (this .menuBar != null)
0545:                    this .menuBar.removeAll();
0546:                this .removeAll();
0547:
0548:                SubstanceLookAndFeel
0549:                        .unregisterThemeChangeListener(this .themeChangeListener);
0550:                this .themeChangeListener = null;
0551:                SubstanceLookAndFeel
0552:                        .unregisterWatermarkChangeListener(this .watermarkChangeListener);
0553:                this .watermarkChangeListener = null;
0554:                SubstanceLookAndFeel
0555:                        .unregisterButtonShaperChangeListener(this .buttonShaperChangeListener);
0556:                this .buttonShaperChangeListener = null;
0557:                SubstanceLookAndFeel
0558:                        .unregisterGradientPainterChangeListener(this .gradientPainterChangeListener);
0559:                this .gradientPainterChangeListener = null;
0560:                SubstanceLookAndFeel
0561:                        .unregisterBorderPainterChangeListener(this .borderPainterChangeListener);
0562:                this .borderPainterChangeListener = null;
0563:            }
0564:
0565:            /**
0566:             * Installs the necessary listeners.
0567:             */
0568:            private void installListeners() {
0569:                if (this .window != null) {
0570:                    this .windowListener = new WindowHandler();
0571:                    this .window.addWindowListener(this .windowListener);
0572:                    this .propertyChangeListener = new PropertyChangeHandler();
0573:                    this .window
0574:                            .addPropertyChangeListener(this .propertyChangeListener);
0575:                }
0576:
0577:                // Property change listener for pulsating close button
0578:                // when window has been marked as changed.
0579:                // Fix for defect 109 - memory leak on theme change.
0580:                this .propertyListener = new PropertyChangeListener() {
0581:                    public void propertyChange(final PropertyChangeEvent evt) {
0582:                        if (SubstanceLookAndFeel.WINDOW_MODIFIED.equals(evt
0583:                                .getPropertyName())) {
0584:                            syncCloseButtonTooltip();
0585:                            // if (Boolean.TRUE.equals(evt.getNewValue())) {
0586:                            // SubstanceTitlePane.this.closeButton
0587:                            // .setToolTipText(SubstanceLookAndFeel
0588:                            // .getLabelBundle().getString(
0589:                            // "SystemMenu.close")
0590:                            // + " ["
0591:                            // + SubstanceLookAndFeel
0592:                            // .getLabelBundle()
0593:                            // .getString(
0594:                            // "Tooltip.contentsNotSaved")
0595:                            // + "]");
0596:                            // } else {
0597:                            // SubstanceTitlePane.this.closeButton
0598:                            // .setToolTipText(SubstanceLookAndFeel
0599:                            // .getLabelBundle().getString(
0600:                            // "SystemMenu.close"));
0601:                            // }
0602:                            // SubstanceTitlePane.this.closeButton.repaint();
0603:                        }
0604:
0605:                        if ("componentOrientation"
0606:                                .equals(evt.getPropertyName())) {
0607:                            SwingUtilities.invokeLater(new Runnable() {
0608:                                public void run() {
0609:                                    if (SubstanceTitlePane.this .menuBar != null) {
0610:                                        SubstanceTitlePane.this .menuBar
0611:                                                .applyComponentOrientation((ComponentOrientation) evt
0612:                                                        .getNewValue());
0613:                                    }
0614:                                }
0615:                            });
0616:                        }
0617:                    }
0618:                };
0619:                // Wire it on the frame itself and its root pane.
0620:                this .rootPane.addPropertyChangeListener(this .propertyListener);
0621:                if (this .getFrame() != null)
0622:                    this .getFrame().addPropertyChangeListener(
0623:                            this .propertyListener);
0624:
0625:                if (SubstanceLookAndFeel.isDebugUiMode()) {
0626:                    this .substanceDebugUiListener = new MouseAdapter() {
0627:                        @Override
0628:                        public void mousePressed(MouseEvent e) {
0629:                            process(e);
0630:                        }
0631:
0632:                        @Override
0633:                        public void mouseReleased(MouseEvent e) {
0634:                            process(e);
0635:                        }
0636:
0637:                        protected void process(MouseEvent e) {
0638:                            if (e.isPopupTrigger()) {
0639:                                JPopupMenu popup = new JPopupMenu();
0640:                                JMenu cbMenu = new JMenu("Color blindness");
0641:                                JMenuItem protanopiaCurrent = new JMenuItem(
0642:                                        "Protanopia current");
0643:                                protanopiaCurrent
0644:                                        .addActionListener(new ThemeChanger(
0645:                                                SubstanceLookAndFeel.getTheme()
0646:                                                        .protanopia()));
0647:                                cbMenu.add(protanopiaCurrent);
0648:                                JMenuItem deuteranopiaCurrent = new JMenuItem(
0649:                                        "Deuteranopia current");
0650:                                deuteranopiaCurrent
0651:                                        .addActionListener(new ThemeChanger(
0652:                                                SubstanceLookAndFeel.getTheme()
0653:                                                        .deuteranopia()));
0654:                                cbMenu.add(deuteranopiaCurrent);
0655:                                JMenuItem tritanopiaCurrent = new JMenuItem(
0656:                                        "Tritanopia current");
0657:                                tritanopiaCurrent
0658:                                        .addActionListener(new ThemeChanger(
0659:                                                SubstanceLookAndFeel.getTheme()
0660:                                                        .tritanopia()));
0661:                                cbMenu.add(tritanopiaCurrent);
0662:
0663:                                cbMenu.addSeparator();
0664:
0665:                                JMenuItem restoreOriginal = new JMenuItem(
0666:                                        "Restore original");
0667:                                if (SubstanceLookAndFeel.getTheme() instanceof  SubstanceColorBlindTheme) {
0668:                                    restoreOriginal
0669:                                            .addActionListener(new ThemeChanger(
0670:                                                    ((SubstanceColorBlindTheme) SubstanceLookAndFeel
0671:                                                            .getTheme())
0672:                                                            .getOriginalTheme()));
0673:                                } else {
0674:                                    restoreOriginal.setEnabled(false);
0675:                                }
0676:                                cbMenu.add(restoreOriginal);
0677:
0678:                                popup.add(cbMenu);
0679:
0680:                                JMenu animMenu = new JMenu("Animation rate");
0681:                                JMenuItem debugNone = new JMenuItem("None");
0682:                                debugNone
0683:                                        .addActionListener(new AnimationChanger(
0684:                                                AnimationKind.NONE));
0685:                                animMenu.add(debugNone);
0686:                                JMenuItem debugAnim = new JMenuItem(
0687:                                        "Debug rate (extra slow)");
0688:                                debugAnim
0689:                                        .addActionListener(new AnimationChanger(
0690:                                                AnimationKind.DEBUG));
0691:                                animMenu.add(debugAnim);
0692:                                JMenuItem debugAnimFast = new JMenuItem(
0693:                                        "Debug rate (faster)");
0694:                                debugAnimFast
0695:                                        .addActionListener(new AnimationChanger(
0696:                                                AnimationKind.DEBUG_FAST));
0697:                                animMenu.add(debugAnimFast);
0698:                                JMenuItem debugSlow = new JMenuItem("Slow rate");
0699:                                debugSlow
0700:                                        .addActionListener(new AnimationChanger(
0701:                                                AnimationKind.SLOW));
0702:                                animMenu.add(debugSlow);
0703:                                JMenuItem debugRegular = new JMenuItem(
0704:                                        "Regular rate");
0705:                                debugRegular
0706:                                        .addActionListener(new AnimationChanger(
0707:                                                AnimationKind.REGULAR));
0708:                                animMenu.add(debugRegular);
0709:                                JMenuItem debugFast = new JMenuItem("Fast rate");
0710:                                debugFast
0711:                                        .addActionListener(new AnimationChanger(
0712:                                                AnimationKind.FAST));
0713:                                animMenu.add(debugFast);
0714:
0715:                                popup.add(animMenu);
0716:
0717:                                JMenu focusMenu = new JMenu("Focus kind");
0718:                                for (FocusKind fKind : FocusKind.values()) {
0719:                                    JMenuItem focusMenuItem = new JMenuItem(
0720:                                            fKind.name().toLowerCase());
0721:                                    focusMenuItem
0722:                                            .addActionListener(new FocusKindChanger(
0723:                                                    fKind));
0724:                                    focusMenu.add(focusMenuItem);
0725:                                }
0726:                                popup.add(focusMenu);
0727:
0728:                                JMenuItem dumpHierarchy = new JMenuItem(
0729:                                        "Dump hierarchy");
0730:                                dumpHierarchy
0731:                                        .addActionListener(new ActionListener() {
0732:                                            public void actionPerformed(
0733:                                                    ActionEvent e) {
0734:                                                dump(rootPane, 0);
0735:                                            }
0736:                                        });
0737:                                popup.add(dumpHierarchy);
0738:
0739:                                final JCheckBoxMenuItem ltrChange = new JCheckBoxMenuItem(
0740:                                        "Is left-to-right");
0741:                                ltrChange.setSelected(rootPane
0742:                                        .getComponentOrientation()
0743:                                        .isLeftToRight());
0744:                                ltrChange
0745:                                        .addActionListener(new ActionListener() {
0746:                                            public void actionPerformed(
0747:                                                    ActionEvent e) {
0748:                                                SwingUtilities
0749:                                                        .invokeLater(new Runnable() {
0750:                                                            public void run() {
0751:                                                                rootPane
0752:                                                                        .applyComponentOrientation(ltrChange
0753:                                                                                .isSelected() ? ComponentOrientation.LEFT_TO_RIGHT
0754:                                                                                : ComponentOrientation.RIGHT_TO_LEFT);
0755:                                                            }
0756:                                                        });
0757:                                            }
0758:                                        });
0759:                                popup.add(ltrChange);
0760:
0761:                                final JCheckBoxMenuItem useThemedIcons = new JCheckBoxMenuItem(
0762:                                        "Use themed icons");
0763:                                useThemedIcons
0764:                                        .setSelected(SubstanceCoreUtilities
0765:                                                .useThemedDefaultIcon(null));
0766:                                useThemedIcons
0767:                                        .addActionListener(new ActionListener() {
0768:                                            public void actionPerformed(
0769:                                                    ActionEvent e) {
0770:                                                SwingUtilities
0771:                                                        .invokeLater(new Runnable() {
0772:                                                            public void run() {
0773:                                                                UIManager
0774:                                                                        .put(
0775:                                                                                SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS,
0776:                                                                                useThemedIcons
0777:                                                                                        .isSelected() ? Boolean.TRUE
0778:                                                                                        : null);
0779:                                                                rootPane
0780:                                                                        .repaint();
0781:                                                            }
0782:                                                        });
0783:                                            }
0784:                                        });
0785:                                popup.add(useThemedIcons);
0786:
0787:                                final JCheckBoxMenuItem ghostDebugMode = new JCheckBoxMenuItem(
0788:                                        "Ghost debug mode");
0789:                                ghostDebugMode
0790:                                        .addActionListener(new ActionListener() {
0791:                                            public void actionPerformed(
0792:                                                    ActionEvent e) {
0793:                                                SwingUtilities
0794:                                                        .invokeLater(new Runnable() {
0795:                                                            public void run() {
0796:                                                                ghostDebugMode
0797:                                                                        .setEnabled(false);
0798:                                                                GhostPaintingUtils.MAX_ICON_GHOSTING_ALPHA = 0.8f;
0799:                                                                GhostPaintingUtils.MIN_ICON_GHOSTING_ALPHA = 0.6f;
0800:                                                                GhostPaintingUtils.MAX_PRESS_GHOSTING_ALPHA = 0.8f;
0801:                                                                GhostPaintingUtils.MIN_PRESS_GHOSTING_ALPHA = 0.6f;
0802:                                                                GhostPaintingUtils.DECAY_FACTOR = 0.7f;
0803:                                                            }
0804:                                                        });
0805:                                            }
0806:                                        });
0807:                                popup.add(ghostDebugMode);
0808:
0809:                                popup.show(SubstanceTitlePane.this , e.getX(), e
0810:                                        .getY());
0811:                            }
0812:                        }
0813:                    };
0814:                    this .addMouseListener(this .substanceDebugUiListener);
0815:                }
0816:            }
0817:
0818:            /**
0819:             * Uninstalls the necessary listeners.
0820:             */
0821:            private void uninstallListeners() {
0822:                if (this .window != null) {
0823:                    this .window.removeWindowListener(this .windowListener);
0824:                    this .windowListener = null;
0825:                    this .window
0826:                            .removePropertyChangeListener(this .propertyChangeListener);
0827:                    this .propertyChangeListener = null;
0828:                }
0829:
0830:                // Fix for defect 109 - memory leak on theme change.
0831:                this .rootPane
0832:                        .removePropertyChangeListener(this .propertyListener);
0833:                if (this .getFrame() != null)
0834:                    this .getFrame().removePropertyChangeListener(
0835:                            this .propertyListener);
0836:                this .propertyListener = null;
0837:
0838:                if (this .substanceDebugUiListener != null) {
0839:                    this .removeMouseListener(this .substanceDebugUiListener);
0840:                    this .substanceDebugUiListener = null;
0841:                }
0842:            }
0843:
0844:            /**
0845:             * Returns the <code>JRootPane</code> this was created for.
0846:             */
0847:            @Override
0848:            public JRootPane getRootPane() {
0849:                return this .rootPane;
0850:            }
0851:
0852:            /**
0853:             * Returns the decoration style of the <code>JRootPane</code>.
0854:             * 
0855:             * @return Decoration style of the <code>JRootPane</code>.
0856:             */
0857:            private int getWindowDecorationStyle() {
0858:                return this .getRootPane().getWindowDecorationStyle();
0859:            }
0860:
0861:            /*
0862:             * (non-Javadoc)
0863:             * 
0864:             * @see java.awt.Component#addNotify()
0865:             */
0866:            @Override
0867:            public void addNotify() {
0868:                super .addNotify();
0869:
0870:                this .uninstallListeners();
0871:
0872:                this .window = SwingUtilities.getWindowAncestor(this );
0873:                if (this .window != null) {
0874:                    this .setActive(this .window.isActive());
0875:                    if (Boolean.TRUE.equals(SwingUtilities.getRootPane(this )
0876:                            .getClientProperty(HAS_BEEN_UNINSTALLED))) {
0877:                        // System.out.println("Reinstalling");
0878:                        this .installSubcomponents();
0879:                        this .installDefaults();
0880:                        this .setLayout(this .createLayout());
0881:                        this .setToolTipText(this .getTitle());
0882:                    }
0883:                    if (this .window instanceof  Frame) {
0884:                        this .setState(((Frame) this .window).getExtendedState());
0885:                    } else {
0886:                        this .setState(0);
0887:                    }
0888:                    this .installListeners();
0889:                }
0890:                this .setToolTipText(this .getTitle());
0891:            }
0892:
0893:            /*
0894:             * (non-Javadoc)
0895:             * 
0896:             * @see java.awt.Component#removeNotify()
0897:             */
0898:            @Override
0899:            public void removeNotify() {
0900:                // System.out.println("Uninstalling");
0901:                SwingUtilities.getRootPane(this ).putClientProperty(
0902:                        HAS_BEEN_UNINSTALLED, Boolean.TRUE);
0903:                super .removeNotify();
0904:
0905:                this .uninstall();
0906:                this .window = null;
0907:                //
0908:                // // Fix for defect 189 - memory leak on disposed frames
0909:                // if (menuBar != null) {
0910:                // MenuBarUI menuBarUI = menuBar.getUI();
0911:                // if (menuBarUI instanceof SubstanceMenuBarUI) {
0912:                // ((SubstanceMenuBarUI) menuBarUI).uninstallUI(menuBar);
0913:                // }
0914:                // }
0915:            }
0916:
0917:            /**
0918:             * Adds any sub-Components contained in the <code>SubstanceTitlePane</code>.
0919:             */
0920:            private void installSubcomponents() {
0921:                int decorationStyle = this .getWindowDecorationStyle();
0922:                if (decorationStyle == JRootPane.FRAME) {
0923:                    this .createActions();
0924:                    this .menuBar = this .createMenuBar();
0925:                    this .add(this .menuBar);
0926:                    this .createButtons();
0927:                    this .add(this .minimizeButton);
0928:                    this .add(this .toggleButton);
0929:                    this .add(this .closeButton);
0930:
0931:                    if (SubstanceTitlePane.canHaveHeapStatusPanel) {
0932:                        this .heapStatusPanel = new HeapStatusPanel(this );
0933:                        this .add(this .heapStatusPanel);
0934:                        boolean isHeapStatusPanelShowing = Boolean.TRUE
0935:                                .equals(this .rootPane
0936:                                        .getClientProperty(SubstanceLookAndFeel.HEAP_STATUS_PANEL));
0937:                        this .heapStatusPanel
0938:                                .setVisible(isHeapStatusPanelShowing);
0939:                        this .heapStatusPanel.setPreferredSize(new Dimension(80,
0940:                                this .getPreferredSize().height));
0941:                        this .heapStatusPanel
0942:                                .setToolTipText(SubstanceCoreUtilities
0943:                                        .getResourceBundle(rootPane).getString(
0944:                                                "Tooltip.heapStatusPanel"));
0945:                        this .heapStatusPanel
0946:                                .addMouseListener(new MouseAdapter() {
0947:                                    @Override
0948:                                    public void mouseClicked(MouseEvent e) {
0949:                                        System.gc();
0950:                                    }
0951:                                });
0952:
0953:                        HeapStatusThread.registerPanel(this .heapStatusPanel);
0954:                    }
0955:                } else {
0956:                    if ((decorationStyle == JRootPane.PLAIN_DIALOG)
0957:                            || (decorationStyle == JRootPane.INFORMATION_DIALOG)
0958:                            || (decorationStyle == JRootPane.ERROR_DIALOG)
0959:                            || (decorationStyle == JRootPane.COLOR_CHOOSER_DIALOG)
0960:                            || (decorationStyle == JRootPane.FILE_CHOOSER_DIALOG)
0961:                            || (decorationStyle == JRootPane.QUESTION_DIALOG)
0962:                            || (decorationStyle == JRootPane.WARNING_DIALOG)) {
0963:                        this .createActions();
0964:                        this .createButtons();
0965:                        this .add(this .closeButton);
0966:                    }
0967:                }
0968:            }
0969:
0970:            /**
0971:             * Installs the fonts and necessary properties.
0972:             */
0973:            private void installDefaults() {
0974:                this .setFont(UIManager.getFont("InternalFrame.titleFont", this 
0975:                        .getLocale()));
0976:            }
0977:
0978:            /**
0979:             * Returns the <code>JMenuBar</code> displaying the appropriate system
0980:             * menu items.
0981:             * 
0982:             * @return <code>JMenuBar</code> displaying the appropriate system menu
0983:             *         items.
0984:             */
0985:            protected JMenuBar createMenuBar() {
0986:                this .menuBar = new SubstanceMenuBar();
0987:                this .menuBar.setFocusable(false);
0988:                this .menuBar.setBorderPainted(true);
0989:                this .menuBar.add(this .createMenu());
0990:                this .menuBar.setOpaque(false);
0991:                // support for RTL
0992:                this .menuBar.applyComponentOrientation(this .rootPane
0993:                        .getComponentOrientation());
0994:                return this .menuBar;
0995:            }
0996:
0997:            /**
0998:             * Create the <code>Action</code>s that get associated with the buttons
0999:             * and menu items.
1000:             */
1001:            private void createActions() {
1002:                this .closeAction = new CloseAction();
1003:                if (this .getWindowDecorationStyle() == JRootPane.FRAME) {
1004:                    this .iconifyAction = new IconifyAction();
1005:                    this .restoreAction = new RestoreAction();
1006:                    this .maximizeAction = new MaximizeAction();
1007:                }
1008:            }
1009:
1010:            /**
1011:             * Returns the <code>JMenu</code> displaying the appropriate menu items
1012:             * for manipulating the Frame.
1013:             * 
1014:             * @return <code>JMenu</code> displaying the appropriate menu items for
1015:             *         manipulating the Frame.
1016:             */
1017:            private JMenu createMenu() {
1018:                JMenu menu = new JMenu("");
1019:                menu.setOpaque(false);
1020:                menu.setBackground(null);
1021:                if (this .getWindowDecorationStyle() == JRootPane.FRAME) {
1022:                    this .addMenuItems(menu);
1023:                }
1024:                return menu;
1025:            }
1026:
1027:            /**
1028:             * Adds the necessary <code>JMenuItem</code>s to the specified menu.
1029:             * 
1030:             * @param menu
1031:             *            Menu.
1032:             */
1033:            private void addMenuItems(JMenu menu) {
1034:                menu.add(this .restoreAction);
1035:
1036:                menu.add(this .iconifyAction);
1037:
1038:                if (Toolkit.getDefaultToolkit().isFrameStateSupported(
1039:                        Frame.MAXIMIZED_BOTH)) {
1040:                    menu.add(this .maximizeAction);
1041:                }
1042:
1043:                if (SubstanceLookAndFeel.toShowExtraElements()) {
1044:                    menu.addSeparator();
1045:                    JMenu skinMenu = new JMenu(SubstanceCoreUtilities
1046:                            .getResourceBundle(rootPane).getString(
1047:                                    "SystemMenu.skins"));
1048:                    Map<String, SkinInfo> allSkins = SubstanceLookAndFeel
1049:                            .getAllSkins();
1050:                    for (Map.Entry<String, SkinInfo> skinEntry : allSkins
1051:                            .entrySet()) {
1052:                        final String skinClassName = skinEntry.getValue()
1053:                                .getClassName();
1054:                        JMenuItem jmiSkin = new JMenuItem(skinEntry.getKey());
1055:                        jmiSkin.addActionListener(new ActionListener() {
1056:                            public void actionPerformed(ActionEvent e) {
1057:                                SwingUtilities.invokeLater(new Runnable() {
1058:                                    public void run() {
1059:                                        SubstanceLookAndFeel
1060:                                                .setSkin(skinClassName);
1061:                                    }
1062:                                });
1063:                            }
1064:                        });
1065:
1066:                        // try {
1067:                        // SubstanceSkin skin = ((SubstanceSkin) Class.forName(
1068:                        // skinClassName).newInstance());
1069:                        // Container cont = rootPane.getParent();
1070:                        // if (cont instanceof Frame) {
1071:                        // Image icon = ((Frame) cont).getIconImage();
1072:                        // if (icon != null) {
1073:                        // jmiSkin.setIcon(new ImageIcon(SubstanceImageCreator
1074:                        // .getThemeImage(new ImageIcon(icon), skin
1075:                        // .getTheme())));
1076:                        // }
1077:                        // }
1078:                        // } catch (Exception exc) {
1079:                        // }
1080:                        //
1081:                        skinMenu.add(jmiSkin);
1082:                    }
1083:                    menu.add(skinMenu);
1084:
1085:                    JMenu themeMenu = new JMenu(SubstanceCoreUtilities
1086:                            .getResourceBundle(rootPane).getString(
1087:                                    "SystemMenu.themes"));
1088:                    ButtonGroup bgTheme = new ButtonGroup();
1089:                    JMenu brightThemes = new JMenu(SubstanceCoreUtilities
1090:                            .getResourceBundle(rootPane).getString(
1091:                                    "SystemMenu.themesBright"));
1092:                    JMenu coldThemes = new JMenu(SubstanceCoreUtilities
1093:                            .getResourceBundle(rootPane).getString(
1094:                                    "SystemMenu.themesCold"));
1095:                    JMenu darkThemes = new JMenu(SubstanceCoreUtilities
1096:                            .getResourceBundle(rootPane).getString(
1097:                                    "SystemMenu.themesDark"));
1098:                    JMenu invertedThemes = SubstanceLookAndFeel
1099:                            .toEnableInvertedThemes() ? new JMenu(
1100:                            SubstanceCoreUtilities.getResourceBundle(rootPane)
1101:                                    .getString("SystemMenu.themesInverted"))
1102:                            : null;
1103:                    JMenu negatedThemes = SubstanceLookAndFeel
1104:                            .toEnableNegatedThemes() ? new JMenu(
1105:                            SubstanceCoreUtilities.getResourceBundle(rootPane)
1106:                                    .getString("SystemMenu.themesNegated"))
1107:                            : null;
1108:                    JMenu mixedThemes = SubstanceLookAndFeel.hasMixedThemes() ? new JMenu(
1109:                            SubstanceCoreUtilities.getResourceBundle(rootPane)
1110:                                    .getString("SystemMenu.themesMixed"))
1111:                            : null;
1112:
1113:                    themeMenu.add(brightThemes);
1114:                    themeMenu.add(coldThemes);
1115:                    themeMenu.add(darkThemes);
1116:                    if (invertedThemes != null)
1117:                        themeMenu.add(invertedThemes);
1118:                    if (negatedThemes != null)
1119:                        themeMenu.add(negatedThemes);
1120:                    if (mixedThemes != null)
1121:                        themeMenu.add(mixedThemes);
1122:
1123:                    this .themeMenuHandler = new TraitMenuHandler();
1124:                    Map<String, ThemeInfo> allThemes = SubstanceLookAndFeel
1125:                            .getAllThemes();
1126:                    for (Map.Entry<String, ThemeInfo> themeEntry : allThemes
1127:                            .entrySet()) {
1128:                        final ThemeInfo themeInfo = themeEntry.getValue();
1129:                        final String themeClassName = themeInfo.getClassName();
1130:                        JRadioButtonMenuItem jmiTheme = new JRadioButtonMenuItem(
1131:                                themeEntry.getKey());
1132:                        this .themeMenuHandler.addTraitButton(themeInfo
1133:                                .getDisplayName(), jmiTheme);
1134:
1135:                        jmiTheme.addActionListener(new ActionListener() {
1136:                            public void actionPerformed(ActionEvent e) {
1137:                                SwingUtilities.invokeLater(new Runnable() {
1138:                                    public void run() {
1139:                                        SubstanceLookAndFeel
1140:                                                .setCurrentTheme(themeInfo);
1141:                                        // update all existing root panes
1142:                                        for (Frame frame : Frame.getFrames()) {
1143:                                            SwingUtilities
1144:                                                    .updateComponentTreeUI(frame);
1145:                                        }
1146:                                    }
1147:                                });
1148:                            }
1149:                        });
1150:                        try {
1151:                            switch (themeInfo.getThemeKind()) {
1152:                            case MIXED:
1153:                                MixedThemeInfo mixedThemeInfo = (MixedThemeInfo) themeInfo;
1154:                                String[] themeClassNames = mixedThemeInfo
1155:                                        .getThemeClassNames();
1156:                                SubstanceTheme[] themeInstances = new SubstanceTheme[themeClassNames.length];
1157:                                for (int i = 0; i < themeClassNames.length; i++) {
1158:                                    Class<?> themeClass = Class
1159:                                            .forName(themeClassNames[i]);
1160:                                    themeInstances[i] = (SubstanceTheme) themeClass
1161:                                            .newInstance();
1162:                                }
1163:
1164:                                SubstanceTheme mixTheme = new SubstanceMixTheme(
1165:                                        themeInstances);
1166:                                jmiTheme.setIcon(SubstanceImageCreator
1167:                                        .getThemeIcon(mixTheme));
1168:                                break;
1169:                            default:
1170:                                Class<?> themeClass = Class
1171:                                        .forName(themeClassName);
1172:                                SubstanceTheme theme = (SubstanceTheme) themeClass
1173:                                        .newInstance();
1174:                                if (themeInfo.getThemeKind() == ThemeKind.INVERTED)
1175:                                    theme = new SubstanceInvertedTheme(theme);
1176:                                if (themeInfo.getThemeKind() == ThemeKind.NEGATED)
1177:                                    theme = new SubstanceNegatedTheme(theme);
1178:                                jmiTheme.setIcon(SubstanceImageCreator
1179:                                        .getThemeIcon(theme));
1180:                            }
1181:                        } catch (Exception exc) {
1182:                            continue;
1183:                        }
1184:                        if (themeEntry.getKey().equals(
1185:                                SubstanceLookAndFeel.getCurrentThemeName())) {
1186:                            jmiTheme.setSelected(true);
1187:                        }
1188:                        switch (themeEntry.getValue().getThemeKind()) {
1189:                        case BRIGHT:
1190:                            brightThemes.add(jmiTheme);
1191:                            break;
1192:                        case COLD:
1193:                            coldThemes.add(jmiTheme);
1194:                            break;
1195:                        case DARK:
1196:                            darkThemes.add(jmiTheme);
1197:                            break;
1198:                        case INVERTED:
1199:                            invertedThemes.add(jmiTheme);
1200:                            break;
1201:                        case NEGATED:
1202:                            negatedThemes.add(jmiTheme);
1203:                            break;
1204:                        case MIXED:
1205:                            mixedThemes.add(jmiTheme);
1206:                            break;
1207:                        }
1208:                        bgTheme.add(jmiTheme);
1209:                    }
1210:
1211:                    themeMenu.setIcon(SubstanceImageCreator.getThemeIcon(null));
1212:                    menu.add(themeMenu);
1213:
1214:                    this .themeChangeListener = new ThemeChangeListener() {
1215:                        public void themeChanged() {
1216:                            themeMenuHandler
1217:                                    .selectTraitButton(SubstanceLookAndFeel
1218:                                            .getTheme());
1219:                        }
1220:                    };
1221:                    SubstanceLookAndFeel
1222:                            .registerThemeChangeListener(this .themeChangeListener);
1223:
1224:                    JMenu watermarkMenu = new JMenu(SubstanceCoreUtilities
1225:                            .getResourceBundle(rootPane).getString(
1226:                                    "SystemMenu.watermarks"));
1227:                    ButtonGroup bgWatermark = new ButtonGroup();
1228:                    this .watermarkMenuHandler = new TraitMenuHandler();
1229:                    Map<String, WatermarkInfo> allWatermarks = SubstanceLookAndFeel
1230:                            .getAllWatermarks();
1231:                    for (Map.Entry<String, WatermarkInfo> watermarkEntry : allWatermarks
1232:                            .entrySet()) {
1233:                        final String watermarkClassName = watermarkEntry
1234:                                .getValue().getClassName();
1235:                        JRadioButtonMenuItem jmiWatermark = new JRadioButtonMenuItem(
1236:                                watermarkEntry.getKey());
1237:                        this .watermarkMenuHandler.addTraitButton(watermarkEntry
1238:                                .getValue().getDisplayName(), jmiWatermark);
1239:                        jmiWatermark.addActionListener(new ActionListener() {
1240:                            public void actionPerformed(ActionEvent e) {
1241:                                SwingUtilities.invokeLater(new Runnable() {
1242:                                    public void run() {
1243:                                        SubstanceLookAndFeel
1244:                                                .setCurrentWatermark(watermarkClassName);
1245:                                        // update all existing root panes
1246:                                        for (Frame frame : Frame.getFrames()) {
1247:                                            SwingUtilities
1248:                                                    .updateComponentTreeUI(frame);
1249:                                        }
1250:                                    }
1251:                                });
1252:                            }
1253:                        });
1254:                        if (watermarkEntry.getKey().equals(
1255:                                SubstanceLookAndFeel.getCurrentWatermarkName())) {
1256:                            jmiWatermark.setSelected(true);
1257:                        }
1258:
1259:                        try {
1260:                            Class<?> watermarkClass = Class
1261:                                    .forName(watermarkClassName);
1262:                            SubstanceWatermark watermark = (SubstanceWatermark) watermarkClass
1263:                                    .newInstance();
1264:                            jmiWatermark.setIcon(SubstanceImageCreator
1265:                                    .getWatermarkIcon(watermark));
1266:                        } catch (Exception exc) {
1267:                        }
1268:
1269:                        bgWatermark.add(jmiWatermark);
1270:                        watermarkMenu.add(jmiWatermark);
1271:                    }
1272:                    menu.add(watermarkMenu);
1273:                    this .watermarkChangeListener = new WatermarkChangeListener() {
1274:                        public void watermarkChanged() {
1275:                            watermarkMenuHandler
1276:                                    .selectTraitButton(SubstanceLookAndFeel
1277:                                            .getCurrentWatermark());
1278:                        }
1279:                    };
1280:                    SubstanceLookAndFeel
1281:                            .registerWatermarkChangeListener(this .watermarkChangeListener);
1282:
1283:                    JMenu buttonShaperMenu = new JMenu(SubstanceCoreUtilities
1284:                            .getResourceBundle(rootPane).getString(
1285:                                    "SystemMenu.buttonShapers"));
1286:                    ButtonGroup bgButtonShaper = new ButtonGroup();
1287:                    this .buttonShaperMenuHandler = new TraitMenuHandler();
1288:                    Map<String, ButtonShaperInfo> allButtonShapers = SubstanceLookAndFeel
1289:                            .getAllButtonShapers();
1290:                    for (Map.Entry<String, ButtonShaperInfo> buttonShaperEntry : allButtonShapers
1291:                            .entrySet()) {
1292:                        final String buttonShaperClassName = buttonShaperEntry
1293:                                .getValue().getClassName();
1294:                        JRadioButtonMenuItem jmiButtonShaper = new JRadioButtonMenuItem(
1295:                                buttonShaperEntry.getKey());
1296:                        this .buttonShaperMenuHandler.addTraitButton(
1297:                                buttonShaperEntry.getValue().getDisplayName(),
1298:                                jmiButtonShaper);
1299:                        jmiButtonShaper.addActionListener(new ActionListener() {
1300:                            public void actionPerformed(ActionEvent e) {
1301:                                SwingUtilities.invokeLater(new Runnable() {
1302:                                    public void run() {
1303:                                        SubstanceLookAndFeel
1304:                                                .setCurrentButtonShaper(buttonShaperClassName);
1305:                                        // update all existing root panes
1306:                                        for (Frame frame : Frame.getFrames()) {
1307:                                            SwingUtilities
1308:                                                    .updateComponentTreeUI(frame);
1309:                                        }
1310:                                    }
1311:                                });
1312:                            }
1313:                        });
1314:                        if (buttonShaperEntry.getKey().equals(
1315:                                SubstanceLookAndFeel
1316:                                        .getCurrentButtonShaperName())) {
1317:                            jmiButtonShaper.setSelected(true);
1318:                        }
1319:                        bgButtonShaper.add(jmiButtonShaper);
1320:                        buttonShaperMenu.add(jmiButtonShaper);
1321:                    }
1322:                    menu.add(buttonShaperMenu);
1323:                    this .buttonShaperChangeListener = new ButtonShaperChangeListener() {
1324:                        public void buttonShaperChanged() {
1325:                            buttonShaperMenuHandler
1326:                                    .selectTraitButton(SubstanceLookAndFeel
1327:                                            .getCurrentButtonShaper());
1328:                        }
1329:                    };
1330:                    SubstanceLookAndFeel
1331:                            .registerButtonShaperChangeListener(this .buttonShaperChangeListener);
1332:
1333:                    JMenu borderPainterMenu = new JMenu(SubstanceCoreUtilities
1334:                            .getResourceBundle(rootPane).getString(
1335:                                    "SystemMenu.borderPainters"));
1336:                    ButtonGroup bgBorderPainter = new ButtonGroup();
1337:                    this .borderPainterMenuHandler = new TraitMenuHandler();
1338:                    Map<String, BorderPainterInfo> allBorderPainters = SubstanceLookAndFeel
1339:                            .getAllBorderPainters();
1340:                    for (Map.Entry<String, BorderPainterInfo> borderPainterEntry : allBorderPainters
1341:                            .entrySet()) {
1342:                        final String borderPainterClassName = borderPainterEntry
1343:                                .getValue().getClassName();
1344:                        JRadioButtonMenuItem jmiBorderPainter = new JRadioButtonMenuItem(
1345:                                borderPainterEntry.getKey());
1346:                        this .borderPainterMenuHandler.addTraitButton(
1347:                                borderPainterEntry.getValue().getDisplayName(),
1348:                                jmiBorderPainter);
1349:                        jmiBorderPainter
1350:                                .addActionListener(new ActionListener() {
1351:                                    public void actionPerformed(ActionEvent e) {
1352:                                        SwingUtilities
1353:                                                .invokeLater(new Runnable() {
1354:                                                    public void run() {
1355:
1356:                                                        SubstanceLookAndFeel
1357:                                                                .setCurrentBorderPainter(borderPainterClassName);
1358:                                                        // update all existing root panes
1359:                                                        for (Frame frame : Frame
1360:                                                                .getFrames()) {
1361:                                                            SwingUtilities
1362:                                                                    .updateComponentTreeUI(frame);
1363:                                                        }
1364:                                                    }
1365:                                                });
1366:                                    }
1367:                                });
1368:                        if (borderPainterEntry.getKey().equals(
1369:                                SubstanceLookAndFeel
1370:                                        .getCurrentBorderPainterName())) {
1371:                            jmiBorderPainter.setSelected(true);
1372:                        }
1373:                        bgBorderPainter.add(jmiBorderPainter);
1374:                        borderPainterMenu.add(jmiBorderPainter);
1375:                    }
1376:                    menu.add(borderPainterMenu);
1377:                    this .borderPainterChangeListener = new BorderPainterChangeListener() {
1378:                        public void borderPainterChanged() {
1379:                            borderPainterMenuHandler
1380:                                    .selectTraitButton(SubstanceLookAndFeel
1381:                                            .getCurrentBorderPainter());
1382:                        }
1383:                    };
1384:                    SubstanceLookAndFeel
1385:                            .registerBorderPainterChangeListener(this .borderPainterChangeListener);
1386:
1387:                    JMenu gradientPainterMenu = new JMenu(
1388:                            SubstanceCoreUtilities.getResourceBundle(rootPane)
1389:                                    .getString("SystemMenu.gradientPainters"));
1390:                    ButtonGroup bgGradientPainter = new ButtonGroup();
1391:                    this .gradientPainterMenuHandler = new TraitMenuHandler();
1392:                    Map<String, GradientPainterInfo> allGradientPainters = SubstanceLookAndFeel
1393:                            .getAllGradientPainters();
1394:                    for (Map.Entry<String, GradientPainterInfo> gradientPainterEntry : allGradientPainters
1395:                            .entrySet()) {
1396:                        final String gradientPainterClassName = gradientPainterEntry
1397:                                .getValue().getClassName();
1398:                        JRadioButtonMenuItem jmiGradientPainter = new JRadioButtonMenuItem(
1399:                                gradientPainterEntry.getKey());
1400:                        this .gradientPainterMenuHandler.addTraitButton(
1401:                                gradientPainterEntry.getValue()
1402:                                        .getDisplayName(), jmiGradientPainter);
1403:                        jmiGradientPainter
1404:                                .addActionListener(new ActionListener() {
1405:                                    public void actionPerformed(ActionEvent e) {
1406:                                        SwingUtilities
1407:                                                .invokeLater(new Runnable() {
1408:                                                    public void run() {
1409:                                                        SubstanceLookAndFeel
1410:                                                                .setCurrentGradientPainter(gradientPainterClassName);
1411:                                                        // update all existing root panes
1412:                                                        for (Frame frame : Frame
1413:                                                                .getFrames()) {
1414:                                                            SwingUtilities
1415:                                                                    .updateComponentTreeUI(frame);
1416:                                                        }
1417:                                                    }
1418:                                                });
1419:                                    }
1420:                                });
1421:                        if (gradientPainterEntry.getKey().equals(
1422:                                SubstanceLookAndFeel
1423:                                        .getCurrentGradientPainterName())) {
1424:                            jmiGradientPainter.setSelected(true);
1425:                        }
1426:                        bgGradientPainter.add(jmiGradientPainter);
1427:                        gradientPainterMenu.add(jmiGradientPainter);
1428:                    }
1429:                    menu.add(gradientPainterMenu);
1430:                    this .gradientPainterChangeListener = new GradientPainterChangeListener() {
1431:                        public void gradientPainterChanged() {
1432:                            gradientPainterMenuHandler
1433:                                    .selectTraitButton(SubstanceLookAndFeel
1434:                                            .getCurrentGradientPainter());
1435:                        }
1436:                    };
1437:                    SubstanceLookAndFeel
1438:                            .registerGradientPainterChangeListener(this .gradientPainterChangeListener);
1439:
1440:                    if (SubstanceTitlePane.canHaveHeapStatusPanel
1441:                            && (!(this .rootPane
1442:                                    .getClientProperty(SubstanceTitlePane.HEAP_STATUS_PANEL_PERMANENT) instanceof  Boolean))) {
1443:                        this .heapStatusMenuItem = new JCheckBoxMenuItem(
1444:                                SubstanceCoreUtilities.getResourceBundle(
1445:                                        rootPane).getString(
1446:                                        "SystemMenu.showHeapStatus"));
1447:                        boolean isHeapStatusPanelShowing = Boolean.TRUE
1448:                                .equals(this .rootPane
1449:                                        .getClientProperty(SubstanceLookAndFeel.HEAP_STATUS_PANEL));
1450:                        this .heapStatusMenuItem
1451:                                .setSelected(isHeapStatusPanelShowing);
1452:                        this .heapStatusMenuItem
1453:                                .addActionListener(new ActionListener() {
1454:                                    public void actionPerformed(ActionEvent e) {
1455:                                        SubstanceTitlePane.this .heapStatusPanel
1456:                                                .setVisible(!SubstanceTitlePane.this .heapStatusPanel
1457:                                                        .isVisible());
1458:                                        SubstanceTitlePane.this .rootPane
1459:                                                .putClientProperty(
1460:                                                        SubstanceLookAndFeel.HEAP_STATUS_PANEL,
1461:                                                        Boolean
1462:                                                                .valueOf(SubstanceTitlePane.this .heapStatusPanel
1463:                                                                        .isVisible()));
1464:                                    }
1465:                                });
1466:                        menu.add(this .heapStatusMenuItem);
1467:                    }
1468:                }
1469:
1470:                menu.addSeparator();
1471:
1472:                menu.add(this .closeAction);
1473:            }
1474:
1475:            /**
1476:             * Returns a <code>JButton</code> appropriate for placement on the
1477:             * TitlePane.
1478:             * 
1479:             * @return Title button.
1480:             */
1481:            private JButton createTitleButton() {
1482:                JButton button = new SubstanceTitleButton();
1483:
1484:                button.setFocusPainted(false);
1485:                button.setFocusable(false);
1486:                button.setOpaque(true);
1487:
1488:                return button;
1489:            }
1490:
1491:            /**
1492:             * Creates the Buttons that will be placed on the TitlePane.
1493:             */
1494:            private void createButtons() {
1495:                SubstanceTheme iconTheme = SubstanceLookAndFeel.getTheme()
1496:                        .getActiveTitlePaneTheme();
1497:
1498:                this .closeButton = this .createTitleButton();
1499:                this .closeButton.setAction(this .closeAction);
1500:                this .closeButton.setText(null);
1501:                this .closeButton.putClientProperty("paintActive", Boolean.TRUE);
1502:                this .closeButton.setBorder(null);
1503:                // this.closeButton.setToolTipText(SubstanceLookAndFeel
1504:                // .getLabelBundle().getString(
1505:                // "SystemMenu.close"));
1506:
1507:                Icon closeIcon = new TransitionAwareIcon(closeButton,
1508:                        new TransitionAwareIcon.Delegate() {
1509:                            public Icon getThemeIcon(SubstanceTheme theme) {
1510:                                return SubstanceIconFactory.getTitlePaneIcon(
1511:                                        SubstanceIconFactory.IconKind.CLOSE,
1512:                                        theme);
1513:                            }
1514:                        });
1515:                this .closeButton.setIcon(closeIcon);
1516:
1517:                this .closeButton.setFocusable(false);
1518:                this .closeButton.putClientProperty(
1519:                        SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
1520:
1521:                this .closeButton.putClientProperty(
1522:                        SubstanceButtonUI.IS_TITLE_CLOSE_BUTTON, Boolean.TRUE);
1523:
1524:                if (this .getWindowDecorationStyle() == JRootPane.FRAME) {
1525:                    // Icon maximizeIcon = SubstanceIconFactory.getTitlePaneIcon(
1526:                    // SubstanceIconFactory.IconKind.MAXIMIZE, iconTheme);
1527:
1528:                    // Icon restoreSizeIcon = SubstanceIconFactory.getTitlePaneIcon(
1529:                    // SubstanceIconFactory.IconKind.RESTORE, SubstanceLookAndFeel
1530:                    // .getColorScheme());
1531:
1532:                    this .minimizeButton = this .createTitleButton();
1533:                    this .minimizeButton.setAction(this .iconifyAction);
1534:                    this .minimizeButton.setText(null);
1535:                    this .minimizeButton.putClientProperty("paintActive",
1536:                            Boolean.TRUE);
1537:                    this .minimizeButton.setBorder(null);
1538:
1539:                    Icon minIcon = new TransitionAwareIcon(this .minimizeButton,
1540:                            new TransitionAwareIcon.Delegate() {
1541:                                public Icon getThemeIcon(SubstanceTheme theme) {
1542:                                    return SubstanceIconFactory
1543:                                            .getTitlePaneIcon(
1544:                                                    SubstanceIconFactory.IconKind.MINIMIZE,
1545:                                                    theme);
1546:                                }
1547:                            });
1548:                    this .minimizeButton.setIcon(minIcon);
1549:
1550:                    this .minimizeButton.setFocusable(false);
1551:                    this .minimizeButton.putClientProperty(
1552:                            SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
1553:                    this .minimizeButton.setToolTipText(SubstanceCoreUtilities
1554:                            .getResourceBundle(rootPane).getString(
1555:                                    "SystemMenu.iconify"));
1556:
1557:                    this .toggleButton = this .createTitleButton();
1558:                    this .toggleButton.setAction(this .restoreAction);
1559:                    this .toggleButton.putClientProperty("paintActive",
1560:                            Boolean.TRUE);
1561:                    this .toggleButton.setBorder(null);
1562:                    this .toggleButton.setText(null);
1563:
1564:                    Icon maxIcon = new TransitionAwareIcon(this .toggleButton,
1565:                            new TransitionAwareIcon.Delegate() {
1566:                                public Icon getThemeIcon(SubstanceTheme theme) {
1567:                                    return SubstanceIconFactory
1568:                                            .getTitlePaneIcon(
1569:                                                    SubstanceIconFactory.IconKind.MAXIMIZE,
1570:                                                    theme);
1571:                                }
1572:                            });
1573:                    this .toggleButton.setIcon(maxIcon);
1574:
1575:                    this .toggleButton.setToolTipText(SubstanceCoreUtilities
1576:                            .getResourceBundle(rootPane).getString(
1577:                                    "SystemMenu.maximize"));
1578:                    this .toggleButton.setFocusable(false);
1579:                    this .toggleButton.putClientProperty(
1580:                            SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
1581:
1582:                }
1583:                syncCloseButtonTooltip();
1584:            }
1585:
1586:            /**
1587:             * Returns the <code>LayoutManager</code> that should be installed on the
1588:             * <code>SubstanceTitlePane</code>.
1589:             * 
1590:             * @return Layout manager.
1591:             */
1592:            private LayoutManager createLayout() {
1593:                return new TitlePaneLayout();
1594:            }
1595:
1596:            /**
1597:             * Updates state dependant upon the Window's active state.
1598:             * 
1599:             * @param isActive
1600:             *            if <code>true</code>, the window is in active state.
1601:             */
1602:            private void setActive(boolean isActive) {
1603:                Boolean activeB = isActive ? Boolean.TRUE : Boolean.FALSE;
1604:
1605:                if (this .getWindowDecorationStyle() == JRootPane.FRAME) {
1606:                    this .closeButton.putClientProperty("paintActive", activeB);
1607:                    this .minimizeButton.putClientProperty("paintActive",
1608:                            activeB);
1609:                    this .toggleButton.putClientProperty("paintActive", activeB);
1610:                }
1611:                this .getRootPane().repaint();
1612:            }
1613:
1614:            /**
1615:             * Sets the state of the Window.
1616:             * 
1617:             * @param state
1618:             *            Window state.
1619:             */
1620:            private void setState(int state) {
1621:                this .setState(state, false);
1622:            }
1623:
1624:            /**
1625:             * Sets the state of the window. If <code>updateRegardless</code> is true
1626:             * and the state has not changed, this will update anyway.
1627:             * 
1628:             * @param state
1629:             *            Window state.
1630:             * @param updateRegardless
1631:             *            if <code>true</code>, the update is done in any case.
1632:             */
1633:            private void setState(int state, boolean updateRegardless) {
1634:                Window w = this .getWindow();
1635:
1636:                if ((w != null)
1637:                        && (this .getWindowDecorationStyle() == JRootPane.FRAME)) {
1638:                    if ((this .state == state) && !updateRegardless) {
1639:                        return;
1640:                    }
1641:                    Frame frame = this .getFrame();
1642:
1643:                    if (frame != null) {
1644:                        JRootPane rootPane = this .getRootPane();
1645:
1646:                        if (((state & Frame.MAXIMIZED_BOTH) != 0)
1647:                                && ((rootPane.getBorder() == null) || (rootPane
1648:                                        .getBorder() instanceof  UIResource))
1649:                                && frame.isShowing()) {
1650:                            rootPane.setBorder(null);
1651:                        } else {
1652:                            if ((state & Frame.MAXIMIZED_BOTH) == 0) {
1653:                                // This is a croak, if state becomes bound, this can
1654:                                // be nuked.
1655:                                this .rootPaneUI.installBorder(rootPane);
1656:                            }
1657:                        }
1658:                        if (frame.isResizable()) {
1659:                            // special handling of mixed dark themes
1660:                            SubstanceTheme iconTheme = SubstanceLookAndFeel
1661:                                    .getTheme().getActiveTitlePaneTheme();
1662:                            // if (iconTheme.getKind() == ThemeKind.DARK_MIXED)
1663:                            // iconTheme = ((SubstanceMixDarkBiTheme) iconTheme)
1664:                            // .getOriginalDarkTheme();
1665:
1666:                            if ((state & Frame.MAXIMIZED_BOTH) != 0) {
1667:                                Icon restoreIcon = new TransitionAwareIcon(
1668:                                        this .toggleButton,
1669:                                        new TransitionAwareIcon.Delegate() {
1670:                                            public Icon getThemeIcon(
1671:                                                    SubstanceTheme theme) {
1672:                                                return SubstanceIconFactory
1673:                                                        .getTitlePaneIcon(
1674:                                                                SubstanceIconFactory.IconKind.RESTORE,
1675:                                                                theme);
1676:                                            }
1677:                                        });
1678:                                this .updateToggleButton(this .restoreAction,
1679:                                        restoreIcon);
1680:                                this .toggleButton
1681:                                        .setToolTipText(SubstanceCoreUtilities
1682:                                                .getResourceBundle(rootPane)
1683:                                                .getString("SystemMenu.restore"));
1684:                                this .maximizeAction.setEnabled(false);
1685:                                this .restoreAction.setEnabled(true);
1686:                            } else {
1687:                                Icon maxIcon = new TransitionAwareIcon(
1688:                                        this .toggleButton,
1689:                                        new TransitionAwareIcon.Delegate() {
1690:                                            public Icon getThemeIcon(
1691:                                                    SubstanceTheme theme) {
1692:                                                return SubstanceIconFactory
1693:                                                        .getTitlePaneIcon(
1694:                                                                SubstanceIconFactory.IconKind.MAXIMIZE,
1695:                                                                theme);
1696:                                            }
1697:                                        });
1698:                                this .updateToggleButton(this .maximizeAction,
1699:                                        maxIcon);
1700:                                this .toggleButton
1701:                                        .setToolTipText(SubstanceCoreUtilities
1702:                                                .getResourceBundle(rootPane)
1703:                                                .getString(
1704:                                                        "SystemMenu.maximize"));
1705:                                this .maximizeAction.setEnabled(true);
1706:                                this .restoreAction.setEnabled(false);
1707:                            }
1708:                            if ((this .toggleButton.getParent() == null)
1709:                                    || (this .minimizeButton.getParent() == null)) {
1710:                                this .add(this .toggleButton);
1711:                                this .add(this .minimizeButton);
1712:                                this .revalidate();
1713:                                this .repaint();
1714:                            }
1715:                            this .toggleButton.setText(null);
1716:                        } else {
1717:                            this .maximizeAction.setEnabled(false);
1718:                            this .restoreAction.setEnabled(false);
1719:                            if (this .toggleButton.getParent() != null) {
1720:                                this .remove(this .toggleButton);
1721:                                this .revalidate();
1722:                                this .repaint();
1723:                            }
1724:                        }
1725:                    } else {
1726:                        // Not contained in a Frame
1727:                        this .maximizeAction.setEnabled(false);
1728:                        this .restoreAction.setEnabled(false);
1729:                        this .iconifyAction.setEnabled(false);
1730:                        this .remove(this .toggleButton);
1731:                        this .remove(this .minimizeButton);
1732:                        this .revalidate();
1733:                        this .repaint();
1734:                    }
1735:                    this .closeAction.setEnabled(true);
1736:                    this .state = state;
1737:                }
1738:            }
1739:
1740:            /**
1741:             * Updates the toggle button to contain the Icon <code>icon</code>, and
1742:             * Action <code>action</code>.
1743:             * 
1744:             * @param action
1745:             *            Action.
1746:             * @param icon
1747:             *            Icon.
1748:             */
1749:            private void updateToggleButton(Action action, Icon icon) {
1750:                this .toggleButton.setAction(action);
1751:                this .toggleButton.setIcon(icon);
1752:                this .toggleButton.setText(null);
1753:            }
1754:
1755:            /**
1756:             * Returns the Frame rendering in. This will return null if the
1757:             * <code>JRootPane</code> is not contained in a <code>Frame</code>.
1758:             * 
1759:             * @return Frame.
1760:             */
1761:            private Frame getFrame() {
1762:                Window window = this .getWindow();
1763:
1764:                if (window instanceof  Frame) {
1765:                    return (Frame) window;
1766:                }
1767:                return null;
1768:            }
1769:
1770:            /**
1771:             * Returns the <code>Window</code> the <code>JRootPane</code> is
1772:             * contained in. This will return null if there is no parent ancestor of the
1773:             * <code>JRootPane</code>.
1774:             * 
1775:             * @return Window.
1776:             */
1777:            private Window getWindow() {
1778:                return this .window;
1779:            }
1780:
1781:            /**
1782:             * Returns the String to display as the title.
1783:             * 
1784:             * @return Display title.
1785:             */
1786:            private String getTitle() {
1787:                Window w = this .getWindow();
1788:
1789:                if (w instanceof  Frame) {
1790:                    return ((Frame) w).getTitle();
1791:                }
1792:                if (w instanceof  Dialog) {
1793:                    return ((Dialog) w).getTitle();
1794:                }
1795:                return null;
1796:            }
1797:
1798:            /*
1799:             * (non-Javadoc)
1800:             * 
1801:             * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
1802:             */
1803:            @Override
1804:            public void paintComponent(Graphics g) {
1805:                // long start = System.nanoTime();
1806:                // As state isn't bound, we need a convenience place to check
1807:                // if it has changed. Changing the state typically changes the
1808:                if (this .getFrame() != null) {
1809:                    this .setState(this .getFrame().getExtendedState());
1810:                }
1811:                final JRootPane rootPane = this .getRootPane();
1812:                Window window = this .getWindow();
1813:                boolean leftToRight = (window == null) ? rootPane
1814:                        .getComponentOrientation().isLeftToRight() : window
1815:                        .getComponentOrientation().isLeftToRight();
1816:                boolean isSelected = (window == null) ? true : window
1817:                        .isActive();
1818:                final int width = this .getWidth();
1819:                final int height = this .getHeight();
1820:
1821:                final SubstanceTheme theme = isSelected ? SubstanceLookAndFeel
1822:                        .getTheme().getActiveTitlePaneTheme()
1823:                        : SubstanceLookAndFeel.getTheme()
1824:                                .getDefaultTitlePaneTheme();
1825:
1826:                int xOffset = 0;
1827:                String theTitle = this .getTitle();
1828:                int leftEnd;
1829:                int rightEnd;
1830:                if (leftToRight) {
1831:                    // offset of border
1832:                    xOffset = 5;
1833:
1834:                    leftEnd = (this .menuBar == null) ? 0 : (this .menuBar
1835:                            .getWidth() + 10);
1836:                    xOffset += leftEnd;
1837:
1838:                    // find the leftmost button for the right end
1839:                    AbstractButton leftmostButton = null;
1840:
1841:                    if ((this .minimizeButton != null)
1842:                            && (this .minimizeButton.getParent() != null)
1843:                            && (this .minimizeButton.getBounds().width != 0)) {
1844:                        leftmostButton = this .minimizeButton;
1845:                    } else {
1846:                        if ((this .toggleButton != null)
1847:                                && (this .toggleButton.getParent() != null)
1848:                                && (this .toggleButton.getBounds().width != 0)) {
1849:                            leftmostButton = this .toggleButton;
1850:                        } else {
1851:                            if ((this .closeButton != null)
1852:                                    && (this .closeButton.getParent() != null)) {
1853:                                leftmostButton = this .closeButton;
1854:                            }
1855:                        }
1856:                    }
1857:
1858:                    rightEnd = this .getWidth();
1859:                    if (leftmostButton != null) {
1860:                        Rectangle rect = leftmostButton.getBounds();
1861:                        rightEnd = rect.getBounds().x - 5;
1862:                        if ((this .heapStatusPanel != null)
1863:                                && (this .heapStatusPanel.isVisible()))
1864:                            rightEnd = this .heapStatusPanel.getBounds().x - 5;
1865:                        rightEnd--;
1866:                    }
1867:
1868:                    if (theTitle != null) {
1869:                        FontMetrics fm = rootPane.getFontMetrics(g.getFont());
1870:                        int titleWidth = rightEnd - leftEnd - 20;
1871:                        String clippedTitle = SubstanceCoreUtilities
1872:                                .clipString(fm, titleWidth, theTitle);
1873:                        // show tooltip with full title only if necessary
1874:                        if (theTitle.equals(clippedTitle))
1875:                            this .setToolTipText(null);
1876:                        else
1877:                            this .setToolTipText(theTitle);
1878:                        theTitle = clippedTitle;
1879:                    }
1880:                } else {
1881:                    // RTL support
1882:
1883:                    xOffset = width - 5;
1884:
1885:                    rightEnd = (this .menuBar == null) ? width - 5 : width - 5
1886:                            - this .menuBar.getWidth() - 10;
1887:
1888:                    // find the rightmost button for the left transition band
1889:                    AbstractButton rightmostButton = null;
1890:
1891:                    if ((this .minimizeButton != null)
1892:                            && (this .minimizeButton.getParent() != null)
1893:                            && (this .minimizeButton.getBounds().width != 0)) {
1894:                        rightmostButton = this .minimizeButton;
1895:                    } else {
1896:                        if ((this .toggleButton != null)
1897:                                && (this .toggleButton.getParent() != null)
1898:                                && (this .toggleButton.getBounds().width != 0)) {
1899:                            rightmostButton = this .toggleButton;
1900:                        } else {
1901:                            if ((this .closeButton != null)
1902:                                    && (this .closeButton.getParent() != null)) {
1903:                                rightmostButton = this .closeButton;
1904:                            }
1905:                        }
1906:                    }
1907:
1908:                    leftEnd = 5;
1909:                    if (rightmostButton != null) {
1910:                        Rectangle rect = rightmostButton.getBounds();
1911:                        leftEnd = (int) rect.getBounds().getMaxX() + 5;
1912:                        if ((this .heapStatusPanel != null)
1913:                                && (this .heapStatusPanel.isVisible()))
1914:                            leftEnd = (int) this .heapStatusPanel.getBounds()
1915:                                    .getMaxX() + 5;
1916:                        leftEnd++;
1917:                    }
1918:
1919:                    if (theTitle != null) {
1920:                        FontMetrics fm = rootPane.getFontMetrics(g.getFont());
1921:                        int titleWidth = rightEnd - leftEnd - 20;
1922:                        String clippedTitle = SubstanceCoreUtilities
1923:                                .clipString(fm, titleWidth, theTitle);
1924:                        // show tooltip with full title only if necessary
1925:                        if (theTitle.equals(clippedTitle)) {
1926:                            this .setToolTipText(null);
1927:                        } else {
1928:                            this .setToolTipText(theTitle);
1929:                        }
1930:                        theTitle = clippedTitle;
1931:                        xOffset = rightEnd - fm.stringWidth(theTitle);
1932:                    }
1933:                }
1934:
1935:                Graphics2D graphics = (Graphics2D) g.create();
1936:                Font font = SubstanceLookAndFeel.getFontPolicy().getFontSet(
1937:                        "Substance", null).getWindowTitleFont();
1938:                graphics.setFont(font);
1939:
1940:                SubstanceTextPainter textPainter = SubstanceLookAndFeel
1941:                        .getCurrentTextPainter();
1942:                textPainter.init(this , null, true);
1943:
1944:                if (textPainter.needsBackgroundImage()) {
1945:                    textPainter
1946:                            .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
1947:                                public void paintBackground(Graphics g) {
1948:                                    SubstanceDecorationUtilities
1949:                                            .paintDecorationBackground(g,
1950:                                                    SubstanceTitlePane.this ,
1951:                                                    false);
1952:                                }
1953:                            });
1954:                } else {
1955:                    SubstanceDecorationUtilities.paintDecorationBackground(
1956:                            graphics, SubstanceTitlePane.this , false);
1957:                }
1958:
1959:                // draw the title (if needed)
1960:                if (theTitle != null) {
1961:                    FontMetrics fm = rootPane
1962:                            .getFontMetrics(graphics.getFont());
1963:                    int yOffset = ((height - fm.getHeight()) / 2)
1964:                            + fm.getAscent();
1965:
1966:                    SubstanceCoreUtilities.paintTextWithDropShadow(this ,
1967:                            graphics, theme.getForegroundColor(), theTitle,
1968:                            width, height, xOffset, yOffset);
1969:                }
1970:                textPainter.renderSurface(graphics);
1971:
1972:                GhostPaintingUtils.paintGhostImages(this , graphics);
1973:
1974:                // long end = System.nanoTime();
1975:                // System.out.println(end - start);
1976:                graphics.dispose();
1977:            }
1978:
1979:            // public Color getTitlePaneForegroundColor(SubstanceTheme theme) {
1980:            // return SubstanceCoreUtilities.isThemeDark(theme) ? theme
1981:            // .getColorScheme().getForegroundColor()
1982:            // : new Color(
1983:            // SubstanceColorUtilities
1984:            // .getInterpolatedRGB(theme.getColorScheme()
1985:            // .getUltraDarkColor(), theme
1986:            // .getColorScheme()
1987:            // .getForegroundColor(), 0.5));
1988:            // }
1989:
1990:            /**
1991:             * Actions used to <code>close</code> the <code>Window</code>.
1992:             */
1993:            private class CloseAction extends AbstractAction {
1994:                /**
1995:                 * Creates a new close action.
1996:                 */
1997:                public CloseAction() {
1998:                    super (SubstanceCoreUtilities.getResourceBundle(rootPane)
1999:                            .getString("SystemMenu.close"),
2000:                            SubstanceImageCreator
2001:                                    .getCloseIcon(SubstanceLookAndFeel
2002:                                            .getTheme()));
2003:                }
2004:
2005:                public void actionPerformed(ActionEvent e) {
2006:                    Window window = SubstanceTitlePane.this .getWindow();
2007:
2008:                    if (window != null) {
2009:                        window.dispatchEvent(new WindowEvent(window,
2010:                                WindowEvent.WINDOW_CLOSING));
2011:                    }
2012:                }
2013:            }
2014:
2015:            /**
2016:             * Actions used to <code>iconfiy</code> the <code>Frame</code>.
2017:             */
2018:            private class IconifyAction extends AbstractAction {
2019:                /**
2020:                 * Creates a new iconify action.
2021:                 */
2022:                public IconifyAction() {
2023:                    super (SubstanceCoreUtilities.getResourceBundle(rootPane)
2024:                            .getString("SystemMenu.iconify"),
2025:                            SubstanceImageCreator
2026:                                    .getMinimizeIcon(SubstanceLookAndFeel
2027:                                            .getTheme()));
2028:                }
2029:
2030:                public void actionPerformed(ActionEvent e) {
2031:                    Frame frame = SubstanceTitlePane.this .getFrame();
2032:                    if (frame != null) {
2033:                        frame.setExtendedState(SubstanceTitlePane.this .state
2034:                                | Frame.ICONIFIED);
2035:                    }
2036:                }
2037:            }
2038:
2039:            /**
2040:             * Actions used to <code>restore</code> the <code>Frame</code>.
2041:             */
2042:            private class RestoreAction extends AbstractAction {
2043:                /**
2044:                 * Creates a new restore action.
2045:                 */
2046:                public RestoreAction() {
2047:                    super (SubstanceCoreUtilities.getResourceBundle(rootPane)
2048:                            .getString("SystemMenu.restore"),
2049:                            SubstanceImageCreator
2050:                                    .getRestoreIcon(SubstanceLookAndFeel
2051:                                            .getTheme()));
2052:                }
2053:
2054:                public void actionPerformed(ActionEvent e) {
2055:                    Frame frame = SubstanceTitlePane.this .getFrame();
2056:
2057:                    if (frame == null) {
2058:                        return;
2059:                    }
2060:
2061:                    if ((SubstanceTitlePane.this .state & Frame.ICONIFIED) != 0) {
2062:                        frame.setExtendedState(SubstanceTitlePane.this .state
2063:                                & ~Frame.ICONIFIED);
2064:                    } else {
2065:                        frame.setExtendedState(SubstanceTitlePane.this .state
2066:                                & ~Frame.MAXIMIZED_BOTH);
2067:                    }
2068:                }
2069:            }
2070:
2071:            /**
2072:             * Actions used to <code>restore</code> the <code>Frame</code>.
2073:             */
2074:            private class MaximizeAction extends AbstractAction {
2075:                /**
2076:                 * Creates a new maximize action.
2077:                 */
2078:                public MaximizeAction() {
2079:                    super (SubstanceCoreUtilities.getResourceBundle(rootPane)
2080:                            .getString("SystemMenu.maximize"),
2081:                            SubstanceImageCreator
2082:                                    .getMaximizeIcon(SubstanceLookAndFeel
2083:                                            .getTheme()));
2084:                }
2085:
2086:                public void actionPerformed(ActionEvent e) {
2087:                    Frame frame = SubstanceTitlePane.this .getFrame();
2088:                    if (frame != null) {
2089:                        if (frame instanceof  JFrame) {
2090:                            SubstanceRootPaneUI rpUI = (SubstanceRootPaneUI) ((JFrame) frame)
2091:                                    .getRootPane().getUI();
2092:                            rpUI.setMaximized();
2093:                        }
2094:                        frame.setExtendedState(SubstanceTitlePane.this .state
2095:                                | Frame.MAXIMIZED_BOTH);
2096:                    }
2097:                }
2098:            }
2099:
2100:            /**
2101:             * Class responsible for drawing the system menu. Looks up the image to draw
2102:             * from the Frame associated with the <code>JRootPane</code>.
2103:             */
2104:            public class SubstanceMenuBar extends JMenuBar {
2105:                @Override
2106:                public void paint(Graphics g) {
2107:                    Frame frame = SubstanceTitlePane.this .getFrame();
2108:
2109:                    Image image = (frame != null) ? frame.getIconImage() : null;
2110:
2111:                    if (image != null) {
2112:                        int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
2113:                        double coef = Math.max((double) iSize
2114:                                / (double) image.getWidth(null), (double) iSize
2115:                                / (double) image.getHeight(null));
2116:                        if (coef < 1.0) {
2117:                            // fix for defect 255 - large icons need to be properly
2118:                            // scaled down. While we can use
2119:                            // RenderingHints.VALUE_INTERPOLATION_BILINEAR, it will not
2120:                            // work good on large icons (such as 128*128), resulting in
2121:                            // bad images. Here, we use multi-step scaling by Romain
2122:                            // Guy.
2123:                            BufferedImage bi = SubstanceCoreUtilities
2124:                                    .getBlankImage(image.getWidth(null), image
2125:                                            .getHeight(null));
2126:                            bi.getGraphics().drawImage(image, 0, 0, null);
2127:                            g.drawImage(LafWidgetUtilities.createThumbnail(bi,
2128:                                    iSize), 0, 0, null);
2129:                        } else
2130:                            g.drawImage(image, 0, 0, null);
2131:                    } else {
2132:                        Icon icon = UIManager.getIcon("InternalFrame.icon");
2133:
2134:                        if (icon != null) {
2135:                            icon.paintIcon(this , g, 0, 0);
2136:                        }
2137:                    }
2138:                }
2139:
2140:                @Override
2141:                public Dimension getMinimumSize() {
2142:                    return this .getPreferredSize();
2143:                }
2144:
2145:                @Override
2146:                public Dimension getPreferredSize() {
2147:                    Dimension size = super .getPreferredSize();
2148:
2149:                    int iSize = SubstanceSizeUtils.getTitlePaneIconSize();
2150:                    return new Dimension(Math.max(iSize, size.width), Math.max(
2151:                            size.height, iSize));
2152:                }
2153:            }
2154:
2155:            /**
2156:             * Layout manager for the title pane.
2157:             * 
2158:             * @author Kirill Graphics
2159:             */
2160:            private class TitlePaneLayout implements  LayoutManager {
2161:                /*
2162:                 * (non-Javadoc)
2163:                 * 
2164:                 * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
2165:                 *      java.awt.Component)
2166:                 */
2167:                public void addLayoutComponent(String name, Component c) {
2168:                }
2169:
2170:                /*
2171:                 * (non-Javadoc)
2172:                 * 
2173:                 * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
2174:                 */
2175:                public void removeLayoutComponent(Component c) {
2176:                }
2177:
2178:                /*
2179:                 * (non-Javadoc)
2180:                 * 
2181:                 * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
2182:                 */
2183:                public Dimension preferredLayoutSize(Container c) {
2184:                    int height = this .computeHeight();
2185:                    return new Dimension(height, height);
2186:                }
2187:
2188:                /**
2189:                 * Computes title pane height.
2190:                 * 
2191:                 * @return Title pane height.
2192:                 */
2193:                private int computeHeight() {
2194:                    FontMetrics fm = SubstanceTitlePane.this .rootPane
2195:                            .getFontMetrics(SubstanceTitlePane.this .getFont());
2196:                    int fontHeight = fm.getHeight();
2197:                    fontHeight += 7;
2198:                    int iconHeight = 0;
2199:                    if (SubstanceTitlePane.this .getWindowDecorationStyle() == JRootPane.FRAME) {
2200:                        iconHeight = SubstanceSizeUtils.getTitlePaneIconSize();
2201:                    }
2202:
2203:                    int finalHeight = Math.max(fontHeight, iconHeight);
2204:                    return finalHeight;
2205:                }
2206:
2207:                /*
2208:                 * (non-Javadoc)
2209:                 * 
2210:                 * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
2211:                 */
2212:                public Dimension minimumLayoutSize(Container c) {
2213:                    return this .preferredLayoutSize(c);
2214:                }
2215:
2216:                /*
2217:                 * (non-Javadoc)
2218:                 * 
2219:                 * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
2220:                 */
2221:                public void layoutContainer(Container c) {
2222:                    boolean leftToRight = (SubstanceTitlePane.this .window == null) ? SubstanceTitlePane.this 
2223:                            .getRootPane().getComponentOrientation()
2224:                            .isLeftToRight()
2225:                            : SubstanceTitlePane.this .window
2226:                                    .getComponentOrientation().isLeftToRight();
2227:
2228:                    int w = SubstanceTitlePane.this .getWidth();
2229:                    int x;
2230:                    int y = 3;
2231:                    int spacing;
2232:                    int buttonHeight;
2233:                    int buttonWidth;
2234:
2235:                    if ((SubstanceTitlePane.this .closeButton != null)
2236:                            && (SubstanceTitlePane.this .closeButton.getIcon() != null)) {
2237:                        buttonHeight = SubstanceTitlePane.this .closeButton
2238:                                .getIcon().getIconHeight();
2239:                        buttonWidth = SubstanceTitlePane.this .closeButton
2240:                                .getIcon().getIconWidth();
2241:                    } else {
2242:                        buttonHeight = SubstanceSizeUtils
2243:                                .getTitlePaneIconSize();
2244:                        buttonWidth = SubstanceSizeUtils.getTitlePaneIconSize();
2245:                    }
2246:
2247:                    y = (getHeight() - buttonHeight) / 2;
2248:
2249:                    // assumes all buttons have the same dimensions
2250:                    // these dimensions include the borders
2251:
2252:                    x = leftToRight ? w : 0;
2253:
2254:                    spacing = 5;
2255:                    x = leftToRight ? spacing : w - buttonWidth - spacing;
2256:                    if (SubstanceTitlePane.this .menuBar != null) {
2257:                        SubstanceTitlePane.this .menuBar.setBounds(x, y,
2258:                                buttonWidth, buttonHeight);
2259:                    }
2260:
2261:                    x = leftToRight ? w : 0;
2262:                    spacing = 4;
2263:                    x += leftToRight ? -spacing - buttonWidth : spacing;
2264:                    if (SubstanceTitlePane.this .closeButton != null) {
2265:                        SubstanceTitlePane.this .closeButton.setBounds(x, y,
2266:                                buttonWidth, buttonHeight);
2267:                    }
2268:
2269:                    if (!leftToRight)
2270:                        x += buttonWidth;
2271:
2272:                    if (SubstanceTitlePane.this .getWindowDecorationStyle() == JRootPane.FRAME) {
2273:                        if (Toolkit.getDefaultToolkit().isFrameStateSupported(
2274:                                Frame.MAXIMIZED_BOTH)) {
2275:                            if (SubstanceTitlePane.this .toggleButton
2276:                                    .getParent() != null) {
2277:                                spacing = 10;
2278:                                x += leftToRight ? -spacing - buttonWidth
2279:                                        : spacing;
2280:                                SubstanceTitlePane.this .toggleButton.setBounds(
2281:                                        x, y, buttonWidth, buttonHeight);
2282:                                if (!leftToRight) {
2283:                                    x += buttonWidth;
2284:                                }
2285:                            }
2286:                        }
2287:
2288:                        if ((SubstanceTitlePane.this .minimizeButton != null)
2289:                                && (SubstanceTitlePane.this .minimizeButton
2290:                                        .getParent() != null)) {
2291:                            spacing = 2;
2292:                            x += leftToRight ? -spacing - buttonWidth : spacing;
2293:                            SubstanceTitlePane.this .minimizeButton.setBounds(x,
2294:                                    y, buttonWidth, buttonHeight);
2295:                            if (!leftToRight) {
2296:                                x += buttonWidth;
2297:                            }
2298:                        }
2299:
2300:                        if ((SubstanceTitlePane.this .heapStatusPanel != null)
2301:                                && SubstanceTitlePane.this .heapStatusPanel
2302:                                        .isVisible()) {
2303:                            spacing = 5;
2304:                            x += leftToRight ? (-spacing - SubstanceTitlePane.this .heapStatusPanel
2305:                                    .getPreferredSize().width)
2306:                                    : spacing;
2307:                            SubstanceTitlePane.this .heapStatusPanel.setBounds(
2308:                                    x, 1,
2309:                                    SubstanceTitlePane.this .heapStatusPanel
2310:                                            .getPreferredSize().width,
2311:                                    SubstanceTitlePane.this .getHeight() - 3);
2312:                        }
2313:                    }
2314:                    // buttonsWidth = leftToRight ? w - x : x;
2315:                }
2316:
2317:            }
2318:
2319:            /**
2320:             * PropertyChangeListener installed on the Window. Updates the necessary
2321:             * state as the state of the Window changes.
2322:             */
2323:            private class PropertyChangeHandler implements 
2324:                    PropertyChangeListener {
2325:                public void propertyChange(PropertyChangeEvent pce) {
2326:                    String name = pce.getPropertyName();
2327:
2328:                    // Frame.state isn't currently bound.
2329:                    if ("resizable".equals(name) || "state".equals(name)) {
2330:                        Frame frame = SubstanceTitlePane.this .getFrame();
2331:
2332:                        if (frame != null) {
2333:                            SubstanceTitlePane.this .setState(frame
2334:                                    .getExtendedState(), true);
2335:                        }
2336:                        if ("resizable".equals(name)) {
2337:                            SubstanceTitlePane.this .getRootPane().repaint();
2338:                        }
2339:                    } else {
2340:                        if ("title".equals(name)) {
2341:                            SubstanceTitlePane.this .repaint();
2342:                            SubstanceTitlePane.this .setToolTipText((String) pce
2343:                                    .getNewValue());
2344:                        } else {
2345:                            if ("componentOrientation".equals(name)
2346:                                    || "iconImage".equals(name)) {
2347:                                SubstanceTitlePane.this .revalidate();
2348:                                SubstanceTitlePane.this .repaint();
2349:                            }
2350:                        }
2351:                    }
2352:                }
2353:            }
2354:
2355:            /**
2356:             * WindowListener installed on the Window, updates the state as necessary.
2357:             */
2358:            private class WindowHandler extends WindowAdapter {
2359:                @Override
2360:                public void windowActivated(WindowEvent ev) {
2361:                    SubstanceTitlePane.this .setActive(true);
2362:                }
2363:
2364:                @Override
2365:                public void windowDeactivated(WindowEvent ev) {
2366:                    SubstanceTitlePane.this .setActive(false);
2367:                }
2368:            }
2369:
2370:            /**
2371:             * Sets indication whether frame title panes can show the heap status panel.
2372:             * 
2373:             * @param canHaveHeapStatusPanel
2374:             *            if <code>true</code>, title panes can show the heap status
2375:             *            panel.
2376:             */
2377:            public static void setCanHaveHeapStatusPanel(
2378:                    boolean canHaveHeapStatusPanel) {
2379:                SubstanceTitlePane.canHaveHeapStatusPanel = canHaveHeapStatusPanel;
2380:            }
2381:
2382:            /**
2383:             * Returns indication whether frame title panes can show the heap status
2384:             * panel.
2385:             * 
2386:             * @return <code>true</code> if the frame title panes can show the heap
2387:             *         status panel, <code>false</code> otherwise.
2388:             */
2389:            public static boolean getCanHaveHeapStatusPanel() {
2390:                return SubstanceTitlePane.canHaveHeapStatusPanel;
2391:            }
2392:
2393:            /**
2394:             * Sets location for heap status logfile. Relevant if
2395:             * {@link #setCanHaveHeapStatusPanel(boolean)} was called with
2396:             * <code>true</code>.
2397:             * 
2398:             * @param heapStatusLogfileName
2399:             *            Logfile for the heap status panel.
2400:             */
2401:            public static void setHeapStatusLogfileName(
2402:                    String heapStatusLogfileName) {
2403:                SubstanceTitlePane.heapStatusLogfileName = heapStatusLogfileName;
2404:            }
2405:
2406:            /**
2407:             * Makes the heap status panel appear / disappear permanently on the
2408:             * associated title pane and removes the corresponding check box menu items
2409:             * from the system menu.
2410:             * 
2411:             * @param isVisible
2412:             *            if <code>true</code>, the heap status panel will be
2413:             *            permanently shown, if <code>false</code>, the heap status
2414:             *            panel will be permanently hidden.
2415:             */
2416:            public void setHeapStatusPanePermanentVisibility(boolean isVisible) {
2417:                if (!(this .rootPane
2418:                        .getClientProperty(SubstanceTitlePane.HEAP_STATUS_PANEL_PERMANENT) instanceof  Boolean)) {
2419:                    this .menuBar.getMenu(0).remove(this .heapStatusMenuItem);
2420:                    this .heapStatusMenuItem = null;
2421:                }
2422:                this .heapStatusPanel.setVisible(isVisible);
2423:                this .rootPane.putClientProperty(
2424:                        SubstanceTitlePane.HEAP_STATUS_PANEL_PERMANENT, Boolean
2425:                                .valueOf(isVisible));
2426:                this .rootPane.putClientProperty(
2427:                        SubstanceLookAndFeel.HEAP_STATUS_PANEL, Boolean
2428:                                .valueOf(isVisible));
2429:                if (!isVisible) {
2430:                    HeapStatusThread.unregisterPanel(this .heapStatusPanel);
2431:                } else {
2432:                    HeapStatusThread.registerPanel(this .heapStatusPanel);
2433:                }
2434:                this .repaint();
2435:            }
2436:
2437:            protected static class ThemeChanger implements  ActionListener {
2438:                protected SubstanceTheme newTheme;
2439:
2440:                public ThemeChanger(SubstanceTheme newTheme) {
2441:                    super ();
2442:                    this .newTheme = newTheme;
2443:                }
2444:
2445:                public void actionPerformed(ActionEvent e) {
2446:                    SwingUtilities.invokeLater(new Runnable() {
2447:                        public void run() {
2448:                            SubstanceLookAndFeel.setCurrentTheme(newTheme);
2449:                            // update all existing root panes
2450:                            for (Frame frame : Frame.getFrames()) {
2451:                                SwingUtilities.updateComponentTreeUI(frame);
2452:                            }
2453:                        }
2454:                    });
2455:                }
2456:            }
2457:
2458:            protected static class AnimationChanger implements  ActionListener {
2459:                protected AnimationKind newAnimationKind;
2460:
2461:                public AnimationChanger(AnimationKind newAnimationKind) {
2462:                    super ();
2463:                    this .newAnimationKind = newAnimationKind;
2464:                }
2465:
2466:                public void actionPerformed(ActionEvent e) {
2467:                    SwingUtilities.invokeLater(new Runnable() {
2468:                        public void run() {
2469:                            UIManager.put(LafWidget.ANIMATION_KIND,
2470:                                    newAnimationKind);
2471:                        }
2472:                    });
2473:                }
2474:            }
2475:
2476:            protected static class FocusKindChanger implements  ActionListener {
2477:                protected FocusKind newFocusKind;
2478:
2479:                public FocusKindChanger(FocusKind newFocusKind) {
2480:                    super ();
2481:                    this .newFocusKind = newFocusKind;
2482:                }
2483:
2484:                public void actionPerformed(ActionEvent e) {
2485:                    SwingUtilities.invokeLater(new Runnable() {
2486:                        public void run() {
2487:                            UIManager.put(SubstanceLookAndFeel.FOCUS_KIND,
2488:                                    newFocusKind);
2489:                        }
2490:                    });
2491:                }
2492:            }
2493:
2494:            /**
2495:             * Synchronizes the tooltip of the close button.
2496:             */
2497:            protected void syncCloseButtonTooltip() {
2498:                if (SubstanceCoreUtilities.isRootPaneModified(this 
2499:                        .getRootPane())) {
2500:                    this .closeButton.setToolTipText(SubstanceCoreUtilities
2501:                            .getResourceBundle(rootPane).getString(
2502:                                    "SystemMenu.close")
2503:                            + " ["
2504:                            + SubstanceCoreUtilities
2505:                                    .getResourceBundle(rootPane).getString(
2506:                                            "Tooltip.contentsNotSaved") + "]");
2507:                } else {
2508:                    this .closeButton.setToolTipText(SubstanceCoreUtilities
2509:                            .getResourceBundle(rootPane).getString(
2510:                                    "SystemMenu.close"));
2511:                }
2512:                this .closeButton.repaint();
2513:            }
2514:
2515:            public static void dump(Component comp, int level) {
2516:                StringBuffer sb = new StringBuffer();
2517:                for (int i = 0; i < level; i++)
2518:                    sb.append("  ");
2519:                sb.append(comp.toString());
2520:                System.out.println(sb);
2521:                if (comp instanceof  Container) {
2522:                    Container cont = (Container) comp;
2523:                    for (int i = 0; i < cont.getComponentCount(); i++) {
2524:                        dump(cont.getComponent(i), level + 1);
2525:                    }
2526:                }
2527:            }
2528:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.