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

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


0001:        /*
0002:         * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without 
0005:         * modification, are permitted provided that the following conditions are met:
0006:         * 
0007:         *  o Redistributions of source code must retain the above copyright notice, 
0008:         *    this list of conditions and the following disclaimer. 
0009:         *     
0010:         *  o Redistributions in binary form must reproduce the above copyright notice, 
0011:         *    this list of conditions and the following disclaimer in the documentation 
0012:         *    and/or other materials provided with the distribution. 
0013:         *     
0014:         *  o Neither the name of Substance Kirill Grouchnikov nor the names of 
0015:         *    its contributors may be used to endorse or promote products derived 
0016:         *    from this software without specific prior written permission. 
0017:         *     
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
0020:         * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
0021:         * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
0022:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
0023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
0024:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
0025:         * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
0026:         * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
0027:         * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
0028:         * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
0029:         */
0030:        package org.jvnet.substance;
0031:
0032:        import java.awt.*;
0033:        import java.awt.event.*;
0034:        import java.beans.PropertyChangeEvent;
0035:        import java.lang.reflect.Method;
0036:        import java.security.*;
0037:
0038:        import javax.swing.*;
0039:        import javax.swing.border.Border;
0040:        import javax.swing.event.MouseInputAdapter;
0041:        import javax.swing.event.MouseInputListener;
0042:        import javax.swing.plaf.ComponentUI;
0043:        import javax.swing.plaf.basic.BasicRootPaneUI;
0044:
0045:        import org.jvnet.substance.utils.*;
0046:
0047:        /**
0048:         * UI for root panes in <b>Substance </b> look and feel.
0049:         * 
0050:         * @author Kirill Grouchnikov
0051:         * @author Larry Salibra (fix for defect 198)
0052:         */
0053:        public class SubstanceRootPaneUI extends BasicRootPaneUI {
0054:            /**
0055:             * The amount of space (in pixels) that the cursor is changed on.
0056:             */
0057:            private static final int CORNER_DRAG_WIDTH = 16;
0058:
0059:            /**
0060:             * Region from edges that dragging is active from.
0061:             */
0062:            private static final int BORDER_DRAG_THICKNESS = 5;
0063:
0064:            /**
0065:             * Window the <code>JRootPane</code> is in.
0066:             */
0067:            private Window window;
0068:
0069:            /**
0070:             * <code>JComponent</code> providing window decorations. This will be null
0071:             * if not providing window decorations.
0072:             */
0073:            private JComponent titlePane;
0074:
0075:            /**
0076:             * <code>MouseInputListener</code> that is added to the parent
0077:             * <code>Window</code> the <code>JRootPane</code> is contained in.
0078:             */
0079:            private MouseInputListener substanceMouseInputListener;
0080:
0081:            /**
0082:             * Mouse listener on the title pane (dragging).
0083:             */
0084:            private MouseInputListener substanceTitleMouseInputListener;
0085:
0086:            /**
0087:             * The <code>LayoutManager</code> that is set on the
0088:             * <code>JRootPane</code>.
0089:             */
0090:            private LayoutManager layoutManager;
0091:
0092:            /**
0093:             * <code>LayoutManager</code> of the <code>JRootPane</code> before we
0094:             * replaced it.
0095:             */
0096:            private LayoutManager savedOldLayout;
0097:
0098:            /**
0099:             * <code>JRootPane</code> providing the look and feel for.
0100:             */
0101:            private JRootPane root;
0102:
0103:            /**
0104:             * Window listener that stops all Substance thread when the last frame is
0105:             * disposed.
0106:             */
0107:            protected WindowListener substanceWindowListener;
0108:
0109:            /**
0110:             * The current window.
0111:             */
0112:            protected Window substanceCurrentWindow;
0113:
0114:            /**
0115:             * Hierarchy listener to keep track of the associated top-level window.
0116:             */
0117:            protected HierarchyListener substanceHierarchyListener;
0118:
0119:            /**
0120:             * Component listener to keep track of the primary graphics configuration
0121:             * (for recomputing the maximized bounds) - fix for defect 213.
0122:             */
0123:            protected ComponentListener substanceWindowComponentListener;
0124:
0125:            /**
0126:             * The graphics configuration that contains the top-left corner of the
0127:             * window (fix for defect 213).
0128:             */
0129:            protected GraphicsConfiguration currentRootPaneGC;
0130:
0131:            /**
0132:             * <code>Cursor</code> used to track the cursor set by the user. This is
0133:             * initially <code>Cursor.DEFAULT_CURSOR</code>.
0134:             */
0135:            private Cursor lastCursor = Cursor
0136:                    .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
0137:
0138:            /**
0139:             * Stores the pointer to {@link MouseInfo#getLocationOnScreen()} method
0140:             * (available only under JDK 6.0). Is used to provide fix for defect 198.
0141:             */
0142:            protected static Method getLocationOnScreenMethod;
0143:
0144:            static {
0145:                try {
0146:                    getLocationOnScreenMethod = MouseEvent.class
0147:                            .getDeclaredMethod("getLocationOnScreen",
0148:                                    new Class[0]);
0149:                } catch (Exception e) {
0150:                    // running under JDK 5.0 or sandbox
0151:                    getLocationOnScreenMethod = null;
0152:                }
0153:            }
0154:
0155:            /**
0156:             * Creates a UI for a <code>JRootPane</code>.
0157:             * 
0158:             * @param c
0159:             *            the JRootPane the RootPaneUI will be created for
0160:             * @return the RootPaneUI implementation for the passed in JRootPane
0161:             */
0162:            public static ComponentUI createUI(JComponent c) {
0163:                return new SubstanceRootPaneUI();
0164:            }
0165:
0166:            public SubstanceRootPaneUI() {
0167:            }
0168:
0169:            /**
0170:             * Invokes supers implementation of <code>installUI</code> to install the
0171:             * necessary state onto the passed in <code>JRootPane</code> to render the
0172:             * metal look and feel implementation of <code>RootPaneUI</code>. If the
0173:             * <code>windowDecorationStyle</code> property of the
0174:             * <code>JRootPane</code> is other than <code>JRootPane.NONE</code>,
0175:             * this will add a custom <code>Component</code> to render the widgets to
0176:             * <code>JRootPane</code>, as well as installing a custom
0177:             * <code>Border</code> and <code>LayoutManager</code> on the
0178:             * <code>JRootPane</code>.
0179:             * 
0180:             * @param c
0181:             *            the JRootPane to install state onto
0182:             */
0183:            @Override
0184:            public void installUI(JComponent c) {
0185:                super .installUI(c);
0186:                this .root = (JRootPane) c;
0187:                int style = this .root.getWindowDecorationStyle();
0188:                if (style != JRootPane.NONE) {
0189:                    this .installClientDecorations(this .root);
0190:                }
0191:                // TitleButtonManager.getManager().register(this.root);
0192:            }
0193:
0194:            /**
0195:             * Invokes supers implementation to uninstall any of its state. This will
0196:             * also reset the <code>LayoutManager</code> of the <code>JRootPane</code>.
0197:             * If a <code>Component</code> has been added to the
0198:             * <code>JRootPane</code> to render the window decoration style, this
0199:             * method will remove it. Similarly, this will revert the Border and
0200:             * LayoutManager of the <code>JRootPane</code> to what it was before
0201:             * <code>installUI</code> was invoked.
0202:             * 
0203:             * @param c
0204:             *            the JRootPane to uninstall state from
0205:             */
0206:            @Override
0207:            public void uninstallUI(JComponent c) {
0208:                super .uninstallUI(c);
0209:                this .uninstallClientDecorations(this .root);
0210:
0211:                this .layoutManager = null;
0212:                this .substanceMouseInputListener = null;
0213:
0214:                // TitleButtonManager.getManager().unregister(this.root);
0215:
0216:                this .root = null;
0217:            }
0218:
0219:            /**
0220:             * Installs the appropriate <code>Border</code> onto the
0221:             * <code>JRootPane</code>.
0222:             * 
0223:             * @param root
0224:             *            Root pane.
0225:             */
0226:            public void installBorder(JRootPane root) {
0227:                int style = root.getWindowDecorationStyle();
0228:
0229:                if (style == JRootPane.NONE) {
0230:                    LookAndFeel.uninstallBorder(root);
0231:                } else {
0232:                    LookAndFeel.installBorder(root, "RootPane.border");
0233:                }
0234:            }
0235:
0236:            /**
0237:             * Removes any border that may have been installed.
0238:             * 
0239:             * @param root
0240:             *            Root pane.
0241:             */
0242:            private void uninstallBorder(JRootPane root) {
0243:                LookAndFeel.uninstallBorder(root);
0244:            }
0245:
0246:            /**
0247:             * Installs the necessary Listeners on the parent <code>Window</code>, if
0248:             * there is one.
0249:             * <p>
0250:             * This takes the parent so that cleanup can be done from
0251:             * <code>removeNotify</code>, at which point the parent hasn't been reset
0252:             * yet.
0253:             * 
0254:             * 
0255:             * @param root
0256:             *            Root pane.
0257:             * @param parent
0258:             *            The parent of the JRootPane
0259:             */
0260:            private void installWindowListeners(JRootPane root, Component parent) {
0261:                if (parent instanceof  Window) {
0262:                    this .window = (Window) parent;
0263:                } else {
0264:                    this .window = SwingUtilities.getWindowAncestor(parent);
0265:                }
0266:                // System.out.println(titlePanes.size() + " entries in map after adding
0267:                // "
0268:                // + window.getClass().getName() + ":" + window.hashCode());
0269:                // for (Iterator<Map.Entry<JComponent, WeakReference<Window>>> it =
0270:                // titlePanes
0271:                // .entrySet().iterator(); it.hasNext();) {
0272:                // Map.Entry<JComponent, WeakReference<Window>> entry = it
0273:                // .next();
0274:                // Window w = entry.getValue().get();
0275:                // System.out.println("\t" + w.getClass().getName()
0276:                // + ":" + w.hashCode());
0277:                // }
0278:
0279:                if (this .window != null) {
0280:                    if (this .substanceMouseInputListener == null) {
0281:                        this .substanceMouseInputListener = this 
0282:                                .createWindowMouseInputListener(root);
0283:                    }
0284:                    this .window
0285:                            .addMouseListener(this .substanceMouseInputListener);
0286:                    this .window
0287:                            .addMouseMotionListener(this .substanceMouseInputListener);
0288:
0289:                    if (this .titlePane != null) {
0290:                        if (this .substanceTitleMouseInputListener == null) {
0291:                            this .substanceTitleMouseInputListener = new TitleMouseInputHandler();
0292:                        }
0293:                        this .titlePane
0294:                                .addMouseMotionListener(this .substanceTitleMouseInputListener);
0295:                        this .titlePane
0296:                                .addMouseListener(this .substanceTitleMouseInputListener);
0297:                    }
0298:                    this .setMaximized();
0299:                }
0300:            }
0301:
0302:            /**
0303:             * Uninstalls the necessary Listeners on the <code>Window</code> the
0304:             * Listeners were last installed on.
0305:             * 
0306:             * @param root
0307:             *            Root pane.
0308:             */
0309:            private void uninstallWindowListeners(JRootPane root) {
0310:                if (this .window != null) {
0311:                    this .window
0312:                            .removeMouseListener(this .substanceMouseInputListener);
0313:                    this .window
0314:                            .removeMouseMotionListener(this .substanceMouseInputListener);
0315:                }
0316:                if (this .titlePane != null) {
0317:                    this .titlePane
0318:                            .removeMouseListener(this .substanceTitleMouseInputListener);
0319:                    this .titlePane
0320:                            .removeMouseMotionListener(this .substanceTitleMouseInputListener);
0321:                }
0322:            }
0323:
0324:            /**
0325:             * Installs the appropriate LayoutManager on the <code>JRootPane</code> to
0326:             * render the window decorations.
0327:             * 
0328:             * @param root
0329:             *            Root pane.
0330:             */
0331:            private void installLayout(JRootPane root) {
0332:                if (this .layoutManager == null) {
0333:                    this .layoutManager = this .createLayoutManager();
0334:                }
0335:                this .savedOldLayout = root.getLayout();
0336:                root.setLayout(this .layoutManager);
0337:            }
0338:
0339:            @Override
0340:            protected void installListeners(final JRootPane root) {
0341:                super .installListeners(root);
0342:
0343:                // System.out.println("Listeners on root " + root.hashCode());
0344:
0345:                this .substanceHierarchyListener = new HierarchyListener() {
0346:                    public void hierarchyChanged(HierarchyEvent e) {
0347:                        Component parent = root.getParent();
0348:                        if (parent == null) {
0349:                            // fix for defect 271 - check for null parent
0350:                            // as early as possible
0351:                            return;
0352:                        }
0353:                        // System.out.println("Root pane " + root.hashCode()
0354:                        // + " parent : " + parent.getClass().getName());
0355:                        if (MemoryAnalyzer.isRunning()) {
0356:                            MemoryAnalyzer.enqueueUsage("Root pane @"
0357:                                    + root.hashCode()
0358:                                    + "\n"
0359:                                    + SubstanceCoreUtilities
0360:                                            .getHierarchy(parent));
0361:                        }
0362:                        if (parent.getClass().getName().startsWith(
0363:                                "org.jdesktop.jdic.tray")
0364:                                || (parent.getClass().getName().compareTo(
0365:                                        "javax.swing.Popup$HeavyWeightWindow") == 0)) {
0366:                            // Workaround for bug 240 - using JDIC system tray
0367:                            // menu results in an HierarchyEvent being fired right
0368:                            // after a MouseEvent. Somehow, the
0369:                            // EventQueue.getCurrentEvent() returns the HierarchyEvent
0370:                            // even when the MouseEvent is being processed, resulting
0371:                            // in zeroed modifiers set on the ActionEvent passed
0372:                            // to the action listeners on that menu item.
0373:                            SwingUtilities.invokeLater(new Runnable() {
0374:                                public void run() {
0375:                                    root
0376:                                            .removeHierarchyListener(substanceHierarchyListener);
0377:                                    // System.out.println(root.hashCode() + ":"
0378:                                    // + root.getHierarchyListeners().length);
0379:                                    substanceHierarchyListener = null;
0380:                                };
0381:                            });
0382:                        }
0383:
0384:                        Window currWindow = null;
0385:                        if (parent instanceof  Window) {
0386:                            currWindow = (Window) parent;
0387:                        } else {
0388:                            currWindow = SwingUtilities
0389:                                    .getWindowAncestor(parent);
0390:                        }
0391:                        if (substanceWindowListener != null) {
0392:                            substanceCurrentWindow
0393:                                    .removeWindowListener(substanceWindowListener);
0394:                            substanceWindowListener = null;
0395:                        }
0396:                        if (substanceWindowComponentListener != null) {
0397:                            substanceCurrentWindow
0398:                                    .removeComponentListener(substanceWindowComponentListener);
0399:                            substanceWindowComponentListener = null;
0400:                        }
0401:                        if (currWindow != null) {
0402:                            // fix for bug 116 - stopping threads when all frames
0403:                            // are not displayable
0404:                            substanceWindowListener = new WindowAdapter() {
0405:                                @Override
0406:                                public void windowClosed(WindowEvent e) {
0407:                                    SwingUtilities.invokeLater(new Runnable() {
0408:                                        public void run() {
0409:                                            Frame[] frames = Frame.getFrames();
0410:                                            for (Frame frame : frames) {
0411:                                                if (frame.isDisplayable())
0412:                                                    return;
0413:                                            }
0414:                                            SubstanceLookAndFeel.stopThreads();
0415:                                        }
0416:                                    });
0417:                                }
0418:                            };
0419:
0420:                            if (!(parent instanceof  JInternalFrame)) {
0421:                                currWindow
0422:                                        .addWindowListener(substanceWindowListener);
0423:                            }
0424:
0425:                            // fix for defect 213 - maximizing frame under multiple
0426:                            // screens shouldn't always use insets of the primary
0427:                            // screen.
0428:                            substanceWindowComponentListener = new ComponentAdapter() {
0429:                                @Override
0430:                                public void componentMoved(ComponentEvent e) {
0431:                                    this .processNewPosition();
0432:                                }
0433:
0434:                                @Override
0435:                                public void componentResized(ComponentEvent e) {
0436:                                    this .processNewPosition();
0437:                                }
0438:
0439:                                protected void processNewPosition() {
0440:                                    SwingUtilities.invokeLater(new Runnable() {
0441:                                        public void run() {
0442:                                            // currentRootPaneGC = null;
0443:                                            if (!window.isShowing()
0444:                                                    || !window.isDisplayable()) {
0445:                                                currentRootPaneGC = null;
0446:                                                return;
0447:                                            }
0448:
0449:                                            GraphicsEnvironment ge = GraphicsEnvironment
0450:                                                    .getLocalGraphicsEnvironment();
0451:                                            GraphicsDevice[] gds = ge
0452:                                                    .getScreenDevices();
0453:                                            if (gds.length == 1)
0454:                                                return;
0455:                                            Point midLoc = new Point(
0456:                                                    window
0457:                                                            .getLocationOnScreen().x
0458:                                                            + window.getWidth()
0459:                                                            / 2,
0460:                                                    window
0461:                                                            .getLocationOnScreen().y
0462:                                                            + window
0463:                                                                    .getHeight()
0464:                                                            / 2);
0465:                                            // System.out.println("Loc : "
0466:                                            // + window.getLocationOnScreen()
0467:                                            // + ", width : "
0468:                                            // + window.getWidth()
0469:                                            // + ", mid : " + midLoc);
0470:                                            int index = 0;
0471:                                            for (GraphicsDevice gd : gds) {
0472:                                                GraphicsConfiguration gc = gd
0473:                                                        .getDefaultConfiguration();
0474:                                                Rectangle bounds = gc
0475:                                                        .getBounds();
0476:                                                // System.out.println("Bounds : "
0477:                                                // + bounds);
0478:                                                if (bounds.contains(midLoc)) {
0479:                                                    if (gc != currentRootPaneGC) {
0480:                                                        currentRootPaneGC = gc;
0481:                                                        setMaximized();
0482:                                                        // System.out.println("Set");
0483:                                                    }
0484:                                                    break;
0485:                                                }
0486:                                                index++;
0487:                                            }
0488:                                        }
0489:                                    });
0490:                                }
0491:                            };
0492:                            // fix for defect 225 - install the listener only on
0493:                            // JFrames.
0494:                            if (parent instanceof  JFrame) {
0495:                                currWindow
0496:                                        .addComponentListener(substanceWindowComponentListener);
0497:                            }
0498:
0499:                            SubstanceRootPaneUI.this .window = currWindow;
0500:                        }
0501:                        substanceCurrentWindow = currWindow;
0502:                    }
0503:                };
0504:                root.addHierarchyListener(this .substanceHierarchyListener);
0505:                // System.out.println(root.hashCode() + ":"
0506:                // + root.getHierarchyListeners().length);
0507:
0508:            }
0509:
0510:            /*
0511:             * (non-Javadoc)
0512:             * 
0513:             * @see javax.swing.plaf.basic.BasicRootPaneUI#uninstallListeners(javax.swing.JRootPane)
0514:             */
0515:            @Override
0516:            protected void uninstallListeners(JRootPane root) {
0517:                // fix for bug 116 - stopping threads when all frames are
0518:                // not displayable
0519:                if (this .window != null) {
0520:                    this .window
0521:                            .removeWindowListener(this .substanceWindowListener);
0522:                    this .substanceWindowListener = null;
0523:                    this .window
0524:                            .removeComponentListener(this .substanceWindowComponentListener);
0525:                    this .substanceWindowComponentListener = null;
0526:                }
0527:                root.removeHierarchyListener(this .substanceHierarchyListener);
0528:                this .substanceHierarchyListener = null;
0529:
0530:                super .uninstallListeners(root);
0531:            }
0532:
0533:            /**
0534:             * Uninstalls the previously installed <code>LayoutManager</code>.
0535:             * 
0536:             * @param root
0537:             *            Root pane.
0538:             */
0539:            private void uninstallLayout(JRootPane root) {
0540:                if (this .savedOldLayout != null) {
0541:                    root.setLayout(this .savedOldLayout);
0542:                    this .savedOldLayout = null;
0543:                }
0544:            }
0545:
0546:            /**
0547:             * Installs the necessary state onto the JRootPane to render client
0548:             * decorations. This is ONLY invoked if the <code>JRootPane</code> has a
0549:             * decoration style other than <code>JRootPane.NONE</code>.
0550:             * 
0551:             * @param root
0552:             *            Root pane.
0553:             */
0554:            private void installClientDecorations(JRootPane root) {
0555:                this .installBorder(root);
0556:
0557:                JComponent titlePane = this .createTitlePane(root);
0558:
0559:                this .setTitlePane(root, titlePane);
0560:                this .installWindowListeners(root, root.getParent());
0561:                this .installLayout(root);
0562:                if (this .window != null) {
0563:                    root.revalidate();
0564:                    root.repaint();
0565:                }
0566:            }
0567:
0568:            /**
0569:             * Uninstalls any state that <code>installClientDecorations</code> has
0570:             * installed.
0571:             * <p>
0572:             * NOTE: This may be called if you haven't installed client decorations yet
0573:             * (ie before <code>installClientDecorations</code> has been invoked).
0574:             * 
0575:             * @param root
0576:             *            Root pane.
0577:             */
0578:            private void uninstallClientDecorations(JRootPane root) {
0579:                this .uninstallBorder(root);
0580:                this .uninstallWindowListeners(root);
0581:                this .setTitlePane(root, null);
0582:                this .uninstallLayout(root);
0583:                // We have to revalidate/repaint root if the style is JRootPane.NONE
0584:                // only. When we needs to call revalidate/repaint with other styles
0585:                // the installClientDecorations is always called after this method
0586:                // imediatly and it will cause the revalidate/repaint at the proper
0587:                // time.
0588:                int style = root.getWindowDecorationStyle();
0589:                if (style == JRootPane.NONE) {
0590:                    root.repaint();
0591:                    root.revalidate();
0592:                }
0593:                // Reset the cursor, as we may have changed it to a resize cursor
0594:                if (this .window != null) {
0595:                    this .window.setCursor(Cursor
0596:                            .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
0597:                }
0598:                this .window = null;
0599:            }
0600:
0601:            /**
0602:             * Returns the <code>JComponent</code> to render the window decoration
0603:             * style.
0604:             * 
0605:             * @param root
0606:             *            Root pane.
0607:             * @return The title pane component.
0608:             */
0609:            private JComponent createTitlePane(JRootPane root) {
0610:                return new SubstanceTitlePane(root, this );
0611:            }
0612:
0613:            /**
0614:             * Returns a <code>MouseListener</code> that will be added to the
0615:             * <code>Window</code> containing the <code>JRootPane</code>.
0616:             * 
0617:             * @param root
0618:             *            Root pane.
0619:             * @return Window mouse listener.
0620:             */
0621:            private MouseInputListener createWindowMouseInputListener(
0622:                    JRootPane root) {
0623:                return new MouseInputHandler();
0624:            }
0625:
0626:            /**
0627:             * Returns a <code>LayoutManager</code> that will be set on the
0628:             * <code>JRootPane</code>.
0629:             * 
0630:             * @return Layout manager.
0631:             */
0632:            private LayoutManager createLayoutManager() {
0633:                return new SubstanceRootLayout();
0634:            }
0635:
0636:            /**
0637:             * Sets the window title pane -- the JComponent used to provide a plaf a way
0638:             * to override the native operating system's window title pane with one
0639:             * whose look and feel are controlled by the plaf. The plaf creates and sets
0640:             * this value; the default is null, implying a native operating system
0641:             * window title pane.
0642:             * 
0643:             * @param root
0644:             *            Root pane
0645:             * @param titlePane
0646:             *            The <code>JComponent</code> to use for the window title
0647:             *            pane.
0648:             */
0649:            private void setTitlePane(JRootPane root, JComponent titlePane) {
0650:                JLayeredPane layeredPane = root.getLayeredPane();
0651:                JComponent oldTitlePane = this .getTitlePane();
0652:
0653:                if (oldTitlePane != null) {
0654:                    // fix for defect 109 - memory leak on theme change
0655:                    if (oldTitlePane instanceof  SubstanceTitlePane)
0656:                        ((SubstanceTitlePane) oldTitlePane).uninstall();
0657:                    // oldTitlePane.setVisible(false);
0658:                    layeredPane.remove(oldTitlePane);
0659:                }
0660:                if (titlePane != null) {
0661:                    layeredPane
0662:                            .add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER);
0663:                    titlePane.setVisible(true);
0664:                }
0665:                this .titlePane = titlePane;
0666:            }
0667:
0668:            /**
0669:             * Sets maximized bounds according to the display screen insets.
0670:             */
0671:            public void setMaximized() {
0672:                Component tla = this .root.getTopLevelAncestor();
0673:                // fix for defect 213 - maximizing frame under multiple
0674:                // screens shouldn't always use insets of the primary
0675:                // screen.
0676:                GraphicsConfiguration gc = (currentRootPaneGC != null) ? currentRootPaneGC
0677:                        : tla.getGraphicsConfiguration();
0678:                Rectangle screenBounds = gc.getBounds();
0679:                screenBounds.x = 0;
0680:                screenBounds.y = 0;
0681:                Insets screenInsets = Toolkit.getDefaultToolkit()
0682:                        .getScreenInsets(gc);
0683:                Border rootBorder = this .root.getBorder();
0684:                Insets insets = (rootBorder == null) ? new Insets(0, 0, 0, 0)
0685:                        : rootBorder.getBorderInsets(this .root);
0686:                Rectangle maxBounds = new Rectangle(
0687:                        (screenBounds.x + screenInsets.left) - insets.left,
0688:                        (screenBounds.y + screenInsets.top) - insets.right,
0689:                        screenBounds.width
0690:                                - ((screenInsets.left + screenInsets.right)
0691:                                        - insets.left - insets.right),
0692:                        screenBounds.height
0693:                                - ((screenInsets.top + screenInsets.bottom)
0694:                                        - insets.top - insets.bottom));
0695:                if (tla instanceof  JFrame)
0696:                    ((JFrame) tla).setMaximizedBounds(maxBounds);
0697:                if (MemoryAnalyzer.isRunning()) {
0698:                    MemoryAnalyzer.enqueueUsage("Frame set to bounds "
0699:                            + maxBounds);
0700:                }
0701:            }
0702:
0703:            /**
0704:             * Returns the <code>JComponent</code> rendering the title pane. If this
0705:             * returns null, it implies there is no need to render window decorations.
0706:             * This method is <b>for internal use only</b>.
0707:             * 
0708:             * @see #setTitlePane
0709:             * @return Title pane.
0710:             */
0711:            public JComponent getTitlePane() {
0712:                return this .titlePane;
0713:            }
0714:
0715:            /**
0716:             * Returns the <code>JRootPane</code> we're providing the look and feel
0717:             * for.
0718:             * 
0719:             * @return The associated root pane.
0720:             */
0721:            private JRootPane getRootPane() {
0722:                return this .root;
0723:            }
0724:
0725:            /*
0726:             * (non-Javadoc)
0727:             * 
0728:             * @see javax.swing.plaf.basic.BasicRootPaneUI#propertyChange(java.beans.PropertyChangeEvent)
0729:             */
0730:            @Override
0731:            public void propertyChange(PropertyChangeEvent e) {
0732:                super .propertyChange(e);
0733:
0734:                String propertyName = e.getPropertyName();
0735:                if (propertyName == null) {
0736:                    return;
0737:                }
0738:
0739:                if (propertyName.equals("windowDecorationStyle")) {
0740:                    JRootPane root = (JRootPane) e.getSource();
0741:                    int style = root.getWindowDecorationStyle();
0742:
0743:                    this .uninstallClientDecorations(root);
0744:                    if (style != JRootPane.NONE) {
0745:                        this .installClientDecorations(root);
0746:                    }
0747:                }
0748:                if (propertyName.equals("ancestor")) {
0749:                    this .uninstallWindowListeners(this .root);
0750:                    if (((JRootPane) e.getSource()).getWindowDecorationStyle() != JRootPane.NONE) {
0751:                        this .installWindowListeners(this .root, this .root
0752:                                .getParent());
0753:                    }
0754:                }
0755:                if (propertyName.equals("background")) {
0756:                    SubstanceLookAndFeel.getTitlePaneComponent(window)
0757:                            .setBackground((Color) e.getNewValue());
0758:                }
0759:                return;
0760:            }
0761:
0762:            /**
0763:             * A custom layout manager that is responsible for the layout of
0764:             * layeredPane, glassPane, menuBar and titlePane, if one has been installed.
0765:             */
0766:            // NOTE: Ideally this would extends JRootPane.RootLayout, but that
0767:            // would force this to be non-static.
0768:            private static class SubstanceRootLayout implements  LayoutManager2 {
0769:                /**
0770:                 * Returns the amount of space the layout would like to have.
0771:                 * 
0772:                 * 
0773:                 * aram the Container for which this layout manager is being used
0774:                 * 
0775:                 * @return a Dimension object containing the layout's preferred size
0776:                 */
0777:                public Dimension preferredLayoutSize(Container parent) {
0778:                    Dimension cpd, mbd, tpd;
0779:                    int cpWidth = 0;
0780:                    int cpHeight = 0;
0781:                    int mbWidth = 0;
0782:                    int mbHeight = 0;
0783:                    int tpWidth = 0;
0784:                    // int tpHeight = 0;
0785:                    Insets i = parent.getInsets();
0786:                    JRootPane root = (JRootPane) parent;
0787:
0788:                    if (root.getContentPane() != null) {
0789:                        cpd = root.getContentPane().getPreferredSize();
0790:                    } else {
0791:                        cpd = root.getSize();
0792:                    }
0793:                    if (cpd != null) {
0794:                        cpWidth = cpd.width;
0795:                        cpHeight = cpd.height;
0796:                    }
0797:
0798:                    if (root.getJMenuBar() != null) {
0799:                        mbd = root.getJMenuBar().getPreferredSize();
0800:                        if (mbd != null) {
0801:                            mbWidth = mbd.width;
0802:                            mbHeight = mbd.height;
0803:                        }
0804:                    }
0805:
0806:                    if ((root.getWindowDecorationStyle() != JRootPane.NONE)
0807:                            && (root.getUI() instanceof  SubstanceRootPaneUI)) {
0808:                        JComponent titlePane = ((SubstanceRootPaneUI) root
0809:                                .getUI()).getTitlePane();
0810:                        if (titlePane != null) {
0811:                            tpd = titlePane.getPreferredSize();
0812:                            if (tpd != null) {
0813:                                tpWidth = tpd.width;
0814:                                // tpHeight = tpd.height;
0815:                            }
0816:                        }
0817:                    }
0818:
0819:                    return new Dimension(Math.max(Math.max(cpWidth, mbWidth),
0820:                            tpWidth)
0821:                            + i.left + i.right, cpHeight + mbHeight + tpWidth
0822:                            + i.top + i.bottom);
0823:                }
0824:
0825:                /**
0826:                 * Returns the minimum amount of space the layout needs.
0827:                 * 
0828:                 * 
0829:                 * aram the Container for which this layout manager is being used
0830:                 * 
0831:                 * @return a Dimension object containing the layout's minimum size
0832:                 */
0833:                public Dimension minimumLayoutSize(Container parent) {
0834:                    Dimension cpd, mbd, tpd;
0835:                    int cpWidth = 0;
0836:                    int cpHeight = 0;
0837:                    int mbWidth = 0;
0838:                    int mbHeight = 0;
0839:                    int tpWidth = 0;
0840:                    // int tpHeight = 0;
0841:                    Insets i = parent.getInsets();
0842:                    JRootPane root = (JRootPane) parent;
0843:
0844:                    if (root.getContentPane() != null) {
0845:                        cpd = root.getContentPane().getMinimumSize();
0846:                    } else {
0847:                        cpd = root.getSize();
0848:                    }
0849:                    if (cpd != null) {
0850:                        cpWidth = cpd.width;
0851:                        cpHeight = cpd.height;
0852:                    }
0853:
0854:                    if (root.getJMenuBar() != null) {
0855:                        mbd = root.getJMenuBar().getMinimumSize();
0856:                        if (mbd != null) {
0857:                            mbWidth = mbd.width;
0858:                            mbHeight = mbd.height;
0859:                        }
0860:                    }
0861:                    if ((root.getWindowDecorationStyle() != JRootPane.NONE)
0862:                            && (root.getUI() instanceof  SubstanceRootPaneUI)) {
0863:                        JComponent titlePane = ((SubstanceRootPaneUI) root
0864:                                .getUI()).getTitlePane();
0865:                        if (titlePane != null) {
0866:                            tpd = titlePane.getMinimumSize();
0867:                            if (tpd != null) {
0868:                                tpWidth = tpd.width;
0869:                                // tpHeight = tpd.height;
0870:                            }
0871:                        }
0872:                    }
0873:
0874:                    return new Dimension(Math.max(Math.max(cpWidth, mbWidth),
0875:                            tpWidth)
0876:                            + i.left + i.right, cpHeight + mbHeight + tpWidth
0877:                            + i.top + i.bottom);
0878:                }
0879:
0880:                /**
0881:                 * Returns the maximum amount of space the layout can use.
0882:                 * 
0883:                 * 
0884:                 * aram the Container for which this layout manager is being used
0885:                 * 
0886:                 * @return a Dimension object containing the layout's maximum size
0887:                 */
0888:                public Dimension maximumLayoutSize(Container target) {
0889:                    Dimension cpd, mbd, tpd;
0890:                    int cpWidth = Integer.MAX_VALUE;
0891:                    int cpHeight = Integer.MAX_VALUE;
0892:                    int mbWidth = Integer.MAX_VALUE;
0893:                    int mbHeight = Integer.MAX_VALUE;
0894:                    int tpWidth = Integer.MAX_VALUE;
0895:                    int tpHeight = Integer.MAX_VALUE;
0896:                    Insets i = target.getInsets();
0897:                    JRootPane root = (JRootPane) target;
0898:
0899:                    if (root.getContentPane() != null) {
0900:                        cpd = root.getContentPane().getMaximumSize();
0901:                        if (cpd != null) {
0902:                            cpWidth = cpd.width;
0903:                            cpHeight = cpd.height;
0904:                        }
0905:                    }
0906:
0907:                    if (root.getJMenuBar() != null) {
0908:                        mbd = root.getJMenuBar().getMaximumSize();
0909:                        if (mbd != null) {
0910:                            mbWidth = mbd.width;
0911:                            mbHeight = mbd.height;
0912:                        }
0913:                    }
0914:
0915:                    if ((root.getWindowDecorationStyle() != JRootPane.NONE)
0916:                            && (root.getUI() instanceof  SubstanceRootPaneUI)) {
0917:                        JComponent titlePane = ((SubstanceRootPaneUI) root
0918:                                .getUI()).getTitlePane();
0919:                        if (titlePane != null) {
0920:                            tpd = titlePane.getMaximumSize();
0921:                            if (tpd != null) {
0922:                                tpWidth = tpd.width;
0923:                                tpHeight = tpd.height;
0924:                            }
0925:                        }
0926:                    }
0927:
0928:                    int maxHeight = Math.max(Math.max(cpHeight, mbHeight),
0929:                            tpHeight);
0930:                    // Only overflows if 3 real non-MAX_VALUE heights, sum to >
0931:                    // MAX_VALUE
0932:                    // Only will happen if sums to more than 2 billion units. Not
0933:                    // likely.
0934:                    if (maxHeight != Integer.MAX_VALUE) {
0935:                        maxHeight = cpHeight + mbHeight + tpHeight + i.top
0936:                                + i.bottom;
0937:                    }
0938:
0939:                    int maxWidth = Math
0940:                            .max(Math.max(cpWidth, mbWidth), tpWidth);
0941:                    // Similar overflow comment as above
0942:                    if (maxWidth != Integer.MAX_VALUE) {
0943:                        maxWidth += i.left + i.right;
0944:                    }
0945:
0946:                    return new Dimension(maxWidth, maxHeight);
0947:                }
0948:
0949:                /**
0950:                 * Instructs the layout manager to perform the layout for the specified
0951:                 * container.
0952:                 * 
0953:                 * 
0954:                 * aram the Container for which this layout manager is being used
0955:                 */
0956:                public void layoutContainer(Container parent) {
0957:                    JRootPane root = (JRootPane) parent;
0958:                    Rectangle b = root.getBounds();
0959:                    Insets i = root.getInsets();
0960:                    int nextY = 0;
0961:                    int w = b.width - i.right - i.left;
0962:                    int h = b.height - i.top - i.bottom;
0963:
0964:                    if (root.getLayeredPane() != null) {
0965:                        root.getLayeredPane().setBounds(i.left, i.top, w, h);
0966:                    }
0967:                    if (root.getGlassPane() != null) {
0968:                        root.getGlassPane().setBounds(i.left, i.top, w, h);
0969:                    }
0970:                    // Note: This is laying out the children in the layeredPane,
0971:                    // technically, these are not our children.
0972:                    if ((root.getWindowDecorationStyle() != JRootPane.NONE)
0973:                            && (root.getUI() instanceof  SubstanceRootPaneUI)) {
0974:                        JComponent titlePane = ((SubstanceRootPaneUI) root
0975:                                .getUI()).getTitlePane();
0976:                        if (titlePane != null) {
0977:                            Dimension tpd = titlePane.getPreferredSize();
0978:                            if (tpd != null) {
0979:                                int tpHeight = tpd.height;
0980:                                titlePane.setBounds(0, 0, w, tpHeight);
0981:                                nextY += tpHeight;
0982:                            }
0983:                        }
0984:                    }
0985:                    if (root.getJMenuBar() != null) {
0986:                        Dimension mbd = root.getJMenuBar().getPreferredSize();
0987:                        root.getJMenuBar().setBounds(0, nextY, w, mbd.height);
0988:                        nextY += mbd.height;
0989:                    }
0990:                    if (root.getContentPane() != null) {
0991:                        // Dimension cpd = root.getContentPane().getPreferredSize();
0992:                        root.getContentPane().setBounds(0, nextY, w,
0993:                                h < nextY ? 0 : h - nextY);
0994:                    }
0995:                }
0996:
0997:                public void addLayoutComponent(String name, Component comp) {
0998:                }
0999:
1000:                public void removeLayoutComponent(Component comp) {
1001:                }
1002:
1003:                public void addLayoutComponent(Component comp,
1004:                        Object constraints) {
1005:                }
1006:
1007:                public float getLayoutAlignmentX(Container target) {
1008:                    return 0.0f;
1009:                }
1010:
1011:                public float getLayoutAlignmentY(Container target) {
1012:                    return 0.0f;
1013:                }
1014:
1015:                public void invalidateLayout(Container target) {
1016:                }
1017:            }
1018:
1019:            /**
1020:             * Maps from positions to cursor type. Refer to calculateCorner and
1021:             * calculatePosition for details of this.
1022:             */
1023:            private static final int[] cursorMapping = new int[] {
1024:                    Cursor.NW_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR,
1025:                    Cursor.N_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR,
1026:                    Cursor.NE_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, 0, 0, 0,
1027:                    Cursor.NE_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR, 0, 0, 0,
1028:                    Cursor.E_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR, 0, 0, 0,
1029:                    Cursor.SE_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR,
1030:                    Cursor.SW_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR,
1031:                    Cursor.SE_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR };
1032:
1033:            /**
1034:             * MouseInputHandler is responsible for handling resize/moving of the
1035:             * Window. It sets the cursor directly on the Window when then mouse moves
1036:             * over a hot spot.
1037:             */
1038:            private class MouseInputHandler implements  MouseInputListener {
1039:                /**
1040:                 * Set to true if the drag operation is moving the window.
1041:                 */
1042:                private boolean isMovingWindow;
1043:
1044:                /**
1045:                 * Used to determine the corner the resize is occuring from.
1046:                 */
1047:                private int dragCursor;
1048:
1049:                /**
1050:                 * X location the mouse went down on for a drag operation.
1051:                 */
1052:                private int dragOffsetX;
1053:
1054:                /**
1055:                 * Y location the mouse went down on for a drag operation.
1056:                 */
1057:                private int dragOffsetY;
1058:
1059:                /**
1060:                 * Width of the window when the drag started.
1061:                 */
1062:                private int dragWidth;
1063:
1064:                /**
1065:                 * Height of the window when the drag started.
1066:                 */
1067:                private int dragHeight;
1068:
1069:                /**
1070:                 * PrivilegedExceptionAction needed by mouseDragged method to obtain new
1071:                 * location of window on screen during the drag.
1072:                 */
1073:                private final PrivilegedExceptionAction getLocationAction = new PrivilegedExceptionAction() {
1074:                    public Object run() throws HeadlessException {
1075:                        return MouseInfo.getPointerInfo().getLocation();
1076:                    }
1077:                };
1078:
1079:                public void mousePressed(MouseEvent ev) {
1080:                    JRootPane rootPane = SubstanceRootPaneUI.this .getRootPane();
1081:
1082:                    if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) {
1083:                        return;
1084:                    }
1085:                    Point dragWindowOffset = ev.getPoint();
1086:                    Window w = (Window) ev.getSource();
1087:                    if (w != null) {
1088:                        w.toFront();
1089:                    }
1090:                    Point convertedDragWindowOffset = SwingUtilities
1091:                            .convertPoint(w, dragWindowOffset,
1092:                                    SubstanceRootPaneUI.this .getTitlePane());
1093:
1094:                    Frame f = null;
1095:                    Dialog d = null;
1096:
1097:                    if (w instanceof  Frame) {
1098:                        f = (Frame) w;
1099:                    } else if (w instanceof  Dialog) {
1100:                        d = (Dialog) w;
1101:                    }
1102:
1103:                    int frameState = (f != null) ? f.getExtendedState() : 0;
1104:
1105:                    if ((SubstanceRootPaneUI.this .getTitlePane() != null)
1106:                            && SubstanceRootPaneUI.this .getTitlePane()
1107:                                    .contains(convertedDragWindowOffset)) {
1108:                        if ((((f != null) && ((frameState & Frame.MAXIMIZED_BOTH) == 0)) || (d != null))
1109:                                && (dragWindowOffset.y >= SubstanceRootPaneUI.BORDER_DRAG_THICKNESS)
1110:                                && (dragWindowOffset.x >= SubstanceRootPaneUI.BORDER_DRAG_THICKNESS)
1111:                                && (dragWindowOffset.x < w.getWidth()
1112:                                        - SubstanceRootPaneUI.BORDER_DRAG_THICKNESS)) {
1113:                            this .isMovingWindow = true;
1114:                            this .dragOffsetX = dragWindowOffset.x;
1115:                            this .dragOffsetY = dragWindowOffset.y;
1116:                        }
1117:                    } else if (((f != null) && f.isResizable() && ((frameState & Frame.MAXIMIZED_BOTH) == 0))
1118:                            || ((d != null) && d.isResizable())) {
1119:                        this .dragOffsetX = dragWindowOffset.x;
1120:                        this .dragOffsetY = dragWindowOffset.y;
1121:                        this .dragWidth = w.getWidth();
1122:                        this .dragHeight = w.getHeight();
1123:                        this .dragCursor = this .getCursor(this .calculateCorner(
1124:                                w, dragWindowOffset.x, dragWindowOffset.y));
1125:                    }
1126:                }
1127:
1128:                public void mouseReleased(MouseEvent ev) {
1129:                    if ((this .dragCursor != 0)
1130:                            && (SubstanceRootPaneUI.this .window != null)
1131:                            && !SubstanceRootPaneUI.this .window.isValid()) {
1132:                        // Some Window systems validate as you resize, others won't,
1133:                        // thus the check for validity before repainting.
1134:                        SubstanceRootPaneUI.this .window.validate();
1135:                        SubstanceRootPaneUI.this .getRootPane().repaint();
1136:                    }
1137:                    this .isMovingWindow = false;
1138:                    this .dragCursor = 0;
1139:                }
1140:
1141:                public void mouseMoved(MouseEvent ev) {
1142:                    JRootPane root = SubstanceRootPaneUI.this .getRootPane();
1143:
1144:                    if (root.getWindowDecorationStyle() == JRootPane.NONE) {
1145:                        return;
1146:                    }
1147:
1148:                    Window w = (Window) ev.getSource();
1149:
1150:                    Frame f = null;
1151:                    Dialog d = null;
1152:
1153:                    if (w instanceof  Frame) {
1154:                        f = (Frame) w;
1155:                    } else if (w instanceof  Dialog) {
1156:                        d = (Dialog) w;
1157:                    }
1158:
1159:                    // Update the cursor
1160:                    int cursor = this .getCursor(this .calculateCorner(w, ev
1161:                            .getX(), ev.getY()));
1162:
1163:                    if ((cursor != 0)
1164:                            && (((f != null) && (f.isResizable() && ((f
1165:                                    .getExtendedState() & Frame.MAXIMIZED_BOTH) == 0))) || ((d != null) && d
1166:                                    .isResizable()))) {
1167:                        w.setCursor(Cursor.getPredefinedCursor(cursor));
1168:                    } else {
1169:                        w.setCursor(SubstanceRootPaneUI.this .lastCursor);
1170:                    }
1171:                }
1172:
1173:                /**
1174:                 * Adjusts the bounds.
1175:                 * 
1176:                 * @param bounds
1177:                 *            Original bounds.
1178:                 * @param min
1179:                 *            Minimum dimension.
1180:                 * @param deltaX
1181:                 *            Delta X.
1182:                 * @param deltaY
1183:                 *            Delta Y.
1184:                 * @param deltaWidth
1185:                 *            Delta width.
1186:                 * @param deltaHeight
1187:                 *            Delta height.
1188:                 */
1189:                private void adjust(Rectangle bounds, Dimension min,
1190:                        int deltaX, int deltaY, int deltaWidth, int deltaHeight) {
1191:                    bounds.x += deltaX;
1192:                    bounds.y += deltaY;
1193:                    bounds.width += deltaWidth;
1194:                    bounds.height += deltaHeight;
1195:                    if (min != null) {
1196:                        if (bounds.width < min.width) {
1197:                            int correction = min.width - bounds.width;
1198:                            if (deltaX != 0) {
1199:                                bounds.x -= correction;
1200:                            }
1201:                            bounds.width = min.width;
1202:                        }
1203:                        if (bounds.height < min.height) {
1204:                            int correction = min.height - bounds.height;
1205:                            if (deltaY != 0) {
1206:                                bounds.y -= correction;
1207:                            }
1208:                            bounds.height = min.height;
1209:                        }
1210:                    }
1211:                }
1212:
1213:                @SuppressWarnings("unchecked")
1214:                public void mouseDragged(MouseEvent ev) {
1215:                    Window w = (Window) ev.getSource();
1216:                    Point pt = ev.getPoint();
1217:
1218:                    if (this .isMovingWindow) {
1219:                        Point windowPt;
1220:                        try {
1221:                            windowPt = (Point) AccessController
1222:                                    .doPrivileged(this .getLocationAction);
1223:                            windowPt.x = windowPt.x - this .dragOffsetX;
1224:                            windowPt.y = windowPt.y - this .dragOffsetY;
1225:                            w.setLocation(windowPt);
1226:                        } catch (PrivilegedActionException e) {
1227:                        }
1228:                    } else if (this .dragCursor != 0) {
1229:                        Rectangle r = w.getBounds();
1230:                        Rectangle startBounds = new Rectangle(r);
1231:                        Dimension min = w.getMinimumSize();
1232:
1233:                        switch (this .dragCursor) {
1234:                        case Cursor.E_RESIZE_CURSOR:
1235:                            this .adjust(r, min, 0, 0, pt.x
1236:                                    + (this .dragWidth - this .dragOffsetX)
1237:                                    - r.width, 0);
1238:                            break;
1239:                        case Cursor.S_RESIZE_CURSOR:
1240:                            this .adjust(r, min, 0, 0, 0, pt.y
1241:                                    + (this .dragHeight - this .dragOffsetY)
1242:                                    - r.height);
1243:                            break;
1244:                        case Cursor.N_RESIZE_CURSOR:
1245:                            this .adjust(r, min, 0, pt.y - this .dragOffsetY, 0,
1246:                                    -(pt.y - this .dragOffsetY));
1247:                            break;
1248:                        case Cursor.W_RESIZE_CURSOR:
1249:                            this .adjust(r, min, pt.x - this .dragOffsetX, 0,
1250:                                    -(pt.x - this .dragOffsetX), 0);
1251:                            break;
1252:                        case Cursor.NE_RESIZE_CURSOR:
1253:                            this .adjust(r, min, 0, pt.y - this .dragOffsetY,
1254:                                    pt.x + (this .dragWidth - this .dragOffsetX)
1255:                                            - r.width,
1256:                                    -(pt.y - this .dragOffsetY));
1257:                            break;
1258:                        case Cursor.SE_RESIZE_CURSOR:
1259:                            this .adjust(r, min, 0, 0, pt.x
1260:                                    + (this .dragWidth - this .dragOffsetX)
1261:                                    - r.width, pt.y
1262:                                    + (this .dragHeight - this .dragOffsetY)
1263:                                    - r.height);
1264:                            break;
1265:                        case Cursor.NW_RESIZE_CURSOR:
1266:                            this .adjust(r, min, pt.x - this .dragOffsetX, pt.y
1267:                                    - this .dragOffsetY,
1268:                                    -(pt.x - this .dragOffsetX),
1269:                                    -(pt.y - this .dragOffsetY));
1270:                            break;
1271:                        case Cursor.SW_RESIZE_CURSOR:
1272:                            this .adjust(r, min, pt.x - this .dragOffsetX, 0,
1273:                                    -(pt.x - this .dragOffsetX),
1274:                                    pt.y + (this .dragHeight - this .dragOffsetY)
1275:                                            - r.height);
1276:                            break;
1277:                        default:
1278:                            break;
1279:                        }
1280:                        if (!r.equals(startBounds)) {
1281:                            w.setBounds(r);
1282:                            // Defer repaint/validate on mouseReleased unless dynamic
1283:                            // layout is active.
1284:                            if (Toolkit.getDefaultToolkit()
1285:                                    .isDynamicLayoutActive()) {
1286:                                w.validate();
1287:                                SubstanceRootPaneUI.this .getRootPane()
1288:                                        .repaint();
1289:                            }
1290:                        }
1291:                    }
1292:                }
1293:
1294:                public void mouseEntered(MouseEvent ev) {
1295:                    Window w = (Window) ev.getSource();
1296:                    // fix for defect 107
1297:                    SubstanceRootPaneUI.this .lastCursor = w.getCursor();
1298:                    // Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
1299:                    this .mouseMoved(ev);
1300:                }
1301:
1302:                public void mouseExited(MouseEvent ev) {
1303:                    Window w = (Window) ev.getSource();
1304:                    w.setCursor(SubstanceRootPaneUI.this .lastCursor);
1305:                }
1306:
1307:                public void mouseClicked(MouseEvent ev) {
1308:                    Window w = (Window) ev.getSource();
1309:                    Frame f = null;
1310:
1311:                    if (w instanceof  Frame) {
1312:                        f = (Frame) w;
1313:                    } else {
1314:                        return;
1315:                    }
1316:
1317:                    Point convertedPoint = SwingUtilities.convertPoint(w, ev
1318:                            .getPoint(), SubstanceRootPaneUI.this 
1319:                            .getTitlePane());
1320:
1321:                    int state = f.getExtendedState();
1322:                    if ((SubstanceRootPaneUI.this .getTitlePane() != null)
1323:                            && SubstanceRootPaneUI.this .getTitlePane()
1324:                                    .contains(convertedPoint)) {
1325:                        if (((ev.getClickCount() % 2) == 0)
1326:                                && ((ev.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) {
1327:                            if (f.isResizable()) {
1328:                                if ((state & Frame.MAXIMIZED_BOTH) != 0) {
1329:                                    setMaximized();
1330:                                    f.setExtendedState(state
1331:                                            & ~Frame.MAXIMIZED_BOTH);
1332:                                } else {
1333:                                    setMaximized();
1334:                                    f.setExtendedState(state
1335:                                            | Frame.MAXIMIZED_BOTH);
1336:                                }
1337:                                return;
1338:                            }
1339:                        }
1340:                    }
1341:                }
1342:
1343:                /**
1344:                 * Returns the corner that contains the point <code>x</code>,
1345:                 * <code>y</code>, or -1 if the position doesn't match a corner.
1346:                 * 
1347:                 * @param w
1348:                 *            Window.
1349:                 * @param x
1350:                 *            X coordinate.
1351:                 * @param y
1352:                 *            Y coordinate.
1353:                 * @return Corner that contains the specified point.
1354:                 */
1355:                private int calculateCorner(Window w, int x, int y) {
1356:                    Insets insets = w.getInsets();
1357:                    int xPosition = this .calculatePosition(x - insets.left, w
1358:                            .getWidth()
1359:                            - insets.left - insets.right);
1360:                    int yPosition = this .calculatePosition(y - insets.top, w
1361:                            .getHeight()
1362:                            - insets.top - insets.bottom);
1363:
1364:                    if ((xPosition == -1) || (yPosition == -1)) {
1365:                        return -1;
1366:                    }
1367:                    return yPosition * 5 + xPosition;
1368:                }
1369:
1370:                /**
1371:                 * Returns the Cursor to render for the specified corner. This returns 0
1372:                 * if the corner doesn't map to a valid Cursor
1373:                 * 
1374:                 * @param corner
1375:                 *            Corner
1376:                 * @return Cursor to render for the specified corner.
1377:                 */
1378:                private int getCursor(int corner) {
1379:                    if (corner == -1) {
1380:                        return 0;
1381:                    }
1382:                    return SubstanceRootPaneUI.cursorMapping[corner];
1383:                }
1384:
1385:                /**
1386:                 * Returns an integer indicating the position of <code>spot</code> in
1387:                 * <code>width</code>. The return value will be: 0 if <
1388:                 * BORDER_DRAG_THICKNESS 1 if < CORNER_DRAG_WIDTH 2 if >=
1389:                 * CORNER_DRAG_WIDTH && < width - BORDER_DRAG_THICKNESS 3 if >= width -
1390:                 * CORNER_DRAG_WIDTH 4 if >= width - BORDER_DRAG_THICKNESS 5 otherwise
1391:                 * 
1392:                 * @param spot
1393:                 *            Spot.
1394:                 * @param width
1395:                 *            Width.
1396:                 * @return The position of spot in width.
1397:                 */
1398:                private int calculatePosition(int spot, int width) {
1399:                    if (spot < SubstanceRootPaneUI.BORDER_DRAG_THICKNESS) {
1400:                        return 0;
1401:                    }
1402:                    if (spot < SubstanceRootPaneUI.CORNER_DRAG_WIDTH) {
1403:                        return 1;
1404:                    }
1405:                    if (spot >= (width - SubstanceRootPaneUI.BORDER_DRAG_THICKNESS)) {
1406:                        return 4;
1407:                    }
1408:                    if (spot >= (width - SubstanceRootPaneUI.CORNER_DRAG_WIDTH)) {
1409:                        return 3;
1410:                    }
1411:                    return 2;
1412:                }
1413:            }
1414:
1415:            /**
1416:             * Mouse handler on the title pane.
1417:             * 
1418:             * @author Kirill Grouchnikov
1419:             */
1420:            private class TitleMouseInputHandler extends MouseInputAdapter {
1421:
1422:                /**
1423:                 * Pointer location when the mouse was pressed for a drag relative to
1424:                 * the upper-lefthand corner of the window.
1425:                 */
1426:                private Point dragOffset = new Point(0, 0);
1427:
1428:                @Override
1429:                public void mousePressed(MouseEvent ev) {
1430:                    JRootPane rootPane = SubstanceRootPaneUI.this .getRootPane();
1431:
1432:                    if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) {
1433:                        return;
1434:                    }
1435:
1436:                    Point dragWindowOffset = ev.getPoint();
1437:                    Component source = (Component) ev.getSource();
1438:
1439:                    Point convertedDragWindowOffset = SwingUtilities
1440:                            .convertPoint(source, dragWindowOffset,
1441:                                    getTitlePane());
1442:
1443:                    dragWindowOffset = SwingUtilities.convertPoint(source,
1444:                            dragWindowOffset, SubstanceRootPaneUI.this .window);
1445:
1446:                    if (getTitlePane() != null
1447:                            && getTitlePane().contains(
1448:                                    convertedDragWindowOffset)) {
1449:                        if (SubstanceRootPaneUI.this .window != null) {
1450:                            SubstanceRootPaneUI.this .window.toFront();
1451:                            dragOffset = dragWindowOffset;
1452:                        }
1453:                    }
1454:                }
1455:
1456:                @Override
1457:                public void mouseDragged(MouseEvent ev) {
1458:                    Component source = (Component) ev.getSource();
1459:
1460:                    // Point pt = SwingUtilities.convertPoint(source, ev.getPoint(),
1461:                    // SubstanceRootPaneUI.this.window);
1462:
1463:                    Point eventLocationOnScreen = null;
1464:                    if (getLocationOnScreenMethod != null) {
1465:                        try {
1466:                            // fix for issue 198 - only available under JDK 6.0+
1467:                            eventLocationOnScreen = (Point) getLocationOnScreenMethod
1468:                                    .invoke(ev, new Object[0]);
1469:                        } catch (Exception exc) {
1470:                            eventLocationOnScreen = null;
1471:                        }
1472:                    }
1473:                    if (eventLocationOnScreen == null) {
1474:                        eventLocationOnScreen = new Point(ev.getX()
1475:                                + source.getLocationOnScreen().x, ev.getY()
1476:                                + source.getLocationOnScreen().y);
1477:                    }
1478:                    // Fix for issue 192 - disable dragging maximized frame.
1479:                    if (SubstanceRootPaneUI.this .window instanceof  Frame) {
1480:                        Frame f = (Frame) SubstanceRootPaneUI.this .window;
1481:                        int frameState = (f != null) ? f.getExtendedState() : 0;
1482:                        if ((f != null)
1483:                                && ((frameState & Frame.MAXIMIZED_BOTH) == 0)) {
1484:                            SubstanceRootPaneUI.this .window.setLocation(
1485:                                    eventLocationOnScreen.x - dragOffset.x,
1486:                                    eventLocationOnScreen.y - dragOffset.y);
1487:                        }
1488:                    } else {
1489:                        // fix for issue 193 - allow dragging decorated dialogs.
1490:                        SubstanceRootPaneUI.this .window.setLocation(
1491:                                eventLocationOnScreen.x - dragOffset.x,
1492:                                eventLocationOnScreen.y - dragOffset.y);
1493:                    }
1494:
1495:                }
1496:
1497:                @Override
1498:                public void mouseClicked(MouseEvent ev) {
1499:                    Frame f = null;
1500:
1501:                    if (SubstanceRootPaneUI.this .window instanceof  Frame) {
1502:                        f = (Frame) SubstanceRootPaneUI.this .window;
1503:                    } else {
1504:                        return;
1505:                    }
1506:
1507:                    Point convertedPoint = SwingUtilities.convertPoint(
1508:                            SubstanceRootPaneUI.this .window, ev.getPoint(),
1509:                            SubstanceRootPaneUI.this .getTitlePane());
1510:
1511:                    int state = f.getExtendedState();
1512:                    if ((SubstanceRootPaneUI.this .getTitlePane() != null)
1513:                            && SubstanceRootPaneUI.this .getTitlePane()
1514:                                    .contains(convertedPoint)) {
1515:                        if (((ev.getClickCount() % 2) == 0)
1516:                                && ((ev.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) {
1517:                            if (f.isResizable()) {
1518:                                if ((state & Frame.MAXIMIZED_BOTH) != 0) {
1519:                                    setMaximized();
1520:                                    f.setExtendedState(state
1521:                                            & ~Frame.MAXIMIZED_BOTH);
1522:                                } else {
1523:                                    setMaximized();
1524:                                    f.setExtendedState(state
1525:                                            | Frame.MAXIMIZED_BOTH);
1526:                                }
1527:                                return;
1528:                            }
1529:                        }
1530:                    }
1531:                }
1532:            }
1533:
1534:            /**
1535:             * Makes the heap status panel appear / disappear permanently on the
1536:             * associated title pane and removes the corresponding check box menu items
1537:             * from the system menu.
1538:             * 
1539:             * @param isVisible
1540:             *            if <code>true</code>, the heap status panel will be
1541:             *            permanently shown, if <code>false</code>, the heap status
1542:             *            panel will be permanently hidden.
1543:             */
1544:            public void setHeapStatusPanePermanentVisibility(boolean isVisible) {
1545:                if (this .titlePane instanceof  SubstanceTitlePane) {
1546:                    ((SubstanceTitlePane) this.titlePane)
1547:                            .setHeapStatusPanePermanentVisibility(isVisible);
1548:                }
1549:            }
1550:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.