/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.widgets;
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.graphics.*;
/**
* Instances of this class provide the appearance and
* behavior of Shells
, but are not top
* level shells or dialogs. Class Shell
* shares a significant amount of code with this class,
* and is a subclass.
*
* IMPORTANT: This class was intended to be abstract and
* should never be referenced or instantiated.
* Instead, the class Shell
should be used.
*
*
* Instances are always displayed in one of the maximized,
* minimized or normal states:
*
* -
* When an instance is marked as maximized, 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
RESIZE
) until it is
* no longer maximized.
* -
* When an instance is in the normal 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).
*
-
* When an instance has been marked as minimized,
* 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.
*
*
*
* Note: The styles supported by this class must be treated
* as HINTs, 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.
*
* - Styles:
* - BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL
* - Events:
* - (none)
*
* Class SWT
provides two "convenience constants"
* for the most commonly required style combinations:
*
* SHELL_TRIM
* -
* the result of combining the constants which are required
* to produce a typical application top level shell: (that
* is,
CLOSE | TITLE | MIN | MAX | RESIZE
)
*
* DIALOG_TRIM
* -
* the result of combining the constants which are required
* to produce a typical application dialog shell: (that
* is,
TITLE | CLOSE | BORDER
)
*
*
*
* IMPORTANT: This class is intended to be subclassed only
* within the SWT implementation.
*
*
* @see #getMinimized
* @see #getMaximized
* @see Shell
* @see SWT
* @see Sample code and further information
* @noextend This class is not intended to be subclassed by clients.
*/
public class Decorations extends Canvas {
String text;
Image image;
Image [] images = new Image [0];
boolean minimized, maximized;
Menu menuBar;
Menu [] menus;
Control savedFocus;
Button defaultButton, saveDefault;
long /*int*/ accelGroup, vboxHandle;
Decorations () {
/* Do nothing */
}
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
*
* The style value is either one of the style constants defined in
* class SWT
which is applicable to instances of this
* class, or must be built by bitwise OR'ing together
* (that is, using the int
"|" operator) two or more
* of those SWT
style constants. The class description
* lists the style constants that are applicable to the class.
* Style bits are also inherited from superclasses.
*
*
* @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
* - ERROR_NULL_ARGUMENT - if the parent is null
*
* @exception SWTException
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
* - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
*
*
* @see SWT#BORDER
* @see SWT#CLOSE
* @see SWT#MIN
* @see SWT#MAX
* @see SWT#RESIZE
* @see SWT#TITLE
* @see SWT#NO_TRIM
* @see SWT#SHELL_TRIM
* @see SWT#DIALOG_TRIM
* @see SWT#ON_TOP
* @see SWT#TOOL
* @see Widget#checkSubclass
* @see Widget#getStyle
*/
public Decorations (Composite parent, int style) {
super (parent, checkStyle (style));
}
static int checkStyle (int style) {
if ((style & SWT.NO_TRIM) != 0) {
style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER);
}
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 _setImages (Image [] images) {
if (images != null && images.length > 1) {
Image [] bestImages = new Image [images.length];
System.arraycopy (images, 0, bestImages, 0, images.length);
sort (bestImages);
images = bestImages;
}
long /*int*/ pixbufs = 0;
if (images != null) {
for (int i = 0; i < images.length; i++) {
Image image = images [i];
long /*int*/ pixbuf = ImageList.createPixbuf (image);
pixbufs = OS.g_list_append (pixbufs, pixbuf);
}
}
OS.gtk_window_set_icon_list (topHandle (), pixbufs);
long /*int*/ [] data = new long /*int*/ [1];
long /*int*/ temp = pixbufs;
while (temp != 0) {
OS.memmove (data, temp, OS.PTR_SIZEOF);
OS.g_object_unref (data [0]);
temp = OS.g_list_next (temp);
}
if (pixbufs != 0) OS.g_list_free (pixbufs);
}
void addMenu (Menu menu) {
if (menus == null) menus = new Menu [4];
for (int i=0; i data2.width || data1.height > data2.height ? -1 : 1;
}
Widget computeTabGroup () {
return this;
}
Control computeTabRoot () {
return this;
}
void createAccelGroup () {
if (accelGroup != 0) return;
accelGroup = OS.gtk_accel_group_new ();
if (accelGroup == 0) error (SWT.ERROR_NO_HANDLES);
//FIXME - what should we do for Decorations
long /*int*/ shellHandle = topHandle ();
OS.gtk_window_add_accel_group (shellHandle, accelGroup);
}
void createWidget (int index) {
super.createWidget (index);
text = "";
}
void destroyAccelGroup () {
if (accelGroup == 0) return;
long /*int*/ shellHandle = topHandle ();
OS.gtk_window_remove_accel_group (shellHandle, accelGroup);
//TEMPORARY CODE
// OS.g_object_unref (accelGroup);
accelGroup = 0;
}
void fixAccelGroup () {
if (menuBar == null) return;
destroyAccelGroup ();
createAccelGroup ();
menuBar.addAccelerators (accelGroup);
}
void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) {
if (this == newDecorations) return;
if (control == savedFocus) savedFocus = null;
if (control == defaultButton) defaultButton = null;
if (control == saveDefault) saveDefault = null;
if (menus == null) return;
Menu menu = control.menu;
if (menu != null) {
int index = 0;
while (index
* ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @see #setDefaultButton(Button)
*/
public Button getDefaultButton () {
checkWidget();
Button button = defaultButton != null ? defaultButton : saveDefault;
if (button != null && button.isDisposed ()) return null;
return button;
}
/**
* Returns the receiver's image if it had previously been
* set using setImage()
. 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.
*
* Note: This method will return null if called before
* setImage()
is called. It does not provide
* access to a window manager provided, "default" image
* even if one exists.
*
*
* @return the image
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public Image getImage () {
checkWidget ();
return image;
}
/**
* Returns the receiver's images if they had previously been
* set using setImages()
. Images are 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. Depending where the icon is displayed, the platform
* chooses the icon with the "best" attributes. It is expected
* that the array will contain the same icon rendered at different
* sizes, with different depth and transparency attributes.
*
*
* Note: This method will return an empty array if called before
* setImages()
is called. It does not provide
* access to a window manager provided, "default" image
* even if one exists.
*
*
* @return the images
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public Image [] getImages () {
checkWidget ();
if (images == null) return new Image [0];
Image [] result = new Image [images.length];
System.arraycopy (images, 0, result, 0, images.length);
return result;
}
/**
* Returns true
if the receiver is currently
* maximized, and false otherwise.
*
*
* @return the maximized state
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @see #setMaximized
*/
public boolean getMaximized () {
checkWidget();
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
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public Menu getMenuBar () {
checkWidget();
return menuBar;
}
/**
* Returns true
if the receiver is currently
* minimized, and false otherwise.
*
*
* @return the minimized state
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @see #setMinimized
*/
public boolean getMinimized () {
checkWidget();
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
* title. If the text has not previously been set,
* returns an empty string.
*
* @return the text
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public String getText () {
checkWidget();
return text;
}
public boolean isReparentable () {
checkWidget ();
return false;
}
boolean isTabGroup () {
return true;
}
boolean isTabItem () {
return false;
}
Decorations menuShell () {
return this;
}
void removeMenu (Menu menu) {
if (menus == null) return;
for (int i=0; isaved default button). 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.
*
* The default button is the button that is selected when
* the receiver is active and the user presses ENTER.
*
*
* @param button the new default button
*
* @exception IllegalArgumentException
* - ERROR_INVALID_ARGUMENT - if the button has been disposed
* - ERROR_INVALID_PARENT - if the control is not in the same widget tree
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public void setDefaultButton (Button button) {
checkWidget();
long /*int*/ buttonHandle = 0;
if (button != null) {
if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
if (button.menuShell () != this) error (SWT.ERROR_INVALID_PARENT);
buttonHandle = button.handle;
}
saveDefault = defaultButton = button;
OS.gtk_window_set_default (topHandle (), buttonHandle);
}
/**
* 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 IllegalArgumentException
* - ERROR_INVALID_ARGUMENT - if the image has been disposed
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public void setImage (Image image) {
checkWidget ();
this.image = image;
_setImages (image != null ? new Image [] {image} : null);
}
/**
* Sets the receiver's images to the argument, which may
* be an empty array. Images are 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. Depending where
* the icon is displayed, the platform chooses the icon with
* the "best" attributes. It is expected that the array will
* contain the same icon rendered at different sizes, with
* different depth and transparency attributes.
*
* @param images the new image array
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the array of images is null
* - ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public void setImages (Image [] images) {
checkWidget ();
if (images == null) error (SWT.ERROR_INVALID_ARGUMENT);
for (int i = 0; i < images.length; i++) {
if (images [i] == null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
}
this.images = images;
_setImages (images);
}
/**
* Sets the maximized state of the receiver.
* If the argument is true
causes the receiver
* to switch to the maximized state, and if the argument is
* false
and the receiver was previously maximized,
* causes the receiver to switch back to either the minimized
* or normal states.
*
* Note: The result of intermixing calls to setMaximized(true)
* and setMinimized(true)
will vary by platform. Typically,
* the behavior will match the platform user's expectations, but not
* always. This should be avoided if possible.
*
*
* @param maximized the new maximized state
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @see #setMinimized
*/
public void setMaximized (boolean maximized) {
checkWidget();
this.maximized = maximized;
}
/**
* Sets the receiver's menu bar to the argument, which
* may be null.
*
* @param menu the new menu bar
*
* @exception IllegalArgumentException
* - ERROR_INVALID_ARGUMENT - if the menu has been disposed
* - ERROR_INVALID_PARENT - if the menu is not in the same widget tree
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
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;
}
/**
* Sets the minimized stated of the receiver.
* If the argument is true
causes the receiver
* to switch to the minimized state, and if the argument is
* false
and the receiver was previously minimized,
* causes the receiver to switch back to either the maximized
* or normal states.
*
* Note: The result of intermixing calls to setMaximized(true)
* and setMinimized(true)
will vary by platform. Typically,
* the behavior will match the platform user's expectations, but not
* always. This should be avoided if possible.
*
*
* @param minimized the new maximized state
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @see #setMaximized
*/
public void setMinimized (boolean minimized) {
checkWidget();
this.minimized = minimized;
}
void setOrientation (boolean create) {
super.setOrientation (create);
if (!create) {
if (menuBar != null) menuBar._setOrientation (style & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT));
}
}
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
* title, to the argument, which must not be null.
*
* @param string the new text
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the text is null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public void setText (String string) {
checkWidget();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
text = string;
}
void sort (Image [] images) {
/* Shell Sort from K&R, pg 108 */
int length = images.length;
if (length <= 1) return;
ImageData [] datas = new ImageData [length];
for (int i = 0; i < length; i++) {
datas [i] = images [i].getImageData ();
}
for (int gap=length/2; gap>0; gap/=2) {
for (int i=gap; i=0; j-=gap) {
if (compare (datas [j], datas [j + gap]) >= 0) {
Image swap = images [j];
images [j] = images [j + gap];
images [j + gap] = swap;
ImageData swapData = datas [j];
datas [j] = datas [j + gap];
datas [j + gap] = swapData;
}
}
}
}
}
boolean traverseItem (boolean next) {
return false;
}
boolean traverseReturn () {
Button button = defaultButton != null ? defaultButton: saveDefault;
if (button == null || button.isDisposed ()) return false;
/*
* Bug in GTK. When a default button that is disabled is
* activated using the Enter key, GTK GP's. The fix is to
* detect this case and stop GTK from processing the Enter
* key.
*/
if (!button.isVisible () || !button.isEnabled ()) return true;
long /*int*/ shellHandle = _getShell ().topHandle ();
return OS.gtk_window_activate_default (shellHandle);
}
}