History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/SystemTray.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/SystemTray.java+504−0
@@ -0,0 +1,504 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt;
27
28import java.util.Vector;
29import java.awt.peer.SystemTrayPeer;
30import java.beans.PropertyChangeListener;
31import java.beans.PropertyChangeSupport;
32import sun.awt.AppContext;
33import sun.awt.SunToolkit;
34import sun.awt.HeadlessToolkit;
35import sun.security.util.SecurityConstants;
36
37/**
38 * The <code>SystemTray</code> class represents the system tray for a
39 * desktop. On Microsoft Windows it is referred to as the "Taskbar
40 * Status Area", on Gnome it is referred to as the "Notification
41 * Area", on KDE it is referred to as the "System Tray". The system
42 * tray is shared by all applications running on the desktop.
43 *
44 * <p> On some platforms the system tray may not be present or may not
45 * be supported, in this case {@link SystemTray#getSystemTray()}
46 * throws {@link UnsupportedOperationException}. To detect whether the
47 * system tray is supported, use {@link SystemTray#isSupported}.
48 *
49 * <p>The <code>SystemTray</code> may contain one or more {@link
50 * TrayIcon TrayIcons}, which are added to the tray using the {@link
51 * #add} method, and removed when no longer needed, using the
52 * {@link #remove}. <code>TrayIcon</code> consists of an
53 * image, a popup menu and a set of associated listeners. Please see
54 * the {@link TrayIcon} class for details.
55 *
56 * <p>Every Java application has a single <code>SystemTray</code>
57 * instance that allows the app to interface with the system tray of
58 * the desktop while the app is running. The <code>SystemTray</code>
59 * instance can be obtained from the {@link #getSystemTray} method.
60 * An application may not create its own instance of
61 * <code>SystemTray</code>.
62 *
63 * <p>The following code snippet demonstrates how to access
64 * and customize the system tray:
65 * <code>
66 * <pre>
67 * {@link TrayIcon} trayIcon = null;
68 * if (SystemTray.isSupported()) {
69 * // get the SystemTray instance
70 * SystemTray tray = SystemTray.{@link #getSystemTray};
71 * // load an image
72 * {@link java.awt.Image} image = {@link java.awt.Toolkit#getImage(String) Toolkit.getDefaultToolkit().getImage}(...);
73 * // create a action listener to listen for default action executed on the tray icon
74 * {@link java.awt.event.ActionListener} listener = new {@link java.awt.event.ActionListener ActionListener}() {
75 * public void {@link java.awt.event.ActionListener#actionPerformed actionPerformed}({@link java.awt.event.ActionEvent} e) {
76 * // execute default action of the application
77 * // ...
78 * }
79 * };
80 * // create a popup menu
81 * {@link java.awt.PopupMenu} popup = new {@link java.awt.PopupMenu#PopupMenu PopupMenu}();
82 * // create menu item for the default action
83 * MenuItem defaultItem = new MenuItem(...);
84 * defaultItem.addActionListener(listener);
85 * popup.add(defaultItem);
86 * /// ... add other items
87 * // construct a TrayIcon
88 * trayIcon = new {@link TrayIcon#TrayIcon(java.awt.Image, String, java.awt.PopupMenu) TrayIcon}(image, "Tray Demo", popup);
89 * // set the TrayIcon properties
90 * trayIcon.{@link TrayIcon#addActionListener(java.awt.event.ActionListener) addActionListener}(listener);
91 * // ...
92 * // add the tray image
93 * try {
94 * tray.{@link SystemTray#add(TrayIcon) add}(trayIcon);
95 * } catch (AWTException e) {
96 * System.err.println(e);
97 * }
98 * // ...
99 * } else {
100 * // disable tray option in your application or
101 * // perform other actions
102 * ...
103 * }
104 * // ...
105 * // some time later
106 * // the application state has changed - update the image
107 * if (trayIcon != null) {
108 * trayIcon.{@link TrayIcon#setImage(java.awt.Image) setImage}(updatedImage);
109 * }
110 * // ...
111 * </pre>
112 * </code>
113 *
114 * @since 1.6
115 * @see TrayIcon
116 *
117 * @author Bino George
118 * @author Denis Mikhalkin
119 * @author Sharon Zakhour
120 * @author Anton Tarasov
121 */
122public class SystemTray {
123 private static SystemTray systemTray;
124 private int currentIconID = 0; // each TrayIcon added gets a unique ID
125
126 transient private SystemTrayPeer peer;
127
128 private static final TrayIcon[] EMPTY_TRAY_ARRAY = new TrayIcon[0];
129
130 /**
131 * Private <code>SystemTray</code> constructor.
132 *
133 */
134 private SystemTray() {
135 addNotify();
136 }
137
138 /**
139 * Gets the <code>SystemTray</code> instance that represents the
140 * desktop's tray area. This always returns the same instance per
141 * application. On some platforms the system tray may not be
142 * supported. You may use the {@link #isSupported} method to
143 * check if the system tray is supported.
144 *
145 * <p>If a SecurityManager is installed, the AWTPermission
146 * {@code accessSystemTray} must be granted in order to get the
147 * {@code SystemTray} instance. Otherwise this method will throw a
148 * SecurityException.
149 *
150 * @return the <code>SystemTray</code> instance that represents
151 * the desktop's tray area
152 * @throws UnsupportedOperationException if the system tray isn't
153 * supported by the current platform
154 * @throws HeadlessException if
155 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
156 * @throws SecurityException if {@code accessSystemTray} permission
157 * is not granted
158 * @see #add(TrayIcon)
159 * @see TrayIcon
160 * @see #isSupported
161 * @see SecurityManager#checkPermission
162 * @see AWTPermission
163 */
164 public static SystemTray getSystemTray() {
165 checkSystemTrayAllowed();
166 if (GraphicsEnvironment.isHeadless()) {
167 throw new HeadlessException();
168 }
169
170 initializeSystemTrayIfNeeded();
171
172 if (!isSupported()) {
173 throw new UnsupportedOperationException(
174 "The system tray is not supported on the current platform.");
175 }
176
177 return systemTray;
178 }
179
180 /**
181 * Returns whether the system tray is supported on the current
182 * platform. In addition to displaying the tray icon, minimal
183 * system tray support includes either a popup menu (see {@link
184 * TrayIcon#setPopupMenu(PopupMenu)}) or an action event (see
185 * {@link TrayIcon#addActionListener(ActionListener)}).
186 *
187 * <p>Developers should not assume that all of the system tray
188 * functionality is supported. To guarantee that the tray icon's
189 * default action is always accessible, add the default action to
190 * both the action listener and the popup menu. See the {@link
191 * SystemTray example} for an example of how to do this.
192 *
193 * <p><b>Note</b>: When implementing <code>SystemTray</code> and
194 * <code>TrayIcon</code> it is <em>strongly recommended</em> that
195 * you assign different gestures to the popup menu and an action
196 * event. Overloading a gesture for both purposes is confusing
197 * and may prevent the user from accessing one or the other.
198 *
199 * @see #getSystemTray
200 * @return <code>false</code> if no system tray access is supported; this
201 * method returns <code>true</code> if the minimal system tray access is
202 * supported but does not guarantee that all system tray
203 * functionality is supported for the current platform
204 */
205 public static boolean isSupported() {
206 Toolkit toolkit = Toolkit.getDefaultToolkit();
207 if (toolkit instanceof SunToolkit) {
208 // connecting tray to native resource
209 initializeSystemTrayIfNeeded();
210 return ((SunToolkit)toolkit).isTraySupported();
211 } else if (toolkit instanceof HeadlessToolkit) {
212 // skip initialization as the init routine
213 // throws HeadlessException
214 return ((HeadlessToolkit)toolkit).isTraySupported();
215 } else {
216 return false;
217 }
218 }
219
220 /**
221 * Adds a <code>TrayIcon</code> to the <code>SystemTray</code>.
222 * The tray icon becomes visible in the system tray once it is
223 * added. The order in which icons are displayed in a tray is not
224 * specified - it is platform and implementation-dependent.
225 *
226 * <p> All icons added by the application are automatically
227 * removed from the <code>SystemTray</code> upon application exit
228 * and also when the desktop system tray becomes unavailable.
229 *
230 * @param trayIcon the <code>TrayIcon</code> to be added
231 * @throws NullPointerException if <code>trayIcon</code> is
232 * <code>null</code>
233 * @throws IllegalArgumentException if the same instance of
234 * a <code>TrayIcon</code> is added more than once
235 * @throws AWTException if the desktop system tray is missing
236 * @see #remove(TrayIcon)
237 * @see #getSystemTray
238 * @see TrayIcon
239 * @see java.awt.Image
240 */
241 public void add(TrayIcon trayIcon) throws AWTException {
242 if (trayIcon == null) {
243 throw new NullPointerException("adding null TrayIcon");
244 }
245 TrayIcon[] oldArray = null, newArray = null;
246 Vector<TrayIcon> icons = null;
247 synchronized (this) {
248 oldArray = systemTray.getTrayIcons();
249 icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class);
250 if (icons == null) {
251 icons = new Vector<TrayIcon>(3);
252 AppContext.getAppContext().put(TrayIcon.class, icons);
253
254 } else if (icons.contains(trayIcon)) {
255 throw new IllegalArgumentException("adding TrayIcon that is already added");
256 }
257 icons.add(trayIcon);
258 newArray = systemTray.getTrayIcons();
259
260 trayIcon.setID(++currentIconID);
261 }
262 try {
263 trayIcon.addNotify();
264 } catch (AWTException e) {
265 icons.remove(trayIcon);
266 throw e;
267 }
268 firePropertyChange("trayIcons", oldArray, newArray);
269 }
270
271 /**
272 * Removes the specified <code>TrayIcon</code> from the
273 * <code>SystemTray</code>.
274 *
275 * <p> All icons added by the application are automatically
276 * removed from the <code>SystemTray</code> upon application exit
277 * and also when the desktop system tray becomes unavailable.
278 *
279 * <p> If <code>trayIcon</code> is <code>null</code> or was not
280 * added to the system tray, no exception is thrown and no action
281 * is performed.
282 *
283 * @param trayIcon the <code>TrayIcon</code> to be removed
284 * @see #add(TrayIcon)
285 * @see TrayIcon
286 */
287 public void remove(TrayIcon trayIcon) {
288 if (trayIcon == null) {
289 return;
290 }
291 TrayIcon[] oldArray = null, newArray = null;
292 synchronized (this) {
293 oldArray = systemTray.getTrayIcons();
294 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class);
295 // TrayIcon with no peer is not contained in the array.
296 if (icons == null || !icons.remove(trayIcon)) {
297 return;
298 }
299 trayIcon.removeNotify();
300 newArray = systemTray.getTrayIcons();
301 }
302 firePropertyChange("trayIcons", oldArray, newArray);
303 }
304
305 /**
306 * Returns an array of all icons added to the tray by this
307 * application. You can't access the icons added by another
308 * application. Some browsers partition applets in different
309 * code bases into separate contexts, and establish walls between
310 * these contexts. In such a scenario, only the tray icons added
311 * from this context will be returned.
312 *
313 * <p> The returned array is a copy of the actual array and may be
314 * modified in any way without affecting the system tray. To
315 * remove a <code>TrayIcon</code> from the
316 * <code>SystemTray</code>, use the {@link
317 * #remove(TrayIcon)} method.
318 *
319 * @return an array of all tray icons added to this tray, or an
320 * empty array if none has been added
321 * @see #add(TrayIcon)
322 * @see TrayIcon
323 */
324 public TrayIcon[] getTrayIcons() {
325 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class);
326 if (icons != null) {
327 return (TrayIcon[])icons.toArray(new TrayIcon[icons.size()]);
328 }
329 return EMPTY_TRAY_ARRAY;
330 }
331
332 /**
333 * Returns the size, in pixels, of the space that a tray icon will
334 * occupy in the system tray. Developers may use this methods to
335 * acquire the preferred size for the image property of a tray icon
336 * before it is created. For convenience, there is a similar
337 * method {@link TrayIcon#getSize} in the <code>TrayIcon</code> class.
338 *
339 * @return the default size of a tray icon, in pixels
340 * @see TrayIcon#setImageAutoSize(boolean)
341 * @see java.awt.Image
342 * @see TrayIcon#getSize()
343 */
344 public Dimension getTrayIconSize() {
345 return peer.getTrayIconSize();
346 }
347
348 /**
349 * Adds a {@code PropertyChangeListener} to the list of listeners for the
350 * specific property. The following properties are currently supported:
351 * <p> </p>
352 * <table border=1 summary="SystemTray properties">
353 * <tr>
354 * <th>Property</th>
355 * <th>Description</th>
356 * </tr>
357 * <tr>
358 * <td>{@code trayIcons}</td>
359 * <td>The {@code SystemTray}'s array of {@code TrayIcon} objects.
360 * The array is accessed via the {@link #getTrayIcons} method.<br>
361 * This property is changed when a tray icon is added to (or removed
362 * from) the system tray.<br> For example, this property is changed
363 * when the system tray becomes unavailable on the desktop<br>
364 * and the tray icons are automatically removed.</td>
365 * </tr>
366 * <tr>
367 * <td>{@code systemTray}</td>
368 * <td>This property contains {@code SystemTray} instance when the system tray
369 * is available or <code>null</code> otherwise.<br> This property is changed
370 * when the system tray becomes available or unavailable on the desktop.<br>
371 * The property is accessed by the {@link #getSystemTray} method.</td>
372 * </tr>
373 * </table>
374 * <p> </p>
375 * The {@code listener} listens to property changes only in this context.
376 * <p>
377 * If {@code listener} is {@code null}, no exception is thrown
378 * and no action is performed.
379 *
380 * @param propertyName the specified property
381 * @param listener the property change listener to be added
382 *
383 * @see #removePropertyChangeListener
384 * @see #getPropertyChangeListeners
385 */
386 public synchronized void addPropertyChangeListener(String propertyName,
387 PropertyChangeListener listener)
388 {
389 if (listener == null) {
390 return;
391 }
392 getCurrentChangeSupport().addPropertyChangeListener(propertyName, listener);
393 }
394
395 /**
396 * Removes a {@code PropertyChangeListener} from the listener list
397 * for a specific property.
398 * <p>
399 * The {@code PropertyChangeListener} must be from this context.
400 * <p>
401 * If {@code propertyName} or {@code listener} is {@code null} or invalid,
402 * no exception is thrown and no action is taken.
403 *
404 * @param propertyName the specified property
405 * @param listener the PropertyChangeListener to be removed
406 *
407 * @see #addPropertyChangeListener
408 * @see #getPropertyChangeListeners
409 */
410 public synchronized void removePropertyChangeListener(String propertyName,
411 PropertyChangeListener listener)
412 {
413 if (listener == null) {
414 return;
415 }
416 getCurrentChangeSupport().removePropertyChangeListener(propertyName, listener);
417 }
418
419 /**
420 * Returns an array of all the listeners that have been associated
421 * with the named property.
422 * <p>
423 * Only the listeners in this context are returned.
424 *
425 * @param propertyName the specified property
426 * @return all of the {@code PropertyChangeListener}s associated with
427 * the named property; if no such listeners have been added or
428 * if {@code propertyName} is {@code null} or invalid, an empty
429 * array is returned
430 *
431 * @see #addPropertyChangeListener
432 * @see #removePropertyChangeListener
433 */
434 public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
435 return getCurrentChangeSupport().getPropertyChangeListeners(propertyName);
436 }
437
438
439 // ***************************************************************
440 // ***************************************************************
441
442
443 /**
444 * Support for reporting bound property changes for Object properties.
445 * This method can be called when a bound property has changed and it will
446 * send the appropriate PropertyChangeEvent to any registered
447 * PropertyChangeListeners.
448 *
449 * @param propertyName the property whose value has changed
450 * @param oldValue the property's previous value
451 * @param newValue the property's new value
452 */
453 private void firePropertyChange(String propertyName,
454 Object oldValue, Object newValue)
455 {
456 if (oldValue != null && newValue != null && oldValue.equals(newValue)) {
457 return;
458 }
459 getCurrentChangeSupport().firePropertyChange(propertyName, oldValue, newValue);
460 }
461
462 /**
463 * Returns the current PropertyChangeSupport instance for the
464 * calling thread's context.
465 *
466 * @return this thread's context's PropertyChangeSupport
467 */
468 private synchronized PropertyChangeSupport getCurrentChangeSupport() {
469 PropertyChangeSupport changeSupport =
470 (PropertyChangeSupport)AppContext.getAppContext().get(SystemTray.class);
471
472 if (changeSupport == null) {
473 changeSupport = new PropertyChangeSupport(this);
474 AppContext.getAppContext().put(SystemTray.class, changeSupport);
475 }
476 return changeSupport;
477 }
478
479 synchronized void addNotify() {
480 if (peer == null) {
481 Toolkit toolkit = Toolkit.getDefaultToolkit();
482 if (toolkit instanceof SunToolkit) {
483 peer = ((SunToolkit)Toolkit.getDefaultToolkit()).createSystemTray(this);
484 } else if (toolkit instanceof HeadlessToolkit) {
485 peer = ((HeadlessToolkit)Toolkit.getDefaultToolkit()).createSystemTray(this);
486 }
487 }
488 }
489
490 static void checkSystemTrayAllowed() {
491 SecurityManager security = System.getSecurityManager();
492 if (security != null) {
493 security.checkPermission(SecurityConstants.AWT.ACCESS_SYSTEM_TRAY_PERMISSION);
494 }
495 }
496
497 private static void initializeSystemTrayIfNeeded() {
498 synchronized (SystemTray.class) {
499 if (systemTray == null) {
500 systemTray = new SystemTray();
501 }
502 }
503 }
504}