Source Code Cross Referenced for XTrayIconPeer.java in  » 6.0-JDK-Platform » solaris » sun » awt » X11 » 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 » 6.0 JDK Platform » solaris » sun.awt.X11 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.awt.X11;
0027:
0028:        import java.awt.*;
0029:        import java.awt.event.*;
0030:        import java.awt.peer.TrayIconPeer;
0031:        import sun.awt.*;
0032:        import java.awt.image.*;
0033:        import java.text.BreakIterator;
0034:        import java.util.Vector;
0035:        import java.lang.reflect.Field;
0036:        import java.util.logging.Logger;
0037:        import java.util.logging.Level;
0038:        import java.util.AbstractQueue;
0039:        import java.util.concurrent.ArrayBlockingQueue;
0040:        import java.security.AccessController;
0041:        import java.security.PrivilegedAction;
0042:        import java.lang.reflect.InvocationTargetException;
0043:
0044:        public class XTrayIconPeer implements  TrayIconPeer {
0045:            private static final Logger ctrLog = Logger
0046:                    .getLogger("sun.awt.X11.XTrayIconPeer.centering");
0047:
0048:            TrayIcon target;
0049:            TrayIconEventProxy eventProxy;
0050:            XTrayIconEmbeddedFrame eframe;
0051:            TrayIconCanvas canvas;
0052:            Balloon balloon;
0053:            Tooltip tooltip;
0054:            PopupMenu popup;
0055:            String tooltipString;
0056:            boolean isTrayIconDisplayed;
0057:            long eframeParentID;
0058:            final XEventDispatcher parentXED, eframeXED;
0059:
0060:            static final XEventDispatcher dummyXED = new XEventDispatcher() {
0061:                public void dispatchEvent(XEvent ev) {
0062:                }
0063:            };
0064:
0065:            volatile boolean isDisposed;
0066:
0067:            boolean isParentWindowLocated;
0068:            int old_x, old_y;
0069:            int ex_width, ex_height;
0070:
0071:            final static int TRAY_ICON_WIDTH = 24;
0072:            final static int TRAY_ICON_HEIGHT = 24;
0073:
0074:            XTrayIconPeer(TrayIcon target) throws AWTException {
0075:                this .target = target;
0076:
0077:                eventProxy = new TrayIconEventProxy(this );
0078:
0079:                canvas = new TrayIconCanvas(target, TRAY_ICON_WIDTH,
0080:                        TRAY_ICON_HEIGHT);
0081:
0082:                eframe = new XTrayIconEmbeddedFrame();
0083:
0084:                eframe.setSize(TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT);
0085:                eframe.add(canvas);
0086:
0087:                // Fix for 6317038: as EmbeddedFrame is instance of Frame, it is blocked
0088:                // by modal dialogs, but in the case of TrayIcon it shouldn't. So we
0089:                // set ModalExclusion property on it.
0090:                AccessController.doPrivileged(new PrivilegedAction() {
0091:                    public Object run() {
0092:                        eframe
0093:                                .setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
0094:                        return null;
0095:                    }
0096:                });
0097:
0098:                if (XWM.getWMID() != XWM.METACITY_WM) {
0099:                    parentXED = dummyXED; // We don't like to leave it 'null'.
0100:
0101:                } else {
0102:                    parentXED = new XEventDispatcher() {
0103:                        // It's executed under AWTLock.
0104:                        public void dispatchEvent(XEvent ev) {
0105:                            if (isDisposed()
0106:                                    || ev.get_type() != XlibWrapper.ConfigureNotify) {
0107:                                return;
0108:                            }
0109:
0110:                            XConfigureEvent ce = ev.get_xconfigure();
0111:
0112:                            ctrLog
0113:                                    .log(
0114:                                            Level.FINE,
0115:                                            "ConfigureNotify on parent of {0}: {1}x{2}+{3}+{4} (old: {5}+{6})",
0116:                                            new Object[] { XTrayIconPeer.this ,
0117:                                                    ce.get_width(),
0118:                                                    ce.get_height(),
0119:                                                    ce.get_x(), ce.get_y(),
0120:                                                    old_x, old_y });
0121:
0122:                            // A workaround for Gnome/Metacity (it doesn't affect the behaviour on KDE).
0123:                            // On Metacity the EmbeddedFrame's parent window bounds are larger
0124:                            // than TrayIcon size required (that is we need a square but a rectangle
0125:                            // is provided by the Panel Notification Area). The parent's background color
0126:                            // differs from the Panel's one. To hide the background we resize parent
0127:                            // window so that it fits the EmbeddedFrame.
0128:                            // However due to resizing the parent window it loses centering in the Panel.
0129:                            // We center it when discovering that some of its side is of size greater
0130:                            // than the fixed value. Centering is being done by "X" (when the parent's width
0131:                            // is greater) and by "Y" (when the parent's height is greater).
0132:
0133:                            // Actually we need this workaround until we could detect taskbar color.
0134:
0135:                            if (ce.get_height() != TRAY_ICON_HEIGHT
0136:                                    && ce.get_width() != TRAY_ICON_WIDTH) {
0137:
0138:                                // If both the height and the width differ from the fixed size then WM
0139:                                // must level at least one side to the fixed size. For some reason it may take
0140:                                // a few hops (even after reparenting) and we have to skip the intermediate ones.
0141:                                ctrLog
0142:                                        .log(
0143:                                                Level.FINE,
0144:                                                "ConfigureNotify on parent of {0}. Skipping as intermediate resizing.",
0145:                                                XTrayIconPeer.this );
0146:                                return;
0147:
0148:                            } else if (ce.get_height() > TRAY_ICON_HEIGHT) {
0149:
0150:                                ctrLog
0151:                                        .log(
0152:                                                Level.FINE,
0153:                                                "ConfigureNotify on parent of {0}. Centering by \"Y\".",
0154:                                                XTrayIconPeer.this );
0155:
0156:                                XlibWrapper.XMoveResizeWindow(XToolkit
0157:                                        .getDisplay(), eframeParentID, ce
0158:                                        .get_x(), ce.get_y() + ce.get_height()
0159:                                        / 2 - TRAY_ICON_HEIGHT / 2,
0160:                                        TRAY_ICON_WIDTH, TRAY_ICON_HEIGHT);
0161:                                ex_height = ce.get_height();
0162:                                ex_width = 0;
0163:
0164:                            } else if (ce.get_width() > TRAY_ICON_WIDTH) {
0165:
0166:                                ctrLog
0167:                                        .log(
0168:                                                Level.FINE,
0169:                                                "ConfigureNotify on parent of {0}. Centering by \"X\".",
0170:                                                XTrayIconPeer.this );
0171:
0172:                                XlibWrapper.XMoveResizeWindow(XToolkit
0173:                                        .getDisplay(), eframeParentID, ce
0174:                                        .get_x()
0175:                                        + ce.get_width()
0176:                                        / 2
0177:                                        - TRAY_ICON_WIDTH
0178:                                        / 2, ce.get_y(), TRAY_ICON_WIDTH,
0179:                                        TRAY_ICON_HEIGHT);
0180:                                ex_width = ce.get_width();
0181:                                ex_height = 0;
0182:
0183:                            } else if (isParentWindowLocated
0184:                                    && ce.get_x() != old_x
0185:                                    && ce.get_y() != old_y) {
0186:                                // If moving by both "X" and "Y".
0187:                                // When some tray icon gets removed from the tray, a Java icon may be repositioned.
0188:                                // In this case the parent window also lose centering. We have to restore it.
0189:
0190:                                if (ex_height != 0) {
0191:
0192:                                    ctrLog
0193:                                            .log(
0194:                                                    Level.FINE,
0195:                                                    "ConfigureNotify on parent of {0}. Move detected. Centering by \"Y\".",
0196:                                                    XTrayIconPeer.this );
0197:
0198:                                    XlibWrapper.XMoveWindow(XToolkit
0199:                                            .getDisplay(), eframeParentID, ce
0200:                                            .get_x(), ce.get_y() + ex_height
0201:                                            / 2 - TRAY_ICON_HEIGHT / 2);
0202:
0203:                                } else if (ex_width != 0) {
0204:
0205:                                    ctrLog
0206:                                            .log(
0207:                                                    Level.FINE,
0208:                                                    "ConfigureNotify on parent of {0}. Move detected. Centering by \"X\".",
0209:                                                    XTrayIconPeer.this );
0210:
0211:                                    XlibWrapper.XMoveWindow(XToolkit
0212:                                            .getDisplay(), eframeParentID, ce
0213:                                            .get_x()
0214:                                            + ex_width
0215:                                            / 2
0216:                                            - TRAY_ICON_WIDTH
0217:                                            / 2, ce.get_y());
0218:                                } else {
0219:                                    ctrLog
0220:                                            .log(
0221:                                                    Level.FINE,
0222:                                                    "ConfigureNotify on parent of {0}. Move detected. Skipping.",
0223:                                                    XTrayIconPeer.this );
0224:                                }
0225:                            }
0226:                            old_x = ce.get_x();
0227:                            old_y = ce.get_y();
0228:                            isParentWindowLocated = true;
0229:                        }
0230:                    };
0231:                }
0232:                eframeXED = new XEventDispatcher() {
0233:                    // It's executed under AWTLock.
0234:                    XTrayIconPeer xtiPeer = XTrayIconPeer.this ;
0235:
0236:                    public void dispatchEvent(XEvent ev) {
0237:                        if (isDisposed()
0238:                                || ev.get_type() != XlibWrapper.ReparentNotify) {
0239:                            return;
0240:                        }
0241:
0242:                        XReparentEvent re = ev.get_xreparent();
0243:                        eframeParentID = re.get_parent();
0244:
0245:                        if (eframeParentID == XToolkit.getDefaultRootWindow()) {
0246:
0247:                            if (isTrayIconDisplayed) { // most likely Notification Area was removed
0248:                                SunToolkit.executeOnEventHandlerThread(
0249:                                        xtiPeer.target, new Runnable() {
0250:                                            public void run() {
0251:                                                SystemTray.getSystemTray()
0252:                                                        .remove(xtiPeer.target);
0253:                                            }
0254:                                        });
0255:                            }
0256:                            return;
0257:                        }
0258:
0259:                        if (!isTrayIconDisplayed) {
0260:                            addXED(eframeParentID, parentXED,
0261:                                    XlibWrapper.StructureNotifyMask);
0262:
0263:                            isTrayIconDisplayed = true;
0264:                            XToolkit.awtLockNotifyAll();
0265:                        }
0266:                    }
0267:                };
0268:
0269:                addXED(getWindow(), eframeXED, XlibWrapper.StructureNotifyMask);
0270:
0271:                XSystemTrayPeer.getPeerInstance().addTrayIcon(this ); // throws AWTException
0272:
0273:                // Wait till the EmbeddedFrame is reparented
0274:                long start = System.currentTimeMillis();
0275:                final long PERIOD = 2000L;
0276:                XToolkit.awtLock();
0277:                try {
0278:                    while (!isTrayIconDisplayed) {
0279:                        try {
0280:                            XToolkit.awtLockWait(PERIOD);
0281:                        } catch (InterruptedException e) {
0282:                            break;
0283:                        }
0284:                        if (System.currentTimeMillis() - start > PERIOD) {
0285:                            break;
0286:                        }
0287:                    }
0288:                } finally {
0289:                    XToolkit.awtUnlock();
0290:                }
0291:
0292:                // This is unlikely to happen.
0293:                if (!isTrayIconDisplayed || eframeParentID == 0
0294:                        || eframeParentID == XToolkit.getDefaultRootWindow()) {
0295:                    throw new AWTException("TrayIcon couldn't be displayed.");
0296:                }
0297:
0298:                eframe.setVisible(true);
0299:                updateImage();
0300:
0301:                balloon = new Balloon(this , eframe);
0302:                tooltip = new Tooltip(this , eframe);
0303:
0304:                addListeners();
0305:            }
0306:
0307:            public void dispose() {
0308:                if (SunToolkit.isDispatchThreadForAppContext(target)) {
0309:                    disposeOnEDT();
0310:                } else {
0311:                    try {
0312:                        SunToolkit.executeOnEDTAndWait(target, new Runnable() {
0313:                            public void run() {
0314:                                disposeOnEDT();
0315:                            }
0316:                        });
0317:                    } catch (InterruptedException ie) {
0318:                    } catch (InvocationTargetException ite) {
0319:                    }
0320:                }
0321:            }
0322:
0323:            private void disposeOnEDT() {
0324:                // All actions that is to be synchronized with disposal
0325:                // should be executed either under AWTLock, or on EDT.
0326:                // isDisposed value must be checked.
0327:                XToolkit.awtLock();
0328:                isDisposed = true;
0329:                XToolkit.awtUnlock();
0330:
0331:                removeXED(getWindow(), eframeXED);
0332:                removeXED(eframeParentID, parentXED);
0333:                eframe.realDispose();
0334:                balloon.dispose();
0335:                isTrayIconDisplayed = false;
0336:                XToolkit.targetDisposedPeer(target, this );
0337:            }
0338:
0339:            public static void suppressWarningString(Window w) {
0340:                WindowAccessor.setTrayIconWindow(w, true);
0341:            }
0342:
0343:            public void setToolTip(String tooltip) {
0344:                tooltipString = tooltip;
0345:            }
0346:
0347:            public void updateImage() {
0348:                Runnable r = new Runnable() {
0349:                    public void run() {
0350:                        canvas.updateImage(target.getImage());
0351:                    }
0352:                };
0353:
0354:                if (!SunToolkit.isDispatchThreadForAppContext(target)) {
0355:                    SunToolkit.executeOnEventHandlerThread(target, r);
0356:                } else {
0357:                    r.run();
0358:                }
0359:            }
0360:
0361:            public void displayMessage(String caption, String text,
0362:                    String messageType) {
0363:                Point loc = getLocationOnScreen();
0364:                Rectangle screen = eframe.getGraphicsConfiguration()
0365:                        .getBounds();
0366:
0367:                // Check if the tray icon is in the bounds of a screen.
0368:                if (!(loc.x < screen.x || loc.x >= screen.x + screen.width
0369:                        || loc.y < screen.y || loc.y >= screen.y
0370:                        + screen.height)) {
0371:                    balloon.display(caption, text, messageType);
0372:                }
0373:            }
0374:
0375:            // It's synchronized with disposal by EDT.
0376:            public void showPopupMenu(int x, int y) {
0377:                if (isDisposed())
0378:                    return;
0379:
0380:                assert SunToolkit.isDispatchThreadForAppContext(target);
0381:
0382:                PopupMenu newPopup = target.getPopupMenu();
0383:                if (popup != newPopup) {
0384:                    if (popup != null) {
0385:                        eframe.remove(popup);
0386:                    }
0387:                    if (newPopup != null) {
0388:                        eframe.add(newPopup);
0389:                    }
0390:                    popup = newPopup;
0391:                }
0392:
0393:                if (popup != null) {
0394:                    Point loc = ((XBaseWindow) eframe.getPeer())
0395:                            .toLocal(new Point(x, y));
0396:                    popup.show(eframe, loc.x, loc.y);
0397:                }
0398:            }
0399:
0400:            // ******************************************************************
0401:            // ******************************************************************
0402:
0403:            private void addXED(long window, XEventDispatcher xed, long mask) {
0404:                if (window == 0) {
0405:                    return;
0406:                }
0407:                XToolkit.awtLock();
0408:                try {
0409:                    XlibWrapper.XSelectInput(XToolkit.getDisplay(), window,
0410:                            mask);
0411:                } finally {
0412:                    XToolkit.awtUnlock();
0413:                }
0414:                XToolkit.addEventDispatcher(window, xed);
0415:            }
0416:
0417:            private void removeXED(long window, XEventDispatcher xed) {
0418:                if (window == 0) {
0419:                    return;
0420:                }
0421:                XToolkit.awtLock();
0422:                try {
0423:                    XToolkit.removeEventDispatcher(window, xed);
0424:                } finally {
0425:                    XToolkit.awtUnlock();
0426:                }
0427:            }
0428:
0429:            // Private method for testing purposes.
0430:            private Point getLocationOnScreen() {
0431:                return eframe.getLocationOnScreen();
0432:            }
0433:
0434:            private Rectangle getBounds() {
0435:                Point loc = getLocationOnScreen();
0436:                return new Rectangle(loc.x, loc.y, loc.x + TRAY_ICON_WIDTH,
0437:                        loc.y + TRAY_ICON_HEIGHT);
0438:            }
0439:
0440:            void addListeners() {
0441:                canvas.addMouseListener(eventProxy);
0442:                canvas.addMouseMotionListener(eventProxy);
0443:            }
0444:
0445:            long getWindow() {
0446:                return ((XEmbeddedFramePeer) eframe.getPeer()).getWindow();
0447:            }
0448:
0449:            boolean isDisposed() {
0450:                return isDisposed;
0451:            }
0452:
0453:            static class TrayIconEventProxy implements  MouseListener,
0454:                    MouseMotionListener {
0455:                XTrayIconPeer xtiPeer;
0456:
0457:                TrayIconEventProxy(XTrayIconPeer xtiPeer) {
0458:                    this .xtiPeer = xtiPeer;
0459:                }
0460:
0461:                public void handleEvent(MouseEvent e) {
0462:                    // Event handling is synchronized with disposal by EDT.
0463:                    if (xtiPeer.isDisposed()) {
0464:                        return;
0465:                    }
0466:                    Point coord = XBaseWindow
0467:                            .toOtherWindow(xtiPeer.getWindow(), XToolkit
0468:                                    .getDefaultRootWindow(), e.getX(), e.getY());
0469:
0470:                    if (e.isPopupTrigger()) {
0471:                        xtiPeer.showPopupMenu(coord.x, coord.y);
0472:                    }
0473:
0474:                    e.translatePoint(coord.x - e.getX(), coord.y - e.getY());
0475:                    e.setSource(xtiPeer.target);
0476:                    Toolkit.getDefaultToolkit().getSystemEventQueue()
0477:                            .postEvent(e);
0478:                }
0479:
0480:                public void mouseClicked(MouseEvent e) {
0481:                    if ((e.getClickCount() > 1 || xtiPeer.balloon.isVisible())
0482:                            && e.getButton() == MouseEvent.BUTTON1) {
0483:                        ActionEvent aev = new ActionEvent(xtiPeer.target,
0484:                                ActionEvent.ACTION_PERFORMED, xtiPeer.target
0485:                                        .getActionCommand(), e.getWhen(), e
0486:                                        .getModifiers());
0487:                        Toolkit.getDefaultToolkit().getSystemEventQueue()
0488:                                .postEvent(aev);
0489:                    }
0490:                    if (xtiPeer.balloon.isVisible()) {
0491:                        xtiPeer.balloon.hide();
0492:                    }
0493:                    handleEvent(e);
0494:                }
0495:
0496:                public void mouseEntered(MouseEvent e) {
0497:                    xtiPeer.tooltip.enter();
0498:                    handleEvent(e);
0499:                }
0500:
0501:                public void mouseExited(MouseEvent e) {
0502:                    xtiPeer.tooltip.exit();
0503:                    handleEvent(e);
0504:                }
0505:
0506:                public void mousePressed(MouseEvent e) {
0507:                    handleEvent(e);
0508:                }
0509:
0510:                public void mouseReleased(MouseEvent e) {
0511:                    handleEvent(e);
0512:                }
0513:
0514:                public void mouseDragged(MouseEvent e) {
0515:                    handleEvent(e);
0516:                }
0517:
0518:                public void mouseMoved(MouseEvent e) {
0519:                    handleEvent(e);
0520:                }
0521:            }
0522:
0523:            static boolean isTrayIconStuffWindow(Window w) {
0524:                return (w instanceof  Tooltip) || (w instanceof  Balloon)
0525:                        || (w instanceof  XTrayIconEmbeddedFrame);
0526:            }
0527:
0528:            // ***************************************
0529:            // Special embedded frame for tray icon
0530:            // ***************************************
0531:
0532:            private static class XTrayIconEmbeddedFrame extends XEmbeddedFrame {
0533:                public XTrayIconEmbeddedFrame() {
0534:                    super (XToolkit.getDefaultRootWindow(), true, true);
0535:                }
0536:
0537:                public boolean isUndecorated() {
0538:                    return true;
0539:                }
0540:
0541:                public boolean isResizable() {
0542:                    return false;
0543:                }
0544:
0545:                // embedded frame for tray icon shouldn't be disposed by anyone except tray icon
0546:                public void dispose() {
0547:                }
0548:
0549:                public void realDispose() {
0550:                    super .dispose();
0551:                }
0552:            };
0553:
0554:            // ***************************************
0555:            // Classes for painting an image on canvas
0556:            // ***************************************
0557:
0558:            static class TrayIconCanvas extends IconCanvas {
0559:                TrayIcon target;
0560:                boolean autosize;
0561:
0562:                TrayIconCanvas(TrayIcon target, int width, int height) {
0563:                    super (width, height);
0564:                    this .target = target;
0565:                }
0566:
0567:                // Invoke on EDT.
0568:                protected void repaintImage(boolean doClear) {
0569:                    boolean old_autosize = autosize;
0570:                    autosize = target.isImageAutoSize();
0571:
0572:                    curW = autosize ? width : image.getWidth(observer);
0573:                    curH = autosize ? height : image.getHeight(observer);
0574:
0575:                    super .repaintImage(doClear || (old_autosize != autosize));
0576:                }
0577:            }
0578:
0579:            static class IconCanvas extends Canvas {
0580:                volatile Image image;
0581:                IconObserver observer;
0582:                int width, height;
0583:                int curW, curH;
0584:
0585:                IconCanvas(int width, int height) {
0586:                    this .width = curW = width;
0587:                    this .height = curH = height;
0588:                }
0589:
0590:                // Invoke on EDT.
0591:                public void updateImage(Image image) {
0592:                    this .image = image;
0593:                    if (observer == null) {
0594:                        observer = new IconObserver();
0595:                    }
0596:                    repaintImage(true);
0597:                }
0598:
0599:                // Invoke on EDT.
0600:                protected void repaintImage(boolean doClear) {
0601:                    Graphics g = getGraphics();
0602:                    if (g != null) {
0603:                        try {
0604:                            if (isVisible()) {
0605:                                if (doClear) {
0606:                                    update(g);
0607:                                } else {
0608:                                    paint(g);
0609:                                }
0610:                            }
0611:                        } finally {
0612:                            g.dispose();
0613:                        }
0614:                    }
0615:                }
0616:
0617:                // Invoke on EDT.
0618:                public void paint(Graphics g) {
0619:                    if (g != null && curW > 0 && curH > 0) {
0620:                        BufferedImage bufImage = new BufferedImage(curW, curH,
0621:                                BufferedImage.TYPE_INT_ARGB);
0622:                        Graphics2D gr = bufImage.createGraphics();
0623:                        if (gr != null) {
0624:                            try {
0625:                                gr.setColor(getBackground());
0626:                                gr.fillRect(0, 0, curW, curH);
0627:                                gr.drawImage(image, 0, 0, curW, curH, observer);
0628:                                gr.dispose();
0629:
0630:                                g.drawImage(bufImage, 0, 0, curW, curH, null);
0631:                            } finally {
0632:                                gr.dispose();
0633:                            }
0634:                        }
0635:                    }
0636:                }
0637:
0638:                class IconObserver implements  ImageObserver {
0639:                    public boolean imageUpdate(final Image image,
0640:                            final int flags, int x, int y, int width, int height) {
0641:                        if (image != IconCanvas.this .image || // if the image has been changed
0642:                                !IconCanvas.this .isVisible()) {
0643:                            return false;
0644:                        }
0645:                        if ((flags & (ImageObserver.FRAMEBITS
0646:                                | ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT)) != 0) {
0647:                            SunToolkit.executeOnEventHandlerThread(
0648:                                    IconCanvas.this , new Runnable() {
0649:                                        public void run() {
0650:                                            repaintImage(false);
0651:                                        }
0652:                                    });
0653:                        }
0654:                        return (flags & ImageObserver.ALLBITS) == 0;
0655:                    }
0656:                }
0657:            }
0658:
0659:            // ***************************************
0660:            // Classes for toolitp and balloon windows
0661:            // ***************************************
0662:
0663:            static class Tooltip extends InfoWindow {
0664:                XTrayIconPeer xtiPeer;
0665:                Label textLabel = new Label("");
0666:                Runnable starter = new Runnable() {
0667:                    public void run() {
0668:                        display();
0669:                    }
0670:                };
0671:
0672:                final static int TOOLTIP_SHOW_TIME = 10000;
0673:                final static int TOOLTIP_START_DELAY_TIME = 1000;
0674:                final static int TOOLTIP_MAX_LENGTH = 64;
0675:                final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
0676:                final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255,
0677:                        255, 220);
0678:                final static Font TOOLTIP_TEXT_FONT = XWindow.defaultFont;
0679:
0680:                Tooltip(XTrayIconPeer xtiPeer, Frame parent) {
0681:                    super (parent, Color.black);
0682:                    this .xtiPeer = xtiPeer;
0683:
0684:                    suppressWarningString(this );
0685:
0686:                    setCloser(null, TOOLTIP_SHOW_TIME);
0687:                    textLabel.setBackground(TOOLTIP_BACKGROUND_COLOR);
0688:                    textLabel.setFont(TOOLTIP_TEXT_FONT);
0689:                    add(textLabel);
0690:                }
0691:
0692:                /*
0693:                 * WARNING: this method is executed on Toolkit thread!
0694:                 */
0695:                void display() {
0696:                    String tip = xtiPeer.tooltipString;
0697:                    if (tip == null) {
0698:                        return;
0699:                    } else if (tip.length() > TOOLTIP_MAX_LENGTH) {
0700:                        textLabel.setText(tip.substring(0, TOOLTIP_MAX_LENGTH));
0701:                    } else {
0702:                        textLabel.setText(tip);
0703:                    }
0704:
0705:                    // Execute on EDT to avoid deadlock (see 6280857).
0706:                    SunToolkit.executeOnEventHandlerThread(xtiPeer.target,
0707:                            new Runnable() {
0708:                                public void run() {
0709:                                    if (xtiPeer.isDisposed()) {
0710:                                        return;
0711:                                    }
0712:                                    Point pointer = (Point) AccessController
0713:                                            .doPrivileged(new PrivilegedAction() {
0714:                                                public Object run() {
0715:                                                    if (!isPointerOverTrayIcon(xtiPeer
0716:                                                            .getBounds())) {
0717:                                                        return null;
0718:                                                    }
0719:                                                    return MouseInfo
0720:                                                            .getPointerInfo()
0721:                                                            .getLocation();
0722:                                                }
0723:                                            });
0724:                                    if (pointer == null) {
0725:                                        return;
0726:                                    }
0727:                                    show(new Point(pointer.x, pointer.y),
0728:                                            TOOLTIP_MOUSE_CURSOR_INDENT);
0729:                                }
0730:                            });
0731:                }
0732:
0733:                void enter() {
0734:                    XToolkit.schedule(starter, TOOLTIP_START_DELAY_TIME);
0735:                }
0736:
0737:                void exit() {
0738:                    XToolkit.remove(starter);
0739:                    if (isVisible()) {
0740:                        hide();
0741:                    }
0742:                }
0743:
0744:                boolean isPointerOverTrayIcon(Rectangle trayRect) {
0745:                    Point p = MouseInfo.getPointerInfo().getLocation();
0746:                    return !(p.x < trayRect.x
0747:                            || p.x > (trayRect.x + trayRect.width)
0748:                            || p.y < trayRect.y || p.y > (trayRect.y + trayRect.height));
0749:                }
0750:            }
0751:
0752:            static class Balloon extends InfoWindow {
0753:                final static int BALLOON_SHOW_TIME = 10000;
0754:                final static int BALLOON_TEXT_MAX_LENGTH = 256;
0755:                final static int BALLOON_WORD_LINE_MAX_LENGTH = 16;
0756:                final static int BALLOON_WORD_LINE_MAX_COUNT = 4;
0757:                final static int BALLOON_ICON_WIDTH = 32;
0758:                final static int BALLOON_ICON_HEIGHT = 32;
0759:                final static int BALLOON_TRAY_ICON_INDENT = 0;
0760:                final static Color BALLOON_CAPTION_BACKGROUND_COLOR = new Color(
0761:                        200, 200, 255);
0762:                final static Font BALLOON_CAPTION_FONT = new Font(Font.DIALOG,
0763:                        Font.BOLD, 12);
0764:
0765:                XTrayIconPeer xtiPeer;
0766:                Panel mainPanel = new Panel();
0767:                Panel captionPanel = new Panel();
0768:                Label captionLabel = new Label("");
0769:                Button closeButton = new Button("X");
0770:                Panel textPanel = new Panel();
0771:                IconCanvas iconCanvas = new IconCanvas(BALLOON_ICON_WIDTH,
0772:                        BALLOON_ICON_HEIGHT);
0773:                Label[] lineLabels = new Label[BALLOON_WORD_LINE_MAX_COUNT];
0774:                ActionPerformer ap = new ActionPerformer();
0775:
0776:                Image iconImage;
0777:                Image errorImage;
0778:                Image warnImage;
0779:                Image infoImage;
0780:                boolean gtkImagesLoaded;
0781:
0782:                Displayer displayer = new Displayer();
0783:
0784:                Balloon(final XTrayIconPeer xtiPeer, Frame parent) {
0785:                    super (parent, new Color(90, 80, 190));
0786:                    this .xtiPeer = xtiPeer;
0787:
0788:                    suppressWarningString(this );
0789:
0790:                    setCloser(new Runnable() {
0791:                        public void run() {
0792:                            if (textPanel != null) {
0793:                                textPanel.removeAll();
0794:                                textPanel.setSize(0, 0);
0795:                                iconCanvas.setSize(0, 0);
0796:                                XToolkit.awtLock();
0797:                                try {
0798:                                    displayer.isDisplayed = false;
0799:                                    XToolkit.awtLockNotifyAll();
0800:                                } finally {
0801:                                    XToolkit.awtUnlock();
0802:                                }
0803:                            }
0804:                        }
0805:                    }, BALLOON_SHOW_TIME);
0806:
0807:                    add(mainPanel);
0808:
0809:                    captionLabel.setFont(BALLOON_CAPTION_FONT);
0810:                    captionLabel.addMouseListener(ap);
0811:
0812:                    captionPanel.setLayout(new BorderLayout());
0813:                    captionPanel.add(captionLabel, BorderLayout.WEST);
0814:                    captionPanel.add(closeButton, BorderLayout.EAST);
0815:                    captionPanel
0816:                            .setBackground(BALLOON_CAPTION_BACKGROUND_COLOR);
0817:                    captionPanel.addMouseListener(ap);
0818:
0819:                    closeButton.addActionListener(new ActionListener() {
0820:                        public void actionPerformed(ActionEvent e) {
0821:                            hide();
0822:                        }
0823:                    });
0824:
0825:                    mainPanel.setLayout(new BorderLayout());
0826:                    mainPanel.setBackground(Color.white);
0827:                    mainPanel.add(captionPanel, BorderLayout.NORTH);
0828:                    mainPanel.add(iconCanvas, BorderLayout.WEST);
0829:                    mainPanel.add(textPanel, BorderLayout.CENTER);
0830:
0831:                    iconCanvas.addMouseListener(ap);
0832:
0833:                    for (int i = 0; i < BALLOON_WORD_LINE_MAX_COUNT; i++) {
0834:                        lineLabels[i] = new Label();
0835:                        lineLabels[i].addMouseListener(ap);
0836:                        lineLabels[i].setBackground(Color.white);
0837:                    }
0838:
0839:                    displayer.start();
0840:                }
0841:
0842:                void display(String caption, String text, String messageType) {
0843:                    if (!gtkImagesLoaded) {
0844:                        loadGtkImages();
0845:                    }
0846:                    displayer.display(caption, text, messageType);
0847:                }
0848:
0849:                private void _display(String caption, String text,
0850:                        String messageType) {
0851:                    captionLabel.setText(caption);
0852:
0853:                    BreakIterator iter = BreakIterator.getWordInstance();
0854:                    if (text != null) {
0855:                        iter.setText(text);
0856:                        int start = iter.first(), end;
0857:                        int nLines = 0;
0858:
0859:                        do {
0860:                            end = iter.next();
0861:
0862:                            if (end == BreakIterator.DONE
0863:                                    || text.substring(start, end).length() >= 50) {
0864:                                lineLabels[nLines].setText(text.substring(
0865:                                        start, end == BreakIterator.DONE ? iter
0866:                                                .last() : end));
0867:                                textPanel.add(lineLabels[nLines++]);
0868:                                start = end;
0869:                            }
0870:                            if (nLines == BALLOON_WORD_LINE_MAX_COUNT) {
0871:                                if (end != BreakIterator.DONE) {
0872:                                    lineLabels[nLines - 1].setText(new String(
0873:                                            lineLabels[nLines - 1].getText()
0874:                                                    + " ..."));
0875:                                }
0876:                                break;
0877:                            }
0878:                        } while (end != BreakIterator.DONE);
0879:
0880:                        textPanel.setLayout(new GridLayout(nLines, 1));
0881:                    }
0882:
0883:                    if ("ERROR".equals(messageType)) {
0884:                        iconImage = errorImage;
0885:                    } else if ("WARNING".equals(messageType)) {
0886:                        iconImage = warnImage;
0887:                    } else if ("INFO".equals(messageType)) {
0888:                        iconImage = infoImage;
0889:                    } else {
0890:                        iconImage = null;
0891:                    }
0892:
0893:                    if (iconImage != null) {
0894:                        Dimension tpSize = textPanel.getSize();
0895:                        iconCanvas
0896:                                .setSize(
0897:                                        BALLOON_ICON_WIDTH,
0898:                                        (BALLOON_ICON_HEIGHT > tpSize.height ? BALLOON_ICON_HEIGHT
0899:                                                : tpSize.height));
0900:                    }
0901:
0902:                    SunToolkit.executeOnEventHandlerThread(xtiPeer.target,
0903:                            new Runnable() {
0904:                                public void run() {
0905:                                    if (xtiPeer.isDisposed()) {
0906:                                        return;
0907:                                    }
0908:                                    Point parLoc = getParent()
0909:                                            .getLocationOnScreen();
0910:                                    Dimension parSize = getParent().getSize();
0911:                                    show(new Point(
0912:                                            parLoc.x + parSize.width / 2,
0913:                                            parLoc.y + parSize.height / 2),
0914:                                            BALLOON_TRAY_ICON_INDENT);
0915:                                    if (iconImage != null) {
0916:                                        iconCanvas.updateImage(iconImage); // call it after the show(..) above
0917:                                    }
0918:                                }
0919:                            });
0920:                }
0921:
0922:                public void dispose() {
0923:                    displayer.interrupt();
0924:                    super .dispose();
0925:                }
0926:
0927:                void loadGtkImages() {
0928:                    if (!gtkImagesLoaded) {
0929:                        errorImage = (Image) Toolkit.getDefaultToolkit()
0930:                                .getDesktopProperty(
0931:                                        "gtk.icon.gtk-dialog-error.6.rtl");
0932:                        warnImage = (Image) Toolkit.getDefaultToolkit()
0933:                                .getDesktopProperty(
0934:                                        "gtk.icon.gtk-dialog-warning.6.rtl");
0935:                        infoImage = (Image) Toolkit.getDefaultToolkit()
0936:                                .getDesktopProperty(
0937:                                        "gtk.icon.gtk-dialog-info.6.rtl");
0938:                        gtkImagesLoaded = true;
0939:                    }
0940:                }
0941:
0942:                class ActionPerformer extends MouseAdapter {
0943:                    public void mouseClicked(MouseEvent e) {
0944:                        // hide the balloon by any click
0945:                        hide();
0946:                        if (e.getButton() == MouseEvent.BUTTON1) {
0947:                            ActionEvent aev = new ActionEvent(xtiPeer.target,
0948:                                    ActionEvent.ACTION_PERFORMED,
0949:                                    xtiPeer.target.getActionCommand(), e
0950:                                            .getWhen(), e.getModifiers());
0951:                            Toolkit.getDefaultToolkit().getSystemEventQueue()
0952:                                    .postEvent(aev);
0953:                        }
0954:                    }
0955:                }
0956:
0957:                class Displayer extends Thread {
0958:                    final int MAX_CONCURRENT_MSGS = 10;
0959:
0960:                    ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(
0961:                            MAX_CONCURRENT_MSGS);
0962:                    boolean isDisplayed;
0963:
0964:                    Displayer() {
0965:                        setDaemon(true);
0966:                    }
0967:
0968:                    public void run() {
0969:                        while (true) {
0970:                            Message msg = null;
0971:                            try {
0972:                                msg = (Message) messageQueue.take();
0973:                            } catch (InterruptedException e) {
0974:                                return;
0975:                            }
0976:
0977:                            /*
0978:                             * Wait till the previous message is displayed if any
0979:                             */
0980:                            XToolkit.awtLock();
0981:                            try {
0982:                                while (isDisplayed) {
0983:                                    try {
0984:                                        XToolkit.awtLockWait();
0985:                                    } catch (InterruptedException e) {
0986:                                        return;
0987:                                    }
0988:                                }
0989:                                isDisplayed = true;
0990:                            } finally {
0991:                                XToolkit.awtUnlock();
0992:                            }
0993:                            _display(msg.caption, msg.text, msg.messageType);
0994:                        }
0995:                    }
0996:
0997:                    void display(String caption, String text, String messageType) {
0998:                        messageQueue.offer(new Message(caption, text,
0999:                                messageType));
1000:                    }
1001:                }
1002:
1003:                class Message {
1004:                    String caption, text, messageType;
1005:
1006:                    Message(String caption, String text, String messageType) {
1007:                        this .caption = caption;
1008:                        this .text = text;
1009:                        this .messageType = messageType;
1010:                    }
1011:                }
1012:            }
1013:
1014:            static class InfoWindow extends Window {
1015:                Container container;
1016:                Closer closer;
1017:
1018:                InfoWindow(Frame parent, Color borderColor) {
1019:                    super (parent);
1020:                    container = new Container() {
1021:                        public Insets getInsets() {
1022:                            return new Insets(1, 1, 1, 1);
1023:                        }
1024:                    };
1025:                    setLayout(new BorderLayout());
1026:                    setBackground(borderColor);
1027:                    add(container, BorderLayout.CENTER);
1028:                    container.setLayout(new BorderLayout());
1029:
1030:                    closer = new Closer();
1031:                }
1032:
1033:                public Component add(Component c) {
1034:                    container.add(c, BorderLayout.CENTER);
1035:                    return c;
1036:                }
1037:
1038:                void setCloser(Runnable action, int time) {
1039:                    closer.set(action, time);
1040:                }
1041:
1042:                // Must be executed on EDT.
1043:                protected void show(Point corner, int indent) {
1044:                    assert SunToolkit
1045:                            .isDispatchThreadForAppContext(InfoWindow.this );
1046:
1047:                    pack();
1048:
1049:                    Dimension size = getSize();
1050:                    // TODO: When 6356322 is fixed we should get screen bounds in
1051:                    // this way: eframe.getGraphicsConfiguration().getBounds().
1052:                    Dimension scrSize = Toolkit.getDefaultToolkit()
1053:                            .getScreenSize();
1054:
1055:                    if (corner.x < scrSize.width / 2
1056:                            && corner.y < scrSize.height / 2) { // 1st square
1057:                        setLocation(corner.x + indent, corner.y + indent);
1058:
1059:                    } else if (corner.x >= scrSize.width / 2
1060:                            && corner.y < scrSize.height / 2) { // 2nd square
1061:                        setLocation(corner.x - indent - size.width, corner.y
1062:                                + indent);
1063:
1064:                    } else if (corner.x < scrSize.width / 2
1065:                            && corner.y >= scrSize.height / 2) { // 3rd square
1066:                        setLocation(corner.x + indent, corner.y - indent
1067:                                - size.height);
1068:
1069:                    } else if (corner.x >= scrSize.width / 2
1070:                            && corner.y >= scrSize.height / 2) { // 4th square
1071:                        setLocation(corner.x - indent - size.width, corner.y
1072:                                - indent - size.height);
1073:                    }
1074:
1075:                    InfoWindow.super .show();
1076:                    InfoWindow.this .closer.schedule();
1077:                }
1078:
1079:                public void hide() {
1080:                    closer.close();
1081:                }
1082:
1083:                class Closer implements  Runnable {
1084:                    Runnable action;
1085:                    int time;
1086:
1087:                    public void run() {
1088:                        doClose();
1089:                    }
1090:
1091:                    void set(Runnable action, int time) {
1092:                        this .action = action;
1093:                        this .time = time;
1094:                    }
1095:
1096:                    void schedule() {
1097:                        XToolkit.schedule(this , time);
1098:                    }
1099:
1100:                    void close() {
1101:                        XToolkit.remove(this );
1102:                        doClose();
1103:                    }
1104:
1105:                    // WARNING: this method may be executed on Toolkit thread.
1106:                    private void doClose() {
1107:                        SunToolkit.executeOnEventHandlerThread(InfoWindow.this ,
1108:                                new Runnable() {
1109:                                    public void run() {
1110:                                        InfoWindow.super.hide();
1111:                                        invalidate();
1112:                                        if (action != null) {
1113:                                            action.run();
1114:                                        }
1115:                                    }
1116:                                });
1117:                    }
1118:                }
1119:            }
1120:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.