package org.eclipse.swt.widgets; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved | |
*/ | |
import org.eclipse.swt.internal.*; | |
import org.eclipse.swt.internal.win32.*; | |
import org.eclipse.swt.*; | |
import org.eclipse.swt.graphics.*; | |
/** | |
* Instances of this class provide the appearance and | |
* behavior of <code>Shells</code>, but are not top | |
* level shells or dialogs. Class <code>Shell</code> | |
* shares a significant amount of code with this class, | |
* and is a subclass. | |
* <p> | |
* Instances are always displayed in one of the maximized, | |
* minimized or normal states: | |
* <ul> | |
* <li> | |
* When an instance is marked as <em>maximized</em>, the | |
* window manager will typically resize it to fill the | |
* entire visible area of the display, and the instance | |
* is usually put in a state where it can not be resized | |
* (even if it has style <code>RESIZE</code>) until it is | |
* no longer maximized. | |
* </li><li> | |
* When an instance is in the <em>normal</em> state (neither | |
* maximized or minimized), its appearance is controlled by | |
* the style constants which were specified when it was created | |
* and the restrictions of the window manager (see below). | |
* </li><li> | |
* When an instance has been marked as <em>minimized</em>, | |
* its contents (client area) will usually not be visible, | |
* and depending on the window manager, it may be | |
* "iconified" (that is, replaced on the desktop by a small | |
* simplified representation of itself), relocated to a | |
* distinguished area of the screen, or hidden. Combinations | |
* of these changes are also possible. | |
* </li> | |
* </ul> | |
* </p> | |
* Note: The styles supported by this class must be treated | |
* as <em>HINT</em>s, since the window manager for the | |
* desktop on which the instance is visible has ultimate | |
* control over the appearance and behavior of decorations. | |
* For example, some window managers only support resizable | |
* windows and will always assume the RESIZE style, even if | |
* it is not set. | |
* <dl> | |
* <dt><b>Styles:</b></dt> | |
* <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE</dd> | |
* <dt><b>Events:</b></dt> | |
* <dd>(none)</dd> | |
* </dl> | |
* Class <code>SWT</code> provides two "convenience constants" | |
* for the most commonly required style combinations: | |
* <dl> | |
* <dt><code>SHELL_TRIM</code></dt> | |
* <dd> | |
* the result of combining the constants which are required | |
* to produce a typical application top level shell: (that | |
* is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>) | |
* </dd> | |
* <dt><code>DIALOG_TRIM</code></dt> | |
* <dd> | |
* the result of combining the constants which are required | |
* to produce a typical application dialog shell: (that | |
* is, <code>TITLE | CLOSE | BORDER</code>) | |
* </dd> | |
* </dl> | |
* <p> | |
* IMPORTANT: This class is intended to be subclassed <em>only</em> | |
* within the SWT implementation. | |
* </p> | |
* | |
* @see #getMinimized | |
* @see #getMaximized | |
* @see Shell | |
* @see SWT | |
*/ | |
public class Decorations extends Canvas { | |
Image image; | |
Menu menuBar; | |
Menu [] menus; | |
MenuItem [] items; | |
Control savedFocus; | |
Button defaultButton, saveDefault; | |
int swFlags, hAccel, nAccel; | |
/** | |
* Prevents uninitialized instances from being created outside the package. | |
*/ | |
Decorations () { | |
} | |
/** | |
* Constructs a new instance of this class given its parent | |
* and a style value describing its behavior and appearance. | |
* <p> | |
* The style value is either one of the style constants defined in | |
* class <code>SWT</code> which is applicable to instances of this | |
* class, or must be built by <em>bitwise OR</em>'ing together | |
* (that is, using the <code>int</code> "|" operator) two or more | |
* of those <code>SWT</code> style constants. The class description | |
* for all SWT widget classes should include a comment which | |
* describes the style constants which are applicable to the class. | |
* </p> | |
* | |
* @param parent a composite control which will be the parent of the new instance (cannot be null) | |
* @param style the style of control to construct | |
* | |
* @exception IllegalArgumentException <ul> | |
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
* </ul> | |
* @exception SWTException <ul> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
* </ul> | |
* | |
* @see SWT | |
* @see Widget#checkSubclass | |
* @see Widget#getStyle | |
*/ | |
public Decorations (Composite parent, int style) { | |
super (parent, checkStyle (style)); | |
} | |
void add (Menu menu) { | |
if (menus == null) menus = new Menu [4]; | |
for (int i=0; i<menus.length; i++) { | |
if (menus [i] == null) { | |
menus [i] = menu; | |
return; | |
} | |
} | |
Menu [] newMenus = new Menu [menus.length + 4]; | |
newMenus [menus.length] = menu; | |
System.arraycopy (menus, 0, newMenus, 0, menus.length); | |
menus = newMenus; | |
} | |
void add (MenuItem item) { | |
if (items == null) items = new MenuItem [12]; | |
for (int i=0; i<items.length; i++) { | |
if (items [i] == null) { | |
items [item.id = i] = item; | |
return; | |
} | |
} | |
MenuItem [] newItems = new MenuItem [items.length + 12]; | |
newItems [item.id = items.length] = item; | |
System.arraycopy (items, 0, newItems, 0, items.length); | |
items = newItems; | |
} | |
void bringToTop () { | |
/* | |
* This code is intentionally commented. On some platforms, | |
* the NO_TRIM style creates a shell that will stay on top | |
* of every other shell on the desktop. Using SetWindowPos () | |
* with HWND_TOP caused problems on Windows so this code is | |
* commented out until this functionality is specified and | |
* the problems are fixed. | |
*/ | |
// if ((style & SWT.NO_TRIM) != 0) { | |
// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; | |
// OS.SetWindowPos (handle, OS.HWND_TOP, 0, 0, 0, 0, flags); | |
// } else { | |
OS.BringWindowToTop (handle); | |
// } | |
} | |
static int checkStyle (int style) { | |
if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) != 0) { | |
style |= SWT.TITLE; | |
} | |
return style; | |
} | |
protected void checkSubclass () { | |
if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
} | |
void createAcceleratorTable () { | |
hAccel = nAccel = 0; | |
if (menuBar == null || items == null) return; | |
int size = ACCEL.sizeof; | |
ACCEL accel = new ACCEL (); | |
byte [] buffer1 = new byte [size]; | |
byte [] buffer2 = new byte [items.length * size]; | |
for (int i=0; i<items.length; i++) { | |
MenuItem item = items [i]; | |
if (item != null && item.accelerator != 0) { | |
Menu parent = item.parent; | |
while (parent != null && parent != menuBar) { | |
parent = parent.getParentMenu (); | |
} | |
if (parent == menuBar) { | |
item.fillAccel (accel); | |
OS.MoveMemory (buffer1, accel, size); | |
System.arraycopy (buffer1, 0, buffer2, nAccel * size, size); | |
nAccel++; | |
} | |
} | |
} | |
if (nAccel != 0) hAccel = OS.CreateAcceleratorTable (buffer2, nAccel); | |
} | |
void createHandle () { | |
super.createHandle (); | |
if (parent == null) return; | |
setParent (); | |
setSystemMenu (); | |
} | |
void createWidget () { | |
/* | |
* Bug in Windows. If WS_MINIMIZEBOX or WS_MAXIMIZEBOX | |
* are set, we must also set WS_SYSMENU or the buttons | |
* will not appear. | |
*/ | |
if ((style & (SWT.MIN | SWT.MAX)) != 0) style |= SWT.CLOSE; | |
super.createWidget (); | |
swFlags = OS.SW_SHOWNOACTIVATE; | |
hAccel = -1; | |
} | |
Control currentTabGroup () { | |
return this; | |
} | |
void destroyAcceleratorTable () { | |
if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel); | |
hAccel = -1; | |
} | |
Menu findMenu (int hMenu) { | |
if (menus == null) return null; | |
for (int i=0; i<menus.length; i++) { | |
Menu menu = menus [i]; | |
if ((menu != null) && (hMenu == menu.handle)) return menu; | |
} | |
return null; | |
} | |
MenuItem findMenuItem (int id) { | |
if (items == null) return null; | |
if (0 <= id && id < items.length) return items [id]; | |
return null; | |
} | |
public Rectangle getBounds () { | |
checkWidget (); | |
if (OS.IsIconic (handle)) { | |
WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); | |
lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
OS.GetWindowPlacement (handle, lpwndpl); | |
int width = lpwndpl.right - lpwndpl.left; | |
int height = lpwndpl.bottom - lpwndpl.top; | |
return new Rectangle (lpwndpl.left, lpwndpl.top, width, height); | |
} | |
return super.getBounds (); | |
} | |
public Rectangle getClientArea () { | |
checkWidget (); | |
RECT rect = new RECT (); | |
if (OS.IsIconic (handle)) { | |
WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); | |
lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
OS.GetWindowPlacement (handle, lpwndpl); | |
int width = lpwndpl.right - lpwndpl.left; | |
int height = lpwndpl.bottom - lpwndpl.top; | |
OS.SetRect (rect, 0, 0, width, height); | |
OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, rect); | |
return new Rectangle (0, 0, rect.right, rect.bottom); | |
} | |
return super.getClientArea (); | |
} | |
/** | |
* Returns the receiver's default button if one had | |
* previously been set, otherwise returns null. | |
* | |
* @return the default button or null | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see #setDefaultButton | |
*/ | |
public Button getDefaultButton () { | |
checkWidget (); | |
return defaultButton; | |
} | |
/** | |
* Returns the receiver's image if it had previously been | |
* set using <code>setImage()</code>. The image is typically | |
* displayed by the window manager when the instance is | |
* marked as iconified, and may also be displayed somewhere | |
* in the trim when the instance is in normal or maximized | |
* states. | |
* <p> | |
* Note: This method will return null if called before | |
* <code>setImage()</code> is called. It does not provide | |
* access to a window manager provided, "default" image | |
* even if one exists. | |
* </p> | |
* | |
* @return the image | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public Image getImage () { | |
checkWidget (); | |
return image; | |
} | |
public Point getLocation () { | |
checkWidget (); | |
if (OS.IsIconic (handle)) { | |
WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); | |
lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
OS.GetWindowPlacement (handle, lpwndpl); | |
return new Point (lpwndpl.left, lpwndpl.top); | |
} | |
return super.getLocation (); | |
} | |
/** | |
* Returns <code>true</code> if the receiver is currently | |
* maximized, and false otherwise. | |
* <p> | |
* | |
* @return the maximized state | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see #setMaximized | |
*/ | |
public boolean getMaximized () { | |
checkWidget (); | |
if (OS.IsWindowVisible (handle)) return OS.IsZoomed (handle); | |
return swFlags == OS.SW_SHOWMAXIMIZED; | |
} | |
/** | |
* Returns the receiver's menu bar if one had previously | |
* been set, otherwise returns null. | |
* | |
* @return the menu bar or null | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public Menu getMenuBar () { | |
checkWidget (); | |
return menuBar; | |
} | |
/** | |
* Returns <code>true</code> if the receiver is currently | |
* minimized, and false otherwise. | |
* <p> | |
* | |
* @return the minimized state | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see #setMinimized | |
*/ | |
public boolean getMinimized () { | |
checkWidget (); | |
if (OS.IsWindowVisible (handle)) return OS.IsIconic (handle); | |
return swFlags == OS.SW_SHOWMINNOACTIVE; | |
} | |
String getNameText () { | |
return getText (); | |
} | |
public Point getSize () { | |
checkWidget (); | |
if (OS.IsIconic (handle)) { | |
WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); | |
lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
OS.GetWindowPlacement (handle, lpwndpl); | |
int width = lpwndpl.right - lpwndpl.left; | |
int height = lpwndpl.bottom - lpwndpl.top; | |
return new Point (width, height); | |
} | |
RECT rect = new RECT (); | |
OS.GetWindowRect (handle, rect); | |
int width = rect.right - rect.left; | |
int height = rect.bottom - rect.top; | |
return new Point (width, height); | |
} | |
/** | |
* Returns the receiver's text, which is the string that the | |
* window manager will typically display as the receiver's | |
* <em>title</em>. If the text has not previously been set, | |
* returns an empty string. | |
* | |
* @return the text | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public String getText () { | |
checkWidget (); | |
int length = OS.GetWindowTextLength (handle); | |
if (length == 0) return ""; | |
byte [] buffer1 = new byte [length + 1]; | |
OS.GetWindowText (handle, buffer1, buffer1.length); | |
char [] buffer2 = Converter.mbcsToWcs (0, buffer1); | |
return new String (buffer2, 0, buffer2.length - 1); | |
} | |
Decorations menuShell () { | |
return this; | |
} | |
void releaseWidget () { | |
if (menuBar != null) { | |
menuBar.releaseWidget (); | |
menuBar.releaseHandle (); | |
} | |
menuBar = null; | |
if (menus != null) { | |
for (int i=0; i<menus.length; i++) { | |
Menu menu = menus [i]; | |
if (menu != null && !menu.isDisposed ()) { | |
menu.dispose (); | |
} | |
} | |
} | |
menus = null; | |
super.releaseWidget (); | |
if (image != null) { | |
int hOld = OS.SendMessage (handle, OS.WM_GETICON, OS.ICON_BIG, 0); | |
if (hOld != 0 && image.handle != hOld) OS.DestroyIcon (hOld); | |
} | |
items = null; | |
image = null; | |
savedFocus = null; | |
defaultButton = saveDefault = null; | |
if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel); | |
hAccel = -1; | |
} | |
void remove (Menu menu) { | |
if (menus == null) return; | |
for (int i=0; i<menus.length; i++) { | |
if (menus [i] == menu) { | |
menus [i] = null; | |
return; | |
} | |
} | |
} | |
void remove (MenuItem item) { | |
if (items == null) return; | |
items [item.id] = null; | |
item.id = -1; | |
} | |
boolean restoreFocus () { | |
if (savedFocus != null && savedFocus.isDisposed ()) savedFocus = null; | |
if (savedFocus == null) return false; | |
return savedFocus.forceFocus (); | |
} | |
void saveFocus () { | |
Control control = getDisplay ().getFocusControl (); | |
if (control != null) setSavedFocus (control); | |
} | |
void setBounds (int x, int y, int width, int height, int flags) { | |
if (OS.IsIconic (handle)) { | |
WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT (); | |
lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
OS.GetWindowPlacement (handle, lpwndpl); | |
lpwndpl.showCmd = 0; | |
if ((flags & OS.SWP_NOMOVE) == 0) { | |
lpwndpl.left = x; | |
lpwndpl.top = y; | |
} | |
if ((flags & OS.SWP_NOSIZE) == 0) { | |
lpwndpl.right = x + width; | |
lpwndpl.bottom = y + height; | |
} | |
OS.SetWindowPlacement (handle, lpwndpl); | |
return; | |
} | |
super.setBounds (x, y, width, height, flags); | |
} | |
/** | |
* If the argument is not null, sets the receiver's default | |
* button to the argument, and if the argument is null, sets | |
* the receiver's default button to the first button which | |
* was set as the receiver's default button (called the | |
* <em>saved default button</em>). If no default button had | |
* previously been set, or the saved default button was | |
* disposed, the receiver's default button will be set to | |
* null. | |
* | |
* @param the new default button | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setDefaultButton (Button button) { | |
checkWidget (); | |
setDefaultButton (button, true); | |
} | |
void setDefaultButton (Button button, boolean save) { | |
if (button == null) { | |
if (defaultButton == saveDefault) return; | |
} else { | |
if ((button.style & SWT.PUSH) == 0) return; | |
if (button == defaultButton) return; | |
} | |
if (defaultButton != null) { | |
if (!defaultButton.isDisposed ()) defaultButton.setDefault (false); | |
} | |
if ((defaultButton = button) == null) defaultButton = saveDefault; | |
if (defaultButton != null) { | |
if (!defaultButton.isDisposed ()) defaultButton.setDefault (true); | |
} | |
if (save || saveDefault == null) saveDefault = defaultButton; | |
if (saveDefault != null && saveDefault.isDisposed ()) saveDefault = null; | |
} | |
public boolean setFocus () { | |
checkWidget (); | |
if (this instanceof Shell) return super.setFocus (); | |
/* | |
* Bug in Windows. Setting the focus to a child of the | |
* receiver interferes with moving and resizing of the | |
* parent shell. The fix (for now) is to always set the | |
* focus to the shell. | |
*/ | |
int hwndFocus = OS.SetFocus (getShell ().handle); | |
return hwndFocus == OS.GetFocus (); | |
} | |
/** | |
* Sets the receiver's image to the argument, which may | |
* be null. The image is typically displayed by the window | |
* manager when the instance is marked as iconified, and | |
* may also be displayed somewhere in the trim when the | |
* instance is in normal or maximized states. | |
* | |
* @param image the new image (or null) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setImage (Image image) { | |
checkWidget (); | |
int hIcon = 0; | |
if (image != null) { | |
switch (image.type) { | |
case SWT.BITMAP: | |
int hOld = OS.SendMessage (handle, OS.WM_GETICON, OS.ICON_BIG, 0); | |
if (hOld != 0 && image != null) { | |
int hImage = this.image.handle; | |
if (hImage != hOld) OS.DestroyIcon (hOld); | |
} | |
/* Copy the bitmap in case it's a DIB */ | |
int hBitmap = image.handle; | |
BITMAP bm = new BITMAP (); | |
OS.GetObject (hBitmap, BITMAP.sizeof, bm); | |
byte [] lpvBits = new byte [(bm.bmWidth + 15) / 16 * 2 * bm.bmHeight]; | |
int hMask = OS.CreateBitmap (bm.bmWidth, bm.bmHeight, 1, 1, lpvBits); | |
int hDC = OS.GetDC (handle); | |
int hdcMem = OS.CreateCompatibleDC (hDC); | |
int hColor = OS.CreateCompatibleBitmap (hDC, bm.bmWidth, bm.bmHeight); | |
OS.SelectObject (hdcMem, hColor); | |
int hdcBmp = OS.CreateCompatibleDC (hDC); | |
OS.SelectObject (hdcBmp, hBitmap); | |
OS.BitBlt (hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcBmp, 0, 0, OS.SRCCOPY); | |
ICONINFO info = new ICONINFO (); | |
info.fIcon = true; | |
info.hbmMask = hMask; | |
info.hbmColor = hColor; | |
hIcon = OS.CreateIconIndirect (info); | |
OS.DeleteObject (hMask); | |
OS.DeleteObject(hColor); | |
OS.DeleteDC (hdcBmp); | |
OS.DeleteDC (hdcMem); | |
OS.ReleaseDC (handle, hDC); | |
break; | |
case SWT.ICON: | |
hIcon = image.handle; | |
break; | |
default: | |
return; | |
} | |
} | |
this.image = image; | |
OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_BIG, hIcon); | |
/* | |
* Bug in Windows. When WM_SETICON is used to remove an | |
* icon from the window trimmings for a window with the | |
* extended style bits WS_EX_DLGMODALFRAME, the window | |
* trimmings do not redraw to hide the previous icon. | |
* The fix is to force a redraw. | |
*/ | |
if (hIcon == 0 && ((style & SWT.BORDER) != 0)) { | |
OS.RedrawWindow (handle, null, 0, OS.RDW_FRAME | OS.RDW_INVALIDATE); | |
} | |
} | |
/** | |
* Sets the maximized state of the receiver. | |
* If the argument is <code>true</code> causes the receiver | |
* to switch to the maximized state, and if the argument is | |
* <code>false</code> and the receiver was previously maximized, | |
* causes the receiver to switch back to either the minimized | |
* or normal states. | |
* <p> | |
* Note: The result of intermixing calls to<code>setMaximized(true)</code> | |
* and <code>setMinimized(true)</code> will vary by platform. Typically, | |
* the behavior will match the platform user's expectations, but not | |
* always. This should be avoided if possible. | |
* </p> | |
* | |
* @param the new maximized state | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see #setMinimized | |
*/ | |
public void setMaximized (boolean maximized) { | |
checkWidget (); | |
swFlags = OS.SW_RESTORE; | |
if (maximized) swFlags = OS.SW_SHOWMAXIMIZED; | |
if (!OS.IsWindowVisible (handle)) return; | |
if (maximized == OS.IsZoomed (handle)) return; | |
OS.ShowWindow (handle, swFlags); | |
OS.UpdateWindow (handle); | |
} | |
/** | |
* Sets the receiver's menu bar to the argument, which | |
* may be null. | |
* | |
* @param menu the new menu bar | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setMenuBar (Menu menu) { | |
checkWidget (); | |
if (menuBar == menu) return; | |
if (menu != null) { | |
if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR); | |
if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT); | |
} | |
menuBar = menu; | |
int hMenu = 0; | |
if (menuBar != null) hMenu = menuBar.handle; | |
OS.SetMenu (handle, hMenu); | |
destroyAcceleratorTable (); | |
} | |
/** | |
* Sets the minimized stated of the receiver. | |
* If the argument is <code>true</code> causes the receiver | |
* to switch to the minimized state, and if the argument is | |
* <code>false</code> and the receiver was previously minimized, | |
* causes the receiver to switch back to either the maximized | |
* or normal states. | |
* <p> | |
* Note: The result of intermixing calls to<code>setMaximized(true)</code> | |
* and <code>setMinimized(true)</code> will vary by platform. Typically, | |
* the behavior will match the platform user's expectations, but not | |
* always. This should be avoided if possible. | |
* </p> | |
* | |
* @param the new maximized state | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see #setMaximized | |
*/ | |
public void setMinimized (boolean minimized) { | |
checkWidget (); | |
swFlags = OS.SW_RESTORE; | |
if (minimized) swFlags = OS.SW_SHOWMINNOACTIVE; | |
if (!OS.IsWindowVisible (handle)) return; | |
if (minimized == OS.IsIconic (handle)) return; | |
OS.ShowWindow (handle, swFlags); | |
OS.UpdateWindow (handle); | |
} | |
void setParent () { | |
/* | |
* In order for an MDI child window to support | |
* a menu bar, setParent () is needed to reset | |
* the parent. Otherwise, the MDI child window | |
* will appear as a separate shell. This is an | |
* undocumented and dangerous Windows feature. | |
*/ | |
Display display = getDisplay (); | |
int hwndParent = parent.handle; | |
display.lockActiveWindow = true; | |
OS.SetParent (handle, hwndParent); | |
if (!OS.IsWindowVisible (hwndParent)) { | |
OS.ShowWindow (handle, OS.SW_SHOWNA); | |
} | |
display.lockActiveWindow = false; | |
} | |
void setSavedFocus (Control control) { | |
if (this == control) { | |
savedFocus = null; | |
return; | |
} | |
if (this != control.menuShell ()) return; | |
savedFocus = control; | |
} | |
void setSystemMenu () { | |
int hMenu = OS.GetSystemMenu (handle, false); | |
if (hMenu == 0) return; | |
int oldCount = OS.GetMenuItemCount (hMenu); | |
if ((style & SWT.RESIZE) == 0) { | |
OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND); | |
} | |
if ((style & SWT.MIN) == 0) { | |
OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND); | |
} | |
if ((style & SWT.MAX) == 0) { | |
OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND); | |
} | |
if ((style & (SWT.MIN | SWT.MAX)) == 0) { | |
OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND); | |
} | |
int newCount = OS.GetMenuItemCount (hMenu); | |
if ((style & SWT.CLOSE) == 0 || newCount != oldCount) { | |
OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND); | |
MENUITEMINFO info = new MENUITEMINFO (); | |
info.cbSize = MENUITEMINFO.sizeof; | |
info.fMask = OS.MIIM_ID; | |
int index = 0; | |
while (index < newCount) { | |
if (OS.GetMenuItemInfo (hMenu, index, true, info)) { | |
if (info.wID == OS.SC_CLOSE) break; | |
} | |
index++; | |
} | |
if (index != newCount) { | |
OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION); | |
if ((style & SWT.CLOSE) == 0) { | |
OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND); | |
} | |
} | |
} | |
} | |
/** | |
* Sets the receiver's text, which is the string that the | |
* window manager will typically display as the receiver's | |
* <em>title</em>, to the argument, which may not be null. | |
* | |
* @param text the new text | |
* | |
* @exception IllegalArgumentException <ul> | |
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
* </ul> | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setText (String string) { | |
checkWidget (); | |
if (string == null) error (SWT.ERROR_NULL_ARGUMENT); | |
byte [] buffer = Converter.wcsToMbcs (0, string, true); | |
OS.SetWindowText (handle, buffer); | |
} | |
public void setVisible (boolean visible) { | |
checkWidget (); | |
if (visible == OS.IsWindowVisible (handle)) return; | |
if (visible) { | |
/* | |
* It is possible (but unlikely), that application | |
* code could have disposed the widget in the show | |
* event. If this happens, just return. | |
*/ | |
sendEvent (SWT.Show); | |
if (isDisposed ()) return; | |
OS.DrawMenuBar (handle); | |
OS.ShowWindow (handle, swFlags); | |
OS.UpdateWindow (handle); | |
} else { | |
if (OS.IsIconic (handle)) { | |
swFlags = OS.SW_SHOWMINNOACTIVE; | |
} else { | |
if (OS.IsZoomed (handle)) { | |
swFlags = OS.SW_SHOWMAXIMIZED; | |
} else { | |
if (handle == OS.GetActiveWindow ()) { | |
swFlags = OS.SW_RESTORE; | |
} else { | |
swFlags = OS.SW_SHOWNOACTIVATE; | |
} | |
} | |
} | |
OS.ShowWindow (handle, OS.SW_HIDE); | |
sendEvent (SWT.Hide); | |
} | |
} | |
boolean translateAccelerator (MSG msg) { | |
if (!isEnabled ()) return false; | |
if (hAccel == -1) createAcceleratorTable (); | |
if (hAccel == 0) return false; | |
return OS.TranslateAccelerator (handle, hAccel, msg) != 0; | |
} | |
boolean traverseItem (boolean next) { | |
return false; | |
} | |
int widgetExtStyle () { | |
int bits = 0; | |
if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW; | |
if ((style & SWT.RESIZE) != 0) return bits; | |
if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME; | |
return bits; | |
} | |
int widgetStyle () { | |
/* Set WS_POPUP and clear WS_VISIBLE and WS_TABSTOP */ | |
int bits = super.widgetStyle () | OS.WS_POPUP; | |
bits &= ~(OS.WS_VISIBLE | OS.WS_TABSTOP); | |
/* Set the title bits and no-trim bits */ | |
bits &= ~OS.WS_BORDER; | |
if ((style & SWT.NO_TRIM) != 0) return bits; | |
if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION; | |
/* Set the min and max button bits */ | |
if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX; | |
if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX; | |
/* | |
* Bug in Windows. The WS_CAPTION style must be | |
* set when the window is resizable or it does not | |
* draw properly. | |
*/ | |
if ((style & SWT.RESIZE) != 0) { | |
bits |= OS.WS_CAPTION | OS.WS_THICKFRAME; | |
} else { | |
if ((style & SWT.BORDER) == 0) bits |= OS.WS_BORDER; | |
} | |
/* | |
* Feature in Windows. Both WS_SYSMENU and WS_CAPTION | |
* must be set in order to get a system menu. | |
*/ | |
if ((style & SWT.CLOSE) != 0) { | |
bits |= OS.WS_SYSMENU | OS.WS_CAPTION; | |
} | |
return bits; | |
} | |
int windowProc (int msg, int wParam, int lParam) { | |
switch (msg) { | |
case OS.WM_APP: | |
case OS.WM_APP+1: | |
if (hAccel == -1) createAcceleratorTable (); | |
return msg == OS.WM_APP ? nAccel : hAccel; | |
} | |
return super.windowProc (msg, wParam, lParam); | |
} | |
LRESULT WM_ACTIVATE (int wParam, int lParam) { | |
LRESULT result = super.WM_ACTIVATE (wParam, lParam); | |
if (result != null) return result; | |
if ((wParam & 0xFFFF) == 0) { | |
/* | |
* It is possible (but unlikely), that application | |
* code could have disposed the widget in the deactivate | |
* event. If this happens, end the processing of the | |
* Windows message by returning zero as the result of | |
* the window proc. | |
*/ | |
sendEvent (SWT.Deactivate); | |
if (isDisposed ()) return LRESULT.ZERO; | |
saveFocus (); | |
} else { | |
/* | |
* It is possible (but unlikely), that application | |
* code could have disposed the widget in the activate | |
* event. If this happens, end the processing of the | |
* Windows message by returning zero as the result of | |
* the window proc. | |
*/ | |
sendEvent (SWT.Activate); | |
if (isDisposed ()) return LRESULT.ZERO; | |
if (restoreFocus ()) return LRESULT.ZERO; | |
} | |
return result; | |
} | |
LRESULT WM_CLOSE (int wParam, int lParam) { | |
LRESULT result = super.WM_CLOSE (wParam, lParam); | |
if (result != null) return result; | |
Event event = new Event (); | |
sendEvent (SWT.Close, event); | |
// the widget could be disposed at this point | |
if (event.doit && !isDisposed ()) dispose (); | |
return LRESULT.ZERO; | |
} | |
LRESULT WM_KILLFOCUS (int wParam, int lParam) { | |
LRESULT result = super.WM_KILLFOCUS (wParam, lParam); | |
if (result != null) return result; | |
saveFocus (); | |
return result; | |
} | |
LRESULT WM_NCACTIVATE (int wParam, int lParam) { | |
LRESULT result = super.WM_NCACTIVATE (wParam, lParam); | |
if (result != null) return result; | |
if (wParam == 0) { | |
Display display = getDisplay (); | |
if (display.lockActiveWindow) return LRESULT.ZERO; | |
} | |
return result; | |
} | |
LRESULT WM_QUERYOPEN (int wParam, int lParam) { | |
LRESULT result = super.WM_QUERYOPEN (wParam, lParam); | |
if (result != null) return result; | |
sendEvent (SWT.Deiconify); | |
// widget could be disposed at this point | |
return result; | |
} | |
LRESULT WM_SETFOCUS (int wParam, int lParam) { | |
LRESULT result = super.WM_SETFOCUS (wParam, lParam); | |
if (result != null) return result; | |
restoreFocus (); | |
return result; | |
} | |
LRESULT WM_SIZE (int wParam, int lParam) { | |
LRESULT result = super.WM_SIZE (wParam, lParam); | |
/* | |
* It is possible (but unlikely), that application | |
* code could have disposed the widget in the resize | |
* event. If this happens, end the processing of the | |
* Windows message by returning the result of the | |
* WM_SIZE message. | |
*/ | |
if (isDisposed ()) return result; | |
if (wParam == OS.SIZE_MINIMIZED) { | |
sendEvent (SWT.Iconify); | |
// widget could be disposed at this point | |
} | |
return result; | |
} | |
} |