KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > jdic > tray > internal > impl > WinTrayIconService


1 /*
2  * Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is
3  * subject to license terms.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the Lesser GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA.
19  */

20
21 package org.jdesktop.jdic.tray.internal.impl;
22
23
24 /**
25  * The <code>WinTrayIconService</code> interface is the contract for a Windows
26  * <code>TrayIcon</code> implementation.
27  *
28  */

29
30 import org.jdesktop.jdic.tray.internal.TrayIconService;
31 import java.awt.*;
32 import java.awt.image.*;
33 import javax.swing.*;
34 import javax.swing.event.PopupMenuListener JavaDoc;
35 import javax.swing.event.PopupMenuEvent JavaDoc;
36 import java.awt.event.*;
37 import java.lang.reflect.InvocationTargetException JavaDoc;
38 import java.lang.reflect.Method JavaDoc;
39 import java.util.*;
40
41 import sun.awt.image.IntegerComponentRaster;
42
43
44 public class WinTrayIconService implements TrayIconService{
45
46     private JPopupMenu menu;
47     private Icon icon;
48     private boolean autoSize;
49     private byte[] caption = "JDIC TrayIcon".getBytes();
50
51     private long hicon;
52     private Image oldIconImage;
53     static private HashMap map = new HashMap();
54
55     private LinkedList actionList = new LinkedList();
56     private LinkedList balloonListeners = new LinkedList();
57
58     static int noIcons;
59
60     int iconID;
61
62     AnimationObserver observer;
63
64     private final int WINDOWS_TASKBAR_ICON_WIDTH = 16;
65     private final int WINDOWS_TASKBAR_ICON_HEIGHT = 16;
66
67     static class PopupParent extends JDialog{
68         public PopupParent(){
69             super((Frame)null, "JDIC Tray Icon");
70             try{
71                 Method JavaDoc setAlwaysOnTop = this.getClass().getMethod("setAlwaysOnTop", new Class JavaDoc[]{boolean.class});
72                 setAlwaysOnTop.invoke(this, new Object JavaDoc[]{Boolean.TRUE});
73             }catch(NoSuchMethodException JavaDoc e){
74             }catch(Exception JavaDoc e){
75                 e.printStackTrace();
76             }
77             this.setUndecorated(true);
78             this.setBounds(0, 0, 0, 0);
79         }
80     }
81     static PopupParent popupParentFrame;
82     
83     boolean created;
84
85     static {
86         Runtime.getRuntime().addShutdownHook(new Thread JavaDoc() {
87             public void run() {
88                 removeAllIcons();
89             }
90         });
91     }
92
93     public static void removeAllIcons() {
94         for (int i = 0; i < noIcons; i++) {
95             removeIcon(i);
96         }
97     }
98
99     public WinTrayIconService() {
100         iconID = noIcons++;
101         if(popupParentFrame == null){
102             popupParentFrame = new PopupParent();
103         }
104     }
105
106     private native long createIconIndirect(int[] rData, byte[] andMask,
107             int nScanStride, int width,
108             int height, int xHotSpot,
109             int yHotSpot);
110
111     private native void createIcon(long hIcon, int id, byte[] tooltip);
112
113     private native void updateNativeIcon(long hIcon, int id, byte[] tooltip);
114     
115     private native void showBalloonMessage(long hIcon, int id, byte[] caption, byte[] text, int type);
116     
117     private native void deleteHIcon(long hIcon);
118     
119     private native int[] getRectangleOnScreen(int id);
120
121     private static native void removeIcon(int id);
122     
123     public void showBalloonMessage(String JavaDoc caption, String JavaDoc text, int type){
124         byte[] batitle = caption == null ? new byte[0]: caption.getBytes();
125         byte[] bacontent = text == null ? new byte[0] : text.getBytes();
126         showBalloonMessage(hicon, iconID, batitle, bacontent, type);
127     }
128     
129     public void addNotify() {
130         if(popupParentFrame == null){
131             popupParentFrame = new PopupParent();
132         }
133         popupParentFrame.pack();
134         map.put(new Integer JavaDoc(iconID), this);
135
136         observer = new AnimationObserver();
137         updateIcon(null);
138         created = true;
139     }
140
141     private void updateBufferedImage() {
142     }
143
144     public void setPopupMenu(JPopupMenu m) {
145         menu = m;
146         if (menu != null) {
147             menu.setLightWeightPopupEnabled(false);
148
149             menu.addPopupMenuListener(new PopupMenuListener JavaDoc() {
150                 public void popupMenuWillBecomeVisible(PopupMenuEvent JavaDoc e) {
151                 }
152
153                 public void popupMenuWillBecomeInvisible(PopupMenuEvent JavaDoc e) {
154                     popupParentFrame.setVisible(false);
155                     popupParentFrame.toBack();
156                 }
157
158                 public void popupMenuCanceled(PopupMenuEvent JavaDoc e) {
159                 }
160             });
161
162             // in jdk1.4, the popup menu is still visible after the invoker window lost focus.
163
popupParentFrame.addWindowFocusListener(new WindowFocusListener() {
164                 public void windowGainedFocus(WindowEvent e) {
165                 }
166
167                 public void windowLostFocus(WindowEvent e) {
168                     menu.setVisible(false);
169                 }
170             });
171
172         }
173     }
174
175     protected long createNativeIcon(BufferedImage bimage, int w, int h,
176             int xHotSpot, int yHotSpot) {
177
178         int pixels[] = ((DataBufferInt) bimage.getRaster().getDataBuffer()).getData();
179         Raster raster = bimage.getRaster();
180         byte[] andMask = new byte[(w * h) / 8];
181         int npixels = pixels.length;
182
183         for (int i = 0; i < npixels; i++) {
184             int ibyte = i / 8;
185             int omask = 1 << (7 - (i % 8));
186
187             if ((pixels[i] & 0xff000000) == 0) {
188                 // Transparent bit
189
if (ibyte < andMask.length) {
190                     andMask[ibyte] |= omask;
191                 }
192             }
193         } {
194             int ficW = raster.getWidth();
195
196             if (raster instanceof IntegerComponentRaster) {
197                 ficW = ((IntegerComponentRaster) raster).getScanlineStride();
198             }
199             return createIconIndirect(((DataBufferInt) bimage.getRaster().getDataBuffer()).getData(),
200                     andMask, ficW, raster.getWidth(), raster.getHeight(),
201                     xHotSpot, yHotSpot);
202         }
203     }
204
205     public void processEvent(int mouseState, int x, int y) {
206         
207         switch (mouseState) {
208         case 0x200: // WM_MOUSEMOVE
209
break;
210
211         case 0x202: // WM_LBUTTONUP
212
ListIterator li = actionList.listIterator(0);
213             ActionListener al;
214
215             while (li.hasNext()) {
216                 al = (ActionListener) li.next();
217                 al.actionPerformed(new ActionEvent(this,
218                         ActionEvent.ACTION_PERFORMED, "PressAction",
219                         System.currentTimeMillis(), 0));
220             }
221             break;
222
223         case 0x205: // WM_RBUTTONUP
224
if (menu != null) {
225                 Point p = new Point(x, y);
226                 Dimension d = menu.getPreferredSize();
227                 Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
228                 p.x = p.x + d.width > s.width ? p.x - d.width : p.x;
229                 p.y = p.y + d.height > s.height ? p.y - d.height : p.y;
230                 popupParentFrame.setVisible(true);
231                 menu.show(popupParentFrame.getContentPane(), p.x, p.y);
232                 popupParentFrame.toFront();
233             }
234             break;
235         case 0x0405: // NIN_BALLOONUSERCLICK
236
ListIterator ml = balloonListeners.listIterator(0);
237             ActionListener listener;
238
239             while (ml.hasNext()) {
240                 listener = (ActionListener) ml.next();
241                 listener.actionPerformed(new ActionEvent(this,
242                         ActionEvent.ACTION_PERFORMED, "PressAction",
243                         System.currentTimeMillis(), 0));
244             }
245             break;
246         }
247     }
248
249     public synchronized static void notifyEvent(int id, final int mouseState, final int x, final int y) {
250         final WinTrayIconService instance = (WinTrayIconService) map.get(new Integer JavaDoc(id));
251         if(instance == null)
252             return;
253         try {
254             EventQueue.invokeLater(new Runnable JavaDoc() {
255                 public void run() {
256                     instance.processEvent(mouseState, x, y);
257                 }
258             });
259         } catch (Exception JavaDoc e) {
260             e.printStackTrace();
261         }
262     }
263
264     private void updateIcon(Image iconImage) {
265         Graphics2D g;
266         if (icon != null) {
267             if (iconImage == null) {
268                 iconImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
269                 g = (Graphics2D) ((BufferedImage)iconImage).getGraphics();
270                 g.setComposite(AlphaComposite.Src);
271                 icon.paintIcon(observer, g, 0, 0);
272                 oldIconImage = iconImage;
273             }
274
275             // Temp image is used for scaling.
276

277             BufferedImage tmpImage = new BufferedImage(WINDOWS_TASKBAR_ICON_WIDTH, WINDOWS_TASKBAR_ICON_HEIGHT,
278                     BufferedImage.TYPE_INT_ARGB);
279             g = (Graphics2D) tmpImage.getGraphics();
280
281             try {
282                 g.setComposite(AlphaComposite.Src);
283                 g.drawImage(iconImage, 0, 0, WINDOWS_TASKBAR_ICON_WIDTH,WINDOWS_TASKBAR_ICON_HEIGHT, null);
284             } finally {
285                 g.dispose();
286             }
287             tmpImage.flush();
288
289             // Free old icon.
290
if (hicon != 0) {
291                 deleteHIcon(hicon);
292             }
293             hicon = createNativeIcon(tmpImage, WINDOWS_TASKBAR_ICON_WIDTH, WINDOWS_TASKBAR_ICON_HEIGHT, 0, 0);
294             if (created) {
295                 updateNativeIcon(hicon, iconID, caption);
296             }
297             else {
298                 createIcon(hicon, iconID, caption);
299             }
300         }
301     }
302
303     private class AnimationObserver extends Component {
304         boolean update = true;
305
306         public void setUpdate(boolean b) {
307             update = b;
308         }
309         public boolean imageUpdate(Image img,
310                 int infoflags,
311                 int x,
312                 int y,
313                 int width,
314                 int height) {
315
316             if (update && created) {
317                 updateIcon(img);
318             }
319             return update;
320         }
321     }
322
323     public void setIcon(final Icon i) {
324         icon = i;
325         if (created) {
326             observer.setUpdate(false);
327             observer = new AnimationObserver();
328             updateIcon(null);
329         }
330     }
331
332     public void setCaption(String JavaDoc s) {
333         caption = (s == null ? "" : s ).getBytes();
334         if (created) {
335             observer.setUpdate(false);
336             observer = new AnimationObserver();
337             updateIcon(null);
338         }
339     }
340
341     public void setIconAutoSize(boolean b) {
342         // Not necessary for Win32 impl.
343
}
344
345     public void addActionListener(ActionListener l) {
346         actionList.add(l);
347     }
348
349     public void removeActionListener(ActionListener l) {
350         actionList.remove(l);
351     }
352
353     public Point getLocationOnScreen() {
354         int[] rect = this.getRectangleOnScreen(iconID);
355         return new Point(rect[0], rect[1]);
356     }
357
358     void remove() {
359         removeIcon(iconID);
360         // Free old icon.
361
if (hicon != 0) {
362             deleteHIcon(hicon);
363         }
364         map.remove(new Integer JavaDoc(iconID));
365         created = false;
366         if(map.size() == 0){
367             popupParentFrame.dispose();
368             popupParentFrame = null;
369         }
370     }
371     private static void restartTaskbar() {
372             Iterator keyiterator = map.keySet().iterator();
373             while (keyiterator.hasNext()) {
374                 WinTrayIconService iconService = (WinTrayIconService)map.get(keyiterator.next());
375                 if (iconService.created) {
376                     iconService.remove();
377                     iconService.addNotify();
378                 }
379             }
380         }
381
382     public void addBalloonActionListener(ActionListener al) {
383         balloonListeners.add(al);
384     }
385     
386     public void removeBalloonActionListener(ActionListener al) {
387         balloonListeners.remove(al);
388     }
389 }
390
Popular Tags