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 26 package java.awt; 27 28 import java.util.Vector; 29 import java.awt.peer.SystemTrayPeer; 30 import java.beans.PropertyChangeListener; 31 import java.beans.PropertyChangeSupport; 32 import sun.awt.AppContext; 33 import sun.awt.SunToolkit; 34 import sun.awt.HeadlessToolkit; 35 import sun.awt.AWTAccessor; 36 import sun.awt.AWTPermissions; 37 38 /** 39 * The <code>SystemTray</code> class represents the system tray for a 40 * desktop. On Microsoft Windows it is referred to as the "Taskbar 41 * Status Area", on Gnome it is referred to as the "Notification 42 * Area", on KDE it is referred to as the "System Tray". The system 43 * tray is shared by all applications running on the desktop. 44 * 45 * <p> On some platforms the system tray may not be present or may not 46 * be supported, in this case {@link SystemTray#getSystemTray()} 47 * throws {@link UnsupportedOperationException}. To detect whether the 48 * system tray is supported, use {@link SystemTray#isSupported}. 49 * 50 * <p>The <code>SystemTray</code> may contain one or more {@link 51 * TrayIcon TrayIcons}, which are added to the tray using the {@link 52 * #add} method, and removed when no longer needed, using the 53 * {@link #remove}. <code>TrayIcon</code> consists of an 54 * image, a popup menu and a set of associated listeners. Please see 55 * the {@link TrayIcon} class for details. 56 * 57 * <p>Every Java application has a single <code>SystemTray</code> 58 * instance that allows the app to interface with the system tray of 59 * the desktop while the app is running. The <code>SystemTray</code> 60 * instance can be obtained from the {@link #getSystemTray} method. 61 * An application may not create its own instance of 62 * <code>SystemTray</code>. 63 * 64 * <p>The following code snippet demonstrates how to access 65 * and customize the system tray: 66 * <pre> 67 * <code> 68 * {@link TrayIcon} trayIcon = null; 69 * if (SystemTray.isSupported()) { 70 * // get the SystemTray instance 71 * SystemTray tray = SystemTray.{@link #getSystemTray}; 72 * // load an image 73 * {@link java.awt.Image} image = {@link java.awt.Toolkit#getImage(String) Toolkit.getDefaultToolkit().getImage}(...); 74 * // create a action listener to listen for default action executed on the tray icon 75 * {@link java.awt.event.ActionListener} listener = new {@link java.awt.event.ActionListener ActionListener}() { 76 * public void {@link java.awt.event.ActionListener#actionPerformed actionPerformed}({@link java.awt.event.ActionEvent} e) { 77 * // execute default action of the application 78 * // ... 79 * } 80 * }; 81 * // create a popup menu 82 * {@link java.awt.PopupMenu} popup = new {@link java.awt.PopupMenu#PopupMenu PopupMenu}(); 124 private static SystemTray systemTray; 125 private int currentIconID = 0; // each TrayIcon added gets a unique ID 126 127 private transient SystemTrayPeer peer; 128 129 private static final TrayIcon[] EMPTY_TRAY_ARRAY = new TrayIcon[0]; 130 131 static { 132 AWTAccessor.setSystemTrayAccessor( 133 new AWTAccessor.SystemTrayAccessor() { 134 public void firePropertyChange(SystemTray tray, 135 String propertyName, 136 Object oldValue, 137 Object newValue) { 138 tray.firePropertyChange(propertyName, oldValue, newValue); 139 } 140 }); 141 } 142 143 /** 144 * Private <code>SystemTray</code> constructor. 145 * 146 */ 147 private SystemTray() { 148 addNotify(); 149 } 150 151 /** 152 * Gets the <code>SystemTray</code> instance that represents the 153 * desktop's tray area. This always returns the same instance per 154 * application. On some platforms the system tray may not be 155 * supported. You may use the {@link #isSupported} method to 156 * check if the system tray is supported. 157 * 158 * <p>If a SecurityManager is installed, the AWTPermission 159 * {@code accessSystemTray} must be granted in order to get the 160 * {@code SystemTray} instance. Otherwise this method will throw a 161 * SecurityException. 162 * 163 * @return the <code>SystemTray</code> instance that represents 164 * the desktop's tray area 165 * @throws UnsupportedOperationException if the system tray isn't 166 * supported by the current platform 167 * @throws HeadlessException if 168 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 169 * @throws SecurityException if {@code accessSystemTray} permission 170 * is not granted 171 * @see #add(TrayIcon) 172 * @see TrayIcon 173 * @see #isSupported 174 * @see SecurityManager#checkPermission 175 * @see AWTPermission 176 */ 177 public static SystemTray getSystemTray() { 178 checkSystemTrayAllowed(); 179 if (GraphicsEnvironment.isHeadless()) { 180 throw new HeadlessException(); 181 } 182 183 initializeSystemTrayIfNeeded(); 184 185 if (!isSupported()) { 186 throw new UnsupportedOperationException( 187 "The system tray is not supported on the current platform."); 188 } 189 190 return systemTray; 191 } 192 193 /** 194 * Returns whether the system tray is supported on the current 195 * platform. In addition to displaying the tray icon, minimal 196 * system tray support includes either a popup menu (see {@link 197 * TrayIcon#setPopupMenu(PopupMenu)}) or an action event (see 198 * {@link TrayIcon#addActionListener(ActionListener)}). 199 * 200 * <p>Developers should not assume that all of the system tray 201 * functionality is supported. To guarantee that the tray icon's 202 * default action is always accessible, add the default action to 203 * both the action listener and the popup menu. See the {@link 204 * SystemTray example} for an example of how to do this. 205 * 206 * <p><b>Note</b>: When implementing <code>SystemTray</code> and 207 * <code>TrayIcon</code> it is <em>strongly recommended</em> that 208 * you assign different gestures to the popup menu and an action 209 * event. Overloading a gesture for both purposes is confusing 210 * and may prevent the user from accessing one or the other. 211 * 212 * @see #getSystemTray 213 * @return <code>false</code> if no system tray access is supported; this 214 * method returns <code>true</code> if the minimal system tray access is 215 * supported but does not guarantee that all system tray 216 * functionality is supported for the current platform 217 */ 218 public static boolean isSupported() { 219 Toolkit toolkit = Toolkit.getDefaultToolkit(); 220 if (toolkit instanceof SunToolkit) { 221 // connecting tray to native resource 222 initializeSystemTrayIfNeeded(); 223 return ((SunToolkit)toolkit).isTraySupported(); 224 } else if (toolkit instanceof HeadlessToolkit) { 225 // skip initialization as the init routine 226 // throws HeadlessException 227 return ((HeadlessToolkit)toolkit).isTraySupported(); 228 } else { 229 return false; 230 } 231 } 232 233 /** 234 * Adds a <code>TrayIcon</code> to the <code>SystemTray</code>. 235 * The tray icon becomes visible in the system tray once it is 236 * added. The order in which icons are displayed in a tray is not 237 * specified - it is platform and implementation-dependent. 238 * 239 * <p> All icons added by the application are automatically 240 * removed from the <code>SystemTray</code> upon application exit 241 * and also when the desktop system tray becomes unavailable. 242 * 243 * @param trayIcon the <code>TrayIcon</code> to be added 244 * @throws NullPointerException if <code>trayIcon</code> is 245 * <code>null</code> 246 * @throws IllegalArgumentException if the same instance of 247 * a <code>TrayIcon</code> is added more than once 248 * @throws AWTException if the desktop system tray is missing 249 * @see #remove(TrayIcon) 250 * @see #getSystemTray 251 * @see TrayIcon 252 * @see java.awt.Image 253 */ 254 public void add(TrayIcon trayIcon) throws AWTException { 255 if (trayIcon == null) { 256 throw new NullPointerException("adding null TrayIcon"); 257 } 258 TrayIcon[] oldArray = null, newArray = null; 259 Vector<TrayIcon> icons = null; 260 synchronized (this) { 261 oldArray = systemTray.getTrayIcons(); 262 @SuppressWarnings("unchecked") 263 Vector<TrayIcon> tmp = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 264 icons = tmp; 265 if (icons == null) { 266 icons = new Vector<TrayIcon>(3); 267 AppContext.getAppContext().put(TrayIcon.class, icons); 268 269 } else if (icons.contains(trayIcon)) { 270 throw new IllegalArgumentException("adding TrayIcon that is already added"); 271 } 272 icons.add(trayIcon); 273 newArray = systemTray.getTrayIcons(); 274 275 trayIcon.setID(++currentIconID); 276 } 277 try { 278 trayIcon.addNotify(); 279 } catch (AWTException e) { 280 icons.remove(trayIcon); 281 throw e; 282 } 283 firePropertyChange("trayIcons", oldArray, newArray); 284 } 285 286 /** 287 * Removes the specified <code>TrayIcon</code> from the 288 * <code>SystemTray</code>. 289 * 290 * <p> All icons added by the application are automatically 291 * removed from the <code>SystemTray</code> upon application exit 292 * and also when the desktop system tray becomes unavailable. 293 * 294 * <p> If <code>trayIcon</code> is <code>null</code> or was not 295 * added to the system tray, no exception is thrown and no action 296 * is performed. 297 * 298 * @param trayIcon the <code>TrayIcon</code> to be removed 299 * @see #add(TrayIcon) 300 * @see TrayIcon 301 */ 302 public void remove(TrayIcon trayIcon) { 303 if (trayIcon == null) { 304 return; 305 } 306 TrayIcon[] oldArray = null, newArray = null; 307 synchronized (this) { 308 oldArray = systemTray.getTrayIcons(); 309 @SuppressWarnings("unchecked") 310 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 311 // TrayIcon with no peer is not contained in the array. 312 if (icons == null || !icons.remove(trayIcon)) { 313 return; 314 } 315 trayIcon.removeNotify(); 316 newArray = systemTray.getTrayIcons(); 317 } 318 firePropertyChange("trayIcons", oldArray, newArray); 319 } 320 321 /** 322 * Returns an array of all icons added to the tray by this 323 * application. You can't access the icons added by another 324 * application. Some browsers partition applets in different 325 * code bases into separate contexts, and establish walls between 326 * these contexts. In such a scenario, only the tray icons added 327 * from this context will be returned. 328 * 329 * <p> The returned array is a copy of the actual array and may be 330 * modified in any way without affecting the system tray. To 331 * remove a <code>TrayIcon</code> from the 332 * <code>SystemTray</code>, use the {@link 333 * #remove(TrayIcon)} method. 334 * 335 * @return an array of all tray icons added to this tray, or an 336 * empty array if none has been added 337 * @see #add(TrayIcon) 338 * @see TrayIcon 339 */ 340 public TrayIcon[] getTrayIcons() { 341 @SuppressWarnings("unchecked") 342 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 343 if (icons != null) { 344 return icons.toArray(new TrayIcon[icons.size()]); 345 } 346 return EMPTY_TRAY_ARRAY; 347 } 348 349 /** 350 * Returns the size, in pixels, of the space that a tray icon will 351 * occupy in the system tray. Developers may use this methods to 352 * acquire the preferred size for the image property of a tray icon 353 * before it is created. For convenience, there is a similar 354 * method {@link TrayIcon#getSize} in the <code>TrayIcon</code> class. 355 * 356 * @return the default size of a tray icon, in pixels 357 * @see TrayIcon#setImageAutoSize(boolean) 358 * @see java.awt.Image 359 * @see TrayIcon#getSize() 360 */ 361 public Dimension getTrayIconSize() { 362 return peer.getTrayIconSize(); 363 } 364 365 /** 366 * Adds a {@code PropertyChangeListener} to the list of listeners for the 367 * specific property. The following properties are currently supported: 368 * 369 * <table border=1 summary="SystemTray properties"> 370 * <tr> 371 * <th>Property</th> 372 * <th>Description</th> 373 * </tr> 374 * <tr> 375 * <td>{@code trayIcons}</td> 376 * <td>The {@code SystemTray}'s array of {@code TrayIcon} objects. 377 * The array is accessed via the {@link #getTrayIcons} method.<br> 378 * This property is changed when a tray icon is added to (or removed 379 * from) the system tray.<br> For example, this property is changed 380 * when the system tray becomes unavailable on the desktop<br> 381 * and the tray icons are automatically removed.</td> 382 * </tr> 383 * <tr> 384 * <td>{@code systemTray}</td> 385 * <td>This property contains {@code SystemTray} instance when the system tray 386 * is available or <code>null</code> otherwise.<br> This property is changed 387 * when the system tray becomes available or unavailable on the desktop.<br> 388 * The property is accessed by the {@link #getSystemTray} method.</td> 389 * </tr> 390 * </table> 391 * <p> 392 * The {@code listener} listens to property changes only in this context. 393 * <p> 394 * If {@code listener} is {@code null}, no exception is thrown 395 * and no action is performed. 396 * 397 * @param propertyName the specified property 398 * @param listener the property change listener to be added 399 * 400 * @see #removePropertyChangeListener 401 * @see #getPropertyChangeListeners 402 */ 403 public synchronized void addPropertyChangeListener(String propertyName, 404 PropertyChangeListener listener) 405 { 406 if (listener == null) { | 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 26 package java.awt; 27 28 import java.util.Vector; 29 import java.awt.peer.SystemTrayPeer; 30 import java.beans.PropertyChangeListener; 31 import java.beans.PropertyChangeSupport; 32 import sun.awt.AppContext; 33 import sun.awt.SunToolkit; 34 import sun.awt.HeadlessToolkit; 35 import sun.awt.AWTAccessor; 36 import sun.awt.AWTPermissions; 37 38 /** 39 * The {@code SystemTray} class represents the system tray for a 40 * desktop. On Microsoft Windows it is referred to as the "Taskbar 41 * Status Area", on Gnome it is referred to as the "Notification 42 * Area", on KDE it is referred to as the "System Tray". The system 43 * tray is shared by all applications running on the desktop. 44 * 45 * <p> On some platforms the system tray may not be present or may not 46 * be supported, in this case {@link SystemTray#getSystemTray()} 47 * throws {@link UnsupportedOperationException}. To detect whether the 48 * system tray is supported, use {@link SystemTray#isSupported}. 49 * 50 * <p>The {@code SystemTray} may contain one or more {@link 51 * TrayIcon TrayIcons}, which are added to the tray using the {@link 52 * #add} method, and removed when no longer needed, using the 53 * {@link #remove}. {@code TrayIcon} consists of an 54 * image, a popup menu and a set of associated listeners. Please see 55 * the {@link TrayIcon} class for details. 56 * 57 * <p>Every Java application has a single {@code SystemTray} 58 * instance that allows the app to interface with the system tray of 59 * the desktop while the app is running. The {@code SystemTray} 60 * instance can be obtained from the {@link #getSystemTray} method. 61 * An application may not create its own instance of 62 * {@code SystemTray}. 63 * 64 * <p>The following code snippet demonstrates how to access 65 * and customize the system tray: 66 * <pre> 67 * <code> 68 * {@link TrayIcon} trayIcon = null; 69 * if (SystemTray.isSupported()) { 70 * // get the SystemTray instance 71 * SystemTray tray = SystemTray.{@link #getSystemTray}; 72 * // load an image 73 * {@link java.awt.Image} image = {@link java.awt.Toolkit#getImage(String) Toolkit.getDefaultToolkit().getImage}(...); 74 * // create a action listener to listen for default action executed on the tray icon 75 * {@link java.awt.event.ActionListener} listener = new {@link java.awt.event.ActionListener ActionListener}() { 76 * public void {@link java.awt.event.ActionListener#actionPerformed actionPerformed}({@link java.awt.event.ActionEvent} e) { 77 * // execute default action of the application 78 * // ... 79 * } 80 * }; 81 * // create a popup menu 82 * {@link java.awt.PopupMenu} popup = new {@link java.awt.PopupMenu#PopupMenu PopupMenu}(); 124 private static SystemTray systemTray; 125 private int currentIconID = 0; // each TrayIcon added gets a unique ID 126 127 private transient SystemTrayPeer peer; 128 129 private static final TrayIcon[] EMPTY_TRAY_ARRAY = new TrayIcon[0]; 130 131 static { 132 AWTAccessor.setSystemTrayAccessor( 133 new AWTAccessor.SystemTrayAccessor() { 134 public void firePropertyChange(SystemTray tray, 135 String propertyName, 136 Object oldValue, 137 Object newValue) { 138 tray.firePropertyChange(propertyName, oldValue, newValue); 139 } 140 }); 141 } 142 143 /** 144 * Private {@code SystemTray} constructor. 145 * 146 */ 147 private SystemTray() { 148 addNotify(); 149 } 150 151 /** 152 * Gets the {@code SystemTray} instance that represents the 153 * desktop's tray area. This always returns the same instance per 154 * application. On some platforms the system tray may not be 155 * supported. You may use the {@link #isSupported} method to 156 * check if the system tray is supported. 157 * 158 * <p>If a SecurityManager is installed, the AWTPermission 159 * {@code accessSystemTray} must be granted in order to get the 160 * {@code SystemTray} instance. Otherwise this method will throw a 161 * SecurityException. 162 * 163 * @return the {@code SystemTray} instance that represents 164 * the desktop's tray area 165 * @throws UnsupportedOperationException if the system tray isn't 166 * supported by the current platform 167 * @throws HeadlessException if 168 * {@code GraphicsEnvironment.isHeadless()} returns {@code true} 169 * @throws SecurityException if {@code accessSystemTray} permission 170 * is not granted 171 * @see #add(TrayIcon) 172 * @see TrayIcon 173 * @see #isSupported 174 * @see SecurityManager#checkPermission 175 * @see AWTPermission 176 */ 177 public static SystemTray getSystemTray() { 178 checkSystemTrayAllowed(); 179 if (GraphicsEnvironment.isHeadless()) { 180 throw new HeadlessException(); 181 } 182 183 initializeSystemTrayIfNeeded(); 184 185 if (!isSupported()) { 186 throw new UnsupportedOperationException( 187 "The system tray is not supported on the current platform."); 188 } 189 190 return systemTray; 191 } 192 193 /** 194 * Returns whether the system tray is supported on the current 195 * platform. In addition to displaying the tray icon, minimal 196 * system tray support includes either a popup menu (see {@link 197 * TrayIcon#setPopupMenu(PopupMenu)}) or an action event (see 198 * {@link TrayIcon#addActionListener(ActionListener)}). 199 * 200 * <p>Developers should not assume that all of the system tray 201 * functionality is supported. To guarantee that the tray icon's 202 * default action is always accessible, add the default action to 203 * both the action listener and the popup menu. See the {@link 204 * SystemTray example} for an example of how to do this. 205 * 206 * <p><b>Note</b>: When implementing {@code SystemTray} and 207 * {@code TrayIcon} it is <em>strongly recommended</em> that 208 * you assign different gestures to the popup menu and an action 209 * event. Overloading a gesture for both purposes is confusing 210 * and may prevent the user from accessing one or the other. 211 * 212 * @see #getSystemTray 213 * @return {@code false} if no system tray access is supported; this 214 * method returns {@code true} if the minimal system tray access is 215 * supported but does not guarantee that all system tray 216 * functionality is supported for the current platform 217 */ 218 public static boolean isSupported() { 219 Toolkit toolkit = Toolkit.getDefaultToolkit(); 220 if (toolkit instanceof SunToolkit) { 221 // connecting tray to native resource 222 initializeSystemTrayIfNeeded(); 223 return ((SunToolkit)toolkit).isTraySupported(); 224 } else if (toolkit instanceof HeadlessToolkit) { 225 // skip initialization as the init routine 226 // throws HeadlessException 227 return ((HeadlessToolkit)toolkit).isTraySupported(); 228 } else { 229 return false; 230 } 231 } 232 233 /** 234 * Adds a {@code TrayIcon} to the {@code SystemTray}. 235 * The tray icon becomes visible in the system tray once it is 236 * added. The order in which icons are displayed in a tray is not 237 * specified - it is platform and implementation-dependent. 238 * 239 * <p> All icons added by the application are automatically 240 * removed from the {@code SystemTray} upon application exit 241 * and also when the desktop system tray becomes unavailable. 242 * 243 * @param trayIcon the {@code TrayIcon} to be added 244 * @throws NullPointerException if {@code trayIcon} is 245 * {@code null} 246 * @throws IllegalArgumentException if the same instance of 247 * a {@code TrayIcon} is added more than once 248 * @throws AWTException if the desktop system tray is missing 249 * @see #remove(TrayIcon) 250 * @see #getSystemTray 251 * @see TrayIcon 252 * @see java.awt.Image 253 */ 254 public void add(TrayIcon trayIcon) throws AWTException { 255 if (trayIcon == null) { 256 throw new NullPointerException("adding null TrayIcon"); 257 } 258 TrayIcon[] oldArray = null, newArray = null; 259 Vector<TrayIcon> icons = null; 260 synchronized (this) { 261 oldArray = systemTray.getTrayIcons(); 262 @SuppressWarnings("unchecked") 263 Vector<TrayIcon> tmp = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 264 icons = tmp; 265 if (icons == null) { 266 icons = new Vector<TrayIcon>(3); 267 AppContext.getAppContext().put(TrayIcon.class, icons); 268 269 } else if (icons.contains(trayIcon)) { 270 throw new IllegalArgumentException("adding TrayIcon that is already added"); 271 } 272 icons.add(trayIcon); 273 newArray = systemTray.getTrayIcons(); 274 275 trayIcon.setID(++currentIconID); 276 } 277 try { 278 trayIcon.addNotify(); 279 } catch (AWTException e) { 280 icons.remove(trayIcon); 281 throw e; 282 } 283 firePropertyChange("trayIcons", oldArray, newArray); 284 } 285 286 /** 287 * Removes the specified {@code TrayIcon} from the 288 * {@code SystemTray}. 289 * 290 * <p> All icons added by the application are automatically 291 * removed from the {@code SystemTray} upon application exit 292 * and also when the desktop system tray becomes unavailable. 293 * 294 * <p> If {@code trayIcon} is {@code null} or was not 295 * added to the system tray, no exception is thrown and no action 296 * is performed. 297 * 298 * @param trayIcon the {@code TrayIcon} to be removed 299 * @see #add(TrayIcon) 300 * @see TrayIcon 301 */ 302 public void remove(TrayIcon trayIcon) { 303 if (trayIcon == null) { 304 return; 305 } 306 TrayIcon[] oldArray = null, newArray = null; 307 synchronized (this) { 308 oldArray = systemTray.getTrayIcons(); 309 @SuppressWarnings("unchecked") 310 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 311 // TrayIcon with no peer is not contained in the array. 312 if (icons == null || !icons.remove(trayIcon)) { 313 return; 314 } 315 trayIcon.removeNotify(); 316 newArray = systemTray.getTrayIcons(); 317 } 318 firePropertyChange("trayIcons", oldArray, newArray); 319 } 320 321 /** 322 * Returns an array of all icons added to the tray by this 323 * application. You can't access the icons added by another 324 * application. Some browsers partition applets in different 325 * code bases into separate contexts, and establish walls between 326 * these contexts. In such a scenario, only the tray icons added 327 * from this context will be returned. 328 * 329 * <p> The returned array is a copy of the actual array and may be 330 * modified in any way without affecting the system tray. To 331 * remove a {@code TrayIcon} from the 332 * {@code SystemTray}, use the {@link 333 * #remove(TrayIcon)} method. 334 * 335 * @return an array of all tray icons added to this tray, or an 336 * empty array if none has been added 337 * @see #add(TrayIcon) 338 * @see TrayIcon 339 */ 340 public TrayIcon[] getTrayIcons() { 341 @SuppressWarnings("unchecked") 342 Vector<TrayIcon> icons = (Vector<TrayIcon>)AppContext.getAppContext().get(TrayIcon.class); 343 if (icons != null) { 344 return icons.toArray(new TrayIcon[icons.size()]); 345 } 346 return EMPTY_TRAY_ARRAY; 347 } 348 349 /** 350 * Returns the size, in pixels, of the space that a tray icon will 351 * occupy in the system tray. Developers may use this methods to 352 * acquire the preferred size for the image property of a tray icon 353 * before it is created. For convenience, there is a similar 354 * method {@link TrayIcon#getSize} in the {@code TrayIcon} class. 355 * 356 * @return the default size of a tray icon, in pixels 357 * @see TrayIcon#setImageAutoSize(boolean) 358 * @see java.awt.Image 359 * @see TrayIcon#getSize() 360 */ 361 public Dimension getTrayIconSize() { 362 return peer.getTrayIconSize(); 363 } 364 365 /** 366 * Adds a {@code PropertyChangeListener} to the list of listeners for the 367 * specific property. The following properties are currently supported: 368 * 369 * <table border=1 summary="SystemTray properties"> 370 * <tr> 371 * <th>Property</th> 372 * <th>Description</th> 373 * </tr> 374 * <tr> 375 * <td>{@code trayIcons}</td> 376 * <td>The {@code SystemTray}'s array of {@code TrayIcon} objects. 377 * The array is accessed via the {@link #getTrayIcons} method.<br> 378 * This property is changed when a tray icon is added to (or removed 379 * from) the system tray.<br> For example, this property is changed 380 * when the system tray becomes unavailable on the desktop<br> 381 * and the tray icons are automatically removed.</td> 382 * </tr> 383 * <tr> 384 * <td>{@code systemTray}</td> 385 * <td>This property contains {@code SystemTray} instance when the system tray 386 * is available or {@code null} otherwise.<br> This property is changed 387 * when the system tray becomes available or unavailable on the desktop.<br> 388 * The property is accessed by the {@link #getSystemTray} method.</td> 389 * </tr> 390 * </table> 391 * <p> 392 * The {@code listener} listens to property changes only in this context. 393 * <p> 394 * If {@code listener} is {@code null}, no exception is thrown 395 * and no action is performed. 396 * 397 * @param propertyName the specified property 398 * @param listener the property change listener to be added 399 * 400 * @see #removePropertyChangeListener 401 * @see #getPropertyChangeListeners 402 */ 403 public synchronized void addPropertyChangeListener(String propertyName, 404 PropertyChangeListener listener) 405 { 406 if (listener == null) { |