Source code: org/eclipse/swt/widgets/TrayItem.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.swt.widgets;
12
13 import org.eclipse.swt.*;
14 import org.eclipse.swt.events.*;
15 import org.eclipse.swt.graphics.*;
16 import org.eclipse.swt.internal.*;
17 import org.eclipse.swt.internal.gtk.*;
18
19 /**
20 * Instances of this class represent icons that can be placed on the
21 * system tray or task bar status area.
22 *
23 * <dl>
24 * <dt><b>Styles:</b></dt>
25 * <dd>(none)</dd>
26 * <dt><b>Events:</b></dt>
27 * <dd>DefaultSelection, MenuDetect, Selection</dd>
28 * </dl>
29 * <p>
30 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
31 * </p>
32 *
33 * @since 3.0
34 */
35 public class TrayItem extends Item {
36 Tray parent;
37 String toolTipText;
38 long /*int*/ imageHandle;
39 long /*int*/ tooltipsHandle;
40
41 /**
42 * Constructs a new instance of this class given its parent
43 * (which must be a <code>Tray</code>) and a style value
44 * describing its behavior and appearance. The item is added
45 * to the end of the items maintained by its parent.
46 * <p>
47 * The style value is either one of the style constants defined in
48 * class <code>SWT</code> which is applicable to instances of this
49 * class, or must be built by <em>bitwise OR</em>'ing together
50 * (that is, using the <code>int</code> "|" operator) two or more
51 * of those <code>SWT</code> style constants. The class description
52 * lists the style constants that are applicable to the class.
53 * Style bits are also inherited from superclasses.
54 * </p>
55 *
56 * @param parent a composite control which will be the parent of the new instance (cannot be null)
57 * @param style the style of control to construct
58 *
59 * @exception IllegalArgumentException <ul>
60 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
61 * </ul>
62 * @exception SWTException <ul>
63 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
64 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
65 * </ul>
66 *
67 * @see SWT
68 * @see Widget#checkSubclass
69 * @see Widget#getStyle
70 */
71 public TrayItem (Tray parent, int style) {
72 super (parent, style);
73 this.parent = parent;
74 createWidget (parent.getItemCount ());
75 }
76
77 /**
78 * Adds the listener to the collection of listeners who will
79 * be notified when the receiver is selected, by sending
80 * it one of the messages defined in the <code>SelectionListener</code>
81 * interface.
82 * <p>
83 * <code>widgetSelected</code> is called when the receiver is selected
84 * <code>widgetDefaultSelected</code> is called when the receiver is double-clicked
85 * </p>
86 *
87 * @param listener the listener which should be notified
88 *
89 * @exception IllegalArgumentException <ul>
90 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
91 * </ul>
92 * @exception SWTException <ul>
93 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
94 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
95 * </ul>
96 *
97 * @see SelectionListener
98 * @see #removeSelectionListener
99 * @see SelectionEvent
100 */
101 public void addSelectionListener(SelectionListener listener) {
102 checkWidget ();
103 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
104 TypedListener typedListener = new TypedListener (listener);
105 addListener (SWT.Selection, typedListener);
106 addListener (SWT.DefaultSelection, typedListener);
107 }
108
109 void createWidget (int index) {
110 super.createWidget (index);
111 parent.createItem (this, index);
112 }
113
114 void createHandle (int index) {
115 state |= HANDLE;
116 handle = OS.gtk_plug_new (0);
117 if (handle == 0) error (SWT.ERROR_NO_HANDLES);
118 imageHandle = OS.gtk_image_new ();
119 if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
120 OS.gtk_container_add (handle, imageHandle);
121 OS.gtk_widget_show (handle);
122 OS.gtk_widget_show (imageHandle);
123 long /*int*/ id = OS.gtk_plug_get_id (handle);
124 int monitor = 0;
125 long /*int*/ screen = OS.gdk_screen_get_default ();
126 if (screen != 0) {
127 monitor = OS.gdk_screen_get_number (screen);
128 }
129 byte [] trayBuffer = Converter.wcsToMbcs (null, "_NET_SYSTEM_TRAY_S" + monitor, true);
130 long /*int*/ trayAtom = OS.gdk_atom_intern (trayBuffer, true);
131 long /*int*/ xTrayAtom = OS.gdk_x11_atom_to_xatom (trayAtom);
132 long /*int*/ xDisplay = OS.GDK_DISPLAY ();
133 long /*int*/ trayWindow = OS.XGetSelectionOwner (xDisplay, xTrayAtom);
134 byte [] messageBuffer = Converter.wcsToMbcs (null, "_NET_SYSTEM_TRAY_OPCODE", true);
135 long /*int*/ messageAtom = OS.gdk_atom_intern (messageBuffer, true);
136 long /*int*/ xMessageAtom = OS.gdk_x11_atom_to_xatom (messageAtom);
137 XClientMessageEvent event = new XClientMessageEvent ();
138 event.type = OS.ClientMessage;
139 event.window = trayWindow;
140 event.message_type = xMessageAtom;
141 event.format = 32;
142 event.data [0] = OS.GDK_CURRENT_TIME;
143 event.data [1] = OS.SYSTEM_TRAY_REQUEST_DOCK;
144 event.data [2] = id;
145 long /*int*/ clientEvent = OS.g_malloc (XClientMessageEvent.sizeof);
146 OS.memmove (clientEvent, event, XClientMessageEvent.sizeof);
147 OS.XSendEvent (OS.GDK_DISPLAY (), trayWindow, false, OS.NoEventMask, clientEvent);
148 OS.g_free (clientEvent);
149 }
150
151 /**
152 * Returns the receiver's tool tip text, or null if it has
153 * not been set.
154 *
155 * @return the receiver's tool tip text
156 *
157 * @exception SWTException <ul>
158 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
159 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
160 * </ul>
161 */
162 public String getToolTipText () {
163 checkWidget ();
164 return toolTipText;
165 }
166
167 long /*int*/ gtk_button_press_event (long /*int*/ widget, long /*int*/ eventPtr) {
168 GdkEventButton gdkEvent = new GdkEventButton ();
169 OS.memmove (gdkEvent, eventPtr, GdkEventButton.sizeof);
170 if (gdkEvent.type == OS.GDK_3BUTTON_PRESS) return 0;
171 if (gdkEvent.button == 3 && gdkEvent.type == OS.GDK_BUTTON_PRESS) {
172 sendEvent (SWT.MenuDetect);
173 return 0;
174 }
175 if (gdkEvent.type == OS.GDK_2BUTTON_PRESS) {
176 postEvent (SWT.DefaultSelection);
177 } else {
178 postEvent (SWT.Selection);
179 }
180 return 0;
181 }
182
183 void hookEvents () {
184 int eventMask = OS.GDK_BUTTON_PRESS_MASK;
185 OS.gtk_widget_add_events (handle, eventMask);
186 OS.g_signal_connect (handle, OS.button_press_event, display.windowProc3, BUTTON_PRESS_EVENT);
187 }
188
189 /**
190 * Returns <code>true</code> if the receiver is visible and
191 * <code>false</code> otherwise.
192 *
193 * @return the receiver's visibility
194 *
195 * @exception SWTException <ul>
196 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
197 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
198 * </ul>
199 */
200 public boolean getVisible () {
201 checkWidget ();
202 return OS.GTK_WIDGET_VISIBLE (handle);
203 }
204
205 void releaseChild () {
206 super.releaseChild ();
207 parent.destroyItem (this);
208 }
209
210 void releaseWidget () {
211 super.releaseWidget ();
212 if (tooltipsHandle != 0) OS.g_object_unref (tooltipsHandle);
213 imageHandle = tooltipsHandle = 0;
214 toolTipText = null;
215 if (handle != 0) OS.gtk_widget_destroy (handle);
216 handle = 0;
217 }
218
219 /**
220 * Removes the listener from the collection of listeners who will
221 * be notified when the receiver is selected.
222 *
223 * @param listener the listener which should no longer be notified
224 *
225 * @exception IllegalArgumentException <ul>
226 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
227 * </ul>
228 * @exception SWTException <ul>
229 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
230 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
231 * </ul>
232 *
233 * @see SelectionListener
234 * @see #addSelectionListener
235 */
236 public void removeSelectionListener (SelectionListener listener) {
237 checkWidget ();
238 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
239 if (eventTable == null) return;
240 eventTable.unhook (SWT.Selection, listener);
241 eventTable.unhook (SWT.DefaultSelection, listener);
242 }
243
244 /**
245 * Sets the receiver's image.
246 *
247 * @param image the new image
248 *
249 * @exception IllegalArgumentException <ul>
250 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
251 * </ul>
252 * @exception SWTException <ul>
253 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
255 * </ul>
256 */
257 public void setImage (Image image) {
258 checkWidget ();
259 if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
260 this.image = image;
261 if (image != null) {
262 Rectangle rect = image.getBounds ();
263 OS.gtk_widget_set_size_request (handle, rect.width, rect.height);
264 OS.gtk_image_set_from_pixmap (imageHandle, image.pixmap, image.mask);
265 OS.gtk_widget_show (imageHandle);
266 } else {
267 OS.gtk_widget_set_size_request (handle, 1, 1);
268 OS.gtk_image_set_from_pixmap (imageHandle, 0, 0);
269 OS.gtk_widget_hide (imageHandle);
270 }
271 }
272
273 /**
274 * Sets the receiver's tool tip text to the argument, which
275 * may be null indicating that no tool tip text should be shown.
276 *
277 * @param value the new tool tip text (or null)
278 *
279 * @exception SWTException <ul>
280 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
281 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
282 * </ul>
283 */
284 public void setToolTipText (String string) {
285 checkWidget ();
286 toolTipText = string;
287 byte [] buffer = null;
288 if (string != null && string.length () > 0) {
289 buffer = Converter.wcsToMbcs (null, string, true);
290 }
291 if (tooltipsHandle == 0) {
292 tooltipsHandle = OS.gtk_tooltips_new ();
293 if (tooltipsHandle == 0) error (SWT.ERROR_NO_HANDLES);
294 OS.g_object_ref (tooltipsHandle);
295 OS.gtk_object_sink (tooltipsHandle);
296 }
297 OS.gtk_tooltips_set_tip (tooltipsHandle, handle, buffer, null);
298 }
299
300 /**
301 * Makes the receiver visible if the argument is <code>true</code>,
302 * and makes it invisible otherwise.
303 *
304 * @param visible the new visibility state
305 *
306 * @exception SWTException <ul>
307 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
308 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
309 * </ul>
310 */
311 public void setVisible (boolean visible) {
312 checkWidget ();
313 if (OS.GTK_WIDGET_VISIBLE (handle) == visible) return;
314 if (visible) {
315 /*
316 * It is possible (but unlikely), that application
317 * code could have disposed the widget in the show
318 * event. If this happens, just return.
319 */
320 sendEvent (SWT.Show);
321 if (isDisposed ()) return;
322 OS.gtk_widget_show (handle);
323 } else {
324 OS.gtk_widget_hide (handle);
325 sendEvent (SWT.Hide);
326 }
327 }
328 }