KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > Decorations


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.internal.win32.*;
15 import org.eclipse.swt.*;
16 import org.eclipse.swt.graphics.*;
17
18 /**
19  * Instances of this class provide the appearance and
20  * behavior of <code>Shells</code>, but are not top
21  * level shells or dialogs. Class <code>Shell</code>
22  * shares a significant amount of code with this class,
23  * and is a subclass.
24  * <p>
25  * IMPORTANT: This class was intended to be abstract and
26  * should <em>never</em> be referenced or instantiated.
27  * Instead, the class <code>Shell</code> should be used.
28  * </p>
29  * <p>
30  * Instances are always displayed in one of the maximized,
31  * minimized or normal states:
32  * <ul>
33  * <li>
34  * When an instance is marked as <em>maximized</em>, the
35  * window manager will typically resize it to fill the
36  * entire visible area of the display, and the instance
37  * is usually put in a state where it can not be resized
38  * (even if it has style <code>RESIZE</code>) until it is
39  * no longer maximized.
40  * </li><li>
41  * When an instance is in the <em>normal</em> state (neither
42  * maximized or minimized), its appearance is controlled by
43  * the style constants which were specified when it was created
44  * and the restrictions of the window manager (see below).
45  * </li><li>
46  * When an instance has been marked as <em>minimized</em>,
47  * its contents (client area) will usually not be visible,
48  * and depending on the window manager, it may be
49  * "iconified" (that is, replaced on the desktop by a small
50  * simplified representation of itself), relocated to a
51  * distinguished area of the screen, or hidden. Combinations
52  * of these changes are also possible.
53  * </li>
54  * </ul>
55  * </p>
56  * Note: The styles supported by this class must be treated
57  * as <em>HINT</em>s, since the window manager for the
58  * desktop on which the instance is visible has ultimate
59  * control over the appearance and behavior of decorations.
60  * For example, some window managers only support resizable
61  * windows and will always assume the RESIZE style, even if
62  * it is not set.
63  * <dl>
64  * <dt><b>Styles:</b></dt>
65  * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
66  * <dt><b>Events:</b></dt>
67  * <dd>(none)</dd>
68  * </dl>
69  * Class <code>SWT</code> provides two "convenience constants"
70  * for the most commonly required style combinations:
71  * <dl>
72  * <dt><code>SHELL_TRIM</code></dt>
73  * <dd>
74  * the result of combining the constants which are required
75  * to produce a typical application top level shell: (that
76  * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
77  * </dd>
78  * <dt><code>DIALOG_TRIM</code></dt>
79  * <dd>
80  * the result of combining the constants which are required
81  * to produce a typical application dialog shell: (that
82  * is, <code>TITLE | CLOSE | BORDER</code>)
83  * </dd>
84  * </dl>
85  * <p>
86  * IMPORTANT: This class is intended to be subclassed <em>only</em>
87  * within the SWT implementation.
88  * </p>
89  *
90  * @see #getMinimized
91  * @see #getMaximized
92  * @see Shell
93  * @see SWT
94  */

95
96 public class Decorations extends Canvas {
97     Image image, smallImage, largeImage;
98     Image [] images;
99     Menu menuBar;
100     Menu [] menus;
101     Control savedFocus;
102     Button defaultButton, saveDefault;
103     int swFlags, hAccel, nAccel;
104     boolean moved, resized, opened;
105     int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT;
106     int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT;
107
108 /**
109  * Prevents uninitialized instances from being created outside the package.
110  */

111 Decorations () {
112 }
113
114 /**
115  * Constructs a new instance of this class given its parent
116  * and a style value describing its behavior and appearance.
117  * <p>
118  * The style value is either one of the style constants defined in
119  * class <code>SWT</code> which is applicable to instances of this
120  * class, or must be built by <em>bitwise OR</em>'ing together
121  * (that is, using the <code>int</code> "|" operator) two or more
122  * of those <code>SWT</code> style constants. The class description
123  * lists the style constants that are applicable to the class.
124  * Style bits are also inherited from superclasses.
125  * </p>
126  *
127  * @param parent a composite control which will be the parent of the new instance (cannot be null)
128  * @param style the style of control to construct
129  *
130  * @exception IllegalArgumentException <ul>
131  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
132  * </ul>
133  * @exception SWTException <ul>
134  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
135  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
136  * </ul>
137  *
138  * @see SWT#BORDER
139  * @see SWT#CLOSE
140  * @see SWT#MIN
141  * @see SWT#MAX
142  * @see SWT#RESIZE
143  * @see SWT#TITLE
144  * @see SWT#NO_TRIM
145  * @see SWT#SHELL_TRIM
146  * @see SWT#DIALOG_TRIM
147  * @see SWT#ON_TOP
148  * @see SWT#TOOL
149  * @see Widget#checkSubclass
150  * @see Widget#getStyle
151  */

152 public Decorations (Composite parent, int style) {
153     super (parent, checkStyle (style));
154 }
155
156 void _setMaximized (boolean maximized) {
157     swFlags = maximized ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
158     if (OS.IsWinCE) {
159         /*
160         * Note: WinCE does not support SW_SHOWMAXIMIZED and SW_RESTORE. The
161         * workaround is to resize the window to fit the parent client area.
162         */

163         if (maximized) {
164             RECT rect = new RECT ();
165             OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, rect, 0);
166             int width = rect.right - rect.left, height = rect.bottom - rect.top;
167             if (OS.IsPPC) {
168                 /* Leave space for the menu bar */
169                 if (menuBar != null) {
170                     int hwndCB = menuBar.hwndCB;
171                     RECT rectCB = new RECT ();
172                     OS.GetWindowRect (hwndCB, rectCB);
173                     height -= rectCB.bottom - rectCB.top;
174                 }
175             }
176             int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
177             SetWindowPos (handle, 0, rect.left, rect.top, width, height, flags);
178         }
179     } else {
180         if (!OS.IsWindowVisible (handle)) return;
181         if (maximized == OS.IsZoomed (handle)) return;
182         OS.ShowWindow (handle, swFlags);
183         OS.UpdateWindow (handle);
184     }
185 }
186
187 void _setMinimized (boolean minimized) {
188     if (OS.IsWinCE) return;
189     swFlags = minimized ? OS.SW_SHOWMINNOACTIVE : OS.SW_RESTORE;
190     if (!OS.IsWindowVisible (handle)) return;
191     if (minimized == OS.IsIconic (handle)) return;
192     int flags = swFlags;
193     if (flags == OS.SW_SHOWMINNOACTIVE && handle == OS.GetActiveWindow ()) {
194         flags = OS.SW_MINIMIZE;
195     }
196     OS.ShowWindow (handle, flags);
197     OS.UpdateWindow (handle);
198 }
199
200 void addMenu (Menu menu) {
201     if (menus == null) menus = new Menu [4];
202     for (int i=0; i<menus.length; i++) {
203         if (menus [i] == null) {
204             menus [i] = menu;
205             return;
206         }
207     }
208     Menu [] newMenus = new Menu [menus.length + 4];
209     newMenus [menus.length] = menu;
210     System.arraycopy (menus, 0, newMenus, 0, menus.length);
211     menus = newMenus;
212 }
213
214 void bringToTop () {
215     /*
216     * This code is intentionally commented. On some platforms,
217     * the ON_TOP style creates a shell that will stay on top
218     * of every other shell on the desktop. Using SetWindowPos ()
219     * with HWND_TOP caused problems on Windows 98 so this code is
220     * commented out until this functionality is specified and
221     * the problems are fixed.
222     */

223 // if ((style & SWT.ON_TOP) != 0) {
224
// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
225
// OS.SetWindowPos (handle, OS.HWND_TOP, 0, 0, 0, 0, flags);
226
// } else {
227
OS.BringWindowToTop (handle);
228         // widget could be disposed at this point
229
// }
230
}
231
232 static int checkStyle (int style) {
233     if ((style & SWT.NO_TRIM) != 0) {
234         style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER);
235     }
236     if (OS.IsWinCE) {
237         /*
238         * Feature in WinCE PPC. WS_MINIMIZEBOX or WS_MAXIMIZEBOX
239         * are not supposed to be used. If they are, the result
240         * is a button which does not repaint correctly. The fix
241         * is to remove this style.
242         */

243         if ((style & SWT.MIN) != 0) style &= ~SWT.MIN;
244         if ((style & SWT.MAX) != 0) style &= ~SWT.MAX;
245         return style;
246     }
247     if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) != 0) {
248         style |= SWT.TITLE;
249     }
250     
251     /*
252     * If either WS_MINIMIZEBOX or WS_MAXIMIZEBOX are set,
253     * we must also set WS_SYSMENU or the buttons will not
254     * appear.
255     */

256     if ((style & (SWT.MIN | SWT.MAX)) != 0) style |= SWT.CLOSE;
257     
258     /*
259     * Both WS_SYSMENU and WS_CAPTION must be set in order
260     * to for the system menu to appear.
261     */

262     if ((style & SWT.CLOSE) != 0) style |= SWT.TITLE;
263     
264     /*
265     * Bug in Windows. The WS_CAPTION style must be
266     * set when the window is resizable or it does not
267     * draw properly.
268     */

269     /*
270     * This code is intentionally commented. It seems
271     * that this problem originally in Windows 3.11,
272     * has been fixed in later versions. Because the
273     * exact nature of the drawing problem is unknown,
274     * keep the commented code around in case it comes
275     * back.
276     */

277 // if ((style & SWT.RESIZE) != 0) style |= SWT.TITLE;
278

279     return style;
280 }
281
282 void checkBorder () {
283     /* Do nothing */
284 }
285
286 void checkOpened () {
287     if (!opened) resized = false;
288 }
289
290 protected void checkSubclass () {
291     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
292 }
293
294 int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
295     if (handle == 0) return 0;
296     return OS.DefMDIChildProc (hwnd, msg, wParam, lParam);
297 }
298
299 void closeWidget () {
300     Event event = new Event ();
301     sendEvent (SWT.Close, event);
302     if (event.doit && !isDisposed ()) dispose ();
303 }
304
305 int compare (ImageData data1, ImageData data2, int width, int height, int depth) {
306     int value1 = Math.abs (data1.width - width), value2 = Math.abs (data2.width - width);
307     if (value1 == value2) {
308         int transparent1 = data1.getTransparencyType ();
309         int transparent2 = data2.getTransparencyType ();
310         if (transparent1 == transparent2) {
311             if (data1.depth == data2.depth) return 0;
312             return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1;
313         }
314         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
315             if (transparent1 == SWT.TRANSPARENCY_ALPHA) return -1;
316             if (transparent2 == SWT.TRANSPARENCY_ALPHA) return 1;
317         }
318         if (transparent1 == SWT.TRANSPARENCY_MASK) return -1;
319         if (transparent2 == SWT.TRANSPARENCY_MASK) return 1;
320         if (transparent1 == SWT.TRANSPARENCY_PIXEL) return -1;
321         if (transparent2 == SWT.TRANSPARENCY_PIXEL) return 1;
322         return 0;
323     }
324     return value1 < value2 ? -1 : 1;
325 }
326
327 Control computeTabGroup () {
328     return this;
329 }
330
331 Control computeTabRoot () {
332     return this;
333 }
334
335 public Rectangle computeTrim (int x, int y, int width, int height) {
336     checkWidget ();
337
338     /* Get the size of the trimmings */
339     RECT rect = new RECT ();
340     OS.SetRect (rect, x, y, x + width, y + height);
341     int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
342     int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
343     boolean hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) != 0;
344     OS.AdjustWindowRectEx (rect, bits1, hasMenu, bits2);
345
346     /* Get the size of the scroll bars */
347     if (horizontalBar != null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
348     if (verticalBar != null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
349
350     /* Compute the height of the menu bar */
351     if (hasMenu) {
352         RECT testRect = new RECT ();
353         OS.SetRect (testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
354         OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, testRect);
355         while ((testRect.bottom - testRect.top) < height) {
356             if (testRect.bottom - testRect.top == 0) break;
357             rect.top -= OS.GetSystemMetrics (OS.SM_CYMENU) - OS.GetSystemMetrics (OS.SM_CYBORDER);
358             OS.SetRect (testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
359             OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, testRect);
360         }
361     }
362     return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
363 }
364
365 void createAccelerators () {
366     hAccel = nAccel = 0;
367     int maxAccel = 0;
368     MenuItem [] items = display.items;
369     if (menuBar == null || items == null) {
370         if (!OS.IsPPC) return;
371         maxAccel = 1;
372     } else {
373         maxAccel = OS.IsPPC ? items.length + 1 : items.length;
374     }
375     ACCEL accel = new ACCEL ();
376     byte [] buffer1 = new byte [ACCEL.sizeof];
377     byte [] buffer2 = new byte [maxAccel * ACCEL.sizeof];
378     if (menuBar != null && items != null) {
379         for (int i=0; i<items.length; i++) {
380             MenuItem item = items [i];
381             if (item != null && item.accelerator != 0) {
382                 Menu menu = item.parent;
383                 if (menu.parent == this) {
384                     while (menu != null && menu != menuBar) {
385                         menu = menu.getParentMenu ();
386                     }
387                     if (menu == menuBar) {
388                         item.fillAccel (accel);
389                         OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
390                         System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
391                         nAccel++;
392                     }
393                 }
394             }
395         }
396     }
397     if (OS.IsPPC) {
398         /*
399         * Note on WinCE PPC. Close the shell when user taps CTRL-Q.
400         * IDOK represents the "Done Button" which also closes the shell.
401         */

402         accel.fVirt = (byte) (OS.FVIRTKEY | OS.FCONTROL);
403         accel.key = (short) 'Q';
404         accel.cmd = (short) OS.IDOK;
405         OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
406         System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
407         nAccel++;
408     }
409     if (nAccel != 0) hAccel = OS.CreateAcceleratorTable (buffer2, nAccel);
410 }
411
412 void createHandle () {
413     super.createHandle ();
414     if (parent != null || ((style & SWT.TOOL) != 0)) {
415         setParent ();
416         setSystemMenu ();
417     }
418 }
419
420 void createWidget () {
421     super.createWidget ();
422     swFlags = OS.IsWinCE ? OS.SW_SHOWMAXIMIZED : OS.SW_SHOWNOACTIVATE;
423     hAccel = -1;
424 }
425
426 void destroyAccelerators () {
427     if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
428     hAccel = -1;
429 }
430
431 public void dispose () {
432     if (isDisposed()) return;
433     if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
434     if (!(this instanceof Shell)) {
435         if (!traverseDecorations (true)) {
436             Shell shell = getShell ();
437             shell.setFocus ();
438         }
439         setVisible (false);
440     }
441     super.dispose ();
442 }
443
444 Menu findMenu (int hMenu) {
445     if (menus == null) return null;
446     for (int i=0; i<menus.length; i++) {
447         Menu menu = menus [i];
448         if (menu != null && hMenu == menu.handle) return menu;
449     }
450     return null;
451 }
452
453 void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) {
454     if (this == newDecorations) return;
455     if (control == savedFocus) savedFocus = null;
456     if (control == defaultButton) defaultButton = null;
457     if (control == saveDefault) saveDefault = null;
458     if (menus == null) return;
459     Menu menu = control.menu;
460     if (menu != null) {
461         int index = 0;
462         while (index <menus.length) {
463             if (menus [index] == menu) {
464                 control.setMenu (null);
465                 return;
466             }
467             index++;
468         }
469         menu.fixMenus (newDecorations);
470         destroyAccelerators ();
471         newDecorations.destroyAccelerators ();
472     }
473 }
474
475 public Rectangle getBounds () {
476     checkWidget ();
477     if (!OS.IsWinCE) {
478         if (OS.IsIconic (handle)) {
479             WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
480             lpwndpl.length = WINDOWPLACEMENT.sizeof;
481             OS.GetWindowPlacement (handle, lpwndpl);
482             int width = lpwndpl.right - lpwndpl.left;
483             int height = lpwndpl.bottom - lpwndpl.top;
484             return new Rectangle (lpwndpl.left, lpwndpl.top, width, height);
485         }
486     }
487     return super.getBounds ();
488 }
489
490 public Rectangle getClientArea () {
491     checkWidget ();
492     /*
493     * Note: The CommandBar is part of the client area,
494     * not the trim. Applications don't expect this so
495     * subtract the height of the CommandBar.
496     */

497     if (OS.IsHPC) {
498         Rectangle rect = super.getClientArea ();
499         if (menuBar != null) {
500             int hwndCB = menuBar.hwndCB;
501             int height = OS.CommandBar_Height (hwndCB);
502             rect.y += height;
503             rect.height = Math.max (0, rect.height - height);
504         }
505         return rect;
506     }
507     if (!OS.IsWinCE) {
508         if (OS.IsIconic (handle)) {
509             WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
510             lpwndpl.length = WINDOWPLACEMENT.sizeof;
511             OS.GetWindowPlacement (handle, lpwndpl);
512             int width = lpwndpl.right - lpwndpl.left;
513             int height = lpwndpl.bottom - lpwndpl.top;
514             /*
515             * Feature in Windows. For some reason WM_NCCALCSIZE does
516             * not compute the client area when the window is minimized.
517             * The fix is to compute it using AdjustWindowRectEx() and
518             * GetSystemMetrics().
519             *
520             * NOTE: This code fails to compute the correct client area
521             * for a minimized window where the menu bar would wrap were
522             * the window restored. There is no fix for this problem at
523             * this time.
524             */

525             if (horizontalBar != null) width -= OS.GetSystemMetrics (OS.SM_CYHSCROLL);
526             if (verticalBar != null) height -= OS.GetSystemMetrics (OS.SM_CXVSCROLL);
527             RECT rect = new RECT ();
528             int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
529             int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
530             boolean hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) != 0;
531             OS.AdjustWindowRectEx (rect, bits1, hasMenu, bits2);
532             width = Math.max (0, width - (rect.right - rect.left));
533             height = Math.max (0, height - (rect.bottom - rect.top));
534             return new Rectangle (0, 0, width, height);
535         }
536     }
537     return super.getClientArea ();
538 }
539
540 /**
541  * Returns the receiver's default button if one had
542  * previously been set, otherwise returns null.
543  *
544  * @return the default button or null
545  *
546  * @exception SWTException <ul>
547  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
548  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
549  * </ul>
550  *
551  * @see #setDefaultButton(Button)
552  */

553 public Button getDefaultButton () {
554     checkWidget ();
555     return defaultButton;
556 }
557
558 /**
559  * Returns the receiver's image if it had previously been
560  * set using <code>setImage()</code>. The image is typically
561  * displayed by the window manager when the instance is
562  * marked as iconified, and may also be displayed somewhere
563  * in the trim when the instance is in normal or maximized
564  * states.
565  * <p>
566  * Note: This method will return null if called before
567  * <code>setImage()</code> is called. It does not provide
568  * access to a window manager provided, "default" image
569  * even if one exists.
570  * </p>
571  *
572  * @return the image
573  *
574  * @exception SWTException <ul>
575  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
576  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
577  * </ul>
578  */

579 public Image getImage () {
580     checkWidget ();
581     return image;
582 }
583
584 /**
585  * Returns the receiver's images if they had previously been
586  * set using <code>setImages()</code>. Images are typically
587  * displayed by the window manager when the instance is
588  * marked as iconified, and may also be displayed somewhere
589  * in the trim when the instance is in normal or maximized
590  * states. Depending where the icon is displayed, the platform
591  * chooses the icon with the "best" attributes. It is expected
592  * that the array will contain the same icon rendered at different
593  * sizes, with different depth and transparency attributes.
594  *
595  * <p>
596  * Note: This method will return an empty array if called before
597  * <code>setImages()</code> is called. It does not provide
598  * access to a window manager provided, "default" image
599  * even if one exists.
600  * </p>
601  *
602  * @return the images
603  *
604  * @exception SWTException <ul>
605  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
606  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
607  * </ul>
608  *
609  * @since 3.0
610  */

611 public Image [] getImages () {
612     checkWidget ();
613     if (images == null) return new Image [0];
614     Image [] result = new Image [images.length];
615     System.arraycopy (images, 0, result, 0, images.length);
616     return result;
617 }
618
619 public Point getLocation () {
620     checkWidget ();
621     if (!OS.IsWinCE) {
622         if (OS.IsIconic (handle)) {
623             WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
624             lpwndpl.length = WINDOWPLACEMENT.sizeof;
625             OS.GetWindowPlacement (handle, lpwndpl);
626             return new Point (lpwndpl.left, lpwndpl.top);
627         }
628     }
629     return super.getLocation ();
630 }
631
632 /**
633  * Returns <code>true</code> if the receiver is currently
634  * maximized, and false otherwise.
635  * <p>
636  *
637  * @return the maximized state
638  *
639  * @exception SWTException <ul>
640  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
641  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
642  * </ul>
643  *
644  * @see #setMaximized
645  */

646 public boolean getMaximized () {
647     checkWidget ();
648     if (OS.IsWinCE) return swFlags == OS.SW_SHOWMAXIMIZED;
649     if (OS.IsWindowVisible (handle)) return OS.IsZoomed (handle);
650     return swFlags == OS.SW_SHOWMAXIMIZED;
651 }
652
653 /**
654  * Returns the receiver's menu bar if one had previously
655  * been set, otherwise returns null.
656  *
657  * @return the menu bar or null
658  *
659  * @exception SWTException <ul>
660  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
661  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
662  * </ul>
663  */

664 public Menu getMenuBar () {
665     checkWidget ();
666     return menuBar;
667 }
668
669 /**
670  * Returns <code>true</code> if the receiver is currently
671  * minimized, and false otherwise.
672  * <p>
673  *
674  * @return the minimized state
675  *
676  * @exception SWTException <ul>
677  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
678  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
679  * </ul>
680  *
681  * @see #setMinimized
682  */

683 public boolean getMinimized () {
684     checkWidget ();
685     if (OS.IsWinCE) return false;
686     if (OS.IsWindowVisible (handle)) return OS.IsIconic (handle);
687     return swFlags == OS.SW_SHOWMINNOACTIVE;
688 }
689
690 String JavaDoc getNameText () {
691     return getText ();
692 }
693
694 public Point getSize () {
695     checkWidget ();
696     if (!OS.IsWinCE) {
697         if (OS.IsIconic (handle)) {
698             WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
699             lpwndpl.length = WINDOWPLACEMENT.sizeof;
700             OS.GetWindowPlacement (handle, lpwndpl);
701             int width = lpwndpl.right - lpwndpl.left;
702             int height = lpwndpl.bottom - lpwndpl.top;
703             return new Point (width, height);
704         }
705     }
706     return super.getSize ();
707 }
708
709 /**
710  * Returns the receiver's text, which is the string that the
711  * window manager will typically display as the receiver's
712  * <em>title</em>. If the text has not previously been set,
713  * returns an empty string.
714  *
715  * @return the text
716  *
717  * @exception SWTException <ul>
718  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
719  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
720  * </ul>
721  */

722 public String JavaDoc getText () {
723     checkWidget ();
724     int length = OS.GetWindowTextLength (handle);
725     if (length == 0) return "";
726     /* Use the character encoding for the default locale */
727     TCHAR buffer = new TCHAR (0, length + 1);
728     OS.GetWindowText (handle, buffer, length + 1);
729     return buffer.toString (0, length);
730 }
731
732 public boolean isReparentable () {
733     checkWidget ();
734     /*
735     * Feature in Windows. Calling SetParent() for a shell causes
736     * a kind of fake MDI to happen. It doesn't work well on Windows
737     * and is not supported on the other platforms. The fix is to
738     * disallow the SetParent().
739     */

740     return false;
741 }
742
743 boolean isTabGroup () {
744     /*
745     * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
746     */

747     return true;
748 }
749
750 boolean isTabItem () {
751     /*
752     * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
753     */

754     return false;
755 }
756
757 Decorations menuShell () {
758     return this;
759 }
760
761 void releaseChildren (boolean destroy) {
762     if (menuBar != null) {
763         menuBar.release (false);
764         menuBar = null;
765     }
766     super.releaseChildren (destroy);
767     if (menus != null) {
768         for (int i=0; i<menus.length; i++) {
769             Menu menu = menus [i];
770             if (menu != null && !menu.isDisposed ()) {
771                 menu.dispose ();
772             }
773         }
774         menus = null;
775     }
776 }
777
778 void releaseWidget () {
779     super.releaseWidget ();
780     if (smallImage != null) smallImage.dispose ();
781     if (largeImage != null) largeImage.dispose ();
782     smallImage = largeImage = image = null;
783     images = null;
784     savedFocus = null;
785     defaultButton = saveDefault = null;
786     if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
787     hAccel = -1;
788 }
789
790 void removeMenu (Menu menu) {
791     if (menus == null) return;
792     for (int i=0; i<menus.length; i++) {
793         if (menus [i] == menu) {
794             menus [i] = null;
795             return;
796         }
797     }
798 }
799
800 boolean restoreFocus () {
801     if (display.ignoreRestoreFocus) return true;
802     if (savedFocus != null && savedFocus.isDisposed ()) savedFocus = null;
803     if (savedFocus != null && savedFocus.setSavedFocus ()) return true;
804     /*
805     * This code is intentionally commented. When no widget
806     * has been given focus, some platforms give focus to the
807     * default button. Windows doesn't do this.
808     */

809 // if (defaultButton != null && !defaultButton.isDisposed ()) {
810
// if (defaultButton.setFocus ()) return true;
811
// }
812
return false;
813 }
814
815 void saveFocus () {
816     Control control = display._getFocusControl ();
817     if (control != null && control != this && this == control.menuShell ()) {
818         setSavedFocus (control);
819     }
820 }
821
822 void setBounds (int x, int y, int width, int height, int flags, boolean defer) {
823     if (OS.IsWinCE) {
824         swFlags = OS.SW_RESTORE;
825     } else {
826         if (OS.IsIconic (handle)) {
827             setPlacement (x, y, width, height, flags);
828             return;
829         }
830     }
831     forceResize ();
832     RECT rect = new RECT ();
833     OS.GetWindowRect (handle, rect);
834     boolean sameOrigin = true;
835     if ((OS.SWP_NOMOVE & flags) == 0) {
836         sameOrigin = rect.left == x && rect.top == y;
837         if (!sameOrigin) moved = true;
838     }
839     boolean sameExtent = true;
840     if ((OS.SWP_NOSIZE & flags) == 0) {
841         sameExtent = rect.right - rect.left == width && rect.bottom - rect.top == height;
842         if (!sameExtent) resized = true;
843     }
844     if (!OS.IsWinCE) {
845         if (OS.IsZoomed (handle)) {
846             if (sameOrigin && sameExtent) return;
847             setPlacement (x, y, width, height, flags);
848             _setMaximized (false);
849             return;
850         }
851     }
852     super.setBounds (x, y, width, height, flags, defer);
853 }
854
855 /**
856  * If the argument is not null, sets the receiver's default
857  * button to the argument, and if the argument is null, sets
858  * the receiver's default button to the first button which
859  * was set as the receiver's default button (called the
860  * <em>saved default button</em>). If no default button had
861  * previously been set, or the saved default button was
862  * disposed, the receiver's default button will be set to
863  * null.
864  * <p>
865  * The default button is the button that is selected when
866  * the receiver is active and the user presses ENTER.
867  * </p>
868  *
869  * @param button the new default button
870  *
871  * @exception IllegalArgumentException <ul>
872  * <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li>
873  * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
874  * </ul>
875  * @exception SWTException <ul>
876  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
877  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
878  * </ul>
879  */

880 public void setDefaultButton (Button button) {
881     checkWidget ();
882     if (button != null) {
883         if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
884         if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT);
885     }
886     setDefaultButton (button, true);
887 }
888
889 void setDefaultButton (Button button, boolean save) {
890     if (button == null) {
891         if (defaultButton == saveDefault) {
892             if (save) saveDefault = null;
893             return;
894         }
895     } else {
896         if ((button.style & SWT.PUSH) == 0) return;
897         if (button == defaultButton) return;
898     }
899     if (defaultButton != null) {
900         if (!defaultButton.isDisposed ()) defaultButton.setDefault (false);
901     }
902     if ((defaultButton = button) == null) defaultButton = saveDefault;
903     if (defaultButton != null) {
904         if (!defaultButton.isDisposed ()) defaultButton.setDefault (true);
905     }
906     if (save) saveDefault = defaultButton;
907     if (saveDefault != null && saveDefault.isDisposed ()) saveDefault = null;
908 }
909
910 /**
911  * Sets the receiver's image to the argument, which may
912  * be null. The image is typically displayed by the window
913  * manager when the instance is marked as iconified, and
914  * may also be displayed somewhere in the trim when the
915  * instance is in normal or maximized states.
916  *
917  * @param image the new image (or null)
918  *
919  * @exception IllegalArgumentException <ul>
920  * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
921  * </ul>
922  * @exception SWTException <ul>
923  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
924  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
925  * </ul>
926  */

927 public void setImage (Image image) {
928     checkWidget ();
929     if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
930     this.image = image;
931     setImages (image, null);
932 }
933
934 void setImages (Image image, Image [] images) {
935     /*
936     * Feature in WinCE. WM_SETICON and WM_GETICON set the icon
937     * for the window class, not the window instance. This means
938     * that it is possible to set an icon into a window and then
939     * later free the icon, thus freeing the icon for every window.
940     * The fix is to avoid the API.
941     *
942     * On WinCE PPC, icons in windows are not displayed.
943     */

944     if (OS.IsWinCE) return;
945     if (smallImage != null) smallImage.dispose ();
946     if (largeImage != null) largeImage.dispose ();
947     smallImage = largeImage = null;
948     int hSmallIcon = 0, hLargeIcon = 0;
949     Image smallIcon = null, largeIcon = null;
950     if (image != null) {
951         smallIcon = largeIcon = image;
952     } else {
953         if (images != null && images.length > 0) {
954             int depth = display.getIconDepth ();
955             ImageData [] datas = null;
956             if (images.length > 1) {
957                 Image [] bestImages = new Image [images.length];
958                 System.arraycopy (images, 0, bestImages, 0, images.length);
959                 datas = new ImageData [images.length];
960                 for (int i=0; i<datas.length; i++) {
961                     datas [i] = images [i].getImageData ();
962                 }
963                 images = bestImages;
964                 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON), depth);
965             }
966             smallIcon = images [0];
967             if (images.length > 1) {
968                 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON), depth);
969             }
970             largeIcon = images [0];
971         }
972     }
973     if (smallIcon != null) {
974         switch (smallIcon.type) {
975             case SWT.BITMAP:
976                 smallImage = Display.createIcon (smallIcon);
977                 hSmallIcon = smallImage.handle;
978                 break;
979             case SWT.ICON:
980                 hSmallIcon = smallIcon.handle;
981                 break;
982         }
983     }
984     OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_SMALL, hSmallIcon);
985     if (largeIcon != null) {
986         switch (largeIcon.type) {
987             case SWT.BITMAP:
988                 largeImage = Display.createIcon (largeIcon);
989                 hLargeIcon = largeImage.handle;
990                 break;
991             case SWT.ICON:
992                 hLargeIcon = largeIcon.handle;
993                 break;
994         }
995     }
996     OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_BIG, hLargeIcon);
997     
998     /*
999     * Bug in Windows. When WM_SETICON is used to remove an
1000    * icon from the window trimmings for a window with the
1001    * extended style bits WS_EX_DLGMODALFRAME, the window
1002    * trimmings do not redraw to hide the previous icon.
1003    * The fix is to force a redraw.
1004    */

1005    if (!OS.IsWinCE) {
1006        if (hSmallIcon == 0 && hLargeIcon == 0 && (style & SWT.BORDER) != 0) {
1007            int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
1008            OS.RedrawWindow (handle, null, 0, flags);
1009        }
1010    }
1011}
1012
1013/**
1014 * Sets the receiver's images to the argument, which may
1015 * be an empty array. Images are typically displayed by the
1016 * window manager when the instance is marked as iconified,
1017 * and may also be displayed somewhere in the trim when the
1018 * instance is in normal or maximized states. Depending where
1019 * the icon is displayed, the platform chooses the icon with
1020 * the "best" attributes. It is expected that the array will
1021 * contain the same icon rendered at different sizes, with
1022 * different depth and transparency attributes.
1023 *
1024 * @param images the new image array
1025 *
1026 * @exception IllegalArgumentException <ul>
1027 * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
1028 * <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</li>
1029 * </ul>
1030 * @exception SWTException <ul>
1031 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1032 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1033 * </ul>
1034 *
1035 * @since 3.0
1036 */

1037public void setImages (Image [] images) {
1038    checkWidget ();
1039    if (images == null) error (SWT.ERROR_INVALID_ARGUMENT);
1040    for (int i = 0; i < images.length; i++) {
1041        if (images [i] == null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
1042    }
1043    this.images = images;
1044    setImages (null, images);
1045}
1046
1047/**
1048 * Sets the maximized state of the receiver.
1049 * If the argument is <code>true</code> causes the receiver
1050 * to switch to the maximized state, and if the argument is
1051 * <code>false</code> and the receiver was previously maximized,
1052 * causes the receiver to switch back to either the minimized
1053 * or normal states.
1054 * <p>
1055 * Note: The result of intermixing calls to <code>setMaximized(true)</code>
1056 * and <code>setMinimized(true)</code> will vary by platform. Typically,
1057 * the behavior will match the platform user's expectations, but not
1058 * always. This should be avoided if possible.
1059 * </p>
1060 *
1061 * @param maximized the new maximized state
1062 *
1063 * @exception SWTException <ul>
1064 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1065 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1066 * </ul>
1067 *
1068 * @see #setMinimized
1069 */

1070public void setMaximized (boolean maximized) {
1071    checkWidget ();
1072    Display.lpStartupInfo = null;
1073    _setMaximized (maximized);
1074}
1075
1076/**
1077 * Sets the receiver's menu bar to the argument, which
1078 * may be null.
1079 *
1080 * @param menu the new menu bar
1081 *
1082 * @exception IllegalArgumentException <ul>
1083 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
1084 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
1085 * </ul>
1086 * @exception SWTException <ul>
1087 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1088 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1089 * </ul>
1090 */

1091public void setMenuBar (Menu menu) {
1092    checkWidget ();
1093    if (menuBar == menu) return;
1094    if (menu != null) {
1095        if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
1096        if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
1097        if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
1098    }
1099    if (OS.IsWinCE) {
1100        if (OS.IsHPC) {
1101            boolean resize = menuBar != menu;
1102            if (menuBar != null) OS.CommandBar_Show (menuBar.hwndCB, false);
1103            menuBar = menu;
1104            if (menuBar != null) OS.CommandBar_Show (menuBar.hwndCB, true);
1105            if (resize) {
1106                sendEvent (SWT.Resize);
1107                if (isDisposed ()) return;
1108                if (layout != null) {
1109                    markLayout (false, false);
1110                    updateLayout (true, false);
1111                }
1112            }
1113        } else {
1114            if (OS.IsPPC) {
1115                /*
1116                * Note in WinCE PPC. The menu bar is a separate popup window.
1117                * If the shell is full screen, resize its window to leave
1118                * space for the menu bar.
1119                */

1120                boolean resize = getMaximized () && menuBar != menu;
1121                if (menuBar != null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE);
1122                menuBar = menu;
1123                if (menuBar != null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW);
1124                if (resize) _setMaximized (true);
1125            }
1126            if (OS.IsSP) {
1127                if (menuBar != null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE);
1128                menuBar = menu;
1129                if (menuBar != null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW);
1130            }
1131        }
1132    } else {
1133        if (menu != null) display.removeBar (menu);
1134        menuBar = menu;
1135        int hMenu = menuBar != null ? menuBar.handle: 0;
1136        OS.SetMenu (handle, hMenu);
1137    }
1138    destroyAccelerators ();
1139}
1140
1141/**
1142 * Sets the minimized stated of the receiver.
1143 * If the argument is <code>true</code> causes the receiver
1144 * to switch to the minimized state, and if the argument is
1145 * <code>false</code> and the receiver was previously minimized,
1146 * causes the receiver to switch back to either the maximized
1147 * or normal states.
1148 * <p>
1149 * Note: The result of intermixing calls to <code>setMaximized(true)</code>
1150 * and <code>setMinimized(true)</code> will vary by platform. Typically,
1151 * the behavior will match the platform user's expectations, but not
1152 * always. This should be avoided if possible.
1153 * </p>
1154 *
1155 * @param minimized the new maximized state
1156 *
1157 * @exception SWTException <ul>
1158 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1159 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1160 * </ul>
1161 *
1162 * @see #setMaximized
1163 */

1164public void setMinimized (boolean minimized) {
1165    checkWidget ();
1166    Display.lpStartupInfo = null;
1167    _setMinimized (minimized);
1168}
1169
1170void setParent () {
1171    /*
1172    * In order for an MDI child window to support
1173    * a menu bar, setParent () is needed to reset
1174    * the parent. Otherwise, the MDI child window
1175    * will appear as a separate shell. This is an
1176    * undocumented and possibly dangerous Windows
1177    * feature.
1178    */

1179    int hwndParent = parent.handle;
1180    display.lockActiveWindow = true;
1181    OS.SetParent (handle, hwndParent);
1182    if (!OS.IsWindowVisible (hwndParent)) {
1183        OS.ShowWindow (handle, OS.SW_SHOWNA);
1184    }
1185    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1186    bits &= ~OS.WS_CHILD;
1187    OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP);
1188    OS.SetWindowLong (handle, OS.GWL_ID, 0);
1189    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
1190    SetWindowPos (handle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
1191    display.lockActiveWindow = false;
1192}
1193
1194void setPlacement (int x, int y, int width, int height, int flags) {
1195    WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
1196    lpwndpl.length = WINDOWPLACEMENT.sizeof;
1197    OS.GetWindowPlacement (handle, lpwndpl);
1198    lpwndpl.showCmd = OS.SW_SHOWNA;
1199    if (OS.IsIconic (handle)) {
1200        lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE;
1201    } else {
1202        if (OS.IsZoomed (handle)) {
1203            lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED;
1204        }
1205    }
1206    boolean sameOrigin = true;
1207    if ((flags & OS.SWP_NOMOVE) == 0) {
1208        sameOrigin = lpwndpl.left != x || lpwndpl.top != y;
1209        lpwndpl.right = x + (lpwndpl.right - lpwndpl.left);
1210        lpwndpl.bottom = y + (lpwndpl.bottom - lpwndpl.top);
1211        lpwndpl.left = x;
1212        lpwndpl.top = y;
1213    }
1214    boolean sameExtent = true;
1215    if ((flags & OS.SWP_NOSIZE) == 0) {
1216        sameExtent = lpwndpl.right - lpwndpl.left != width || lpwndpl.bottom - lpwndpl.top != height;
1217        lpwndpl.right = lpwndpl.left + width;
1218        lpwndpl.bottom = lpwndpl.top + height;
1219    }
1220    OS.SetWindowPlacement (handle, lpwndpl);
1221    if (OS.IsIconic (handle)) {
1222        if (sameOrigin) {
1223            moved = true;
1224            Point location = getLocation ();
1225            oldX = location.x;
1226            oldY = location.y;
1227            sendEvent (SWT.Move);
1228            if (isDisposed ()) return;
1229        }
1230        if (sameExtent) {
1231            resized = true;
1232            Rectangle rect = getClientArea ();
1233            oldWidth = rect.width;
1234            oldHeight = rect.height;
1235            sendEvent (SWT.Resize);
1236            if (isDisposed ()) return;
1237            if (layout != null) {
1238                markLayout (false, false);
1239                updateLayout (true, false);
1240            }
1241        }
1242    }
1243}
1244
1245void setSavedFocus (Control control) {
1246    savedFocus = control;
1247}
1248
1249void setSystemMenu () {
1250    if (OS.IsWinCE) return;
1251    int hMenu = OS.GetSystemMenu (handle, false);
1252    if (hMenu == 0) return;
1253    int oldCount = OS.GetMenuItemCount (hMenu);
1254    if ((style & SWT.RESIZE) == 0) {
1255        OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND);
1256    }
1257    if ((style & SWT.MIN) == 0) {
1258        OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND);
1259    }
1260    if ((style & SWT.MAX) == 0) {
1261        OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND);
1262    }
1263    if ((style & (SWT.MIN | SWT.MAX)) == 0) {
1264        OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND);
1265    }
1266    int newCount = OS.GetMenuItemCount (hMenu);
1267    if ((style & SWT.CLOSE) == 0 || newCount != oldCount) {
1268        OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND);
1269        MENUITEMINFO info = new MENUITEMINFO ();
1270        info.cbSize = MENUITEMINFO.sizeof;
1271        info.fMask = OS.MIIM_ID;
1272        int index = 0;
1273        while (index < newCount) {
1274            if (OS.GetMenuItemInfo (hMenu, index, true, info)) {
1275                if (info.wID == OS.SC_CLOSE) break;
1276            }
1277            index++;
1278        }
1279        if (index != newCount) {
1280            OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION);
1281            if ((style & SWT.CLOSE) == 0) {
1282                OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND);
1283            }
1284        }
1285    }
1286}
1287
1288/**
1289 * Sets the receiver's text, which is the string that the
1290 * window manager will typically display as the receiver's
1291 * <em>title</em>, to the argument, which must not be null.
1292 *
1293 * @param string the new text
1294 *
1295 * @exception IllegalArgumentException <ul>
1296 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1297 * </ul>
1298 * @exception SWTException <ul>
1299 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1300 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1301 * </ul>
1302 */

1303public void setText (String JavaDoc string) {
1304    checkWidget ();
1305    if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1306    /* Use the character encoding for the default locale */
1307    TCHAR buffer = new TCHAR (0, string, true);
1308    OS.SetWindowText (handle, buffer);
1309}
1310
1311public void setVisible (boolean visible) {
1312    checkWidget ();
1313    if (drawCount != 0) {
1314        if (((state & HIDDEN) == 0) == visible) return;
1315    } else {
1316        if (visible == OS.IsWindowVisible (handle)) return;
1317    }
1318    if (visible) {
1319        /*
1320        * It is possible (but unlikely), that application
1321        * code could have disposed the widget in the show
1322        * event. If this happens, just return.
1323        */

1324        sendEvent (SWT.Show);
1325        if (isDisposed ()) return;
1326        if (OS.IsHPC) {
1327            if (menuBar != null) {
1328                int hwndCB = menuBar.hwndCB;
1329                OS.CommandBar_DrawMenuBar (hwndCB, 0);
1330            }
1331        }
1332        if (drawCount != 0) {
1333            state &= ~HIDDEN;
1334        } else {
1335            if (OS.IsWinCE) {
1336                OS.ShowWindow (handle, OS.SW_SHOW);
1337            } else {
1338                if (menuBar != null) {
1339                    display.removeBar (menuBar);
1340                    OS.DrawMenuBar (handle);
1341                }
1342                STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
1343                if (lpStartUpInfo != null && (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) != 0) {
1344                    OS.ShowWindow (handle, lpStartUpInfo.wShowWindow);
1345                } else {
1346                    OS.ShowWindow (handle, swFlags);
1347                }
1348            }
1349            if (isDisposed ()) return;
1350            opened = true;
1351            if (!moved) {
1352                moved = true;
1353                Point location = getLocation ();
1354                oldX = location.x;
1355                oldY = location.y;
1356            }
1357            if (!resized) {
1358                resized = true;
1359                Rectangle rect = getClientArea ();
1360                oldWidth = rect.width;
1361                oldHeight = rect.height;
1362            }
1363            OS.UpdateWindow (handle);
1364        }
1365    } else {
1366        if (!OS.IsWinCE) {
1367            if (OS.IsIconic (handle)) {
1368                swFlags = OS.SW_SHOWMINNOACTIVE;
1369            } else {
1370                if (OS.IsZoomed (handle)) {
1371                    swFlags = OS.SW_SHOWMAXIMIZED;
1372                } else {
1373                    if (handle == OS.GetActiveWindow ()) {
1374                        swFlags = OS.SW_RESTORE;
1375                    } else {
1376                        swFlags = OS.SW_SHOWNOACTIVATE;
1377                    }
1378                }
1379            }
1380        }
1381        if (drawCount != 0) {
1382            state |= HIDDEN;
1383        } else {
1384            OS.ShowWindow (handle, OS.SW_HIDE);
1385        }
1386        if (isDisposed ()) return;
1387        sendEvent (SWT.Hide);
1388    }
1389}
1390
1391void sort (Image [] images, ImageData [] datas, int width, int height, int depth) {
1392    /* Shell Sort from K&R, pg 108 */
1393    int length = images.length;
1394    if (length <= 1) return;
1395    for (int gap=length/2; gap>0; gap/=2) {
1396        for (int i=gap; i<length; i++) {
1397            for (int j=i-gap; j>=0; j-=gap) {
1398                if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) {
1399                    Image swap = images [j];
1400                    images [j] = images [j + gap];
1401                    images [j + gap] = swap;
1402                    ImageData swapData = datas [j];
1403                    datas [j] = datas [j + gap];
1404                    datas [j + gap] = swapData;
1405                }
1406            }
1407        }
1408    }
1409}
1410
1411boolean translateAccelerator (MSG msg) {
1412    if (!isEnabled () || !isActive ()) return false;
1413    if (menuBar != null && !menuBar.isEnabled ()) return false;
1414    if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true;
1415    Decorations decorations = parent.menuShell ();
1416    return decorations.translateAccelerator (msg);
1417}
1418
1419boolean translateMenuAccelerator (MSG msg) {
1420    if (hAccel == -1) createAccelerators ();
1421    return hAccel != 0 && OS.TranslateAccelerator (handle, hAccel, msg) != 0;
1422}
1423
1424boolean translateMDIAccelerator (MSG msg) {
1425    if (!(this instanceof Shell)) {
1426        Shell shell = getShell ();
1427        int hwndMDIClient = shell.hwndMDIClient;
1428        if (hwndMDIClient != 0 && OS.TranslateMDISysAccel (hwndMDIClient, msg)) {
1429            return true;
1430        }
1431        if (msg.message == OS.WM_KEYDOWN) {
1432            if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
1433            switch (msg.wParam) {
1434                case OS.VK_F4:
1435                    OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1436                    return true;
1437                case OS.VK_F6:
1438                    if (traverseDecorations (true)) return true;
1439            }
1440            return false;
1441        }
1442        if (msg.message == OS.WM_SYSKEYDOWN) {
1443            switch (msg.wParam) {
1444                case OS.VK_F4:
1445                    OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
1446                    return true;
1447            }
1448            return false;
1449        }
1450    }
1451    return false;
1452}
1453
1454boolean traverseDecorations (boolean next) {
1455    Control [] children = parent._getChildren ();
1456    int length = children.length;
1457    int index = 0;
1458    while (index < length) {
1459        if (children [index] == this) break;
1460        index++;
1461    }
1462    /*
1463    * It is possible (but unlikely), that application
1464    * code could have disposed the widget in focus in
1465    * or out events. Ensure that a disposed widget is
1466    * not accessed.
1467    */

1468    int start = index, offset = (next) ? 1 : -1;
1469    while ((index = (index + offset + length) % length) != start) {
1470        Control child = children [index];
1471        if (!child.isDisposed () && child instanceof Decorations) {
1472            if (child.setFocus ()) return true;
1473        }
1474    }
1475    return false;
1476}
1477
1478boolean traverseItem (boolean next) {
1479    return false;
1480}
1481
1482boolean traverseReturn () {
1483    if (defaultButton == null || defaultButton.isDisposed ()) return false;
1484    if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false;
1485    defaultButton.click ();
1486    return true;
1487}
1488
1489CREATESTRUCT widgetCreateStruct () {
1490    return new CREATESTRUCT ();
1491}
1492
1493int widgetExtStyle () {
1494    int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD;
1495    bits &= ~OS.WS_EX_CLIENTEDGE;
1496    if ((style & SWT.NO_TRIM) != 0) return bits;
1497    if (OS.IsPPC) {
1498        if ((style & SWT.CLOSE) != 0) bits |= OS.WS_EX_CAPTIONOKBTN;
1499    }
1500    if ((style & SWT.RESIZE) != 0) return bits;
1501    if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME;
1502    return bits;
1503}
1504
1505int widgetParent () {
1506    Shell shell = getShell ();
1507    return shell.hwndMDIClient ();
1508}
1509
1510int widgetStyle () {
1511    /*
1512    * Clear WS_VISIBLE and WS_TABSTOP. NOTE: In Windows, WS_TABSTOP
1513    * has the same value as WS_MAXIMIZEBOX so these bits cannot be
1514    * used to control tabbing.
1515    */

1516    int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE);
1517    
1518    /* Set the title bits and no-trim bits */
1519    bits &= ~OS.WS_BORDER;
1520    if ((style & SWT.NO_TRIM) != 0) return bits;
1521    if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
1522    
1523    /* Set the min and max button bits */
1524    if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX;
1525    if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX;
1526    
1527    /* Set the resize, dialog border or border bits */
1528    if ((style & SWT.RESIZE) != 0) {
1529        /*
1530        * Note on WinCE PPC. SWT.RESIZE is used to resize
1531        * the Shell according to the state of the IME.
1532        * It does not set the WS_THICKFRAME style.
1533        */

1534        if (!OS.IsPPC) bits |= OS.WS_THICKFRAME;
1535    } else {
1536        if ((style & SWT.BORDER) == 0) bits |= OS.WS_BORDER;
1537    }
1538
1539    /* Set the system menu and close box bits */
1540    if (!OS.IsPPC && !OS.IsSP) {
1541        if ((style & SWT.CLOSE) != 0) bits |= OS.WS_SYSMENU;
1542    }
1543    
1544    return bits;
1545}
1546
1547int windowProc (int hwnd, int msg, int wParam, int lParam) {
1548    switch (msg) {
1549        case Display.SWT_GETACCEL:
1550        case Display.SWT_GETACCELCOUNT:
1551            if (hAccel == -1) createAccelerators ();
1552            return msg == Display.SWT_GETACCELCOUNT ? nAccel : hAccel;
1553    }
1554    return super.windowProc (hwnd, msg, wParam, lParam);
1555}
1556
1557LRESULT WM_ACTIVATE (int wParam, int lParam) {
1558    LRESULT result = super.WM_ACTIVATE (wParam, lParam);
1559    if (result != null) return result;
1560    /*
1561    * Feature in AWT. When an AWT Window is activated,
1562    * for some reason, it seems to forward the WM_ACTIVATE
1563    * message to the parent. Normally, the parent is an
1564    * AWT Frame. When AWT is embedded in SWT, the SWT
1565    * shell gets the WM_ACTIVATE and assumes that it came
1566    * from Windows. When an SWT shell is activated it
1567    * restores focus to the last control that had focus.
1568    * If this control is an embedded composite, it takes
1569    * focus from the AWT Window. The fix is to ignore
1570    * WM_ACTIVATE messages that come from AWT Windows.
1571    */

1572    if (OS.GetParent (lParam) == handle) {
1573        TCHAR buffer = new TCHAR (0, 128);
1574        OS.GetClassName (lParam, buffer, buffer.length ());
1575        String JavaDoc className = buffer.toString (0, buffer.strlen ());
1576        if (className.equals (Display.AWT_WINDOW_CLASS)) {
1577            return LRESULT.ZERO;
1578        }
1579    }
1580    if ((wParam & 0xFFFF) != 0) {
1581        /*
1582        * When the high word of wParam is non-zero, the activation
1583        * state of the window is being changed while the window is
1584        * minimized. If this is the case, do not report activation
1585        * events or restore the focus.
1586        */

1587        if ((wParam >> 16) != 0) return result;
1588        Control control = display.findControl (lParam);
1589        if (control == null || control instanceof Shell) {
1590            if (this instanceof Shell) {
1591                sendEvent (SWT.Activate);
1592                if (isDisposed ()) return LRESULT.ZERO;
1593            }
1594        }
1595        if (restoreFocus ()) return LRESULT.ZERO;
1596    } else {
1597        Display display = this.display;
1598        boolean lockWindow = display.isXMouseActive ();
1599        if (lockWindow) display.lockActiveWindow = true;
1600        Control control = display.findControl (lParam);
1601        if (control == null || control instanceof Shell) {
1602            if (this instanceof Shell) {
1603                sendEvent (SWT.Deactivate);
1604                if (!isDisposed ()) {
1605                    Shell shell = getShell ();
1606                    shell.setActiveControl (null);
1607                    // widget could be disposed at this point
1608
}
1609            }
1610        }
1611        if (lockWindow) display.lockActiveWindow = false;
1612        if (isDisposed ()) return LRESULT.ZERO;
1613        saveFocus ();
1614    }
1615    return result;
1616}
1617
1618LRESULT WM_CLOSE (int wParam, int lParam) {
1619    LRESULT result = super.WM_CLOSE (wParam, lParam);
1620    if (result != null) return result;
1621    if (isEnabled () && isActive ()) closeWidget ();
1622    return LRESULT.ZERO;
1623}
1624
1625LRESULT WM_HOTKEY (int wParam, int lParam) {
1626    LRESULT result = super.WM_HOTKEY (wParam, lParam);
1627    if (result != null) return result;
1628    if (OS.IsSP) {
1629        /*
1630        * Feature on WinCE SP. The Back key is either used to close
1631        * the foreground Dialog or used as a regular Back key in an EDIT
1632        * control. The article 'Back Key' in MSDN for Smartphone
1633        * describes how an application should handle it. The
1634        * workaround is to override the Back key when creating
1635        * the menubar and handle it based on the style of the Shell.
1636        * If the Shell has the SWT.CLOSE style, close the Shell.
1637        * Otherwise, send the Back key to the window with focus.
1638        */

1639        if (((lParam >> 16) & 0xFFFF) == OS.VK_ESCAPE) {
1640            if ((style & SWT.CLOSE) != 0) {
1641                OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1642            } else {
1643                OS.SHSendBackToFocusWindow (OS.WM_HOTKEY, wParam, lParam);
1644            }
1645            return LRESULT.ZERO;
1646        }
1647    }
1648    return result;
1649}
1650
1651LRESULT WM_KILLFOCUS (int wParam, int lParam) {
1652    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
1653    saveFocus ();
1654    return result;
1655}
1656
1657LRESULT WM_MOVE (int wParam, int lParam) {
1658    if (moved) {
1659        Point location = getLocation ();
1660        if (location.x == oldX && location.y == oldY) {
1661            return null;
1662        }
1663        oldX = location.x;
1664        oldY = location.y;
1665    }
1666    return super.WM_MOVE (wParam, lParam);
1667}
1668
1669LRESULT WM_NCACTIVATE (int wParam, int lParam) {
1670    LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
1671    if (result != null) return result;
1672    if (wParam == 0) {
1673        if (display.lockActiveWindow) return LRESULT.ZERO;
1674        Control control = display.findControl (lParam);
1675        if (control != null) {
1676            Shell shell = getShell ();
1677            Decorations decorations = control.menuShell ();
1678            if (decorations.getShell () == shell) {
1679                if (this instanceof Shell) return LRESULT.ONE;
1680                if (display.ignoreRestoreFocus) {
1681                    if (display.lastHittest != OS.HTCLIENT) {
1682                        result = LRESULT.ONE;
1683                    }
1684                }
1685            }
1686        }
1687    }
1688    if (!(this instanceof Shell)) {
1689        int hwndShell = getShell().handle;
1690        OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam);
1691    }
1692    return result;
1693}
1694
1695LRESULT WM_QUERYOPEN (int wParam, int lParam) {
1696    LRESULT result = super.WM_QUERYOPEN (wParam, lParam);
1697    if (result != null) return result;
1698    sendEvent (SWT.Deiconify);
1699    // widget could be disposed at this point
1700
return result;
1701}
1702
1703LRESULT WM_SETFOCUS (int wParam, int lParam) {
1704    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
1705    if (savedFocus != this) restoreFocus ();
1706    return result;
1707}
1708
1709LRESULT WM_SIZE (int wParam, int lParam) {
1710    LRESULT result = null;
1711    boolean changed = true;
1712    if (resized) {
1713        int newWidth = 0, newHeight = 0;
1714        switch (wParam) {
1715            case OS.SIZE_RESTORED:
1716            case OS.SIZE_MAXIMIZED:
1717                newWidth = lParam & 0xFFFF;
1718                newHeight = lParam >> 16;
1719                break;
1720            case OS.SIZE_MINIMIZED:
1721                Rectangle rect = getClientArea ();
1722                newWidth = rect.width;
1723                newHeight = rect.height;
1724                break;
1725        }
1726        changed = newWidth != oldWidth || newHeight != oldHeight;
1727        if (changed) {
1728            oldWidth = newWidth;
1729            oldHeight = newHeight;
1730        }
1731    }
1732    if (changed) {
1733        result = super.WM_SIZE (wParam, lParam);
1734        if (isDisposed ()) return result;
1735    }
1736    if (wParam == OS.SIZE_MINIMIZED) {
1737        sendEvent (SWT.Iconify);
1738        // widget could be disposed at this point
1739
}
1740    return result;
1741}
1742
1743LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
1744    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
1745    if (result != null) return result;
1746    if (!(this instanceof Shell)) {
1747        int cmd = wParam & 0xFFF0;
1748        switch (cmd) {
1749            case OS.SC_CLOSE: {
1750                OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1751                return LRESULT.ZERO;
1752            }
1753            case OS.SC_NEXTWINDOW: {
1754                traverseDecorations (true);
1755                return LRESULT.ZERO;
1756            }
1757        }
1758    }
1759    return result;
1760}
1761
1762LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
1763    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
1764    if (result != null) return result;
1765    if (display.lockActiveWindow) {
1766        WINDOWPOS lpwp = new WINDOWPOS ();
1767        OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
1768        lpwp.flags |= OS.SWP_NOZORDER;
1769        OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
1770    }
1771    return result;
1772}
1773
1774}
1775
Popular Tags