| package org.eclipse.swt.widgets;
|
|
|
| /*
|
| * (c) Copyright IBM Corp. 2000, 2001.
|
| * All Rights Reserved
|
| */
|
|
|
| import org.eclipse.swt.internal.motif.*;
|
| 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 {
|
| String label;
|
| Image image;
|
| int dialogHandle;
|
| boolean minimized, maximized;
|
| Menu menuBar;
|
| Menu [] menus;
|
| Control savedFocus;
|
| Button defaultButton, saveDefault;
|
| Decorations () {
|
| /* Do nothing */
|
| }
|
| /** |
| * 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 bringToTop () {
|
| /*
|
| * Feature in X. Calling XSetInputFocus() when the
|
| * widget is not viewable causes an X bad match error.
|
| * The fix is to call XSetInputFocus() when the widget
|
| * is viewable.
|
| */
|
| if (minimized) return;
|
| if (!isVisible ()) return;
|
| int display = OS.XtDisplay (handle);
|
| if (display == 0) return;
|
| int window = OS.XtWindow (handle);
|
| if (window == 0) return;
|
| OS.XSetInputFocus (display, window, OS.RevertToParent, OS.CurrentTime);
|
| }
|
| 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);
|
| }
|
| public Rectangle computeTrim (int x, int y, int width, int height) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| Rectangle trim = super.computeTrim (x, y, width, height);
|
| if (menuBar != null) {
|
| XtWidgetGeometry request = new XtWidgetGeometry ();
|
| XtWidgetGeometry result = new XtWidgetGeometry ();
|
| request.request_mode = OS.CWWidth;
|
| request.width = trim.width;
|
| OS.XtQueryGeometry (menuBar.handle, request, result);
|
| trim.height += result.height;
|
| }
|
| return trim;
|
| }
|
| void createHandle (int index) {
|
| state |= HANDLE | CANVAS;
|
| createScrolledHandle (parent.handle);
|
| }
|
| void createWidget (int index) {
|
| super.createWidget (index);
|
| label = "";
|
| }
|
| int dialogHandle () {
|
| if (dialogHandle != 0) return dialogHandle;
|
| return dialogHandle = OS.XmCreateDialogShell (handle, null, null, 0);
|
| }
|
| /** |
| * 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| return image;
|
| }
|
| /** |
| * 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| return maximized;
|
| }
|
| /** |
| * 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| return minimized;
|
| }
|
| String getNameText () {
|
| return getText ();
|
| }
|
| /** |
| * 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 () {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| return label;
|
| }
|
| Decorations menuShell () {
|
| return this;
|
| }
|
| void propagateWidget (boolean enabled) {
|
| super.propagateWidget (enabled);
|
| int [] argList = {OS.XmNmenuBar, 0};
|
| OS.XtGetValues (scrolledHandle, argList, argList.length / 2);
|
| if (argList [1] != 0) propagateHandle (enabled, argList [1]);
|
| }
|
| void releaseHandle () {
|
| super.releaseHandle ();
|
| dialogHandle = 0;
|
| }
|
| void releaseWidget () {
|
| if (menus != null) {
|
| for (int i=0; i<menus.length; i++) {
|
| Menu menu = menus [i];
|
| if (menu != null && !menu.isDisposed ()) {
|
| menu.releaseWidget ();
|
| menu.releaseHandle ();
|
| }
|
| }
|
| }
|
| menuBar = null;
|
| menus = null;
|
| super.releaseWidget ();
|
| defaultButton = saveDefault = null;
|
| label = null;
|
| }
|
| void remove (Menu menu) {
|
| if (menus == null) return;
|
| for (int i=0; i<menus.length; i++) {
|
| if (menus [i] == menu) {
|
| menus [i] = null;
|
| return;
|
| }
|
| }
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| 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;
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| int pixmap = 0, mask = 0;
|
| if (image != null) {
|
| switch (image.type) {
|
| case SWT.BITMAP:
|
| pixmap = image.pixmap;
|
| break;
|
| case SWT.ICON:
|
| pixmap = image.pixmap;
|
| mask = image.mask;
|
| break;
|
| default:
|
| error (SWT.ERROR_INVALID_IMAGE);
|
| }
|
| }
|
| this.image = image;
|
| int [] argList = {
|
| OS.XmNiconPixmap, pixmap,
|
| OS.XmNiconMask, mask,
|
| };
|
| int topHandle = topHandle ();
|
| OS.XtSetValues (topHandle, argList, argList.length / 2);
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| this.maximized = maximized;
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| 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);
|
| }
|
|
|
| /* Ensure the new menu bar is correctly enabled */
|
| if (menuBar != null) {
|
| if (!isEnabled () && menuBar.getEnabled ()) {
|
| propagateHandle (true, menuBar.handle);
|
| }
|
| }
|
| if (menu != null) {
|
| if (!isEnabled ()) {
|
| propagateHandle (false, menu.handle);
|
| }
|
| }
|
|
|
| /*
|
| * Bug in Motif. When a XmMainWindowSetAreas () is used
|
| * to replace an existing menu, both menus must be managed
|
| * before the call to XmMainWindowSetAreas () or the new
|
| * menu will not be layed out properly.
|
| */
|
| int newHandle = (menu != null) ? menu.handle : 0;
|
| int oldHandle = (menuBar != null) ? menuBar.handle : 0;
|
| menuBar = menu;
|
| int hHandle = (horizontalBar != null) ? horizontalBar.handle : 0;
|
| int vHandle = (verticalBar != null) ? verticalBar.handle : 0;
|
| if (newHandle != 0) {
|
| OS.XtSetMappedWhenManaged (newHandle, false);
|
| OS.XtManageChild (newHandle);
|
| }
|
| int clientHandle = (formHandle != 0) ? formHandle : handle;
|
| OS.XmMainWindowSetAreas (scrolledHandle, newHandle, 0, hHandle, vHandle, clientHandle);
|
| if (oldHandle != 0) OS.XtUnmanageChild (oldHandle);
|
| if (newHandle != 0) {
|
| OS.XtSetMappedWhenManaged (newHandle, true);
|
| }
|
|
|
| /*
|
| * Bug in Motif. When a menu bar is removed after the
|
| * main window has been realized, the main window does
|
| * not layout the new menu bar or the work window.
|
| * The fix is to force a layout by temporarily resizing
|
| * the main window.
|
| */
|
| if (newHandle == 0 && OS.XtIsRealized (scrolledHandle)) {
|
| int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0, OS.XmNborderWidth, 0};
|
| OS.XtGetValues (scrolledHandle, argList, argList.length / 2);
|
| OS.XtResizeWidget (scrolledHandle, argList [1] + 1, argList [3], argList [5]);
|
| OS.XtResizeWidget (scrolledHandle, argList [1], argList [3], argList [5]);
|
| }
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| this.minimized = minimized;
|
| }
|
| void setSavedFocus (Control control) {
|
| if (this == control) return;
|
| savedFocus = control;
|
| }
|
| /** |
| * 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) {
|
| if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
| if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
|
| if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
|
| label = string;
|
| }
|
| public void setVisible (boolean visible) {
|
| super.setVisible (visible);
|
| if (!visible) return;
|
| if (savedFocus != null && !savedFocus.isDisposed ()) {
|
| savedFocus.setFocus ();
|
| }
|
| savedFocus = null;
|
| }
|
| }
|