Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java275
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java466
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java650
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java23
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java291
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java540
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java133
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java3112
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java59
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java1127
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java695
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java217
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java712
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java1877
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java408
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Button.java652
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Canvas.java313
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Caret.java530
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ColorDialog.java158
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Combo.java1424
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Composite.java1157
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Control.java3621
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolBar.java709
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolItem.java665
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Decorations.java895
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/DirectoryDialog.java171
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Display.java3018
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandBar.java459
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandItem.java397
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FileDialog.java374
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FontDialog.java243
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Group.java240
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Label.java320
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Link.java461
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/List.java1186
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Menu.java916
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MenuItem.java739
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MessageBox.java197
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ProgressBar.java262
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Sash.java305
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scale.java361
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ScrollBar.java693
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scrollable.java313
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Shell.java1536
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Slider.java492
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Spinner.java991
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabFolder.java731
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabItem.java406
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Table.java2417
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableColumn.java644
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableItem.java1208
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Text.java1510
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolBar.java471
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolItem.java849
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tracker.java892
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TrayItem.java447
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tree.java2406
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeColumn.java613
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeItem.java1638
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Widget.java1478
60 files changed, 50093 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java
new file mode 100644
index 0000000000..6fc68ac112
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage the operating system resources that
+ * implement SWT's RGB color model. To create a color you can either
+ * specify the individual color components as integers in the range
+ * 0 to 255 or provide an instance of an <code>RGB</code>.
+ * <p>
+ * Application code must explicitly invoke the <code>Color.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see RGB
+ * @see Device#getSystemColor
+ * @see <a href="http://www.eclipse.org/swt/snippets/#color">Color and RGB snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Color extends Resource {
+
+ /**
+ * the handle to the OS color resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Color(Device device) {
+ super(device);
+}
+
+/**
+ * Constructs a new instance of this class given a device and the
+ * desired red, green and blue values expressed as ints in the range
+ * 0 to 255 (where 0 is black and 255 is full brightness). On limited
+ * color devices, the color instance created by this call may not have
+ * the same RGB values as the ones specified by the arguments. The
+ * RGB values on the returned instance will be the color values of
+ * the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public Color (Device device, int red, int green, int blue) {
+ super(device);
+ init(red, green, blue);
+ init();
+}
+
+/**
+ * Constructs a new instance of this class given a device and an
+ * <code>RGB</code> describing the desired red, green and blue values.
+ * On limited color devices, the color instance created by this call
+ * may not have the same RGB values as the ones specified by the
+ * argument. The RGB values on the returned instance will be the color
+ * values of the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param rgb the RGB values of the desired color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the rgb argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public Color (Device device, RGB rgb) {
+ super(device);
+ if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(rgb.red, rgb.green, rgb.blue);
+ init();
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Color)) return false;
+ Color color = (Color) object;
+ return device == color.device && (handle & 0xFFFFFF) == (color.handle & 0xFFFFFF);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getBlue () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_B(handle) & 0xFF;
+}
+
+/**
+ * Returns the amount of green in the color, from 0 to 255.
+ *
+ * @return the green component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getGreen () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_G(handle) & 0xFF;
+}
+
+/**
+ * Returns the amount of red in the color, from 0 to 255.
+ *
+ * @return the red component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getRed () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_R(handle) & 0xFF;
+}
+
+/**
+ * Returns an <code>RGB</code> representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public RGB getRGB () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return new RGB(OS.Color_R(handle) & 0xFF, OS.Color_G(handle) & 0xFF, OS.Color_B(handle) & 0xFF);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Allocates the operating system resources associated
+ * with the receiver.
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+void init(int red, int green, int blue) {
+ if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle = OS.Color_FromArgb((byte)0xFF, (byte)red, (byte)green, (byte)blue);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Returns <code>true</code> if the color has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the color.
+ * When a color has been disposed, it is an error to
+ * invoke any other method using the color.
+ *
+ * @return <code>true</code> when the color is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$
+ return "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new color.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Color</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the color
+ * @return a new color object containing the specified device and handle
+ */
+public static Color wpf_new(Device device, int handle) {
+ Color color = new Color(device);
+ color.handle = handle;
+ return color;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java
new file mode 100644
index 0000000000..e1b617cb7f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java
@@ -0,0 +1,466 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.internal.win32.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage operating system resources that
+ * specify the appearance of the on-screen pointer. To create a
+ * cursor you specify the device and either a simple cursor style
+ * describing one of the standard operating system provided cursors
+ * or the image and mask data for the desired appearance.
+ * <p>
+ * Application code must explicitly invoke the <code>Cursor.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>
+ * CURSOR_ARROW, CURSOR_WAIT, CURSOR_CROSS, CURSOR_APPSTARTING, CURSOR_HELP,
+ * CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE,
+ * CURSOR_SIZEN, CURSOR_SIZES, CURSOR_SIZEE, CURSOR_SIZEW, CURSOR_SIZENE, CURSOR_SIZESE,
+ * CURSOR_SIZESW, CURSOR_SIZENW, CURSOR_UPARROW, CURSOR_IBEAM, CURSOR_NO, CURSOR_HAND
+ * </dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the above styles may be specified.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#cursor">Cursor snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Cursor extends Resource {
+
+ /**
+ * the handle to the OS cursor resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Cursor(Device device) {
+ super(device);
+}
+
+/**
+ * Constructs a new cursor given a device and a style
+ * constant describing the desired cursor appearance.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param style the style of cursor to allocate
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - when an unknown style is specified</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ */
+public Cursor(Device device, int style) {
+ super(device);
+ switch (style) {
+ case SWT.CURSOR_HAND: handle = OS.Cursors_Hand(); break;
+ case SWT.CURSOR_ARROW: handle = OS.Cursors_Arrow(); break;
+ case SWT.CURSOR_WAIT: handle = OS.Cursors_Wait(); break;
+ case SWT.CURSOR_CROSS: handle = OS.Cursors_Cross(); break;
+ case SWT.CURSOR_APPSTARTING: handle = OS.Cursors_AppStarting(); break;
+ case SWT.CURSOR_HELP: handle = OS.Cursors_Help(); break;
+ case SWT.CURSOR_SIZEALL: handle = OS.Cursors_SizeAll(); break;
+ case SWT.CURSOR_SIZENESW: handle = OS.Cursors_SizeNESW(); break;
+ case SWT.CURSOR_SIZENS: handle = OS.Cursors_SizeNS(); break;
+ case SWT.CURSOR_SIZENWSE: handle = OS.Cursors_SizeNWSE(); break;
+ case SWT.CURSOR_SIZEWE: handle = OS.Cursors_SizeWE(); break;
+ case SWT.CURSOR_SIZEN: handle = OS.Cursors_ScrollN(); break;
+ case SWT.CURSOR_SIZES: handle = OS.Cursors_ScrollS(); break;
+ case SWT.CURSOR_SIZEE: handle = OS.Cursors_ScrollE(); break;
+ case SWT.CURSOR_SIZEW: handle = OS.Cursors_ScrollW(); break;
+ case SWT.CURSOR_SIZENE: handle = OS.Cursors_ScrollNE(); break;
+ case SWT.CURSOR_SIZESE: handle = OS.Cursors_ScrollSE(); break;
+ case SWT.CURSOR_SIZESW: handle = OS.Cursors_ScrollSW(); break;
+ case SWT.CURSOR_SIZENW: handle = OS.Cursors_ScrollNW(); break;
+ case SWT.CURSOR_UPARROW: handle = OS.Cursors_UpArrow(); break;
+ case SWT.CURSOR_IBEAM: handle = OS.Cursors_IBeam(); break;
+ case SWT.CURSOR_NO: handle = OS.Cursors_No(); break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ init();
+}
+
+/**
+ * Constructs a new cursor given a device, image and mask
+ * data describing the desired cursor appearance, and the x
+ * and y coordinates of the <em>hotspot</em> (that is, the point
+ * within the area covered by the cursor which is considered
+ * to be where the on-screen pointer is "pointing").
+ * <p>
+ * The mask data is allowed to be null, but in this case the source
+ * must be an ImageData representing an icon that specifies both
+ * color data and mask data.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the color data for the cursor
+ * @param mask the mask data for the cursor (or null)
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the source is null</li>
+ * <li>ERROR_NULL_ARGUMENT - if the mask is null and the source does not have a mask</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the source and the mask are not the same
+ * size, or if the hotspot is outside the bounds of the image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ */
+public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
+ super(device);
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) {
+ if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ mask = source.getTransparencyMask();
+ }
+ /* Check the bounds. Mask must be the same size as source */
+ if (mask.width != source.width || mask.height != source.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Convert depth to 1 */
+ mask = ImageData.convertMask(mask);
+ source = ImageData.convertMask(source);
+
+ /* Make sure source and mask scanline pad is 2 */
+ byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2);
+ byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2);
+
+ /* Create the cursor */
+ int hInst = Win32.GetModuleHandleW(null);
+ int cursor = Win32.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData, maskData);
+ if (cursor == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int safeHandle = OS.gcnew_SWTSafeHandle(cursor, false);
+ if (safeHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ handle = OS.CursorInteropHelper_Create(safeHandle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(safeHandle);
+ init();
+}
+
+/**
+ * Constructs a new cursor given a device, image data describing
+ * the desired cursor appearance, and the x and y coordinates of
+ * the <em>hotspot</em> (that is, the point within the area
+ * covered by the cursor which is considered to be where the
+ * on-screen pointer is "pointing").
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the image data for the cursor
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
+ super(device);
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ PaletteData palette = source.palette;
+ if (!(((source.depth == 1 || source.depth == 2 || source.depth == 4 || source.depth == 8) && !palette.isDirect) ||
+ ((source.depth == 8) || (source.depth == 16 || source.depth == 24 || source.depth == 32) && palette.isDirect)))
+ SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+ int width = source.width;
+ int height = source.height;
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ ImageData newData = null;
+ int pixelFormat = 0;
+ boolean transparent = source.maskData != null || source.transparentPixel != -1 || source.alpha != -1 || source.alphaData != null;
+ if (transparent) {
+ pixelFormat = Win32.PixelFormat_Format32bppArgb;
+ if (!(palette.isDirect && source.depth == 32 && redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+ newData = new ImageData(width, height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ } else {
+ switch (source.depth) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ pixelFormat = Win32.PixelFormat_Format24bppRgb;
+ newData = new ImageData(source.width, source.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ break;
+ case 16:
+ if (redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F) {
+ pixelFormat = Win32.PixelFormat_Format16bppRgb555;
+ } else if (redMask == 0xF800 && greenMask == 0x7E0 && blueMask == 0x1F) {
+ pixelFormat = Win32.PixelFormat_Format16bppRgb565;
+ } else {
+ pixelFormat = Win32.PixelFormat_Format16bppRgb555;
+ newData = new ImageData(source.width, source.height, 16, new PaletteData(0x7C00, 0x3E0, 0x1F));
+ }
+ break;
+ case 24:
+ if (redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000) {
+ pixelFormat = Win32.PixelFormat_Format24bppRgb;
+ } else {
+ pixelFormat = Win32.PixelFormat_Format24bppRgb;
+ newData = new ImageData(source.width, source.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ }
+ break;
+ case 32:
+ if (redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000) {
+ pixelFormat = Win32.PixelFormat_Format32bppRgb;
+ } else {
+ pixelFormat = Win32.PixelFormat_Format32bppRgb;
+ newData = new ImageData(source.width, source.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ }
+ }
+ if (newData != null) {
+ PaletteData newPalette = newData.palette;
+ if (palette.isDirect) {
+ ImageData.blit(ImageData.BLIT_SRC,
+ source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, width, height, redMask, greenMask, blueMask,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ int length = rgbs.length;
+ byte[] srcReds = new byte[length];
+ byte[] srcGreens = new byte[length];
+ byte[] srcBlues = new byte[length];
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ if (rgb == null) continue;
+ srcReds[i] = (byte)rgb.red;
+ srcGreens[i] = (byte)rgb.green;
+ srcBlues[i] = (byte)rgb.blue;
+ }
+ ImageData.blit(ImageData.BLIT_SRC,
+ source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ }
+ if (source.transparentPixel != -1) {
+ newData.transparentPixel = newPalette.getPixel(palette.getRGB(source.transparentPixel));
+ }
+ newData.maskPad = source.maskPad;
+ newData.maskData = source.maskData;
+ newData.alpha = source.alpha;
+ newData.alphaData = source.alphaData;
+ source = newData;
+ palette = source.palette;
+ }
+ if (transparent) {
+ if (source.maskData != null || source.transparentPixel != -1) {
+ ImageData maskImage = source.getTransparencyMask();
+ byte[] maskData = maskImage.data;
+ int maskBpl = maskImage.bytesPerLine;
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ source.data[offset] = ((maskData[maskOffset + (x >> 3)]) & (1 << (7 - (x & 0x7)))) != 0 ? (byte)0xff : 0;
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ } else if (source.alpha != -1) {
+ byte alpha = (byte)source.alpha;
+ for (int i = 3, j = 0; i < source.data.length; i+=4, j++) {
+ source.data[i] = alpha;
+ }
+ } else {
+ for (int i = 3, j = 0; i < source.data.length; i+=4, j++) {
+ source.data[i] = source.alphaData[j];
+ }
+ }
+ }
+ int bitmap = OS.gcnew_Bitmap(source.width, source.height, source.bytesPerLine, pixelFormat, source.data);
+ if (bitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int hIcon = OS.Bitmap_GetHicon(bitmap);
+ if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ ICONINFO info = new ICONINFO();
+ Win32.GetIconInfo(hIcon, info);
+ info.fIcon = false;
+ info.xHotspot = hotspotX;
+ info.yHotspot = hotspotY;
+ Win32.DestroyIcon(hIcon);
+ hIcon = Win32.CreateIconIndirect(info);
+ if (info.hbmColor != 0) Win32.DeleteObject(info.hbmColor);
+ if (info.hbmMask != 0)Win32.DeleteObject(info.hbmMask);
+ if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+
+ /* Create the cursor */
+ int safeHandle = OS.gcnew_SWTSafeHandle(hIcon, true);
+ if (safeHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ handle = OS.CursorInteropHelper_Create(safeHandle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(safeHandle);
+ OS.GCHandle_Free(bitmap);
+ init();
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Cursor)) return false;
+ Cursor cursor = (Cursor) object;
+ return device == cursor.device && handle == cursor.handle;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Returns <code>true</code> if the cursor has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the cursor.
+ * When a cursor has been disposed, it is an error to
+ * invoke any other method using the cursor.
+ *
+ * @return <code>true</code> when the cursor is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Cursor {*DISPOSED*}";
+ return "Cursor {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new cursor.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Cursor</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the cursor
+ * @return a new cursor object containing the specified device and handle
+ */
+public static Cursor wpf_new(Device device, int handle) {
+ Cursor cursor = new Cursor(device);
+ cursor.handle = handle;
+ return cursor;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java
new file mode 100644
index 0000000000..fd43333e24
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java
@@ -0,0 +1,650 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * This class is the abstract superclass of all device objects,
+ * such as the Display device and the Printer device. Devices
+ * can have a graphics context (GC) created for them, and they
+ * can be drawn on by sending messages to the associated GC.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class Device implements Drawable {
+
+ /* Debugging */
+ public static boolean DEBUG;
+ public static boolean TRACK;
+ boolean debug = DEBUG;
+ boolean tracking = DEBUG || TRACK;
+ Error [] errors;
+ Object [] objects;
+ Object trackingLock;
+
+ Color[] colors;
+
+ /* System Font */
+ Font systemFont;
+
+ boolean disposed;
+
+ /*
+ * TEMPORARY CODE. When a graphics object is
+ * created and the device parameter is null,
+ * the current Display is used. This presents
+ * a problem because SWT graphics does not
+ * reference classes in SWT widgets. The correct
+ * fix is to remove this feature. Unfortunately,
+ * too many application programs rely on this
+ * feature.
+ */
+ protected static Device CurrentDevice;
+ protected static Runnable DeviceFinder;
+ static {
+ try {
+ Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$
+ } catch (ClassNotFoundException e) {}
+ }
+
+/*
+* TEMPORARY CODE.
+*/
+static synchronized Device getDevice () {
+ if (DeviceFinder != null) DeviceFinder.run();
+ Device device = CurrentDevice;
+ CurrentDevice = null;
+ return device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @see #create
+ * @see #init
+ *
+ * @since 3.1
+ */
+public Device() {
+ this(null);
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #create
+ * @see #init
+ * @see DeviceData
+ */
+public Device(DeviceData data) {
+ synchronized (Device.class) {
+ if (data != null) {
+ debug = data.debug;
+ tracking = data.tracking;
+ }
+ if (tracking) {
+ errors = new Error [128];
+ objects = new Object [128];
+ trackingLock = new Object ();
+ }
+ create (data);
+ init ();
+ }
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * device implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code> and <code>dispose()</code>) on a
+ * device that has had its <code>dispose()</code> method called.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * <p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+protected void checkDevice () {
+ if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+/**
+ * Creates the device in the operating system. If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ * <p>
+ * This method is called before <code>init</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+protected void create (DeviceData data) {
+}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle. If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ * <p>
+ * This method is called after <code>release</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #release
+ */
+protected void destroy () {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver. After this method has been invoked, the receiver
+ * will answer <code>true</code> when sent the message
+ * <code>isDisposed()</code>.
+ *
+ * @see #release
+ * @see #destroy
+ * @see #checkDevice
+ */
+public void dispose () {
+ synchronized (Device.class) {
+ if (isDisposed()) return;
+ checkDevice ();
+ release ();
+ destroy ();
+ disposed = true;
+ if (tracking) {
+ synchronized (trackingLock) {
+ objects = null;
+ errors = null;
+ trackingLock = null;
+ }
+ }
+ }
+}
+
+void dispose_Object (Object object) {
+ synchronized (trackingLock) {
+ for (int i=0; i<objects.length; i++) {
+ if (objects [i] == object) {
+ objects [i] = null;
+ errors [i] = null;
+ return;
+ }
+ }
+ }
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location.
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds () {
+ checkDevice ();
+ int width = (int) OS.SystemParameters_PrimaryScreenWidth();
+ int height = (int) OS.SystemParameters_PrimaryScreenHeight();
+ return new Rectangle (0, 0, width, height);
+}
+
+/**
+ * Returns a <code>DeviceData</code> based on the receiver.
+ * Modifications made to this <code>DeviceData</code> will not
+ * affect the receiver.
+ *
+ * @return a <code>DeviceData</code> containing the device's data and attributes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see DeviceData
+ */
+public DeviceData getDeviceData () {
+ checkDevice();
+ DeviceData data = new DeviceData ();
+ data.debug = debug;
+ data.tracking = tracking;
+ if (tracking) {
+ synchronized (trackingLock) {
+ int count = 0, length = objects.length;
+ for (int i=0; i<length; i++) {
+ if (objects [i] != null) count++;
+ }
+ int index = 0;
+ data.objects = new Object [count];
+ data.errors = new Error [count];
+ for (int i=0; i<length; i++) {
+ if (objects [i] != null) {
+ data.objects [index] = objects [i];
+ data.errors [index] = errors [i];
+ index++;
+ }
+ }
+ }
+ } else {
+ data.objects = new Object [0];
+ data.errors = new Error [0];
+ }
+ return data;
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ */
+public Rectangle getClientArea () {
+ return getBounds ();
+}
+
+/**
+ * Returns the bit depth of the screen, which is the number of
+ * bits it takes to represent the number of unique colors that
+ * the screen is currently capable of displaying. This number
+ * will typically be one of 1, 8, 15, 16, 24 or 32.
+ *
+ * @return the depth of the screen
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getDepth () {
+ checkDevice ();
+ //TODO - implement getDepth
+ return 32;
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the display, and whose y coordinate
+ * is the vertical dots per inch of the display.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point getDPI () {
+ checkDevice ();
+ //TODO implement getDPI
+ return new Point(96, 96);
+}
+
+/**
+ * Returns <code>FontData</code> objects which describe
+ * the fonts that match the given arguments. If the
+ * <code>faceName</code> is null, all fonts will be returned.
+ *
+ * @param faceName the name of the font to look for, or null
+ * @param scalable if true only scalable fonts are returned, otherwise only non-scalable fonts are returned.
+ * @return the matching font data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData [] getFontList (String faceName, boolean scalable) {
+ checkDevice ();
+ if (!scalable) return new FontData[0];
+ int typefaces;
+ if (faceName != null) {
+ int length = faceName.length();
+ char[] chars = new char[length + 1];
+ faceName.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int fontFamily = OS.gcnew_FontFamily(str);
+ typefaces = OS.FontFamily_GetTypefaces(fontFamily);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(str);
+ } else {
+ typefaces = OS.Fonts_SystemTypefaces();
+ }
+ int count = OS.TypefaceCollection_Count(typefaces);
+ int index = 0;
+ FontData[] result = new FontData[count];
+ int enumerator = OS.TypefaceCollection_GetEnumerator(typefaces);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int typeface = OS.TypefaceCollection_Current(enumerator);
+ int fontFamily = OS.Typeface_FontFamily(typeface);
+ int style = OS.Typeface_Style(typeface);
+ int weight = OS.Typeface_Weight(typeface);
+ int stretch = OS.Typeface_Stretch(typeface);
+ int str = OS.FontFamily_Source(fontFamily);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memcpy(chars, charArray, chars.length * 2);
+ int fontStyle = OS.FontStyles_Normal;
+ if (OS.Object_Equals(style, OS.FontStyles_Italic)) fontStyle = OS.FontStyles_Italic;
+ if (OS.Object_Equals(style, OS.FontStyles_Oblique)) fontStyle = OS.FontStyles_Oblique;
+ FontData data = FontData.wpf_new(new String(chars), fontStyle,
+ OS.FontWeight_ToOpenTypeWeight(weight), OS.FontStretch_ToOpenTypeStretch(stretch), 0);
+ OS.GCHandle_Free(charArray);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ OS.GCHandle_Free(typeface);
+ result[index++] = data;
+ }
+ OS.GCHandle_Free(enumerator);
+ OS.GCHandle_Free(typefaces);
+ return result;
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class <code>SWT</code>. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be freed because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT
+ */
+public Color getSystemColor (int id) {
+ checkDevice ();
+ if (0 <= id && id < colors.length) {
+ return colors[id];
+ }
+ return colors[0];
+}
+
+/**
+ * Returns a reasonable font for applications to use.
+ * On some platforms, this will match the "default font"
+ * or "system font" if such can be found. This font
+ * should not be freed because it was allocated by the
+ * system, not the application.
+ * <p>
+ * Typically, applications which want the default look
+ * should simply not set the font on the widgets they
+ * create. Widgets are always created with the correct
+ * default font for the class of user-interface component
+ * they represent.
+ * </p>
+ *
+ * @return a font
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getSystemFont () {
+ checkDevice ();
+ return systemFont;
+}
+
+/**
+ * Returns <code>true</code> if the underlying window system prints out
+ * warning messages on the console, and <code>setWarnings</code>
+ * had previously been called with <code>true</code>.
+ *
+ * @return <code>true</code>if warnings are being handled, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean getWarnings () {
+ checkDevice ();
+ return false;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ * <p>
+ * This method is called after <code>create</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #create
+ */
+protected void init () {
+ /* Create the standard colors */
+ colors = new Color[SWT.COLOR_DARK_GRAY + 1];
+ colors[SWT.COLOR_BLACK] = colors[0] = Color.wpf_new(this, OS.Colors_Black());
+ colors[SWT.COLOR_DARK_RED] = Color.wpf_new(this, OS.Colors_Maroon ());
+ colors[SWT.COLOR_DARK_GREEN] = Color.wpf_new(this, OS.Colors_Green ());
+ colors[SWT.COLOR_DARK_YELLOW] = Color.wpf_new(this, OS.Colors_Olive());
+ colors[SWT.COLOR_DARK_BLUE] = Color.wpf_new(this, OS.Colors_Navy ());
+ colors[SWT.COLOR_DARK_MAGENTA] = Color.wpf_new(this, OS.Colors_Purple());
+ colors[SWT.COLOR_DARK_CYAN] = Color.wpf_new(this, OS.Colors_Teal ());
+ colors[SWT.COLOR_GRAY] = Color.wpf_new(this, OS.Colors_Silver ());
+ colors[SWT.COLOR_DARK_GRAY] = Color.wpf_new(this, OS.Colors_Silver ());
+ colors[SWT.COLOR_RED] = Color.wpf_new(this, OS.Colors_Red ());
+ colors[SWT.COLOR_GREEN] = Color.wpf_new(this, OS.Colors_Lime ());
+ colors[SWT.COLOR_YELLOW] = Color.wpf_new(this, OS.Colors_Yellow ());
+ colors[SWT.COLOR_BLUE] = Color.wpf_new(this, OS.Colors_Blue ());
+ colors[SWT.COLOR_MAGENTA] = Color.wpf_new(this, OS.Colors_Magenta ());
+ colors[SWT.COLOR_CYAN] = Color.wpf_new(this, OS.Colors_Cyan ());
+ colors[SWT.COLOR_WHITE] = Color.wpf_new(this, OS.Colors_White ());
+
+ /* Initialize the system font slot */
+ int fontFamily = OS.SystemFonts_MessageFontFamily();
+ int style = OS.SystemFonts_MessageFontStyle();
+ int weight = OS.SystemFonts_MessageFontWeight();
+ double size = OS.SystemFonts_MessageFontSize();
+ int typeface = OS.gcnew_Typeface(fontFamily, style, weight, OS.FontStretches_Normal);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ systemFont = Font.wpf_new(this, typeface, size);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public abstract int internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public abstract void internal_dispose_GC (int hDC, GCData data);
+
+/**
+ * Returns <code>true</code> if the device has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the device.
+ * When a device has been disposed, it is an error to
+ * invoke any other method using the device.
+ *
+ * @return <code>true</code> when the device is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+ synchronized (Device.class) {
+ return disposed;
+ }
+}
+
+/**
+ * Loads the font specified by a file. The font will be
+ * present in the list of fonts available to the application.
+ *
+ * @param path the font file path
+ * @return whether the font was successfully loaded
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if path is null</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Font
+ *
+ * @since 3.3
+ */
+public boolean loadFont (String path) {
+ checkDevice();
+ if (path == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ int length = path.length ();
+ char[] buffer = new char [length + 1];
+ path.getChars (0, length, buffer, 0);
+ int str = OS.gcnew_String(buffer);
+ int uri = OS.gcnew_Uri(str, OS.UriKind_RelativeOrAbsolute);
+ int list = OS.Fonts_GetTypefaces(uri);
+ int count = OS.TypefaceCollection_Count(list);
+ OS.GCHandle_Free(list);
+ OS.GCHandle_Free(uri);
+ OS.GCHandle_Free(str);
+ return count != 0;
+}
+
+void new_Object (Object object) {
+ synchronized (trackingLock) {
+ for (int i=0; i<objects.length; i++) {
+ if (objects [i] == null) {
+ objects [i] = object;
+ errors [i] = new Error ();
+ return;
+ }
+ }
+ Object [] newObjects = new Object [objects.length + 128];
+ System.arraycopy (objects, 0, newObjects, 0, objects.length);
+ newObjects [objects.length] = object;
+ objects = newObjects;
+ Error [] newErrors = new Error [errors.length + 128];
+ System.arraycopy (errors, 0, newErrors, 0, errors.length);
+ newErrors [errors.length] = new Error ();
+ errors = newErrors;
+ }
+}
+
+/**
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the device handle.
+ * <p>
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in <code>release</code>. Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by <code>destroy</code>.
+ * </p>
+ * This method is called before <code>destroy</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #destroy
+ */
+protected void release () {
+ for (int i = 0; i < colors.length; i++) {
+ if (colors[i] != null) colors[i].dispose();
+ }
+ colors = null;
+ if (systemFont != null) systemFont.dispose();
+ systemFont = null;
+ if (tracking) {
+ synchronized (trackingLock) {
+ if (TRACK & objects != null) {
+ for (int i = 0; i < objects.length; i++) {
+ if (objects[i] != null) {
+ System.err.println(objects[i]);
+ errors[i].printStackTrace();
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * If the underlying window system supports printing warning messages
+ * to the console, setting warnings to <code>false</code> prevents these
+ * messages from being printed. If the argument is <code>true</code> then
+ * message printing is not blocked.
+ *
+ * @param warnings <code>true</code>if warnings should be printed, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setWarnings (boolean warnings) {
+ checkDevice ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java
new file mode 100644
index 0000000000..ad0c2b2afe
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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.graphics;
+
+
+public class DeviceData {
+ /*
+ * Debug fields - may not be honoured
+ * on some SWT platforms.
+ */
+ public boolean debug;
+ public boolean tracking;
+ public Error [] errors;
+ public Object [] objects;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java
new file mode 100644
index 0000000000..7ade47e081
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage operating system resources that
+ * define how text looks when it is displayed. Fonts may be constructed
+ * by providing a device and either name, size and style information
+ * or a <code>FontData</code> object which encapsulates this data.
+ * <p>
+ * Application code must explicitly invoke the <code>Font.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see FontData
+ * @see <a href="http://www.eclipse.org/swt/snippets/#font">Font snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Font extends Resource {
+
+ /**
+ * the handle to the OS font resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+ /**
+ * the handle to the OS font resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public double size;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Font(Device device) {
+ super(device);
+}
+
+/**
+ * Constructs a new font given a device and font data
+ * which describes the desired font's appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fd the FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the fd argument is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ */
+public Font(Device device, FontData fd) {
+ super(device);
+ init(fd);
+ init();
+}
+
+/**
+ * Constructs a new font given a device and an array
+ * of font data which describes the desired font's
+ * appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fds the array of FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the fds argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the length of fds is zero</li>
+ * <li>ERROR_NULL_ARGUMENT - if any fd in the array is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public Font(Device device, FontData[] fds) {
+ super(device);
+ if (fds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (fds.length == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i<fds.length; i++) {
+ if (fds[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ init(fds[0]);
+ init();
+}
+
+/**
+ * Constructs a new font given a device, a font name,
+ * the height of the desired font in points, and a font
+ * style.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the name argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given arguments</li>
+ * </ul>
+ */
+public Font(Device device, String name, int height, int style) {
+ super(device);
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(new FontData (name, height, style));
+ init();
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals(Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Font)) return false;
+ Font font = (Font) object;
+ return device == font.device && handle == font.handle && size == font.size;
+}
+
+/**
+ * Returns an array of <code>FontData</code>s representing the receiver.
+ * On Windows, only one FontData will be returned per font. On X however,
+ * a <code>Font</code> object <em>may</em> be composed of multiple X
+ * fonts. To support this case, we return an array of font data objects.
+ *
+ * @return an array of font data objects describing the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData[] getFontData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int fontFamily = OS.Typeface_FontFamily(handle);
+ int style = OS.Typeface_Style(handle);
+ int weight = OS.Typeface_Weight(handle);
+ int stretch = OS.Typeface_Stretch(handle);
+ int str = OS.FontFamily_Source(fontFamily);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memcpy(chars, charArray, chars.length * 2);
+ int fontStyle = OS.FontStyles_Normal;
+ if (OS.Object_Equals(style, OS.FontStyles_Italic)) fontStyle = OS.FontStyles_Italic;
+ if (OS.Object_Equals(style, OS.FontStyles_Oblique)) fontStyle = OS.FontStyles_Oblique;
+ int size = (int) (this.size * 72 / 96f);
+ FontData data = FontData.wpf_new(new String(chars), fontStyle, OS.FontWeight_ToOpenTypeWeight(weight), OS.FontStretch_ToOpenTypeStretch(stretch), (int)size);
+ OS.GCHandle_Free(charArray);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ return new FontData[] {data};
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+void init (FontData fd) {
+ if (fd == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int length = fd.fontFamily.length();
+ char[] chars = new char[length + 1];
+ fd.fontFamily.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int fontFamily = OS.gcnew_FontFamily(str);
+ int style = fd.style;
+ int weight = OS.FontWeight_FromOpenTypeWeight(fd.weight);
+ int stretch = OS.FontStretch_FromOpenTypeStretch(fd.stretch);
+ handle = OS.gcnew_Typeface(fontFamily, style, weight, stretch);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ size = fd.height * 96 / 72f;
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Returns <code>true</code> if the font has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the font.
+ * When a font has been disposed, it is an error to
+ * invoke any other method using the font.
+ *
+ * @return <code>true</code> when the font is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Font {*DISPOSED*}";
+ return "Font {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Font</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the font
+ * @return a new font object containing the specified device and handle
+ */
+public static Font wpf_new(Device device, int handle, double size) {
+ Font font = new Font(device);
+ font.handle = handle;
+ font.size = size;
+ return font;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java
new file mode 100644
index 0000000000..42211bc96c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java
@@ -0,0 +1,540 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class describe operating system fonts.
+ * <p>
+ * For platform-independent behaviour, use the get and set methods
+ * corresponding to the following properties:
+ * <dl>
+ * <dt>height</dt><dd>the height of the font in points</dd>
+ * <dt>name</dt><dd>the face name of the font, which may include the foundry</dd>
+ * <dt>style</dt><dd>A bitwise combination of NORMAL, ITALIC and BOLD</dd>
+ * </dl>
+ * If extra, platform-dependent functionality is required:
+ * <ul>
+ * <li>On <em>Windows</em>, the data member of the <code>FontData</code>
+ * corresponds to a Windows <code>LOGFONT</code> structure whose fields
+ * may be retrieved and modified.</li>
+ * <li>On <em>X</em>, the fields of the <code>FontData</code> correspond
+ * to the entries in the font's XLFD name and may be retrieved and modified.
+ * </ul>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ *
+ * @see Font
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class FontData {
+
+ /**
+ * A WPF font
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public String fontFamily;
+
+ /**
+ * A WPF font style
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int style;
+
+ /**
+ * A WPF font weight
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int weight;
+
+ /**
+ * A WPF font stretch
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int stretch;
+
+ /**
+ * The height of the font data in points
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int height;
+
+ /**
+ * The locales of the font
+ */
+ String lang, country, variant;
+
+/**
+ * Constructs a new uninitialized font data.
+ */
+public FontData() {
+ fontFamily = "";
+ style = OS.FontStyles_Normal;
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Normal);
+ stretch = OS.FontStretch_ToOpenTypeStretch(OS.FontStretches_Normal);
+ height = 12;
+}
+
+/**
+ * Constructs a new FontData given a string representation
+ * in the form generated by the <code>FontData.toString</code>
+ * method.
+ * <p>
+ * Note that the representation varies between platforms,
+ * and a FontData can only be created from a string that was
+ * generated on the same platform.
+ * </p>
+ *
+ * @param string the string representation of a <code>FontData</code> (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument does not represent a valid description</li>
+ * </ul>
+ *
+ * @see #toString
+ */
+public FontData(String string) {
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int start = 0;
+ int end = string.indexOf('|');
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String version1 = string.substring(start, end);
+ try {
+ if (Integer.parseInt(version1) != 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String name = string.substring(start, end);
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int height = 0;
+ try {
+ height = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int style = 0;
+ try {
+ style = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ if (end == -1) return;
+ String platform = string.substring(start, end);
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ String version2 = string.substring(start, end);
+
+ stretch = OS.FontStretch_ToOpenTypeStretch(OS.FontStretches_Normal);
+ if (platform.equals("WPF") && version2.equals("1")) {
+ try {
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ fontFamily = string.substring(start, end);
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ String styleStr = string.substring(start, end);
+ int length = styleStr.length();
+ char[] chars = new char[length + 1];
+ styleStr.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int converter = OS.TypeDescriptor_GetConverter(OS.FontStyles_Normal);
+ this.style = OS.FontStyles_Normal;
+ int fontStyle = OS.TypeConverter_ConvertFromString(converter, str);
+ if (fontStyle != 0) {
+ if (OS.Object_Equals(OS.FontStyles_Italic, fontStyle)) this.style = OS.FontStyles_Italic;
+ if (OS.Object_Equals(OS.FontStyles_Oblique, fontStyle)) this.style = OS.FontStyles_Oblique;
+ OS.GCHandle_Free(fontStyle);
+ }
+ OS.GCHandle_Free(converter);
+ OS.GCHandle_Free(str);
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ weight = Integer.parseInt(string.substring(start, end));
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) end = string.length();
+ stretch = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ return;
+ }
+ }
+}
+
+/**
+ * Constructs a new font data given a font name,
+ * the height of the desired font in points,
+ * and a font style.
+ *
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ */
+public FontData(String name, int height, int style) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ stretch = OS.FontStretch_ToOpenTypeStretch(OS.FontStretches_Normal);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontData)) return false;
+ FontData fd = (FontData)object;
+ return style == fd.style &&
+ height == fd.height &&
+ weight == fd.weight &&
+ stretch == fd.stretch &&
+ getName().equals(fd.getName());
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight(int)
+ */
+public int getHeight() {
+ return height;
+}
+
+/**
+ * Returns the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @return the <code>String</code> representing a Locale object
+ * @since 3.0
+ */
+public String getLocale () {
+ StringBuffer buffer = new StringBuffer ();
+ char sep = '_';
+ if (lang != null) {
+ buffer.append (lang);
+ buffer.append (sep);
+ }
+ if (country != null) {
+ buffer.append (country);
+ buffer.append (sep);
+ }
+ if (variant != null) {
+ buffer.append (variant);
+ }
+
+ String result = buffer.toString ();
+ int length = result.length ();
+ if (length > 0) {
+ if (result.charAt (length - 1) == sep) {
+ result = result.substring (0, length - 1);
+ }
+ }
+ return result;
+}
+
+/**
+ * Returns the name of the receiver.
+ * On platforms that support font foundries, the return value will
+ * be the foundry followed by a dash ("-") followed by the face name.
+ *
+ * @return the name of this <code>FontData</code>
+ *
+ * @see #setName
+ */
+public String getName() {
+ return fontFamily;
+}
+
+/**
+ * Returns the style of the receiver which is a bitwise OR of
+ * one or more of the <code>SWT</code> constants NORMAL, BOLD
+ * and ITALIC.
+ *
+ * @return the style of this <code>FontData</code>
+ *
+ * @see #setStyle
+ */
+public int getStyle() {
+ int style = SWT.NORMAL;
+ if (weight == OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Bold)) style |= SWT.BOLD;
+ if (style == OS.FontStyles_Italic) style |= SWT.ITALIC;
+ return style;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return style ^ weight ^ stretch ^ getName().hashCode();
+}
+
+/**
+ * Sets the height of the receiver. The parameter is
+ * specified in terms of points, where a point is one
+ * seventy-second of an inch.
+ *
+ * @param height the height of the <code>FontData</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ *
+ * @see #getHeight
+ */
+public void setHeight(int height) {
+ if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.height = height;
+}
+
+/**
+ * Sets the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @param locale the <code>String</code> representing a Locale object
+ * @see java.util.Locale#toString
+ */
+public void setLocale(String locale) {
+ lang = country = variant = null;
+ if (locale != null) {
+ char sep = '_';
+ int length = locale.length();
+ int firstSep, secondSep;
+
+ firstSep = locale.indexOf(sep);
+ if (firstSep == -1) {
+ firstSep = secondSep = length;
+ } else {
+ secondSep = locale.indexOf(sep, firstSep + 1);
+ if (secondSep == -1) secondSep = length;
+ }
+ if (firstSep > 0) lang = locale.substring(0, firstSep);
+ if (secondSep > firstSep + 1) country = locale.substring(firstSep + 1, secondSep);
+ if (length > secondSep + 1) variant = locale.substring(secondSep + 1);
+ }
+}
+
+/**
+ * Sets the name of the receiver.
+ * <p>
+ * Some platforms support font foundries. On these platforms, the name
+ * of the font specified in setName() may have one of the following forms:
+ * <ol>
+ * <li>a face name (for example, "courier")</li>
+ * <li>a foundry followed by a dash ("-") followed by a face name (for example, "adobe-courier")</li>
+ * </ol>
+ * In either case, the name returned from getName() will include the
+ * foundry.
+ * </p>
+ * <p>
+ * On platforms that do not support font foundries, only the face name
+ * (for example, "courier") is used in <code>setName()</code> and
+ * <code>getName()</code>.
+ * </p>
+ *
+ * @param name the name of the font data (must not be null)
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ * </ul>
+ *
+ * @see #getName
+ */
+public void setName(String name) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ fontFamily = name;
+}
+
+/**
+ * Sets the style of the receiver to the argument which must
+ * be a bitwise OR of one or more of the <code>SWT</code>
+ * constants NORMAL, BOLD and ITALIC. All other style bits are
+ * ignored.
+ *
+ * @param style the new style for this <code>FontData</code>
+ *
+ * @see #getStyle
+ */
+public void setStyle(int style) {
+ if ((style & SWT.BOLD) == SWT.BOLD) {
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Bold);
+ } else {
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Normal);
+ }
+ if ((style & SWT.ITALIC) == SWT.ITALIC) {
+ this.style = OS.FontStyles_Italic;
+ } else {
+ this.style = OS.FontStyles_Normal;
+ }
+}
+
+/**
+ * Returns a string representation of the receiver which is suitable
+ * for constructing an equivalent instance using the
+ * <code>FontData(String)</code> constructor.
+ *
+ * @return a string representation of the FontData
+ *
+ * @see FontData
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("1|"); //$NON-NLS-1$
+ buffer.append(getName());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getHeight());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getStyle());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append("WPF|1|"); //$NON-NLS-1$
+ buffer.append(fontFamily);
+ buffer.append("|"); //$NON-NLS-1$
+ int converter = OS.TypeDescriptor_GetConverter(OS.FontStyles_Normal);
+ int str = OS.TypeConverter_ConvertToString(converter, style != 0 ? style : OS.FontStyles_Normal);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memcpy(chars, charArray, chars.length * 2);
+ OS.GCHandle_Free (charArray);
+ OS.GCHandle_Free (str);
+ OS.GCHandle_Free (converter);
+ buffer.append(chars);
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(weight);
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(stretch);
+ return buffer.toString();
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font data.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>FontData</code>. It is marked public only so that
+ * it can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the <code>LOGFONT</code> for the font data
+ * @param height the height of the font data
+ * @return a new font data object containing the specified <code>LOGFONT</code> and height
+ */
+public static FontData wpf_new(String fontFamily, int style, int weight, int stretch, int height) {
+ FontData data = new FontData();
+ data.fontFamily = fontFamily;
+ data.style = style;
+ data.weight = weight;
+ data.stretch = stretch;
+ data.height = height;
+ return data;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java
new file mode 100644
index 0000000000..4a8b8b1fe8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+/**
+ * Instances of this class provide measurement information
+ * about fonts including ascent, descent, height, leading
+ * space between rows, and average character width.
+ * <code>FontMetrics</code> are obtained from <code>GC</code>s
+ * using the <code>getFontMetrics()</code> method.
+ *
+ * @see GC#getFontMetrics
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class FontMetrics {
+ int ascent, descent, averageCharWidth, leading, height;
+
+FontMetrics() {
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontMetrics)) return false;
+ FontMetrics metrics = (FontMetrics)object;
+ return ascent == metrics.ascent && descent == metrics.descent &&
+ averageCharWidth == metrics.averageCharWidth && leading == metrics.leading &&
+ height == metrics.height;
+}
+
+/**
+ * Returns the ascent of the font described by the receiver. A
+ * font's <em>ascent</em> is the distance from the baseline to the
+ * top of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the ascent of the font
+ */
+public int getAscent() {
+ return ascent;
+}
+
+/**
+ * Returns the average character width, measured in pixels,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ */
+public int getAverageCharWidth() {
+ return averageCharWidth;
+}
+
+/**
+ * Returns the descent of the font described by the receiver. A
+ * font's <em>descent</em> is the distance from the baseline to the
+ * bottom of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the descent of the font
+ */
+public int getDescent() {
+ return descent;
+}
+
+/**
+ * Returns the height of the font described by the receiver,
+ * measured in pixels. A font's <em>height</em> is the sum of
+ * its ascent, descent and leading area.
+ *
+ * @return the height of the font
+ *
+ * @see #getAscent
+ * @see #getDescent
+ * @see #getLeading
+ */
+public int getHeight() {
+ return height;
+}
+
+/**
+ * Returns the leading area of the font described by the
+ * receiver. A font's <em>leading area</em> is the space
+ * above its ascent which may include accents or other marks.
+ *
+ * @return the leading space of the font
+ */
+public int getLeading() {
+ return leading;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode() {
+ return ascent ^ descent ^ averageCharWidth ^ leading ^ height;
+}
+
+public static FontMetrics wpf_new(int ascent, int descent, int averageCharWidth, int leading, int height) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.ascent = ascent;
+ fontMetrics.descent = descent;
+ fontMetrics.averageCharWidth = averageCharWidth;
+ fontMetrics.leading = leading;
+ fontMetrics.height = height;
+ return fontMetrics;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java
new file mode 100644
index 0000000000..dae4748e16
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java
@@ -0,0 +1,3112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics;
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Class <code>GC</code> is where all of the drawing capabilities that are
+ * supported by SWT are located. Instances are used to draw on either an
+ * <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * </dl>
+ *
+ * <p>
+ * The SWT drawing coordinate system is the two-dimensional space with the origin
+ * (0,0) at the top left corner of the drawing area and with (x,y) values increasing
+ * to the right and downward respectively.
+ * </p>
+ *
+ * <p>
+ * The result of drawing on an image that was created with an indexed
+ * palette using a color that is not in the palette is platform specific.
+ * Some platforms will match to the nearest color while other will draw
+ * the color itself. This happens because the allocated image might use
+ * a direct palette on platforms that do not support indexed palette.
+ * </p>
+ *
+ * <p>
+ * Application code must explicitly invoke the <code>GC.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required. This is <em>particularly</em>
+ * important on Windows95 and Windows98 where the operating system has a limited
+ * number of device contexts available.
+ * </p>
+ *
+ * <p>
+ * Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified.
+ * </p>
+ *
+ * @see org.eclipse.swt.events.PaintEvent
+ * @see <a href="http://www.eclipse.org/swt/snippets/#gc">GC snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class GC extends Resource {
+
+ /**
+ * the handle to the OS device context
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+ Drawable drawable;
+ GCData data;
+
+ static final int FOREGROUND = 1 << 0;
+ static final int BACKGROUND = 1 << 1;
+ static final int FONT = 1 << 2;
+ static final int LINE_STYLE = 1 << 3;
+ static final int LINE_WIDTH = 1 << 4;
+ static final int LINE_CAP = 1 << 5;
+ static final int LINE_JOIN = 1 << 6;
+ static final int LINE_MITERLIMIT = 1 << 7;
+ static final int ALPHA = 1 << 8;
+ static final int CLIPPING = 1 << 9;
+ static final int TRANSFORM = 1 << 10;
+
+ static final int DRAW = FOREGROUND | LINE_STYLE | LINE_WIDTH | LINE_CAP | LINE_JOIN | ALPHA | CLIPPING | TRANSFORM;
+ static final int FILL = BACKGROUND | ALPHA | CLIPPING | TRANSFORM;
+ static final int IMAGE = ALPHA | CLIPPING | TRANSFORM;
+
+ static final double[] LINE_DOT_ZERO = new double[]{3, 3};
+ static final double[] LINE_DASH_ZERO = new double[]{18, 6};
+ static final double[] LINE_DASHDOT_ZERO = new double[]{9, 6, 3, 6};
+ static final double[] LINE_DASHDOTDOT_ZERO = new double[]{9, 3, 3, 3, 3, 3};
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+GC() {
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground color, background color and font in the GC
+ * to match those in the drawable.
+ * <p>
+ * You must dispose the graphics context when it is no longer required.
+ * </p>
+ * @param drawable the drawable to draw on
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
+ * <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT
+ * - if the drawable is an image that is not a bitmap or an icon
+ * - if the drawable is an image or printer that is already selected
+ * into another graphics context</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
+ * </ul>
+ */
+public GC(Drawable drawable) {
+ this(drawable, SWT.NONE);
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground color, background color and font in the GC
+ * to match those in the drawable.
+ * <p>
+ * You must dispose the graphics context when it is no longer required.
+ * </p>
+ *
+ * @param drawable the drawable to draw on
+ * @param style the style of GC to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
+ * <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT
+ * - if the drawable is an image that is not a bitmap or an icon
+ * - if the drawable is an image or printer that is already selected
+ * into another graphics context</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public GC(Drawable drawable, int style) {
+ if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ GCData data = new GCData ();
+ data.style = checkStyle(style);
+ int hDC = drawable.internal_new_GC(data);
+ Device device = data.device;
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = data.device = device;
+ init (drawable, data, hDC);
+ init();
+}
+
+static int checkStyle(int style) {
+ if ((style & SWT.LEFT_TO_RIGHT) != 0) style &= ~SWT.RIGHT_TO_LEFT;
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+void checkGC(int mask) {
+ int state = data.state;
+ if ((state & mask) == mask) return;
+ state = (state ^ mask) & mask;
+ data.state |= mask;
+ if ((state & (FOREGROUND | LINE_WIDTH | LINE_STYLE | LINE_JOIN | LINE_CAP | LINE_MITERLIMIT)) != 0) {
+ int pen = data.pen;
+ if (pen != 0) OS.GCHandle_Free(pen);
+ pen = data.pen = OS.gcnew_Pen();
+ int brush;
+ Pattern pattern = data.foregroundPattern;
+ if (pattern != null) {
+ brush = pattern.handle;
+ } else {
+ int foreground = data.foreground;
+ brush = OS.gcnew_SolidColorBrush(foreground);
+ if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ }
+ OS.Pen_Brush(pen, brush);
+ if (pattern == null) OS.GCHandle_Free(brush);
+ float width = data.lineWidth;
+ OS.Pen_Thickness(pen, width == 0 ? 1 : width);
+ double[] dashes = null;
+ int dashStyle = 0;
+ switch (data.lineStyle) {
+ case SWT.LINE_SOLID: dashStyle = OS.DashStyles_Solid(); break;
+ case SWT.LINE_DOT: if (width == 0) dashes = LINE_DOT_ZERO; else dashStyle = OS.DashStyles_Dot(); break;
+ case SWT.LINE_DASH: if (width == 0) dashes = LINE_DASH_ZERO; else dashStyle = OS.DashStyles_Dash(); break;
+ case SWT.LINE_DASHDOT: if (width == 0) dashes = LINE_DASHDOT_ZERO; else dashStyle = OS.DashStyles_DashDot(); break;
+ case SWT.LINE_DASHDOTDOT: if (width == 0) dashes = LINE_DASHDOTDOT_ZERO; else dashStyle = OS.DashStyles_DashDotDot(); break;
+ case SWT.LINE_CUSTOM: {
+ if (data.lineDashes != null) {
+ dashes = new double[data.lineDashes.length * 2];
+ for (int i = 0; i < data.lineDashes.length; i++) {
+ double dash = (double)data.lineDashes[i] / Math.max (1, width);
+ dashes[i] = dash;
+ dashes[i + data.lineDashes.length] = dash;
+ }
+ } else {
+ dashStyle = OS.DashStyles_Solid();
+ }
+ }
+ }
+ if (dashes != null) {
+ int list = OS.gcnew_DoubleCollection(dashes.length);
+ for (int i = 0; i < dashes.length; i++) {
+ OS.DoubleCollection_Add(list, dashes[i]);
+ }
+ dashStyle = OS.gcnew_DashStyle(list, data.lineDashesOffset);
+ OS.GCHandle_Free(list);
+ }
+ OS.Pen_DashStyle(pen, dashStyle);
+ OS.GCHandle_Free(dashStyle);
+ int joinStyle = 0;
+ switch (data.lineJoin) {
+ case SWT.JOIN_MITER: joinStyle = OS.PenLineJoin_Miter; break;
+ case SWT.JOIN_BEVEL: joinStyle = OS.PenLineJoin_Bevel; break;
+ case SWT.JOIN_ROUND: joinStyle = OS.PenLineJoin_Round; break;
+ }
+ OS.Pen_LineJoin(pen, joinStyle);
+ int capStyle = OS.PenLineCap_Flat;
+ switch (data.lineCap) {
+ case SWT.CAP_FLAT: capStyle = OS.PenLineCap_Flat; break;
+ case SWT.CAP_ROUND: capStyle = OS.PenLineCap_Round; break;
+ case SWT.CAP_SQUARE: capStyle = OS.PenLineCap_Square; break;
+ }
+ OS.Pen_DashCap(pen, capStyle);
+ OS.Pen_EndLineCap(pen, capStyle);
+ OS.Pen_StartLineCap(pen, capStyle);
+ OS.Pen_MiterLimit(pen, data.lineMiterLimit);
+ }
+ if ((state & BACKGROUND) != 0) {
+ if (data.brush != 0) OS.GCHandle_Free(data.brush);
+ data.brush = 0;
+ Pattern pattern = data.backgroundPattern;
+ if (pattern != null) {
+ data.currentBrush = pattern.handle;
+ } else {
+ int background = data.background;
+ int brush = OS.gcnew_SolidColorBrush(background);
+ if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ data.currentBrush = data.brush = brush;
+ }
+ }
+ if ((state & (ALPHA | CLIPPING | TRANSFORM)) != 0) {
+ for (int i = 0; i < data.pushCount; i++) OS.DrawingContext_Pop(handle);
+ data.pushCount = 0;
+ if (data.alpha != 0xFF) {
+ OS.DrawingContext_PushOpacity(handle, (data.alpha & 0xFF) / (double)0xFF);
+ data.pushCount++;
+ }
+ if (data.clip != 0) {
+ OS.DrawingContext_PushClip(handle, data.clip);
+ data.pushCount++;
+ }
+ if (data.transform != 0) {
+ OS.DrawingContext_PushTransform(handle, data.transform);
+ data.pushCount++;
+ }
+ }
+
+}
+
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position into the image, which must be of type <code>SWT.BITMAP</code>.
+ *
+ * @param image the image to copy into
+ * @param x the x coordinate in the receiver of the area to be copied
+ * @param y the y coordinate in the receiver of the area to be copied
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void copyArea(Image image, int x, int y) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ //TODO - implement copyArea
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) {
+ copyArea(srcX, srcY, width, height, destX, destY, true);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ * @param paint if <code>true</code> paint events will be generated for old and obscured areas
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+
+ //TODO - implement copyArea
+
+// /*
+// * Feature in WinCE. The function WindowFromDC is not part of the
+// * WinCE SDK. The fix is to remember the HWND.
+// */
+// int hwnd = data.hwnd;
+// if (hwnd == 0) {
+// OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+// } else {
+// RECT lprcClip = null;
+// int hrgn = OS.CreateRectRgn(0, 0, 0, 0);
+// if (OS.GetClipRgn(handle, hrgn) == 1) {
+// lprcClip = new RECT();
+// OS.GetRgnBox(hrgn, lprcClip);
+// }
+// OS.DeleteObject(hrgn);
+// RECT lprcScroll = new RECT();
+// OS.SetRect(lprcScroll, srcX, srcY, srcX + width, srcY + height);
+// int flags = paint ? OS.SW_INVALIDATE | OS.SW_ERASE : 0;
+// int res = OS.ScrollWindowEx(hwnd, destX - srcX, destY - srcY, lprcScroll, lprcClip, 0, null, flags);
+//
+// /*
+// * Feature in WinCE. ScrollWindowEx does not accept combined
+// * vertical and horizontal scrolling. The fix is to do a
+// * BitBlt and invalidate the appropriate source area.
+// */
+// if (res == 0 && OS.IsWinCE) {
+// OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+// if (paint) {
+// int deltaX = destX - srcX, deltaY = destY - srcY;
+// boolean disjoint = (destX + width < srcX) || (srcX + width < destX) || (destY + height < srcY) || (srcY + height < destY);
+// if (disjoint) {
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// } else {
+// if (deltaX != 0) {
+// int newX = destX - deltaX;
+// if (deltaX < 0) newX = destX + width;
+// OS.SetRect(lprcScroll, newX, srcY, newX + Math.abs(deltaX), srcY + height);
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// }
+// if (deltaY != 0) {
+// int newY = destY - deltaY;
+// if (deltaY < 0) newY = destY + height;
+// OS.SetRect(lprcScroll, srcX, newY, srcX + width, newY + Math.abs(deltaY));
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// }
+// }
+// }
+// }
+// }
+}
+
+void destroy() {
+ int brush = data.brush;
+ if (brush != 0) OS.GCHandle_Free(brush);
+ data.brush = 0;
+ int pen = data.pen;
+ if (pen != 0) OS.GCHandle_Free(pen);
+ data.pen = 0;
+ int clip = data.clip;
+ if (clip != 0) OS.GCHandle_Free(clip);
+ data.clip = 0;
+ int transform = data.transform;
+ if (transform != 0) OS.GCHandle_Free(transform);
+ data.transform = 0;
+
+ Image image = data.image;
+ if (image != null) image.memGC = null;
+
+ if (drawable != null) drawable.internal_dispose_GC(handle, data);
+ drawable = null;
+ handle = 0;
+ data.image = null;
+ data = null;
+}
+
+/**
+ * Draws the outline of a circular or elliptical arc
+ * within the specified rectangular area.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be drawn
+ * @param y the y coordinate of the upper-left corner of the arc to be drawn
+ * @param width the width of the arc to be drawn
+ * @param height the height of the arc to be drawn
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ if (arcAngle >= 360 || arcAngle <= -360) {
+ int center = OS.gcnew_Point(x + offset + width / 2f, y + offset + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, 0, data.pen, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+ return;
+ }
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ int tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + offset + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + offset + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + offset + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + offset + height/2.0;
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, true);
+ int figure = OS.gcnew_PathFigure();
+ OS.PathFigure_StartPoint(figure, startPoint);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, arc);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, 0, data.pen, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(arc);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(endPoint);
+ OS.GCHandle_Free(startPoint);
+}
+
+/**
+ * Draws a rectangle, based on the specified arguments, which has
+ * the appearance of the platform's <em>focus rectangle</em> if the
+ * platform supports such a notion, and otherwise draws a simple
+ * rectangle in the receiver's foreground color.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void drawFocus (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //TODO - implement drawFocus
+}
+
+/**
+ * Draws the given image in the receiver at the specified
+ * coordinates.
+ *
+ * @param image the image to draw
+ * @param x the x coordinate of where to draw
+ * @param y the y coordinate of where to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
+ * </ul>
+ */
+public void drawImage(Image image, int x, int y) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
+}
+
+/**
+ * Copies a rectangular area from the source image into a (potentially
+ * different sized) rectangular area in the receiver. If the source
+ * and destination areas are of differing sizes, then the source
+ * area will be stretched or shrunk to fit the destination area
+ * as it is copied. The copy fails if any part of the source rectangle
+ * lies outside the bounds of the source image, or if any of the width
+ * or height arguments are negative.
+ *
+ * @param image the source image
+ * @param srcX the x coordinate in the source image to copy from
+ * @param srcY the y coordinate in the source image to copy from
+ * @param srcWidth the width in pixels to copy from the source
+ * @param srcHeight the height in pixels to copy from the source
+ * @param destX the x coordinate in the destination to copy to
+ * @param destY the y coordinate in the destination to copy to
+ * @param destWidth the width in pixels of the destination rectangle
+ * @param destHeight the height in pixels of the destination rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * <li>ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
+ * <li>ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
+ * </ul>
+ */
+public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return;
+ if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false);
+}
+
+void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+ checkGC(IMAGE);
+ int imageHandle = image.handle;
+ int imgWidth = OS.BitmapSource_PixelWidth(imageHandle);
+ int imgHeight = OS.BitmapSource_PixelHeight(imageHandle);
+ if (simple) {
+ srcWidth = destWidth = imgWidth;
+ srcHeight = destHeight = imgHeight;
+ } else {
+ simple = srcX == 0 && srcY == 0 &&
+ srcWidth == destWidth && destWidth == imgWidth &&
+ srcHeight == destHeight && destHeight == imgHeight;
+ if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ int mode = 0;
+ switch (data.interpolation) {
+ case SWT.DEFAULT: mode = OS.BitmapScalingMode_Unspecified; break;
+ case SWT.NONE: mode = OS.BitmapScalingMode_LowQuality; break;
+ case SWT.LOW: mode = OS.BitmapScalingMode_LowQuality; break;
+ case SWT.HIGH: mode = OS.BitmapScalingMode_HighQuality; break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (srcX != 0 || srcY != 0 || srcWidth != imgWidth || srcHeight != imgHeight) {
+ int rect = OS.gcnew_Int32Rect(srcX, srcY, srcWidth, srcHeight);
+ imageHandle = OS.gcnew_CroppedBitmap(imageHandle, rect);
+ OS.RenderOptions_SetBitmapScalingMode(imageHandle, mode);
+ OS.GCHandle_Free(rect);
+ } else {
+ if (mode != OS.RenderOptions_GetBitmapScalingMode(imageHandle)) {
+ imageHandle = OS.Freezable_Clone(imageHandle);
+ OS.RenderOptions_SetBitmapScalingMode(imageHandle, mode);
+ }
+ }
+ int rect = OS.gcnew_Rect(destX, destY, destWidth, destHeight);
+ OS.DrawingContext_DrawImage(handle, imageHandle, rect);
+ OS.GCHandle_Free(rect);
+ if (image.handle != imageHandle) OS.GCHandle_Free(imageHandle);
+}
+
+/**
+ * Draws a line, using the foreground color, between the points
+ * (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
+ *
+ * @param x1 the first point's x coordinate
+ * @param y1 the first point's y coordinate
+ * @param x2 the second point's x coordinate
+ * @param y2 the second point's y coordinate
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawLine (int x1, int y1, int x2, int y2) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int point0 = OS.gcnew_Point(x1 + offset, y1 + offset);
+ int point1 = OS.gcnew_Point(x2 + offset, y2 + offset);
+ OS.DrawingContext_DrawLine(handle, data.pen, point0, point1);
+ OS.GCHandle_Free(point0);
+ OS.GCHandle_Free(point1);
+}
+
+/**
+ * Draws the outline of an oval, using the foreground color,
+ * within the specified rectangular area.
+ * <p>
+ * The result is a circle or ellipse that fits within the
+ * rectangle specified by the <code>x</code>, <code>y</code>,
+ * <code>width</code>, and <code>height</code> arguments.
+ * </p><p>
+ * The oval covers an area that is <code>width + 1</code>
+ * pixels wide and <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be drawn
+ * @param y the y coordinate of the upper left corner of the oval to be drawn
+ * @param width the width of the oval to be drawn
+ * @param height the height of the oval to be drawn
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawOval (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int center = OS.gcnew_Point(x + offset + width / 2f, y + offset + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, 0, data.pen, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+}
+
+/**
+ * Draws the path described by the parameter.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the path to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void drawPath (Path path) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ checkGC(DRAW);
+ //TODO - check offset to draw in the midle of pixel
+ OS.PathGeometry_FillRule(path.handle, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ OS.DrawingContext_DrawGeometry(handle, 0, data.pen, path.handle);
+}
+
+/**
+ * Draws a pixel, using the foreground color, at the specified
+ * point (<code>x</code>, <code>y</code>).
+ * <p>
+ * Note that the receiver's line attributes do not affect this
+ * operation.
+ * </p>
+ *
+ * @param x the point's x coordinate
+ * @param y the point's y coordinate
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void drawPoint (int x, int y) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ int rect = OS.gcnew_Rect(x, y, 1, 1);
+ int brush = OS.Pen_Brush(data.pen);
+ OS.DrawingContext_DrawRectangle(handle, brush, 0, rect);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Draws the closed polygon which is defined by the specified array
+ * of integer coordinates, using the receiver's foreground color. The array
+ * contains alternating x and y values which are considered to represent
+ * points which are the vertices of the polygon. Lines are drawn between
+ * each consecutive pair, and between the first pair and last pair in the
+ * array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawPolygon(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(DRAW);
+ drawPolyLineSegment(pointArray, true, true);
+}
+
+void drawPolyLineSegment(int[] pointArray, boolean closed, boolean stroked) {
+ if (pointArray.length < 4) return;
+ int list = OS.gcnew_PointCollection(pointArray.length / 2);
+ double offset = 0;
+ if (stroked && (data.lineWidth == 0 || (data.lineWidth % 2) == 1)) offset = 0.5;
+ for (int i = 2; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i] + offset, pointArray[i + 1] + offset);
+ OS.PointCollection_Add(list, point);
+ OS.GCHandle_Free(point);
+ }
+ int poly = OS.gcnew_PolyLineSegment(list, stroked);
+ OS.GCHandle_Free(list);
+ int figure = OS.gcnew_PathFigure();
+ int startPoint = OS.gcnew_Point(pointArray[0] + offset, pointArray[1] + offset);
+ OS.PathFigure_StartPoint(figure, startPoint);
+ OS.PathFigure_IsClosed(figure, closed);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, poly);
+ int path = OS.gcnew_PathGeometry();
+// int mode = 0;
+// switch (data.antialias) {
+// case SWT.DEFAULT:
+// case SWT.ON: mode = OS.EdgeMode_Unspecified; break;
+// case SWT.OFF: mode = OS.EdgeMode_Aliased; break;
+// }
+// OS.RenderOptions_SetEdgeMode(path, mode);
+ if (!stroked) OS.PathGeometry_FillRule(path, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, stroked ? 0 : data.currentBrush, stroked ? data.pen : 0, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(startPoint);
+ OS.GCHandle_Free(poly);
+}
+
+/**
+ * Draws the polyline which is defined by the specified array
+ * of integer coordinates, using the receiver's foreground color. The array
+ * contains alternating x and y values which are considered to represent
+ * points which are the corners of the polyline. Lines are drawn between
+ * each consecutive pair, but not between the first pair and last pair in
+ * the array.
+ *
+ * @param pointArray an array of alternating x and y values which are the corners of the polyline
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawPolyline(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(DRAW);
+ drawPolyLineSegment(pointArray, false, true);
+}
+
+/**
+ * Draws the outline of the rectangle specified by the arguments,
+ * using the receiver's foreground color. The left and right edges
+ * of the rectangle are at <code>x</code> and <code>x + width</code>.
+ * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRectangle (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int rect = OS.gcnew_Rect(x + offset, y + offset, width, height);
+ OS.DrawingContext_DrawRectangle(handle, 0, data.pen, rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Draws the outline of the specified rectangle, using the receiver's
+ * foreground color. The left and right edges of the rectangle are at
+ * <code>rect.x</code> and <code>rect.x + rect.width</code>. The top
+ * and bottom edges are at <code>rect.y</code> and
+ * <code>rect.y + rect.height</code>.
+ *
+ * @param rect the rectangle to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRectangle (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ drawRectangle (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Draws the outline of the round-cornered rectangle specified by
+ * the arguments, using the receiver's foreground color. The left and
+ * right edges of the rectangle are at <code>x</code> and <code>x + width</code>.
+ * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
+ * The <em>roundness</em> of the corners is specified by the
+ * <code>arcWidth</code> and <code>arcHeight</code> arguments, which
+ * are respectively the width and height of the ellipse used to draw
+ * the corners.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (arcWidth < 0 || arcHeight < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (arcWidth < 0) arcWidth = -arcWidth;
+ if (arcHeight < 0) arcHeight = -arcHeight;
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int rect = OS.gcnew_Rect(x + offset, y + offset, width, height);
+ OS.DrawingContext_DrawRoundedRectangle(handle, 0, data.pen, rect, arcWidth / 2f, arcHeight / 2f);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. The background of the rectangular area where
+ * the string is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y) {
+ drawString(string, x, y, false);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. If <code>isTransparent</code> is <code>true</code>,
+ * then the background of the rectangular area where the string is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y, boolean isTransparent) {
+ drawText(string, x, y, isTransparent ? SWT.DRAW_TRANSPARENT : 0);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. The background of the rectangular area where
+ * the text is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y) {
+ drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. If <code>isTransparent</code> is <code>true</code>,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y, boolean isTransparent) {
+ int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
+ if (isTransparent) flags |= SWT.DRAW_TRANSPARENT;
+ drawText(string, x, y, flags);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion, line delimiter and mnemonic
+ * processing are performed according to the specified flags. If
+ * <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ * <p>
+ * The parameter <code>flags</code> may be a combination of:
+ * <dl>
+ * <dt><b>DRAW_DELIMITER</b></dt>
+ * <dd>draw multiple lines</dd>
+ * <dt><b>DRAW_TAB</b></dt>
+ * <dd>expand tabs</dd>
+ * <dt><b>DRAW_MNEMONIC</b></dt>
+ * <dd>underline the mnemonic character</dd>
+ * <dt><b>DRAW_TRANSPARENT</b></dt>
+ * <dd>transparent background</dd>
+ * </dl>
+ * </p>
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param flags the flags specifying how to process the text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y, int flags) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int length = string.length ();
+ if (length == 0) return;
+ checkGC(FONT | FOREGROUND | ALPHA | CLIPPING | TRANSFORM | ((flags & SWT.DRAW_TRANSPARENT) != 0 ? 0 : BACKGROUND));
+ char [] buffer = new char [length + 1];
+ string.getChars(0, length, buffer, 0);
+ int mask = SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC;
+ int mnemonic = -1;
+ if ((flags & mask) != mask) {
+ for (int i = 0, j = 0; i < buffer.length; i++) {
+ char c = buffer[i];
+ switch (c) {
+ case '&': {
+ if ((flags & SWT.DRAW_MNEMONIC) != 0) {
+ if (i + 1 < length) {
+ if (buffer[i + 1] == '&') {
+ i++;
+ } else {
+ if (mnemonic == -1) mnemonic = j;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+ case '\r':
+ case '\n':
+ if ((flags & SWT.DRAW_DELIMITER) == 0) continue;
+ break;
+ case '\t':
+ if ((flags & SWT.DRAW_TAB) == 0) continue;
+ break;
+ }
+ buffer[j++] = c;
+ }
+ }
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Pen_Brush(data.pen);
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ int point = OS.gcnew_Point(x, y);
+ if (mnemonic != -1) {
+ int underline = OS.TextDecorations_Underline();
+ OS.FormattedText_SetTextDecorations(text, underline, mnemonic, 1);
+ OS.GCHandle_Free(underline);
+ }
+ if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, data.currentBrush, 0, rect);
+ OS.GCHandle_Free(rect);
+
+ }
+ OS.DrawingContext_DrawText(handle, text, point);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(text);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ return (object == this) || ((object instanceof GC) && (handle == ((GC)object).handle));
+}
+
+/**
+ * Fills the interior of a circular or elliptical arc within
+ * the specified rectangular area, with the receiver's background
+ * color.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be filled
+ * @param y the y coordinate of the upper-left corner of the arc to be filled
+ * @param width the width of the arc to be filled
+ * @param height the height of the arc to be filled
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawArc
+ */
+public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ if (arcAngle >= 360 || arcAngle <= -360) {
+ int center = OS.gcnew_Point(x + width / 2f, y + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, data.currentBrush, 0, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+ return;
+ }
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ int tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int center = OS.gcnew_Point(x + width / 2.0, y + height / 2.0);
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, false);
+ int line = OS.gcnew_LineSegment(center, false);
+ int figure = OS.gcnew_PathFigure();
+ OS.PathFigure_StartPoint(figure, startPoint);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, arc);
+ OS.PathSegmentCollection_Add(segments, line);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, data.currentBrush, 0, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(arc);
+ OS.GCHandle_Free(line);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(endPoint);
+ OS.GCHandle_Free(startPoint);
+}
+
+/**
+ * Fills the interior of the specified rectangle with a gradient
+ * sweeping from left to right or top to bottom progressing
+ * from the receiver's foreground color to its background color.
+ *
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled, may be negative
+ * (inverts direction of gradient if horizontal)
+ * @param height the height of the rectangle to be filled, may be negative
+ * (inverts direction of gradient if vertical)
+ * @param vertical if true sweeps from top to bottom, else
+ * sweeps from left to right
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillGradientRectangle(int x, int y, int width, int height, boolean vertical) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width == 0 || height == 0) return;
+ checkGC(FILL);
+
+ int fromColor = data.foreground;
+ int toColor = data.background;
+
+ boolean swapColors = false;
+ if (width < 0) {
+ x += width; width = -width;
+ if (! vertical) swapColors = true;
+ }
+ if (height < 0) {
+ y += height; height = -height;
+ if (vertical) swapColors = true;
+ }
+ if (swapColors) {
+ int temp = fromColor;
+ fromColor = toColor;
+ toColor = temp;
+ }
+ int brush = OS.gcnew_LinearGradientBrush(fromColor, toColor, vertical ? 90 : 0);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, brush, 0, rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(brush);
+}
+
+/**
+ * Fills the interior of an oval, within the specified
+ * rectangular area, with the receiver's background
+ * color.
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be filled
+ * @param y the y coordinate of the upper left corner of the oval to be filled
+ * @param width the width of the oval to be filled
+ * @param height the height of the oval to be filled
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawOval
+ */
+public void fillOval (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ int center = OS.gcnew_Point(x + width / 2f, y + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, data.currentBrush, 0, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+}
+
+/**
+ * Fills the path described by the parameter.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the path to fill
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void fillPath (Path path) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ checkGC(FILL);
+ OS.PathGeometry_FillRule(path.handle, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ OS.DrawingContext_DrawGeometry(handle, data.currentBrush, 0, path.handle);
+}
+
+/**
+ * Fills the interior of the closed polygon which is defined by the
+ * specified array of integer coordinates, using the receiver's
+ * background color. The array contains alternating x and y values
+ * which are considered to represent points which are the vertices of
+ * the polygon. Lines are drawn between each consecutive pair, and
+ * between the first pair and last pair in the array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawPolygon
+ */
+public void fillPolygon(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(FILL);
+ drawPolyLineSegment(pointArray, true, false);
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * using the receiver's background color.
+ *
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, data.currentBrush, 0, rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Fills the interior of the specified rectangle, using the receiver's
+ * background color.
+ *
+ * @param rect the rectangle to be filled
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ fillRectangle (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Fills the interior of the round-cornered rectangle specified by
+ * the arguments, using the receiver's background color.
+ *
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRoundRectangle
+ */
+public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (arcWidth < 0) arcWidth = -arcWidth;
+ if (arcHeight < 0) arcHeight = -arcHeight;
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRoundedRectangle(handle, data.currentBrush, 0, rect, arcWidth / 2f, arcHeight / 2f);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Returns the <em>advance width</em> of the specified character in
+ * the font which is currently selected into the receiver.
+ * <p>
+ * The advance width is defined as the horizontal distance the cursor
+ * should move after printing the character in the selected font.
+ * </p>
+ *
+ * @param ch the character to measure
+ * @return the distance in the x direction to move past the character before painting the next
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getAdvanceWidth(char ch) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //NOT DONE
+ return stringExtent(new String(new char[]{ch})).x;
+}
+
+/**
+ * Returns <code>true</code> if receiver is using the operating system's
+ * advanced graphics subsystem. Otherwise, <code>false</code> is returned
+ * to indicate that normal graphics are in use.
+ * <p>
+ * Advanced graphics may not be installed for the operating system. In this
+ * case, <code>false</code> is always returned. Some operating system have
+ * only one graphics subsystem. If this subsystem supports advanced graphics,
+ * then <code>true</code> is always returned. If any graphics operation such
+ * as alpha, antialias, patterns, interpolation, paths, clipping or transformation
+ * has caused the receiver to switch from regular to advanced graphics mode,
+ * <code>true</code> is returned. If the receiver has been explicitly switched
+ * to advanced mode and this mode is supported, <code>true</code> is returned.
+ * </p>
+ *
+ * @return the advanced value
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public boolean getAdvanced() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return true;
+}
+
+/**
+ * Returns the receiver's alpha value. The alpha value
+ * is between 0 (transparent) and 255 (opaque).
+ *
+ * @return the alpha value
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getAlpha() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.alpha;
+}
+
+/**
+ * Returns the receiver's anti-aliasing setting value, which will be
+ * one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
+ * <code>SWT.ON</code>. Note that this controls anti-aliasing for all
+ * <em>non-text drawing</em> operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getTextAntialias
+ *
+ * @since 3.1
+ */
+public int getAntialias() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.antialias;
+}
+
+/**
+ * Returns the background color.
+ *
+ * @return the receiver's background color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getBackground() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.wpf_new(data.device, data.background);
+}
+
+/**
+ * Returns the background pattern. The default value is
+ * <code>null</code>.
+ *
+ * @return the receiver's background pattern
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public Pattern getBackgroundPattern() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.backgroundPattern;
+}
+
+/**
+ * Returns the width of the specified character in the font
+ * selected into the receiver.
+ * <p>
+ * The width is defined as the space taken up by the actual
+ * character, not including the leading and tailing whitespace
+ * or overhang.
+ * </p>
+ *
+ * @param ch the character to measure
+ * @return the width of the character
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getCharWidth(char ch) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //NOT DONE
+ return stringExtent(new String(new char[]{ch})).x;
+}
+
+/**
+ * Returns the bounding rectangle of the receiver's clipping
+ * region. If no clipping region is set, the return value
+ * will be a rectangle which covers the entire bounds of the
+ * object the receiver is drawing on.
+ *
+ * @return the bounding rectangle of the clipping region
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getClipping() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int x = 0, y = 0, width = 0, height = 0;
+ int visualType = OS.Object_GetType(data.visual);
+ int drawingVisualType = OS.DrawingVisual_typeid();
+ if (OS.Object_Equals(visualType, drawingVisualType)) {
+ int clip = OS.ContainerVisual_Clip(data.visual);
+ int rect = OS.Geometry_Bounds(clip);
+ width = (int)OS.Rect_Width(rect);
+ height = (int)OS.Rect_Height(rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(clip);
+ } else {
+ width = (int)OS.FrameworkElement_ActualWidth(data.visual);
+ height = (int)OS.FrameworkElement_ActualHeight(data.visual);
+ }
+ OS.GCHandle_Free(drawingVisualType);
+ OS.GCHandle_Free(visualType);
+ if (data.clip != 0) {
+ int bounds = OS.gcnew_Rect(x, y, width, height);
+ int rect = OS.Geometry_Bounds(data.clip);
+ OS.Rect_Intersect(bounds, rect);
+ x = (int)OS.Rect_X(bounds);
+ y = (int)OS.Rect_Y(bounds);
+ width = (int)OS.Rect_Width(bounds);
+ height = (int)OS.Rect_Height(bounds);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(bounds);
+ }
+ return new Rectangle(x, y, width, height);
+}
+
+/**
+ * Sets the region managed by the argument to the current
+ * clipping region of the receiver.
+ *
+ * @param region the region to fill with the clipping region
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the region is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the region is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getClipping (Region region) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ int bounds;
+ int visualType = OS.Object_GetType(data.visual);
+ int drawingVisualType = OS.DrawingVisual_typeid();
+ if (OS.Object_Equals(visualType, drawingVisualType)) {
+ bounds = OS.ContainerVisual_Clip(data.visual);
+ } else {
+ double width = OS.FrameworkElement_ActualWidth(data.visual);
+ double height = OS.FrameworkElement_ActualHeight(data.visual);
+ int rect = OS.gcnew_Rect(0, 0, width, height);
+ bounds = OS.gcnew_RectangleGeometry(rect);
+ OS.GCHandle_Free(rect);
+ }
+ OS.GCHandle_Free(drawingVisualType);
+ OS.GCHandle_Free(visualType);
+ int geometries = OS.GeometryGroup_Children(region.handle);
+ OS.GeometryCollection_Clear(geometries);
+ if (data.clip != 0) {
+ int clip = OS.Geometry_GetFlattenedPathGeometry(data.clip);
+ int newGeometry = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, bounds, clip);
+ OS.GeometryCollection_Add(geometries, newGeometry);
+ OS.GCHandle_Free(clip);
+ OS.GCHandle_Free(newGeometry);
+ } else {
+ OS.GeometryCollection_Add(geometries, bounds);
+ }
+ OS.GCHandle_Free(bounds);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Returns the receiver's fill rule, which will be one of
+ * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
+ *
+ * @return the receiver's fill rule
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getFillRule() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.fillRule;
+}
+
+/**
+ * Returns the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getFont () {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.font;
+}
+
+/**
+ * Returns a FontMetrics which contains information
+ * about the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return font metrics for the receiver's font
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontMetrics getFontMetrics() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FONT);
+ //TODO - find a better way of getting font metrics
+ String string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ double baseline = OS.FormattedText_Baseline(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ return FontMetrics.wpf_new((int)baseline, (int)(height - baseline), (int)width / string.length(), 0, (int)height);
+}
+
+/**
+ * Returns the receiver's foreground color.
+ *
+ * @return the color used for drawing foreground things
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getForeground() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.wpf_new(data.device, data.foreground);
+}
+
+/**
+ * Returns the foreground pattern. The default value is
+ * <code>null</code>.
+ *
+ * @return the receiver's foreground pattern
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public Pattern getForegroundPattern() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.foregroundPattern;
+}
+
+/**
+ * Returns the GCData.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @return the receiver's GCData
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see GCData
+ *
+ * @since 3.2
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public GCData getGCData() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data;
+}
+
+/**
+ * Returns the receiver's interpolation setting, which will be one of
+ * <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>,
+ * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
+ *
+ * @return the receiver's interpolation setting
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getInterpolation() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.interpolation;
+}
+
+/**
+ * Returns the receiver's line attributes.
+ *
+ * @return the line attributes used for drawing lines
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public LineAttributes getLineAttributes() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ float[] dashes = null;
+ if (data.lineDashes != null) {
+ dashes = new float[data.lineDashes.length];
+ System.arraycopy(data.lineDashes, 0, dashes, 0, dashes.length);
+ }
+ return new LineAttributes(data.lineWidth, data.lineCap, data.lineJoin, data.lineStyle, dashes, data.lineDashesOffset, data.lineMiterLimit);
+}
+
+/**
+ * Returns the receiver's line cap style, which will be one
+ * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
+ * or <code>SWT.CAP_SQUARE</code>.
+ *
+ * @return the cap style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getLineCap() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineCap;
+}
+
+/**
+ * Returns the receiver's line dash style. The default value is
+ * <code>null</code>.
+ *
+ * @return the line dash style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int[] getLineDash() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineDashes == null) return null;
+ int[] lineDashes = new int[data.lineDashes.length];
+ System.arraycopy(data.lineDashes, 0, lineDashes, 0, lineDashes.length);
+ return lineDashes;
+}
+
+/**
+ * Returns the receiver's line join style, which will be one
+ * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
+ * or <code>SWT.JOIN_BEVEL</code>.
+ *
+ * @return the join style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getLineJoin() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineJoin;
+}
+
+/**
+ * Returns the receiver's line style, which will be one
+ * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
+ * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
+ * <code>SWT.LINE_DASHDOTDOT</code>.
+ *
+ * @return the style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineStyle() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineStyle;
+}
+
+/**
+ * Returns the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * <code>drawLine</code>, <code>drawRectangle</code>,
+ * <code>drawPolyline</code>, and so forth.
+ *
+ * @return the receiver's line width
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineWidth() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return (int)data.lineWidth;
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public int getStyle () {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.style;
+}
+
+/**
+ * Returns the receiver's text drawing anti-aliasing setting value,
+ * which will be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
+ * <code>SWT.ON</code>. Note that this controls anti-aliasing
+ * <em>only</em> for text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getAntialias
+ *
+ * @since 3.1
+ */
+public int getTextAntialias() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.textAntialias;
+}
+
+/**
+ * Sets the parameter to the transform that is currently being
+ * used by the receiver.
+ *
+ * @param transform the destination to copy the transform into
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Transform
+ *
+ * @since 3.1
+ */
+public void getTransform(Transform transform) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.transform != 0) {
+ OS.MatrixTransform_Matrix(transform.handle, data.transform);
+ } else {
+ transform.setElements(1, 0, 0, 1, 0, 0);
+ }
+}
+
+/**
+ * Returns <code>true</code> if this GC is drawing in the mode
+ * where the resulting color in the destination is the
+ * <em>exclusive or</em> of the color values in the source
+ * and the destination, and <code>false</code> if it is
+ * drawing in the mode where the destination color is being
+ * replaced with the source color value.
+ *
+ * @return <code>true</code> true if the receiver is in XOR mode, and false otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean getXORMode() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.xorMode;
+}
+
+void init(Drawable drawable, GCData data, int hDC) {
+ int foreground = data.foreground;
+ if (foreground != -1) data.state &= ~FOREGROUND;
+ int background = data.background;
+ if (background != 0) data.state &= ~BACKGROUND;
+ Font font = data.font;
+ if (font != null) data.state &= ~FONT;
+ Image image = data.image;
+ if (image != null) image.memGC = this;
+// int layout = data.layout;
+// if (layout != -1) {
+// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+// int flags = OS.GetLayout(hDC);
+// if ((flags & OS.LAYOUT_RTL) != (layout & OS.LAYOUT_RTL)) {
+// flags &= ~OS.LAYOUT_RTL;
+// OS.SetLayout(hDC, flags | layout);
+// }
+// if ((data.style & SWT.RIGHT_TO_LEFT) != 0) data.style |= SWT.MIRRORED;
+// }
+// }
+ this.drawable = drawable;
+ this.data = data;
+ handle = hDC;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Returns <code>true</code> if the receiver has a clipping
+ * region set into it, and <code>false</code> otherwise.
+ * If this method returns false, the receiver will draw on all
+ * available space in the destination. If it returns true,
+ * it will draw only in the area that is covered by the region
+ * that can be accessed with <code>getClipping(region)</code>.
+ *
+ * @return <code>true</code> if the GC has a clipping region, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean isClipped() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.clip != 0;
+}
+
+/**
+ * Returns <code>true</code> if the GC has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the GC.
+ * When a GC has been disposed, it is an error to
+ * invoke any other method using the GC.
+ *
+ * @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Sets the receiver to always use the operating system's advanced graphics
+ * subsystem for all graphics operations if the argument is <code>true</code>.
+ * If the argument is <code>false</code>, the advanced graphics subsystem is
+ * no longer used, advanced graphics state is cleared and the normal graphics
+ * subsystem is used from now on.
+ * <p>
+ * Normally, the advanced graphics subsystem is invoked automatically when
+ * any one of the alpha, antialias, patterns, interpolation, paths, clipping
+ * or transformation operations in the receiver is requested. When the receiver
+ * is switched into advanced mode, the advanced graphics subsystem performs both
+ * advanced and normal graphics operations. Because the two subsystems are
+ * different, their output may differ. Switching to advanced graphics before
+ * any graphics operations are performed ensures that the output is consistent.
+ * </p><p>
+ * Advanced graphics may not be installed for the operating system. In this
+ * case, this operation does nothing. Some operating system have only one
+ * graphics subsystem, so switching from normal to advanced graphics does
+ * nothing. However, switching from advanced to normal graphics will always
+ * clear the advanced graphics state, even for operating systems that have
+ * only one graphics subsystem.
+ * </p>
+ *
+ * @param advanced the new advanced graphics state
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAlpha
+ * @see #setAntialias
+ * @see #setBackgroundPattern
+ * @see #setClipping(Path)
+ * @see #setForegroundPattern
+ * @see #setLineAttributes
+ * @see #setInterpolation
+ * @see #setTextAntialias
+ * @see #setTransform
+ * @see #getAdvanced
+ *
+ * @since 3.1
+ */
+public void setAdvanced(boolean advanced) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (!advanced) {
+ setAlpha(0xFF);
+ setAntialias(SWT.DEFAULT);
+ setBackgroundPattern(null);
+ setClipping((Rectangle)null);
+ setForegroundPattern(null);
+ setInterpolation(SWT.DEFAULT);
+ setTextAntialias(SWT.DEFAULT);
+ setTransform(null);
+ }
+}
+
+/**
+ * Sets the receiver's anti-aliasing value to the parameter,
+ * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
+ * or <code>SWT.ON</code>. Note that this controls anti-aliasing for all
+ * <em>non-text drawing</em> operations.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
+ * <code>SWT.OFF</code> or <code>SWT.ON</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ * @see #setTextAntialias
+ *
+ * @since 3.1
+ */
+public void setAntialias(int antialias) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (antialias) {
+ case SWT.DEFAULT:
+ case SWT.OFF:
+ case SWT.ON:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.antialias = antialias;
+}
+
+/**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param alpha the alpha value
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setAlpha(int alpha) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.alpha = alpha & 0xFF;
+ data.state &= ~ALPHA;
+}
+
+/**
+ * Sets the background color. The background color is used
+ * for fill operations and as the background color when text
+ * is drawn.
+ *
+ * @param color the new background color for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setBackground (Color color) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.backgroundPattern == null && data.background == color.handle) return;
+ data.backgroundPattern = null;
+ data.background = color.handle;
+ data.state &= ~BACKGROUND;
+}
+
+/**
+ * Sets the background pattern. The default value is <code>null</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param pattern the new background pattern
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Pattern
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setBackgroundPattern (Pattern pattern) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.backgroundPattern == pattern) return;
+ data.backgroundPattern = pattern;
+ data.state &= ~BACKGROUND;
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the arguments.
+ *
+ * @param x the x coordinate of the clipping rectangle
+ * @param y the y coordinate of the clipping rectangle
+ * @param width the width of the clipping rectangle
+ * @param height the height of the clipping rectangle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int clip = OS.gcnew_RectangleGeometry(rect);
+ OS.GCHandle_Free(rect);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = clip;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the path specified
+ * by the argument.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the clipping path.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setClipping (Path path) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = path != null ? OS.Geometry_Clone(path.handle) : 0;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the argument. Specifying <code>null</code> for the
+ * rectangle reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param rect the clipping rectangle or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (Rectangle rect) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) {
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = 0;
+ data.state &= ~CLIPPING;
+ } else {
+ setClipping(rect.x, rect.y, rect.width, rect.height);
+ }
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the region specified
+ * by the argument. Specifying <code>null</code> for the
+ * region reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param region the clipping region or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (Region region) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = region != null ? OS.Geometry_Clone(region.handle) : 0;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * Sets the receiver's fill rule to the parameter, which must be one of
+ * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
+ *
+ * @param rule the new fill rule
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.FILL_EVEN_ODD</code>
+ * or <code>SWT.FILL_WINDING</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setFillRule(int rule) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (rule) {
+ case SWT.FILL_WINDING:
+ case SWT.FILL_EVEN_ODD: break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.fillRule = rule;
+}
+
+/**
+ * Sets the font which will be used by the receiver
+ * to draw and measure text to the argument. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setFont (Font font) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ data.font = font != null ? font : data.device.systemFont;
+ data.state &= ~FONT;
+}
+
+/**
+ * Sets the foreground color. The foreground color is used
+ * for drawing operations including when text is drawn.
+ *
+ * @param color the new foreground color for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setForeground (Color color) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.foregroundPattern == null && color.handle == data.foreground) return;
+ data.foregroundPattern = null;
+ data.foreground = color.handle;
+ data.state &= ~FOREGROUND;
+}
+
+/**
+ * Sets the foreground pattern. The default value is <code>null</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param pattern the new foreground pattern
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Pattern
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setForegroundPattern (Pattern pattern) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.foregroundPattern == pattern) return;
+ data.foregroundPattern = pattern;
+ data.state &= ~FOREGROUND;
+}
+
+/**
+ * Sets the receiver's interpolation setting to the parameter, which
+ * must be one of <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>,
+ * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param interpolation the new interpolation setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.DEFAULT</code>,
+ * <code>SWT.NONE</code>, <code>SWT.LOW</code> or <code>SWT.HIGH</code>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setInterpolation(int interpolation) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (interpolation) {
+ case SWT.DEFAULT: break;
+ case SWT.NONE: break;
+ case SWT.LOW: break;
+ case SWT.HIGH: break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.interpolation = interpolation;
+}
+
+/**
+ * Sets the receiver's line attributes.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param attributes the line attributes
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the attributes is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if any of the line attributes is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see LineAttributes
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.3
+ */
+public void setLineAttributes(LineAttributes attributes) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (attributes == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int mask = 0;
+ float lineWidth = attributes.width;
+ if (lineWidth != data.lineWidth) {
+ mask |= LINE_WIDTH;
+ }
+ int lineStyle = attributes.style;
+ if (lineStyle != data.lineStyle) {
+ mask |= LINE_STYLE;
+ switch (lineStyle) {
+ case SWT.LINE_SOLID:
+ case SWT.LINE_DASH:
+ case SWT.LINE_DOT:
+ case SWT.LINE_DASHDOT:
+ case SWT.LINE_DASHDOTDOT:
+ break;
+ case SWT.LINE_CUSTOM:
+ if (attributes.dash == null) lineStyle = SWT.LINE_SOLID;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ int join = attributes.join;
+ if (join != data.lineJoin) {
+ mask |= LINE_JOIN;
+ switch (join) {
+ case SWT.CAP_ROUND:
+ case SWT.CAP_FLAT:
+ case SWT.CAP_SQUARE:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ int cap = attributes.cap;
+ if (cap != data.lineCap) {
+ mask |= LINE_CAP;
+ switch (cap) {
+ case SWT.JOIN_MITER:
+ case SWT.JOIN_ROUND:
+ case SWT.JOIN_BEVEL:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ float[] dashes = attributes.dash;
+ float[] lineDashes = data.lineDashes;
+ if (dashes != null && dashes.length > 0) {
+ boolean changed = lineDashes == null || lineDashes.length != dashes.length;
+ for (int i = 0; i < dashes.length; i++) {
+ float dash = dashes[i];
+ if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (!changed && lineDashes[i] != dash) changed = true;
+ }
+ if (changed) {
+ float[] newDashes = new float[dashes.length];
+ System.arraycopy(dashes, 0, newDashes, 0, dashes.length);
+ dashes = newDashes;
+ mask |= LINE_STYLE;
+ } else {
+ dashes = lineDashes;
+ }
+ } else {
+ if (lineDashes != null && lineDashes.length > 0) {
+ mask |= LINE_STYLE;
+ } else {
+ dashes = lineDashes;
+ }
+ }
+ float dashOffset = attributes.dashOffset;
+ if (dashOffset != data.lineDashesOffset) {
+ mask |= LINE_STYLE;
+ }
+ float miterLimit = attributes.miterLimit;
+ if (miterLimit != data.lineMiterLimit) {
+ mask |= LINE_MITERLIMIT;
+ }
+ if (mask == 0) return;
+ data.lineWidth = lineWidth;
+ data.lineStyle = lineStyle;
+ data.lineCap = cap;
+ data.lineJoin = join;
+ data.lineDashes = dashes;
+ data.lineDashesOffset = dashOffset;
+ data.lineMiterLimit = miterLimit;
+ data.state &= ~mask;
+}
+
+/**
+ * Sets the receiver's line cap style to the argument, which must be one
+ * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
+ * or <code>SWT.CAP_SQUARE</code>.
+ *
+ * @param cap the cap style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineCap(int cap) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineCap == cap) return;
+ switch (cap) {
+ case SWT.CAP_ROUND:
+ case SWT.CAP_FLAT:
+ case SWT.CAP_SQUARE:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineCap = cap;
+ data.state &= ~LINE_CAP;
+}
+
+/**
+ * Sets the receiver's line dash style to the argument. The default
+ * value is <code>null</code>. If the argument is not <code>null</code>,
+ * the receiver's line style is set to <code>SWT.LINE_CUSTOM</code>, otherwise
+ * it is set to <code>SWT.LINE_SOLID</code>.
+ *
+ * @param dashes the dash style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if any of the values in the array is less than or equal 0</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineDash(int[] dashes) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ float[] lineDashes = data.lineDashes;
+ if (dashes != null && dashes.length > 0) {
+ boolean changed = data.lineStyle != SWT.LINE_CUSTOM || lineDashes == null || lineDashes.length != dashes.length;
+ for (int i = 0; i < dashes.length; i++) {
+ int dash = dashes[i];
+ if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (!changed && lineDashes[i] != dash) changed = true;
+ }
+ if (!changed) return;
+ data.lineDashes = new float[dashes.length];
+ for (int i = 0; i < dashes.length; i++) {
+ data.lineDashes[i] = dashes[i];
+ }
+ data.lineStyle = SWT.LINE_CUSTOM;
+ } else {
+ if (data.lineStyle == SWT.LINE_SOLID && (lineDashes == null || lineDashes.length == 0)) return;
+ data.lineDashes = null;
+ data.lineStyle = SWT.LINE_SOLID;
+ }
+ data.state &= ~LINE_STYLE;
+}
+
+/**
+ * Sets the receiver's line join style to the argument, which must be one
+ * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
+ * or <code>SWT.JOIN_BEVEL</code>.
+ *
+ * @param join the join style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineJoin(int join) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineJoin == join) return;
+ switch (join) {
+ case SWT.JOIN_MITER:
+ case SWT.JOIN_ROUND:
+ case SWT.JOIN_BEVEL:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineJoin = join;
+ data.state &= ~LINE_JOIN;
+}
+
+/**
+ * Sets the receiver's line style to the argument, which must be one
+ * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
+ * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
+ * <code>SWT.LINE_DASHDOTDOT</code>.
+ *
+ * @param lineStyle the style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setLineStyle(int lineStyle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineStyle == lineStyle) return;
+ switch (lineStyle) {
+ case SWT.LINE_SOLID:
+ case SWT.LINE_DASH:
+ case SWT.LINE_DOT:
+ case SWT.LINE_DASHDOT:
+ case SWT.LINE_DASHDOTDOT:
+ break;
+ case SWT.LINE_CUSTOM:
+ if (data.lineDashes == null) lineStyle = SWT.LINE_SOLID;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineStyle = lineStyle;
+ data.state &= ~LINE_STYLE;
+}
+
+/**
+ * Sets the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * <code>drawLine</code>, <code>drawRectangle</code>,
+ * <code>drawPolyline</code>, and so forth.
+ * <p>
+ * Note that line width of zero is used as a hint to
+ * indicate that the fastest possible line drawing
+ * algorithms should be used. This means that the
+ * output may be different from line width one.
+ * </p>
+ *
+ * @param lineWidth the width of a line
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setLineWidth(int lineWidth) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineWidth == lineWidth) return;
+ data.lineWidth = lineWidth;
+ data.state &= ~LINE_WIDTH;
+ switch (data.lineStyle) {
+ case SWT.LINE_DOT:
+ case SWT.LINE_DASH:
+ case SWT.LINE_DASHDOT:
+ case SWT.LINE_DASHDOTDOT:
+ data.state &= ~LINE_STYLE;
+ }
+}
+
+/**
+ * If the argument is <code>true</code>, puts the receiver
+ * in a drawing mode where the resulting color in the destination
+ * is the <em>exclusive or</em> of the color values in the source
+ * and the destination, and if the argument is <code>false</code>,
+ * puts the receiver in a drawing mode where the destination color
+ * is replaced with the source color value.
+ * <p>
+ * Note that this mode in fundamentally unsupportable on certain
+ * platforms, notably Carbon (Mac OS X). Clients that want their
+ * code to run on all platforms need to avoid this method.
+ * </p>
+ *
+ * @param xor if <code>true</code>, then <em>xor</em> mode is used, otherwise <em>source copy</em> mode is used
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @deprecated this functionality is not supported on some platforms
+ */
+public void setXORMode(boolean xor) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.xorMode = xor;
+}
+
+/**
+ * Sets the receiver's text anti-aliasing value to the parameter,
+ * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
+ * or <code>SWT.ON</code>. Note that this controls anti-aliasing only
+ * for all <em>text drawing</em> operations.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
+ * <code>SWT.OFF</code> or <code>SWT.ON</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ * @see #setAntialias
+ *
+ * @since 3.1
+ */
+public void setTextAntialias(int antialias) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (antialias) {
+ case SWT.DEFAULT:
+ case SWT.OFF:
+ case SWT.ON:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.textAntialias = antialias;
+}
+
+/**
+ * Sets the transform that is currently being used by the receiver. If
+ * the argument is <code>null</code>, the current transform is set to
+ * the identity transform.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param transform the transform to set
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Transform
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setTransform(Transform transform) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (transform != null && transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ data.transform = transform != null ? OS.gcnew_MatrixTransform(transform.handle) : 0;
+ data.state &= ~TRANSFORM;
+}
+
+/**
+ * Returns the extent of the given string. No tab
+ * expansion or carriage return processing will be performed.
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point stringExtent(String string) {
+ return textExtent(string, 0);
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion and
+ * carriage return processing are performed.
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent(String string) {
+ return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion, line
+ * delimiter and mnemonic processing are performed according to
+ * the specified flags, which can be a combination of:
+ * <dl>
+ * <dt><b>DRAW_DELIMITER</b></dt>
+ * <dd>draw multiple lines</dd>
+ * <dt><b>DRAW_TAB</b></dt>
+ * <dd>expand tabs</dd>
+ * <dt><b>DRAW_MNEMONIC</b></dt>
+ * <dd>underline the mnemonic character</dd>
+ * <dt><b>DRAW_TRANSPARENT</b></dt>
+ * <dd>transparent background</dd>
+ * </dl>
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @param flags the flags specifying how to process the text
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent(String string, int flags) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ checkGC(FONT);
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ if ((flags & (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) != (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) {
+ for (int i = 0, j = 0; i < buffer.length; i++) {
+ char c = buffer[i];
+ switch (c) {
+ case '\r':
+ case '\n':
+ if ((flags & SWT.DRAW_DELIMITER) == 0) continue;
+ break;
+ case '\t':
+ if ((flags & SWT.DRAW_TAB) == 0) continue;
+ break;
+ }
+ buffer[j++] = c;
+ }
+ }
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ return new Point((int)width, (int)height);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "GC {*DISPOSED*}";
+ return "GC {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new graphics context.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param drawable the Drawable for the receiver.
+ * @param data the data for the receiver.
+ *
+ * @return a new <code>GC</code>
+ */
+public static GC wpf_new(Drawable drawable, GCData data) {
+ GC gc = new GC();
+ int hDC = drawable.internal_new_GC(data);
+ gc.device = data.device;
+ gc.init(drawable, data, hDC);
+ return gc;
+}
+
+/**
+ * Invokes platform specific functionality to wrap a graphics context.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the Windows HDC.
+ * @param data the data for the receiver.
+ *
+ * @return a new <code>GC</code>
+ */
+public static GC wpf_new(int hDC, GCData data) {
+ GC gc = new GC();
+ gc.device = data.device;
+ gc.init(null, data, hDC);
+ return gc;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java
new file mode 100644
index 0000000000..e6ad4772c7
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class are descriptions of GCs in terms
+ * of unallocated platform-specific data fields.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the public
+ * API for SWT. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms, and should never be called from application code.
+ * </p>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+
+public final class GCData {
+ public Device device;
+ public int style, state = -1;
+ public int foreground;
+ public int background;
+ public Font font;
+ public Pattern foregroundPattern;
+ public Pattern backgroundPattern;
+ public boolean xorMode;
+ public int fillRule = SWT.FILL_EVEN_ODD;
+ public int interpolation = SWT.DEFAULT;
+ public int antialias = SWT.DEFAULT;
+ public int textAntialias = SWT.DEFAULT;
+ public int lineStyle = SWT.LINE_SOLID;
+ public float lineWidth;
+ public int lineCap = SWT.CAP_FLAT;
+ public int lineJoin = SWT.JOIN_MITER;
+ public float lineDashesOffset;
+ public float[] lineDashes;
+ public float lineMiterLimit = 10;
+ public int alpha = 0xFF;
+
+ public Image image;
+ public int pen;
+ public int brush, currentBrush;
+ public int pushCount;
+ public int clip;
+ public int transform;
+ public int visual;
+ public int drawingContext;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java
new file mode 100644
index 0000000000..90366cfe19
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java
@@ -0,0 +1,1127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+import java.io.*;
+
+/**
+ * Instances of this class are graphics which have been prepared
+ * for display on a specific device. That is, they are ready
+ * to paint using methods such as <code>GC.drawImage()</code>
+ * and display on widgets with, for example, <code>Button.setImage()</code>.
+ * <p>
+ * If loaded from a file format that supports it, an
+ * <code>Image</code> may have transparency, meaning that certain
+ * pixels are specified as being transparent when drawn. Examples
+ * of file formats that support transparency are GIF and PNG.
+ * </p><p>
+ * There are two primary ways to use <code>Images</code>.
+ * The first is to load a graphic file from disk and create an
+ * <code>Image</code> from it. This is done using an <code>Image</code>
+ * constructor, for example:
+ * <pre>
+ * Image i = new Image(device, "C:\\graphic.bmp");
+ * </pre>
+ * A graphic file may contain a color table specifying which
+ * colors the image was intended to possess. In the above example,
+ * these colors will be mapped to the closest available color in
+ * SWT. It is possible to get more control over the mapping of
+ * colors as the image is being created, using code of the form:
+ * <pre>
+ * ImageData data = new ImageData("C:\\graphic.bmp");
+ * RGB[] rgbs = data.getRGBs();
+ * // At this point, rgbs contains specifications of all
+ * // the colors contained within this image. You may
+ * // allocate as many of these colors as you wish by
+ * // using the Color constructor Color(RGB), then
+ * // create the image:
+ * Image i = new Image(device, data);
+ * </pre>
+ * <p>
+ * Applications which require even greater control over the image
+ * loading process should use the support provided in class
+ * <code>ImageLoader</code>.
+ * </p><p>
+ * Application code must explicitly invoke the <code>Image.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see Color
+ * @see ImageData
+ * @see ImageLoader
+ * @see <a href="http://www.eclipse.org/swt/snippets/#image">Image snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, ImageAnalyzer</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Image extends Resource implements Drawable {
+
+ /**
+ * specifies whether the receiver is a bitmap or an icon
+ * (one of <code>SWT.BITMAP</code>, <code>SWT.ICON</code>)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int type;
+
+ /**
+ * the handle to the OS image resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+ /**
+ * specifies the transparent pixel
+ */
+ int transparentPixel = -1;
+
+ /**
+ * the GC which is drawing on the image
+ */
+ GC memGC;
+
+ /**
+ * the alpha data for the image
+ */
+ byte[] alphaData;
+
+ /**
+ * the global alpha value to be used for every pixel
+ */
+ int alpha = -1;
+
+ /**
+ * the image data used to create this image if it is a
+ * icon. Used only in WinCE
+ */
+ ImageData data;
+
+ /**
+ * width of the image
+ */
+ int width = -1;
+
+ /**
+ * height of the image
+ */
+ int height = -1;
+
+ /**
+ * specifies the default scanline padding
+ */
+ static final int DEFAULT_SCANLINE_PAD = 4;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Image (Device device) {
+ super(device);
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * specified width and height. The result may be drawn upon
+ * by creating a GC and using any of its drawing operations,
+ * as shown in the following example:
+ * <pre>
+ * Image i = new Image(device, width, height);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param width the width of the new image
+ * @param height the height of the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, int width, int height) {
+ super(device);
+ init(width, height);
+ init();
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * provided image, with an appearance that varies depending
+ * on the value of the flag. The possible flag values are:
+ * <dl>
+ * <dt><b>{@link SWT#IMAGE_COPY}</b></dt>
+ * <dd>the result is an identical copy of srcImage</dd>
+ * <dt><b>{@link SWT#IMAGE_DISABLE}</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd>
+ * <dt><b>{@link SWT#IMAGE_GRAY}</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd>
+ * </dl>
+ *
+ * @param device the device on which to create the image
+ * @param srcImage the image to use as the source
+ * @param flag the style, either <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if srcImage is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the flag is not one of <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code></li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state</li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, Image srcImage, int flag) {
+ super(device);
+ device = this.device;
+ if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Rectangle rect = srcImage.getBounds();
+ switch (flag) {
+ case SWT.IMAGE_COPY: {
+ type = srcImage.type;
+ handle = OS.BitmapSource_Clone(srcImage.handle);
+ transparentPixel = srcImage.transparentPixel;
+ alpha = srcImage.alpha;
+ if (srcImage.alphaData != null) {
+ alphaData = new byte[srcImage.alphaData.length];
+ System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+ }
+ break;
+ }
+ case SWT.IMAGE_DISABLE: {
+ ImageData data = srcImage.getImageData();
+ PaletteData palette = data.palette;
+ RGB[] rgbs = new RGB[3];
+ rgbs[0] = device.getSystemColor(SWT.COLOR_BLACK).getRGB();
+ rgbs[1] = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW).getRGB();
+ rgbs[2] = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
+ ImageData newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ newData.maskData = data.maskData;
+ newData.maskPad = data.maskPad;
+ if (data.transparentPixel != -1) newData.transparentPixel = 0;
+
+ /* Convert the pixels. */
+ int[] scanline = new int[rect.width];
+ int[] maskScanline = null;
+ ImageData mask = null;
+ if (data.maskData != null) mask = data.getTransparencyMask();
+ if (mask != null) maskScanline = new int[rect.width];
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ int redShift = palette.redShift;
+ int greenShift = palette.greenShift;
+ int blueShift = palette.blueShift;
+ for (int y=0; y<rect.height; y++) {
+ int offset = y * newData.bytesPerLine;
+ data.getPixels(0, y, rect.width, scanline, 0);
+ if (mask != null) mask.getPixels(0, y, rect.width, maskScanline, 0);
+ for (int x=0; x<rect.width; x++) {
+ int pixel = scanline[x];
+ if (!(pixel == data.transparentPixel || (mask != null && maskScanline[x] == 0))) {
+ int red, green, blue;
+ if (palette.isDirect) {
+ red = pixel & redMask;
+ red = (redShift < 0) ? red >>> -redShift : red << redShift;
+ green = pixel & greenMask;
+ green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+ blue = pixel & blueMask;
+ blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+ } else {
+ red = palette.colors[pixel].red;
+ green = palette.colors[pixel].green;
+ blue = palette.colors[pixel].blue;
+ }
+ int intensity = red * red + green * green + blue * blue;
+ if (intensity < 98304) {
+ newData.data[offset] = (byte)1;
+ } else {
+ newData.data[offset] = (byte)2;
+ }
+ }
+ offset++;
+ }
+ }
+ init (newData);
+ break;
+ }
+ case SWT.IMAGE_GRAY: {
+ ImageData data = srcImage.getImageData();
+ PaletteData palette = data.palette;
+ ImageData newData = data;
+ if (!palette.isDirect) {
+ /* Convert the palette entries to gray. */
+ RGB [] rgbs = palette.getRGBs();
+ for (int i=0; i<rgbs.length; i++) {
+ if (data.transparentPixel != i) {
+ RGB color = rgbs [i];
+ int red = color.red;
+ int green = color.green;
+ int blue = color.blue;
+ int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+ color.red = color.green = color.blue = intensity;
+ }
+ }
+ newData.palette = new PaletteData(rgbs);
+ } else {
+ /* Create a 8 bit depth image data with a gray palette. */
+ RGB[] rgbs = new RGB[256];
+ for (int i=0; i<rgbs.length; i++) {
+ rgbs[i] = new RGB(i, i, i);
+ }
+ newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ newData.maskData = data.maskData;
+ newData.maskPad = data.maskPad;
+ if (data.transparentPixel != -1) newData.transparentPixel = 254;
+
+ /* Convert the pixels. */
+ int[] scanline = new int[rect.width];
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ int redShift = palette.redShift;
+ int greenShift = palette.greenShift;
+ int blueShift = palette.blueShift;
+ for (int y=0; y<rect.height; y++) {
+ int offset = y * newData.bytesPerLine;
+ data.getPixels(0, y, rect.width, scanline, 0);
+ for (int x=0; x<rect.width; x++) {
+ int pixel = scanline[x];
+ if (pixel != data.transparentPixel) {
+ int red = pixel & redMask;
+ red = (redShift < 0) ? red >>> -redShift : red << redShift;
+ int green = pixel & greenMask;
+ green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+ int blue = pixel & blueMask;
+ blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+ int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+ if (newData.transparentPixel == intensity) intensity = 255;
+ newData.data[offset] = (byte)intensity;
+ } else {
+ newData.data[offset] = (byte)254;
+ }
+ offset++;
+ }
+ }
+ }
+ init (newData);
+ break;
+ }
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ init();
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * width and height of the specified rectangle. The result
+ * may be drawn upon by creating a GC and using any of its
+ * drawing operations, as shown in the following example:
+ * <pre>
+ * Image i = new Image(device, boundsRectangle);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param bounds a rectangle specifying the image's width and height (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the bounds rectangle is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, Rectangle bounds) {
+ super(device);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(bounds.width, bounds.height);
+ init();
+}
+
+/**
+ * Constructs an instance of this class from the given
+ * <code>ImageData</code>.
+ *
+ * @param device the device on which to create the image
+ * @param data the image data to create the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the image data is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, ImageData data) {
+ super(device);
+ init(data);
+ init();
+}
+
+/**
+ * Constructs an instance of this class, whose type is
+ * <code>SWT.ICON</code>, from the two given <code>ImageData</code>
+ * objects. The two images must be the same size. Pixel transparency
+ * in either image will be ignored.
+ * <p>
+ * The mask image should contain white wherever the icon is to be visible,
+ * and black wherever the icon is to be transparent. In addition,
+ * the source image should contain black wherever the icon is to be
+ * transparent.
+ * </p>
+ *
+ * @param device the device on which to create the icon
+ * @param source the color data for the icon
+ * @param mask the mask data for the icon
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if either the source or mask is null </li>
+ * <li>ERROR_INVALID_ARGUMENT - if source and mask are different sizes</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, ImageData source, ImageData mask) {
+ super(device);
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (source.width != mask.width || source.height != mask.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ mask = ImageData.convertMask (mask);
+ ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data);
+ image.maskPad = mask.scanlinePad;
+ image.maskData = mask.data;
+ init(image);
+ init();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the specified input stream. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type. Application code is still responsible
+ * for closing the input stream.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p><p>
+ * This constructor may be used to load a resource as follows:
+ * </p>
+ * <pre>
+ * static Image loadImage (Display display, Class clazz, String string) {
+ * InputStream stream = clazz.getResourceAsStream (string);
+ * if (stream == null) return null;
+ * Image image = null;
+ * try {
+ * image = new Image (display, stream);
+ * } catch (SWTException ex) {
+ * } finally {
+ * try {
+ * stream.close ();
+ * } catch (IOException ex) {}
+ * }
+ * return image;
+ * }
+ * </pre>
+ *
+ * @param device the device on which to create the image
+ * @param stream the input stream to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
+ * <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data </li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth</li>
+ * <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image (Device device, InputStream stream) {
+ super(device);
+ init(new ImageData(stream));
+ init();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the file with the specified name. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading
+ * a single image only. If the specified file contains
+ * multiple images, only the first one will be used.
+ *
+ * @param device the device on which to create the image
+ * @param filename the name of the file to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_IO - if an IO error occurs while reading from the file</li>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
+ * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image (Device device, String filename) {
+ super(device);
+ if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ try {
+ handle = OS.gcnew_BitmapImage();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int length = filename.length();
+ char[] chars = new char[length + 1];
+ filename.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ if (str == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (!OS.File_Exists(str)) SWT.error(SWT.ERROR_IO);
+ int uri = OS.gcnew_Uri(str, OS.UriKind_RelativeOrAbsolute);
+ if (uri == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.BitmapImage_BeginInit(handle);
+ OS.BitmapImage_CreateOptions(handle, OS.BitmapCreateOptions_PreservePixelFormat);
+ OS.BitmapImage_UriSource(handle, uri);
+ OS.BitmapImage_EndInit(handle);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+ OS.GCHandle_Free(uri);
+ OS.GCHandle_Free(str);
+ return;
+ } catch (SWTException e) {}
+ init(new ImageData(filename));
+ init();
+}
+
+void destroy() {
+ if (memGC != null) memGC.dispose();
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ memGC = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Image)) return false;
+ Image image = (Image) object;
+ return device == image.device && handle == image.handle;
+}
+
+/**
+ * Returns the color to which to map the transparent pixel, or null if
+ * the receiver has no transparent pixel.
+ * <p>
+ * There are certain uses of Images that do not support transparency
+ * (for example, setting an image into a button or label). In these cases,
+ * it may be desired to simulate transparency by using the background
+ * color of the widget to paint the transparent pixels of the image.
+ * Use this method to check which color will be used in these cases
+ * in place of transparency. This value may be set with setBackground().
+ * <p>
+ *
+ * @return the background color of the image, or null if there is no transparency in the image
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getBackground() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (transparentPixel == -1) return null;
+ //TODO implement Image.getBackground()
+ return null;
+}
+
+/**
+ * Returns the bounds of the receiver. The rectangle will always
+ * have x and y values of 0, and the width and height of the
+ * image.
+ *
+ * @return a rectangle specifying the image's bounds
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width == -1 || height == -1) {
+ width = OS.BitmapSource_PixelWidth(handle);
+ height = OS.BitmapSource_PixelHeight(handle);
+ }
+ return new Rectangle(0, 0, width, height);
+}
+
+Point getDPI () {
+ //TODO
+ return new Point (96, 96);
+}
+
+/**
+ * Returns an <code>ImageData</code> based on the receiver
+ * Modifications made to this <code>ImageData</code> will not
+ * affect the Image.
+ *
+ * @return an <code>ImageData</code> containing the image's data and attributes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ *
+ * @see ImageData
+ */
+public ImageData getImageData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int format = OS.BitmapSource_Format(handle);
+ int depth = OS.PixelFormat_BitsPerPixel(format);
+ int width = OS.BitmapSource_PixelWidth(handle);
+ int height = OS.BitmapSource_PixelHeight(handle);
+ int scanlinePad = DEFAULT_SCANLINE_PAD;
+ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad;
+ byte[] buffer = new byte[bytesPerLine * height];
+ int rect = OS.Int32Rect_Empty();
+ OS.BitmapSource_CopyPixels(handle, rect, buffer, buffer.length, bytesPerLine);
+ OS.GCHandle_Free(rect);
+ PaletteData paletteData = null;
+ int palette = OS.BitmapSource_Palette(handle);
+ if (palette != 0) {
+ int colors = OS.BitmapPalette_Colors(palette);
+ int count = OS.ColorList_Count(colors);
+ RGB[] rgbs = new RGB[count];
+ paletteData = new PaletteData(rgbs);
+ if (count != 0) {
+ int index = 0;
+ int enumerator = OS.ColorList_GetEnumerator(colors);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int color = OS.ColorList_Current(enumerator);
+ rgbs[index++] = new RGB(OS.Color_R(color) & 0xFF, OS.Color_G(color) & 0xFF, OS.Color_B(color) & 0xFF);
+ OS.GCHandle_Free(color);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(colors);
+ OS.GCHandle_Free(palette);
+ } else {
+ int[] formats = {
+ OS.PixelFormats_Bgr555(),
+ OS.PixelFormats_Bgr565(),
+ OS.PixelFormats_Bgr24(),
+ OS.PixelFormats_Rgb24(),
+ OS.PixelFormats_Bgr32(),
+ OS.PixelFormats_Bgra32(),
+ OS.PixelFormats_Pbgra32(),
+ OS.PixelFormats_Bgr101010(),
+ };
+ for (int i = 0; i < formats.length; i++) {
+ if (OS.Object_Equals(format, formats[i])) {
+ switch (i) {
+ case 0: paletteData = new PaletteData(0x7C00, 0x3E0, 0x1F); break;
+ case 1: paletteData = new PaletteData(0xF800, 0x7E0, 0x1F); break;
+ case 2: paletteData = new PaletteData(0xFF, 0xFF00, 0xFF0000); break;
+ case 3: paletteData = new PaletteData(0xFF0000, 0xFF00, 0xFF); break;
+ case 4:
+ case 5:
+ case 6: paletteData = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); break;
+ case 7: paletteData = new PaletteData(0x3FF, 0xFFC00, 0x3FF0000); break;
+ }
+ }
+ OS.GCHandle_Free(formats[i]);
+ }
+ }
+ OS.GCHandle_Free(format);
+ ImageData data = new ImageData(width, height, depth, paletteData, scanlinePad, buffer);
+ data.transparentPixel = transparentPixel;
+ if (transparentPixel == -1 && type == SWT.ICON) {
+ /* Get the icon mask data */
+ int maskPad = 2;
+ int maskBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
+ byte[] maskData = new byte[height * maskBpl];
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ if (buffer[offset] != 0) {
+ maskData[maskOffset + (x >> 3)] |= (1 << (7 - (x & 0x7)));
+ } else {
+ maskData[maskOffset + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
+ }
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ data.maskData = maskData;
+ data.maskPad = maskPad;
+ }
+ data.alpha = alpha;
+ if (alpha == -1 && alphaData != null) {
+ data.alphaData = new byte[alphaData.length];
+ System.arraycopy(alphaData, 0, data.alphaData, 0, alphaData.length);
+ }
+ return data;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+void init(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ type = SWT.BITMAP;
+ Point dpi = getDPI();
+ int pixelFormat = OS.PixelFormats_Bgr24();
+ int stride = width * 3;
+ byte[] buffer = new byte[stride * height];
+ for (int i = 0; i < buffer.length; i++) {
+ buffer[i] = (byte)0xFF;
+ }
+ handle = OS.BitmapSource_Create(width, height, dpi.x, dpi.y, pixelFormat, 0, buffer, buffer.length, stride);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(pixelFormat);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+}
+
+void init(ImageData data) {
+ PaletteData palette = data.palette;
+ if (!(((data.depth == 1 || data.depth == 2 || data.depth == 4 || data.depth == 8) && !palette.isDirect) ||
+ ((data.depth == 8) || (data.depth == 16 || data.depth == 24 || data.depth == 32) && palette.isDirect)))
+ SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+ int width = data.width;
+ int height = data.height;
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ ImageData newData = null;
+ int pixelFormat = 0;
+ boolean transparent = false;
+ if (data.maskData != null) {
+ transparent= true;
+ } else {
+ if (data.transparentPixel != -1) {
+ transparent = palette.isDirect;
+ } else {
+ if (data.alpha != -1) {
+ transparent = palette.isDirect;
+ } else {
+ transparent = data.alphaData != null;
+ }
+ }
+ }
+ if (transparent) {
+ pixelFormat = OS.PixelFormats_Bgra32();
+ if (!(palette.isDirect && data.depth == 32 && redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+ newData = new ImageData(width, height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ } else {
+ switch (data.depth) {
+ case 1: pixelFormat = OS.PixelFormats_Indexed1(); break;
+ case 2: pixelFormat = OS.PixelFormats_Indexed2(); break;
+ case 4: pixelFormat = OS.PixelFormats_Indexed4(); break;
+ case 8:
+ if (!palette.isDirect) {
+ pixelFormat = OS.PixelFormats_Indexed8();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ newData = new ImageData(data.width, data.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ case 16:
+ if (redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormats_Bgr555();
+ } else if (redMask == 0xF800 && greenMask == 0x7E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormats_Bgr565();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr555();
+ newData = new ImageData(data.width, data.height, 16, new PaletteData(0x7C00, 0x3E0, 0x1F));
+ }
+ break;
+ case 24:
+ if (redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000) {
+ pixelFormat = OS.PixelFormats_Bgr24();
+ } else if (redMask == 0xFF0000 && greenMask == 0xFF00 && blueMask == 0xFF) {
+ pixelFormat = OS.PixelFormats_Rgb24();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr24();
+ newData = new ImageData(data.width, data.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ }
+ break;
+ case 32:
+ if (redMask == 0x3FF && greenMask == 0xFFC00 && blueMask == 0x3FF0000) {
+ pixelFormat = OS.PixelFormats_Bgr101010();
+ } else if (redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000) {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ newData = new ImageData(data.width, data.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ }
+ }
+ if (newData != null) {
+ PaletteData newPalette = newData.palette;
+ if (palette.isDirect) {
+ ImageData.blit(ImageData.BLIT_SRC,
+ data.data, data.depth, data.bytesPerLine, data.getByteOrder(), 0, 0, width, height, redMask, greenMask, blueMask,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ int length = rgbs.length;
+ byte[] srcReds = new byte[length];
+ byte[] srcGreens = new byte[length];
+ byte[] srcBlues = new byte[length];
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ if (rgb == null) continue;
+ srcReds[i] = (byte)rgb.red;
+ srcGreens[i] = (byte)rgb.green;
+ srcBlues[i] = (byte)rgb.blue;
+ }
+ ImageData.blit(ImageData.BLIT_SRC,
+ data.data, data.depth, data.bytesPerLine, data.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ }
+ if (data.transparentPixel != -1) {
+ newData.transparentPixel = newPalette.getPixel(palette.getRGB(data.transparentPixel));
+ }
+ newData.maskPad = data.maskPad;
+ newData.maskData = data.maskData;
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ data = newData;
+ palette = data.palette;
+ }
+ int bitmapPalette = 0;
+ if (!palette.isDirect) {
+ if (data.transparentPixel != -1) {
+ transparentPixel = data.transparentPixel;
+ } else {
+ alpha = data.alpha;
+ }
+ RGB[] rgbs = palette.colors;
+ int list = OS.gcnew_ColorList(rgbs.length);
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ byte alpha;
+ if (data.transparentPixel != -1) {
+ alpha = (byte)(i == data.transparentPixel ? 0 : 0xFF);
+ } else {
+ alpha = (byte)(data.alpha & 0xFF);
+ }
+ int color = OS.Color_FromArgb(alpha, (byte)rgb.red, (byte)rgb.green, (byte)rgb.blue);
+ OS.ColorList_Add(list, color);
+ OS.GCHandle_Free(color);
+ }
+ bitmapPalette = OS.gcnew_BitmapPalette(list);
+ OS.GCHandle_Free(list);
+ }
+ type = SWT.BITMAP;
+ if (transparent) {
+ if (data.maskData != null || data.transparentPixel != -1) {
+ this.type = data.transparentPixel != -1 ? SWT.BITMAP : SWT.ICON;
+ transparentPixel = data.transparentPixel;
+ ImageData maskImage = data.getTransparencyMask();
+ byte[] maskData = maskImage.data;
+ int maskBpl = maskImage.bytesPerLine;
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ data.data[offset] = ((maskData[maskOffset + (x >> 3)]) & (1 << (7 - (x & 0x7)))) != 0 ? (byte)0xff : 0;
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ } else if (data.alpha != -1) {
+ alpha = data.alpha;
+ for (int i = 3, j = 0; i < data.data.length; i+=4, j++) {
+ data.data[i] = (byte)alpha;
+ }
+ } else {
+ int length = data.alphaData.length;
+ alphaData = new byte[length];
+ System.arraycopy(data.alphaData, 0, alphaData, 0, length);
+ for (int i = 3, j = 0; i < data.data.length; i+=4, j++) {
+ data.data[i] = alphaData[j];
+ }
+ }
+ }
+ Point dpi = getDPI();
+ handle = OS.BitmapSource_Create(width, height, dpi.x, dpi.y, pixelFormat, bitmapPalette, data.data, data.data.length, data.bytesPerLine);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+ OS.GCHandle_Free(pixelFormat);
+ if (bitmapPalette != 0) OS.GCHandle_Free(bitmapPalette);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public int internal_new_GC (GCData data) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ /*
+ * Create a new GC that can draw into the image.
+ * Only supported for bitmaps.
+ */
+ if (type != SWT.BITMAP || memGC != null) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (width == -1 || height == -1) {
+ width = OS.BitmapSource_PixelWidth(handle);
+ height = OS.BitmapSource_PixelHeight(handle);
+ }
+
+ int visual = OS.gcnew_DrawingVisual();
+ if (visual == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int rect = OS.gcnew_Rect(0, 0, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ OS.ContainerVisual_Clip (visual, geometry);
+ int dc = OS.DrawingVisual_RenderOpen(visual);
+ if (dc == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.DrawingContext_DrawImage(dc, handle, rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry);
+ if (data != null) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) == 0) {
+ data.style |= SWT.LEFT_TO_RIGHT;
+ }
+ data.device = device;
+ data.image = this;
+ data.background = OS.Colors_White;
+ data.foreground = OS.Colors_Black;
+ data.font = device.systemFont;
+ data.visual = visual;
+ }
+ return dc;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (int dc, GCData data) {
+ OS.DrawingContext_Close(dc);
+ Point dpi = getDPI();
+ int pixelFormat = OS.PixelFormats_Pbgra32();
+ int renderHandle = OS.gcnew_RenderTargetBitmap(width, height, dpi.x, dpi.y, pixelFormat);
+ OS.GCHandle_Free(pixelFormat);
+ if (renderHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.RenderTargetBitmap_Render(renderHandle, data.visual);
+ OS.GCHandle_Free(data.visual);
+ OS.GCHandle_Free(dc);
+ int format = OS.BitmapSource_Format(handle);
+ int palette = OS.BitmapSource_Palette(handle);
+ OS.GCHandle_Free(handle);
+ handle = OS.gcnew_FormatConvertedBitmap(renderHandle, format, palette, 100);
+ OS.GCHandle_Free(palette);
+ OS.GCHandle_Free(format);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(renderHandle);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+}
+
+/**
+ * Returns <code>true</code> if the image has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the image.
+ * When an image has been disposed, it is an error to
+ * invoke any other method using the image.
+ *
+ * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Sets the color to which to map the transparent pixel.
+ * <p>
+ * There are certain uses of <code>Images</code> that do not support
+ * transparency (for example, setting an image into a button or label).
+ * In these cases, it may be desired to simulate transparency by using
+ * the background color of the widget to paint the transparent pixels
+ * of the image. This method specifies the color that will be used in
+ * these cases. For example:
+ * <pre>
+ * Button b = new Button();
+ * image.setBackground(b.getBackground());
+ * b.setImage(image);
+ * </pre>
+ * </p><p>
+ * The image may be modified by this operation (in effect, the
+ * transparent regions may be filled with the supplied color). Hence
+ * this operation is not reversible and it is not legal to call
+ * this function twice or with a null argument.
+ * </p><p>
+ * This method has no effect if the receiver does not have a transparent
+ * pixel value.
+ * </p>
+ *
+ * @param color the color to use when a transparent pixel is specified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setBackground(Color color) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (transparentPixel == -1) return;
+ //TODO implement Image.setBackground()
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Image {*DISPOSED*}";
+ return "Image {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new image.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param type the type of the image (<code>SWT.BITMAP</code> or <code>SWT.ICON</code>)
+ * @param handle the OS handle for the image
+ * @return a new image object containing the specified device, type and handle
+ */
+public static Image wpf_new(Device device, int type, int handle) {
+ Image image = new Image(device);
+ image.type = type;
+ image.handle = handle;
+ return image;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java
new file mode 100644
index 0000000000..420d66fc52
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java
@@ -0,0 +1,695 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent paths through the two-dimensional
+ * coordinate system. Paths do not have to be continuous, and can be
+ * described using lines, rectangles, arcs, cubic or quadratic bezier curves,
+ * glyphs, or other paths.
+ * <p>
+ * Application code must explicitly invoke the <code>Path.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#path">Path, Pattern snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public class Path extends Resource {
+
+ /**
+ * the OS resource for the Path
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+ int currentFigure, currentPoint;
+
+/**
+ * Constructs a new empty Path.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the path
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Path (Device device) {
+ super(device);
+ handle = OS.gcnew_PathGeometry();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ init();
+}
+
+/**
+ * Constructs a new Path that is a copy of <code>path</code>. If
+ * <code>flatness</code> is less than or equal to zero, an unflatten
+ * copy of the path is created. Otherwise, it specifies the maximum
+ * error between the path and its flatten copy. Smaller numbers give
+ * better approximation.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the path
+ * @param path the path to make a copy
+ * @param flatness the flatness value
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the path is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @since 3.4
+ */
+public Path (Device device, Path path, float flatness) {
+ super(device);
+ if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ flatness = Math.max(0, flatness);
+ if (flatness == 0) {
+ handle = OS.PathGeometry_Clone(path.handle);
+ } else {
+ handle = OS.Geometry_GetFlattenedPathGeometry(path.handle, flatness, OS.ToleranceType_Absolute);
+ }
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ init();
+}
+
+/**
+ * Constructs a new Path with the specifed PathData.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the path
+ * @param data the data for the path
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the data is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @since 3.4
+ */
+public Path (Device device, PathData data) {
+ this(device);
+ if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(data);
+}
+
+/**
+ * Adds to the receiver a circular or elliptical arc that lies within
+ * the specified rectangular area.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc
+ * @param y the y coordinate of the upper-left corner of the arc
+ * @param width the width of the arc
+ * @param height the height of the arc
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addArc(float x, float y, float width, float height, float startAngle, float arcAngle) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ float tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ if (currentFigure == 0) {
+ currentFigure = OS.gcnew_PathFigure();
+ int figures = OS.PathGeometry_Figures(handle);
+ OS.PathFigureCollection_Add(figures, currentFigure);
+ OS.GCHandle_Free(figures);
+ }
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ if (OS.PathSegmentCollection_Count(segments) != 0) {
+ int segment = OS.gcnew_LineSegment(startPoint, true);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segment);
+ } else {
+ OS.PathFigure_StartPoint(currentFigure, startPoint);
+ }
+ if (arcAngle >= 360 || arcAngle <= -360) {
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry = OS.gcnew_EllipseGeometry(rect);
+ OS.PathGeometry_AddGeometry(handle, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ } else {
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, true);
+ OS.PathSegmentCollection_Add(segments, arc);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(arc);
+ }
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(startPoint);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = endPoint;
+}
+
+/**
+ * Adds to the receiver the path described by the parameter.
+ *
+ * @param path the path to add to the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addPath(Path path) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ OS.PathGeometry_AddGeometry(handle, path.handle);
+ if (path.currentPoint != 0) {
+ currentPoint = OS.gcnew_Point(OS.Point_X(path.currentPoint), OS.Point_Y(path.currentPoint));
+ }
+ int figures = OS.PathGeometry_Figures(handle);
+ int count = OS.PathFigureCollection_Count(figures);
+ OS.GCHandle_Free(figures);
+ if (count != 0) {
+ int figure = OS.PathGeometry_Figures(handle, count - 1);
+ if (!OS.PathFigure_IsClosed(figure)) {
+ currentFigure = figure;
+ return;
+ }
+ OS.GCHandle_Free(figure);
+ }
+
+}
+
+/**
+ * Adds to the receiver the rectangle specified by x, y, width and height.
+ *
+ * @param x the x coordinate of the rectangle to add
+ * @param y the y coordinate of the rectangle to add
+ * @param width the width of the rectangle to add
+ * @param height the height of the rectangle to add
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addRectangle(float x, float y, float width, float height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ OS.PathGeometry_AddGeometry(handle, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(rect);
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ int point = OS.gcnew_Point(x, y);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+
+}
+
+/**
+ * Adds to the receiver the pattern of glyphs generated by drawing
+ * the given string using the given font starting at the point (x, y).
+ *
+ * @param string the text to use
+ * @param x the x coordinate of the starting point
+ * @param y the y coordinate of the starting point
+ * @param font the font to use
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the font is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addString(String string, float x, float y, Font font) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (font == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ int point = OS.gcnew_Point(x, y);
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, OS.FlowDirection_LeftToRight, font.handle, font.size, brush);
+ int geometry = OS.FormattedText_BuildGeometry(text, point);
+ OS.PathGeometry_AddGeometry(handle, geometry);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(text);
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = 0;
+}
+
+/**
+ * Closes the current sub path by adding to the receiver a line
+ * from the current point of the path back to the starting point
+ * of the sub path.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void close() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (currentFigure != 0) OS.PathFigure_IsClosed(currentFigure, true);
+ currentFigure = 0;
+}
+
+/**
+ * Returns <code>true</code> if the specified point is contained by
+ * the receiver and false otherwise.
+ * <p>
+ * If outline is <code>true</code>, the point (x, y) checked for containment in
+ * the receiver's outline. If outline is <code>false</code>, the point is
+ * checked to see if it is contained within the bounds of the (closed) area
+ * covered by the receiver.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @param gc the GC to use when testing for containment
+ * @param outline controls whether to check the outline or contained area of the path
+ * @return <code>true</code> if the path contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains(float x, float y, GC gc, boolean outline) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ gc.checkGC(GC.LINE_CAP | GC.LINE_JOIN | GC.LINE_STYLE | GC.LINE_WIDTH | GC.LINE_MITERLIMIT | GC.TRANSFORM);
+ boolean result;
+ int point = OS.gcnew_Point(x, y);
+ if (outline) {
+ result = OS.Geometry_StrokeContains(handle, gc.data.pen, point);
+ } else {
+ result = OS.Geometry_FillContains(handle, point);
+ }
+ OS.GCHandle_Free(point);
+ return result;
+}
+
+/**
+ * Adds to the receiver a cubic bezier curve based on the parameters.
+ *
+ * @param cx1 the x coordinate of the first control point of the spline
+ * @param cy1 the y coordinate of the first control of the spline
+ * @param cx2 the x coordinate of the second control of the spline
+ * @param cy2 the y coordinate of the second control of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int controlPoint1 = OS.gcnew_Point(cx1, cy1);
+ int controlPoint2 = OS.gcnew_Point(cx2, cy2);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_BezierSegment(controlPoint1, controlPoint2, point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+ OS.GCHandle_Free(controlPoint1);
+ OS.GCHandle_Free(controlPoint2);
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = 0;
+}
+
+/**
+ * Replaces the first four elements in the parameter with values that
+ * describe the smallest rectangle that will completely contain the
+ * receiver (i.e. the bounding box).
+ *
+ * @param bounds the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the bounding box</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getBounds(float[] bounds) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.PathGeometry_Bounds(handle);
+ bounds[0] = (float)OS.Rect_X(rect);
+ bounds[1] = (float)OS.Rect_Y(rect);
+ bounds[2] = (float)OS.Rect_Width(rect);
+ bounds[3] = (float)OS.Rect_Height(rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Replaces the first two elements in the parameter with values that
+ * describe the current point of the path.
+ *
+ * @param point the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the end point</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getCurrentPoint(float[] point) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (point == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (point.length < 2) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (currentPoint != 0) {
+ point[0] = (float)OS.Point_X(currentPoint);
+ point[1] = (float)OS.Point_Y(currentPoint);
+ } else {
+ point[0] = point[1] = 0;
+ }
+}
+
+/**
+ * Returns a device independent representation of the receiver.
+ *
+ * @return the PathData for the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see PathData
+ */
+public PathData getPathData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ byte[] types = new byte[128];
+ float[] points = new float[128 * 2];
+ int pointsIndex = 0, typesIndex = 0;
+ int figures = OS.PathGeometry_Figures(handle);
+ int figureCount = OS.PathFigureCollection_Count(figures);
+ OS.GCHandle_Free(figures);
+ for (int i = 0; i < figureCount; i++) {
+ int figure = OS.PathGeometry_Figures(handle, i);
+ int segments = OS.PathFigure_Segments(figure);
+ int segmentCount = OS.PathSegmentCollection_Count(segments);
+ OS.GCHandle_Free(segments);
+ for (int j = 0; j < segmentCount; j++) {
+ int segment = OS.PathFigure_Segments(figure, j);
+ int type = OS.Object_GetType(segment);
+ //TODO - need get points out of every segment
+ //TODO - need to convert ArcSegment to beziers
+
+
+ OS.GCHandle_Free(type);
+ OS.GCHandle_Free(segment);
+ }
+ OS.GCHandle_Free(figure);
+ }
+ if (typesIndex != types.length) {
+ byte[] newTypes = new byte[typesIndex];
+ System.arraycopy(types, 0, newTypes, 0, typesIndex);
+ types = newTypes;
+ }
+ if (pointsIndex != points.length) {
+ float[] newPoints = new float[pointsIndex];
+ System.arraycopy(points, 0, newPoints, 0, pointsIndex);
+ points = newPoints;
+ }
+ PathData result = new PathData();
+ result.types = types;
+ result.points = points;
+ return result;
+}
+
+/**
+ * Adds to the receiver a line from the current point to
+ * the point specified by (x, y).
+ *
+ * @param x the x coordinate of the end of the line to add
+ * @param y the y coordinate of the end of the line to add
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void lineTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_LineSegment(point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+}
+
+void init(PathData data) {
+ byte[] types = data.types;
+ float[] points = data.points;
+ for (int i = 0, j = 0; i < types.length; i++) {
+ switch (types[i]) {
+ case SWT.PATH_MOVE_TO:
+ moveTo(points[j++], points[j++]);
+ break;
+ case SWT.PATH_LINE_TO:
+ lineTo(points[j++], points[j++]);
+ break;
+ case SWT.PATH_CUBIC_TO:
+ cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]);
+ break;
+ case SWT.PATH_QUAD_TO:
+ quadTo(points[j++], points[j++], points[j++], points[j++]);
+ break;
+ case SWT.PATH_CLOSE:
+ close();
+ break;
+ default:
+ dispose();
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+}
+
+/**
+ * Returns <code>true</code> if the Path has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Path.
+ * When a Path has been disposed, it is an error to
+ * invoke any other method using the Path.
+ *
+ * @return <code>true</code> when the Path is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Sets the current point of the receiver to the point
+ * specified by (x, y). Note that this starts a new
+ * sub path.
+ *
+ * @param x the x coordinate of the new end point
+ * @param y the y coordinate of the new end point
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void moveTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ if (currentFigure != 0) {
+ int segments = OS.PathFigure_Segments(currentFigure);
+ int count = OS.PathSegmentCollection_Count(segments);
+ OS.GCHandle_Free(segments);
+ if (count == 0) {
+ OS.PathFigure_StartPoint(currentFigure, point);
+ return;
+ }
+ }
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ newFigure();
+}
+
+void newFigure() {
+ currentFigure = OS.gcnew_PathFigure();
+ if (currentPoint != 0) {
+ OS.PathFigure_StartPoint(currentFigure, currentPoint);
+ }
+ int figures = OS.PathGeometry_Figures(handle);
+ OS.PathFigureCollection_Add(figures, currentFigure);
+ OS.GCHandle_Free(figures);
+}
+
+/**
+ * Adds to the receiver a quadratic curve based on the parameters.
+ *
+ * @param cx the x coordinate of the control point of the spline
+ * @param cy the y coordinate of the control point of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void quadTo(float cx, float cy, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int controlPoint = OS.gcnew_Point(cx, cy);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_QuadraticBezierSegment(controlPoint, point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+ OS.GCHandle_Free(controlPoint);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Path {*DISPOSED*}";
+ return "Path {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java
new file mode 100644
index 0000000000..ec1394e50e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent patterns to use while drawing. Patterns
+ * can be specified either as bitmaps or gradients.
+ * <p>
+ * Application code must explicitly invoke the <code>Pattern.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#path">Path, Pattern snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public class Pattern extends Resource {
+
+ /**
+ * the OS resource for the Pattern
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+/**
+ * Constructs a new Pattern given an image. Drawing with the resulting
+ * pattern will cause the image to be tiled over the resulting area.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the pattern
+ * @param image the image that the pattern will draw
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device, or the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, Image image) {
+ super(device);
+ if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle = OS.gcnew_ImageBrush(image.handle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.TileBrush_TileMode(handle, OS.TileMode_Tile);
+ OS.TileBrush_Stretch(handle, OS.Stretch_Fill);
+ OS.TileBrush_ViewportUnits(handle, OS.BrushMappingMode_Absolute);
+ int rect = OS.gcnew_Rect(0, 0, OS.BitmapSource_PixelWidth(image.handle), OS.BitmapSource_PixelHeight(image.handle));
+ OS.TileBrush_Viewport(handle, rect);
+ OS.GCHandle_Free(rect);
+ init();
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param color2 the ending color of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, Color color2) {
+ this(device, x1, y1, x2, y2, color1, 0xFF, color2, 0xFF);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param alpha1 the starting alpha value of the gradient
+ * @param color2 the ending color of the gradient
+ * @param alpha2 the ending alpha value of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ *
+ * @since 3.2
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
+ super(device);
+ if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int startColor = OS.Color_FromArgb((byte)(alpha1 & 0xFF), OS.Color_R(color1.handle), OS.Color_G(color1.handle), OS.Color_B(color1.handle));
+ if (x1 == x2 && y1 == y2) {
+ handle = OS.gcnew_SolidColorBrush(startColor);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ } else {
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endColor = OS.Color_FromArgb((byte)(alpha2 & 0xFF), OS.Color_R(color2.handle), OS.Color_G(color2.handle), OS.Color_B(color2.handle));
+ int endPoint = OS.gcnew_Point(x2, y2);
+ handle = OS.gcnew_LinearGradientBrush(startColor, endColor, startPoint, endPoint);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GradientBrush_MappingMode(handle, OS.BrushMappingMode_Absolute);
+ OS.GradientBrush_SpreadMethod(handle, OS.GradientSpreadMethod_Repeat);
+ OS.GCHandle_Free(endColor);
+ OS.GCHandle_Free(endPoint);
+ OS.GCHandle_Free(startPoint);
+ }
+ OS.GCHandle_Free(startColor);
+ init();
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Returns <code>true</code> if the Pattern has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Pattern.
+ * When a Pattern has been disposed, it is an error to
+ * invoke any other method using the Pattern.
+ *
+ * @return <code>true</code> when the Pattern is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Pattern {*DISPOSED*}";
+ return "Pattern {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java
new file mode 100644
index 0000000000..e988c51718
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java
@@ -0,0 +1,712 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent areas of an x-y coordinate
+ * system that are aggregates of the areas covered by a number
+ * of polygons.
+ * <p>
+ * Application code must explicitly invoke the <code>Region.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Region extends Resource {
+
+ /**
+ * the OS resource for the region
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+/**
+ * Constructs a new empty region.
+ *
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ */
+public Region () {
+ this(null);
+}
+
+/**
+ * Constructs a new empty region.
+ * <p>
+ * You must dispose the region when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the region
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ *
+ * @see #dispose
+ *
+ * @since 3.0
+ */
+public Region (Device device) {
+ super(device);
+ handle = OS.gcnew_GeometryGroup();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ init();
+}
+
+/**
+ * Constructs a new region given a handle to the operating
+ * system resources that it should represent.
+ *
+ * @param handle the handle for the result
+ */
+Region(Device device, int handle) {
+ super(device);
+ this.handle = handle;
+}
+
+/**
+ * Adds the given polygon to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+*
+ */
+public void add (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ combine(pointArray, OS.GeometryCombineMode_Union);
+}
+
+
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ add (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void add (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ OS.GeometryCollection_Add(geometries, geometry1);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Union, geometry1, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Adds all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to merge
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ OS.GeometryCollection_Add(geometries, region.handle);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Union, region.handle, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+
+void combine (int[] pointArray, int mode) {
+ if (pointArray.length < 4) return;
+ int list = OS.gcnew_PointCollection(pointArray.length / 2);
+ for (int i = 2; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i], pointArray[i + 1]);
+ OS.PointCollection_Add(list, point);
+ OS.GCHandle_Free(point);
+ }
+ int poly = OS.gcnew_PolyLineSegment(list, true);
+ OS.GCHandle_Free(list);
+ int figure = OS.gcnew_PathFigure();
+ int startPoint = OS.gcnew_Point(pointArray[0], pointArray[1]);
+ OS.PathFigure_StartPoint(figure, startPoint);
+ OS.PathFigure_IsClosed(figure, true);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, poly);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ if (mode == OS.GeometryCombineMode_Union) OS.GeometryCollection_Add(geometries, path);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(mode, geometry2, path);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(startPoint);
+ OS.GCHandle_Free(poly);
+}
+
+/**
+ * Returns <code>true</code> if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ boolean result = OS.Geometry_FillContains(handle, point);
+ OS.GCHandle_Free(point);
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the given point is inside the
+ * area specified by the receiver, and <code>false</code>
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (this == object) return true;
+ if (!(object instanceof Region)) return false;
+ Region rgn = (Region)object;
+ return handle == rgn.handle;
+}
+
+/**
+ * Returns a rectangle which represents the rectangular
+ * union of the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @return a bounding rectangle for the region
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#union
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (OS.Geometry_IsEmpty(handle)) return new Rectangle(0, 0, 0, 0);
+ int rect = OS.Geometry_Bounds(handle);
+ Rectangle result = new Rectangle((int)OS.Rect_X(rect), (int)OS.Rect_Y(rect), (int)OS.Rect_Width(rect), (int)OS.Rect_Height(rect));
+ OS.GCHandle_Free(rect);
+ return result;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ intersect (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void intersect (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, geometry1, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Intersects all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to intersect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, region.handle, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Returns <code>true</code> if the rectangle described by the
+ * arguments intersects with any of the polygons the receiver
+ * maintains to describe its area, and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ int result = OS.Geometry_FillContainsWithDetail(handle, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(rect);
+ return result != OS.IntersectionDetail_Empty;
+}
+
+/**
+ * Returns <code>true</code> if the given rectangle intersects
+ * with any of the polygons the receiver maintains to describe
+ * its area and <code>false</code> otherwise.
+ *
+ * @param rect the rectangle to test for intersection
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return intersects(rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns <code>true</code> if the region has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the region.
+ * When a region has been disposed, it is an error to
+ * invoke any other method using the region.
+ *
+ * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and <code>false</code> if
+ * the receiver does cover some area in the plane.
+ *
+ * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean isEmpty () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Geometry_IsEmpty(handle);
+}
+
+/**
+ * Subtracts the given polygon from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ combine(pointArray, OS.GeometryCombineMode_Exclude);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to subtract from the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ subtract (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void subtract (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Exclude, geometry2, geometry1);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Subtracts all of the polygons which make up the area covered
+ * by the argument from the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to subtract
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Exclude, geometry2, region.handle);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param x the x coordinate of the point to translate
+ * @param y the y coordinate of the point to translate
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int transform1 = OS.Geometry_Transform(handle);
+ int transform2 = OS.gcnew_TranslateTransform(x, y);
+ int transform = OS.gcnew_TransformGroup();
+ int transforms = OS.TransformGroup_Children(transform);
+ OS.TransformCollection_Add(transforms, transform1);
+ OS.TransformCollection_Add(transforms, transform2);
+ OS.Geometry_Transform(handle, transform);
+ OS.GCHandle_Free(transform1);
+ OS.GCHandle_Free(transform2);
+ OS.GCHandle_Free(transform);
+ OS.GCHandle_Free(transforms);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param pt the point to translate
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ translate (pt.x, pt.y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Region {*DISPOSED*}";
+ return "Region {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new region.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Region</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the region
+ * @param handle the handle for the region
+ * @return a new region object containing the specified device and handle
+ */
+public static Region wpf_new(Device device, int handle) {
+ return new Region(device, handle);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java
new file mode 100644
index 0000000000..ad7af71cf0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java
@@ -0,0 +1,1877 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * <code>TextLayout</code> is a graphic object that represents
+ * styled text.
+ * <p>
+ * Instances of this class provide support for drawing, cursor
+ * navigation, hit testing, text wrapping, alignment, tab expansion
+ * line breaking, etc. These are aspects required for rendering internationalized text.
+ * </p><p>
+ * Application code must explicitly invoke the <code>TextLayout#dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#textlayout">TextLayout, TextStyle snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample, StyledText tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public final class TextLayout extends Resource {
+ Font font;
+ String text, segmentsText;
+ int lineSpacing;
+ int ascent, descent;
+ int alignment;
+ int wrapWidth;
+ int orientation;
+ int indent;
+ boolean justify;
+ int[] tabs;
+ int[] segments;
+ StyleItem[] styles;
+
+ int string, defaultTextProperties;
+ int[] runs;
+ int[] lines;
+
+ static final RGB LINK_FOREGROUND = new RGB (0, 51, 153);
+ static final char LTR_MARK = '\u200E', RTL_MARK = '\u200F';
+ static final int TAB_COUNT = 32;
+
+class StyleItem {
+ TextStyle style;
+ int start, length;
+ int textProperties;
+
+ void free() {
+ if (textProperties != 0) OS.GCHandle_Free(textProperties);
+ textProperties = 0;
+ }
+ public String toString () {
+ return "StyleItem {" + start + ", " + style + "}";
+ }
+}
+
+/**
+ * Constructs a new instance of this class on the given device.
+ * <p>
+ * You must dispose the text layout when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the text layout
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public TextLayout (Device device) {
+ super(device);
+ wrapWidth = ascent = descent = -1;
+ lineSpacing = 0;
+ orientation = SWT.LEFT_TO_RIGHT;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ text = ""; //$NON-NLS-1$
+ init();
+}
+
+void checkLayout () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+}
+
+/*
+* Compute the runs: itemize, shape, place, and reorder the runs.
+* Break paragraphs into lines, wraps the text, and initialize caches.
+*/
+void computeRuns () {
+ if (lines != null) return;
+
+ int jniRef = OS.NewGlobalRef(this);
+ int textSource = OS.gcnew_SWTTextSource(jniRef);
+ int formatter = OS.TextFormatter_Create();
+ Font font = this.font != null ? this.font : device.systemFont;
+ segmentsText = getSegmentsText();
+ int length = segmentsText.length();
+ char [] buffer = new char [length];
+ segmentsText.getChars (0, length, buffer, 0);
+ string = OS.gcnew_String(buffer, 0 ,length);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ defaultTextProperties = OS.gcnew_SWTTextRunProperties(font.handle, font.size, font.size, 0, 0, 0, OS.BaselineAlignment_Baseline, culture);
+ for (int i = 0; i < styles.length; i++) {
+ StyleItem run = styles[i];
+ TextStyle style = run.style;
+ if (style != null) {
+ Font styleFont = style.font != null ? style.font : font;
+ int fg = 0;
+ if (style.foreground != null) {
+ fg = OS.gcnew_SolidColorBrush(style.foreground.handle);
+ } else {
+ if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
+ int color = OS.Color_FromArgb((byte)0xFF, (byte)LINK_FOREGROUND.red, (byte)LINK_FOREGROUND.green, (byte)LINK_FOREGROUND.blue);
+ fg = OS.gcnew_SolidColorBrush(color);
+ OS.GCHandle_Free(color);
+ }
+ }
+ int bg = 0;
+ if (style.background != null) {
+ bg = OS.gcnew_SolidColorBrush(style.background.handle);
+ }
+ int decorations = 0;
+ if (style.strikeout || style.underline) {
+ decorations = OS.gcnew_TextDecorationCollection(2);
+ if (style.strikeout) {
+ int pen = 0;
+ if (style.strikeoutColor != null) {
+ int color = style.strikeoutColor.handle;
+ int brush = OS.gcnew_SolidColorBrush(color);
+ pen = OS.gcnew_Pen(brush, 1);
+ OS.GCHandle_Free(brush);
+ }
+ int strikeout = OS.gcnew_TextDecoration(OS.TextDecorationLocation_Strikethrough, pen, 0, OS.TextDecorationUnit_FontRecommended, OS.TextDecorationUnit_FontRecommended);
+ OS.TextDecorationCollection_Add(decorations, strikeout);
+ OS.GCHandle_Free(strikeout);
+ if (pen != 0) OS.GCHandle_Free(pen);
+ }
+ if (style.underline) {
+ int brush;
+ if (style.underlineColor != null) {
+ Color color = style.underlineColor;
+ brush = OS.gcnew_SolidColorBrush(color.handle);
+ } else {
+ if (fg != 0) {
+ brush = fg;
+ } else {
+ brush = OS.Brushes_Black();
+ }
+ }
+ int pen = OS.gcnew_Pen(brush, 1f);
+ if (brush != fg) OS.GCHandle_Free(brush);
+ int underline;
+ switch (style.underlineStyle) {
+ case SWT.UNDERLINE_SQUIGGLE:
+ //TODO implement
+ case SWT.UNDERLINE_ERROR:
+ int dashStyle = OS.DashStyles_Dash();
+ OS.Pen_DashStyle(pen, dashStyle);
+ underline = OS.gcnew_TextDecoration(OS.TextDecorationLocation_Underline, pen, 0, OS.TextDecorationUnit_FontRecommended, OS.TextDecorationUnit_FontRecommended);
+ OS.TextDecorationCollection_Add(decorations, underline);
+ OS.GCHandle_Free(underline);
+ OS.GCHandle_Free(dashStyle);
+ break;
+ case SWT.UNDERLINE_DOUBLE:
+ underline = OS.gcnew_TextDecoration(OS.TextDecorationLocation_Underline, pen, 1, OS.TextDecorationUnit_FontRecommended, OS.TextDecorationUnit_FontRecommended);
+ OS.TextDecorationCollection_Add(decorations, underline);
+ OS.GCHandle_Free(underline);
+ //FALLTHROU
+ case SWT.UNDERLINE_LINK:
+ case SWT.UNDERLINE_SINGLE:
+ underline = OS.gcnew_TextDecoration(OS.TextDecorationLocation_Underline, pen, 0, OS.TextDecorationUnit_FontRecommended, OS.TextDecorationUnit_FontRecommended);
+ OS.TextDecorationCollection_Add(decorations, underline);
+ OS.GCHandle_Free(underline);
+ break;
+ }
+ if (pen != 0) OS.GCHandle_Free(pen);
+ }
+ }
+ run.textProperties = OS.gcnew_SWTTextRunProperties(styleFont.handle, styleFont.size, styleFont.size, decorations, fg, bg, OS.BaselineAlignment_Baseline, culture);
+ if (fg != 0) OS.GCHandle_Free(fg);
+ if (bg != 0) OS.GCHandle_Free(bg);
+ if (decorations != 0) OS.GCHandle_Free(decorations);
+ }
+ }
+ int textAlignment = OS.TextAlignment_Left;
+ if (justify) {
+ textAlignment = OS.TextAlignment_Justify;
+ } else {
+ switch (alignment) {
+ case SWT.CENTER: textAlignment = OS.TextAlignment_Center; break;
+ case SWT.RIGHT: textAlignment = OS.TextAlignment_Right; break;
+ }
+ }
+ int flowDirection = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int textWrapping = wrapWidth != -1 ? OS.TextWrapping_Wrap : OS.TextWrapping_NoWrap;
+ int tabCollection = 0;
+ if (tabs != null) {
+ int position = 0;
+ int tabLength = Math.max(tabs.length, TAB_COUNT), i;
+ tabCollection = OS.gcnew_TextTabPropertiesCollection(tabLength);
+ for (i = 0; i < tabs.length; i++) {
+ position = tabs[i];
+ int tab = OS.gcnew_TextTabProperties(OS.TextTabAlignment_Left, position, 0, 0);
+ OS.TextTabPropertiesCollection_Add(tabCollection, tab);
+ OS.GCHandle_Free(tab);
+ }
+ int width = tabs[tabs.length - 1];
+ if (tabs.length > 1) width -= tabs[tabs.length - 2];
+ if (width > 0) {
+ for (; i < length; i++) {
+ position += width;
+ int tab = OS.gcnew_TextTabProperties(OS.TextTabAlignment_Left, position, 0, 0);
+ OS.TextTabPropertiesCollection_Add(tabCollection, tab);
+ OS.GCHandle_Free(tab);
+ }
+ }
+ }
+ int paragraphProperties = OS.gcnew_SWTTextParagraphProperties(flowDirection, textAlignment, false, defaultTextProperties, textWrapping, 0, 0, tabCollection);
+ int firstParagraphProperties = OS.gcnew_SWTTextParagraphProperties(flowDirection, textAlignment, true, defaultTextProperties, textWrapping, 0, indent, tabCollection);
+ int offset = 0;
+ int index = 0;
+ lines = new int[4];
+ int lineBreak = 0;
+ while (offset < length || offset == 0) {
+ char ch;
+ boolean firstLine = offset == 0 || (ch = segmentsText.charAt(offset - 1)) == '\r' || ch == '\n';
+ int paragraphProps = firstLine ? firstParagraphProperties : paragraphProperties;
+ int textLine = OS.TextFormatter_FormatLine(formatter, textSource, offset, wrapWidth != -1 ? wrapWidth : 0, paragraphProps, lineBreak);
+ offset += OS.TextLine_Length(textLine);
+ lineBreak = OS.TextLine_GetTextLineBreak(textLine);
+ if (index == lines.length) {
+ int[] tmpLines = new int[index + 4];
+ System.arraycopy(lines, 0, tmpLines, 0, index);
+ lines = tmpLines;
+ }
+ lines[index++] = textLine;
+ }
+ if (index != lines.length) {
+ int[] tmpLines = new int[index];
+ System.arraycopy(lines, 0, tmpLines, 0, index);
+ lines = tmpLines;
+ }
+ if (tabCollection != 0) OS.GCHandle_Free(tabCollection);
+ OS.GCHandle_Free(paragraphProperties);
+ OS.GCHandle_Free(firstParagraphProperties);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(formatter);
+ OS.GCHandle_Free(textSource);
+ OS.DeleteGlobalRef(jniRef);
+}
+
+ void destroy() {
+ freeRuns();
+ font = null;
+ text = null;
+ segmentsText = null;
+ tabs = null;
+ styles = null;
+// lineOffset = null;
+// lineY = null;
+// lineWidth = null;
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y) {
+ draw(gc, x, y, -1, -1, null, null);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+ draw(gc, x, y, selectionStart, selectionEnd, selectionForeground, selectionBackground, 0);
+}
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ * <p>
+ * The parameter <code>flags</code> can include one of <code>SWT.DELIMITER_SELECTION</code>
+ * or <code>SWT.FULL_SELECTION</code> to specify the selection behavior on all lines except
+ * for the last line, and can also include <code>SWT.LAST_LINE_SELECTION</code> to extend
+ * the specified selection behavior to the last line.
+ * </p>
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ * @param flags drawing options
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground, int flags) {
+ checkLayout();
+ computeRuns();
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionForeground != null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionBackground != null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = text.length();
+ if (length == 0 && flags == 0) return;
+ gc.checkGC(GC.FOREGROUND);
+ int fg = OS.Pen_Brush(gc.data.pen);
+ OS.SWTTextRunProperties_ForegroundBrush(defaultTextProperties, fg);
+ for (int i = 0; i < styles.length; i++) {
+ StyleItem run = styles[i];
+ if (run.textProperties == 0) continue;
+ if (run.style != null && run.style.foreground != null) continue;
+ if (run.style != null && run.style.underline && run.style.underlineStyle == SWT.UNDERLINE_LINK) continue;
+ OS.SWTTextRunProperties_ForegroundBrush(run.textProperties, fg);
+ }
+ int drawingContext = gc.handle;
+ boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+ int selBrush = 0, selGeometry = 0, geometries = 0;
+ if (hasSelection || (flags & SWT.LAST_LINE_SELECTION) != 0) {
+ selectionStart = Math.min(Math.max(0, selectionStart), length - 1);
+ selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1);
+ selectionStart = translateOffset(selectionStart);
+ selectionEnd = translateOffset(selectionEnd);
+ if (selectionBackground != null) {
+ selBrush = OS.gcnew_SolidColorBrush(selectionBackground.handle);
+ } else {
+ selBrush = OS.Brushes_LightSkyBlue();
+ }
+ selGeometry = OS.gcnew_GeometryGroup();
+ geometries = OS.GeometryGroup_Children(selGeometry);
+ }
+ int lineStart = 0, lineEnd = 0;
+ double drawY = y;
+ for (int i = 0; i < lines.length; i++) {
+ int line = lines[i];
+ if (line == 0) break;
+ lineStart = lineEnd;
+ lineEnd = lineStart + OS.TextLine_Length(line);
+ double nextDrawY, selY = drawY;
+ int lineHeight = (int)OS.TextLine_Height(line);
+ if (ascent != -1 && descent != -1) {
+ lineHeight = Math.max(lineHeight, ascent + descent);
+ nextDrawY = drawY + lineHeight + lineSpacing;
+ int baseline = (int)OS.TextLine_Baseline(line);
+ if (ascent > baseline) drawY += ascent - baseline;
+ } else {
+ nextDrawY = drawY + lineHeight + lineSpacing;
+ }
+
+ //draw line text
+ int point = OS.gcnew_Point(x, drawY);
+ OS.TextLine_Draw(line, drawingContext, point, 0);
+ OS.GCHandle_Free(point);
+
+ //draw line selection
+ boolean fullSelection = selectionStart <= lineStart && selectionEnd >= lineEnd;
+ boolean partialSelection = !(selectionStart > lineEnd || lineStart > selectionEnd);
+ if (flags != 0 && (hasSelection || (flags & SWT.LAST_LINE_SELECTION) != 0)) {
+ boolean extent = false;
+ if (i == lines.length - 1 && (flags & SWT.LAST_LINE_SELECTION) != 0) {
+ extent = true;
+ } else {
+ int breakLength = OS.TextLine_NewlineLength(line);
+ if (breakLength != 0) {
+ if (selectionStart <= lineEnd && lineEnd <= selectionEnd) extent = true;
+ } else {
+ if (selectionStart <= lineEnd && lineEnd < selectionEnd && (flags & SWT.FULL_SELECTION) != 0) {
+ extent = true;
+ }
+ }
+ }
+ if (extent) {
+ int extentWidth = (flags & SWT.FULL_SELECTION) != 0 ? 0x7ffffff : lineHeight / 3;
+ int textRect = OS.gcnew_Rect(OS.TextLine_WidthIncludingTrailingWhitespace(line) + x, selY, extentWidth, lineHeight);
+ int geometry = OS.gcnew_RectangleGeometry(textRect);
+ OS.GeometryCollection_Add(geometries, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(textRect);
+ }
+ }
+ if (hasSelection && (fullSelection || partialSelection)) {
+ int selLineStart = Math.max (lineStart, selectionStart);
+ int selLineEnd = Math.min (lineEnd, selectionEnd);
+ int rects = OS.TextLine_GetTextBounds(line, selLineStart, selLineEnd - selLineStart + 1);
+ if (rects != 0) {
+ int enumerator = OS.TextBoundsCollection_GetEnumerator(rects);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int bounds = OS.TextBoundsCollection_Current(enumerator);
+ int textRect = OS.TextBounds_Rectangle(bounds);
+ OS.Rect_X(textRect, OS.Rect_X(textRect) + x);
+ OS.Rect_Y(textRect, selY);
+ OS.Rect_Height(textRect, lineHeight);
+ int geometry = OS.gcnew_RectangleGeometry(textRect);
+ OS.GeometryCollection_Add(geometries, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(textRect);
+ OS.GCHandle_Free(bounds);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(rects);
+ }
+
+ drawY = nextDrawY;
+ }
+ for (int i = 0; i < styles.length - 1; i++) {
+ StyleItem run = styles[i];
+ TextStyle style = run.style;
+ if (style == null) continue;
+ if (style.borderStyle != SWT.NONE && (i + 1 >= styles.length || !style.isAdherentBorder(styles[i + 1].style))) {
+ int start = run.start;
+ int end = styles[i + 1].start - 1;
+ for (int j = i; j > 0 && style.isAdherentBorder(styles[j - 1].style); j--) {
+ start = styles[j - 1].start;
+ }
+ Color color = style.borderColor;
+ if (color == null) color = style.foreground;
+ if (color == null) color = gc.getForeground();
+ int brush = OS.gcnew_SolidColorBrush(color.handle);
+ int pen = OS.gcnew_Pen(brush, 1);
+ OS.GCHandle_Free(brush);
+ int dashStyle = 0;
+ switch (style.borderStyle) {
+ case SWT.BORDER_SOLID:
+ dashStyle = OS.DashStyles_Solid(); break;
+ case SWT.BORDER_DOT:
+ dashStyle = OS.DashStyles_Dot(); break;
+ case SWT.BORDER_DASH:
+ dashStyle = OS.DashStyles_Dash(); break;
+ }
+ OS.Pen_DashStyle(pen, dashStyle);
+ if (dashStyle != 0) OS.GCHandle_Free(dashStyle);
+ int lineY = y;
+ lineStart = lineEnd = 0;
+ for (int j = 0; j < lines.length; j++) {
+ int lineLength = OS.TextLine_Length(lines[j]);
+ lineStart = lineEnd;
+ lineEnd = lineStart + lineLength;
+ if (start < lineEnd) {
+ if (end < lineStart) break;
+ int rangeStart = Math.max(start, lineStart);
+ int rangLength = Math.min(end, lineEnd) - rangeStart + 1;
+ int rects = OS.TextLine_GetTextBounds(lines[j], rangeStart, rangLength);
+ if (rects != 0) {
+ int enumerator = OS.TextBoundsCollection_GetEnumerator(rects);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int bounds = OS.TextBoundsCollection_Current(enumerator);
+ int textRect = OS.TextBounds_Rectangle(bounds);
+ OS.Rect_Y(textRect, OS.Rect_Y(textRect) + lineY);
+ OS.Rect_X(textRect, OS.Rect_X(textRect) + x);
+ OS.Rect_Width(textRect, OS.Rect_Width(textRect) - 1);
+ OS.Rect_Height(textRect, OS.Rect_Height(textRect) - 1);
+ OS.DrawingContext_DrawRectangle(drawingContext, 0, pen, textRect);
+ OS.GCHandle_Free(textRect);
+ OS.GCHandle_Free(bounds);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(rects);
+ }
+ int lineHeight = (int)OS.TextLine_Height(lines[j]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ lineY += lineHeight + lineSpacing;
+ }
+ OS.GCHandle_Free(pen);
+ }
+ }
+
+ if (selGeometry != 0) {
+ OS.DrawingContext_PushOpacity(drawingContext, 0.4);
+ OS.DrawingContext_DrawGeometry(drawingContext, selBrush, 0, selGeometry);
+ OS.DrawingContext_Pop(drawingContext);
+ OS.GCHandle_Free(geometries);
+ OS.GCHandle_Free(selGeometry);
+ }
+ if (selBrush != 0) OS.GCHandle_Free(selBrush);
+ OS.GCHandle_Free(fg);
+}
+
+void freeRuns () {
+ if (lines == null) return;
+ for (int i = 0; i < lines.length; i++) {
+ if (lines[i] != 0) {
+ OS.GCHandle_Free(lines[i]);
+ }
+ }
+ lines = null;
+ if (runs != null) {
+ for (int i = 0; i < runs.length; i++) {
+ if (runs[i] == 0) break;
+ OS.GCHandle_Free(runs[i]);
+ }
+ runs = null;
+ }
+ for (int i = 0; i < styles.length; i++) {
+ styles[i].free();
+ }
+ if (defaultTextProperties != 0) OS.GCHandle_Free(defaultTextProperties);
+ if (string != 0) OS.GCHandle_Free(string);
+ defaultTextProperties = string = 0;
+ segmentsText = null;
+}
+
+/**
+ * Returns the receiver's horizontal text alignment, which will be one
+ * of <code>SWT.LEFT</code>, <code>SWT.CENTER</code> or
+ * <code>SWT.RIGHT</code>.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getAlignment () {
+ checkLayout();
+ return alignment;
+}
+
+/**
+ * Returns the ascent of the receiver.
+ *
+ * @return the ascent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getDescent()
+ * @see #setDescent(int)
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getAscent () {
+ checkLayout();
+ return ascent;
+}
+
+/**
+ * Returns the bounds of the receiver. The width returned is either the
+ * width of the longest line or the width set using {@link TextLayout#setWidth(int)}.
+ * To obtain the text bounds of a line use {@link TextLayout#getLineBounds(int)}.
+ *
+ * @return the bounds of the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setWidth(int)
+ * @see #getLineBounds(int)
+ */
+public Rectangle getBounds () {
+ checkLayout();
+ computeRuns();
+ double width = 0;
+ double height = 0;
+ for (int line=0; line<lines.length; line++) {
+ if (wrapWidth == -1) width = Math.max(width, OS.TextLine_WidthIncludingTrailingWhitespace(lines[line]));
+ int lineHeight = (int)OS.TextLine_Height(lines[line]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ height += lineHeight + lineSpacing;
+ }
+ if (wrapWidth != -1) width = wrapWidth;
+ return new Rectangle (0, 0, (int)width, (int)height);
+}
+
+/**
+ * Returns the bounds for the specified range of characters. The
+ * bounds is the smallest rectangle that encompasses all characters
+ * in the range. The start and end offsets are inclusive and will be
+ * clamped if out of range.
+ *
+ * @param start the start offset
+ * @param end the end offset
+ * @return the bounds of the character range
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds (int start, int end) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (length == 0) return new Rectangle(0, 0, 0, 0);
+ if (start > end) return new Rectangle(0, 0, 0, 0);
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ start = translateOffset(start);
+ end = translateOffset(end);
+ int lineStart = 0, lineEnd = 0, lineY = 0;
+ int rect = 0;
+ for (int i = 0; i < lines.length; i++) {
+ int lineLength = OS.TextLine_Length(lines[i]);
+ lineStart = lineEnd;
+ lineEnd = lineStart + lineLength;
+ if (start < lineEnd) {
+ if (end < lineStart) break;
+ int rangeStart = Math.max(start, lineStart);
+ int rangLength = Math.min(end, lineEnd) - rangeStart + 1;
+ int rects = OS.TextLine_GetTextBounds(lines[i], rangeStart, rangLength);
+ if (rects != 0) {
+ int enumerator = OS.TextBoundsCollection_GetEnumerator(rects);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int bounds = OS.TextBoundsCollection_Current(enumerator);
+ int textRect = OS.TextBounds_Rectangle(bounds);
+ OS.Rect_Y(textRect, OS.Rect_Y(textRect) + lineY);
+ if (rect != 0) {
+ OS.Rect_Union(rect, textRect);
+ OS.GCHandle_Free(textRect);
+ } else {
+ rect = textRect;
+ }
+ OS.GCHandle_Free(bounds);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(rects);
+ }
+ int lineHeight = (int)OS.TextLine_Height(lines[i]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ lineY += lineHeight + lineSpacing;
+ }
+ if (rect == 0) return new Rectangle(0, 0, 0, 0);
+ Rectangle result = new Rectangle((int)OS.Rect_X(rect), (int)OS.Rect_Y(rect), (int)OS.Rect_Width(rect), (int)OS.Rect_Height(rect));
+ OS.GCHandle_Free(rect);
+ return result;
+}
+
+/**
+ * Returns the descent of the receiver.
+ *
+ * @return the descent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getAscent()
+ * @see #setAscent(int)
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getDescent () {
+ checkLayout();
+ return descent;
+}
+
+/**
+ * Returns the default font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getFont () {
+ checkLayout();
+ return font;
+}
+
+/**
+* Returns the receiver's indent.
+*
+* @return the receiver's indent
+*
+* @exception SWTException <ul>
+* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public int getIndent () {
+ checkLayout();
+ return indent;
+}
+
+/**
+* Returns the receiver's justification.
+*
+* @return the receiver's justification
+*
+* @exception SWTException <ul>
+* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public boolean getJustify () {
+ checkLayout();
+ return justify;
+}
+
+/**
+ * Returns the embedding level for the specified character offset. The
+ * embedding level is usually used to determine the directionality of a
+ * character in bidirectional text.
+ *
+ * @param offset the character offset
+ * @return the embedding level
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ */
+public int getLevel (int offset) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ offset = translateOffset(offset);
+ int level = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? 1 : 0;
+ for (int i = 0; i < lines.length; i++) {
+ int lineLength = OS.TextLine_Length(lines[i]);
+ if (lineLength > offset) {
+ int runs = OS.TextLine_GetIndexedGlyphRuns (lines[i]);
+ int enumerator = OS.IndexedGlyphRunCollection_GetEnumerator(runs);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int indexedGlyphRun = OS.IndexedGlyphRunCollection_Current(enumerator);
+ int rangeStart = OS.IndexedGlyphRun_TextSourceCharacterIndex(indexedGlyphRun);
+ int rangeEnd = rangeStart + OS.IndexedGlyphRun_TextSourceLength(indexedGlyphRun);
+ int glyphRun = OS.IndexedGlyphRun_GlyphRun(indexedGlyphRun);
+ int bidiLevel = OS.GlyphRun_BidiLevel(glyphRun);
+ OS.GCHandle_Free(glyphRun);
+ OS.GCHandle_Free(indexedGlyphRun);
+ if (rangeStart <= offset && offset < rangeEnd) {
+ level = bidiLevel;
+ break;
+ }
+ }
+ OS.GCHandle_Free(enumerator);
+ OS.GCHandle_Free(runs);
+ break;
+ }
+ }
+ return level;
+}
+
+/**
+ * Returns the bounds of the line for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the line bounds
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getLineBounds(int lineIndex) {
+ checkLayout();
+ computeRuns();
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ int offset = 0;
+ double y = 0;
+ for (int i=0; i<lineIndex; i++) {
+ offset += OS.TextLine_Length(lines[i]);
+ int lineHeight = (int)OS.TextLine_Height(lines[i]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ y += lineHeight + lineSpacing;
+ }
+ int line = lines[lineIndex];
+ double x = OS.TextLine_Start(line);
+ double width = OS.TextLine_WidthIncludingTrailingWhitespace(line);
+ double height = OS.TextLine_Height(line);
+ if (ascent != -1 && descent != -1) height = Math.max(height, ascent + descent);
+ char ch;
+ boolean firstLine = offset == 0 || (ch = segmentsText.charAt(offset - 1)) == '\r' || ch == '\n';
+ if (firstLine) {
+ x += indent;
+ width -= indent;
+ }
+ return new Rectangle ((int)x, (int)y, (int)width, (int)height);
+}
+
+/**
+ * Returns the receiver's line count. This includes lines caused
+ * by wrapping.
+ *
+ * @return the line count
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineCount () {
+ checkLayout();
+ computeRuns();
+ return lines.length;
+}
+
+/**
+ * Returns the index of the line that contains the specified
+ * character offset.
+ *
+ * @param offset the character offset
+ * @return the line index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineIndex (int offset) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ offset = translateOffset(offset);
+ int start = 0;
+ for (int line=0; line<lines.length; line++) {
+ int lineLength = OS.TextLine_Length(lines[line]);
+ if (start + lineLength > offset) return line;
+ start += lineLength;
+ }
+ return lines.length - 1;
+}
+
+/**
+ * Returns the font metrics for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the font metrics
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontMetrics getLineMetrics (int lineIndex) {
+ checkLayout();
+ computeRuns();
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ int length = text.length();
+ double baseline, height;
+ if (length == 0) {
+ Font font = this.font != null ? this.font : device.systemFont;
+ int str = OS.gcnew_String (new char []{' ', '\0'});
+ int culture = OS.CultureInfo_CurrentUICulture();
+ int direction = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ height = OS.FormattedText_Height(text);
+ baseline = OS.FormattedText_Baseline(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ } else {
+ baseline = OS.TextLine_Baseline(lines[lineIndex]);
+ height = OS.TextLine_Height(lines[lineIndex]);
+ if (ascent != -1 && descent != -1) {
+ baseline = Math.max(baseline, ascent);
+ height = Math.max(height, ascent + descent);
+ }
+ }
+ return FontMetrics.wpf_new((int)baseline, (int)height - (int)baseline, 0, 0, (int)height);
+}
+
+/**
+ * Returns the line offsets. Each value in the array is the
+ * offset for the first character in a line except for the last
+ * value, which contains the length of the text.
+ *
+ * @return the line offsets
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getLineOffsets () {
+ checkLayout();
+ computeRuns();
+ int start = 0;
+ int[] offsets = new int[lines.length+1];
+ for (int i = 0; i < lines.length; i++) {
+ start += OS.TextLine_Length(lines[i]);
+ offsets[i+1] = untranslateOffset(start);
+ }
+ return offsets;
+}
+
+/**
+ * Returns the location for the specified character offset. The
+ * <code>trailing</code> argument indicates whether the offset
+ * corresponds to the leading or trailing edge of the cluster.
+ *
+ * @param offset the character offset
+ * @param trailing the trailing flag
+ * @return the location of the character offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getOffset(Point, int[])
+ * @see #getOffset(int, int, int[])
+ */
+public Point getLocation (int offset, boolean trailing) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ offset = translateOffset(offset);
+ double y = 0;
+ int start = 0, line;
+ for (line=0; line<lines.length; line++) {
+ int lineLength = OS.TextLine_Length(lines[line]);
+ if (start + lineLength > offset) break;
+ start += lineLength;
+ int lineHeight = (int)OS.TextLine_Height(lines[line]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ y += lineHeight + lineSpacing;
+ }
+ int characterHit = OS.gcnew_CharacterHit(offset, trailing ? 1 : 0);
+ double x = OS.TextLine_GetDistanceFromCharacterHit(lines[line], characterHit);
+ OS.GCHandle_Free(characterHit);
+ return new Point((int)x, (int)y);
+}
+
+/**
+ * Returns the next offset for the specified offset and movement
+ * type. The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code>, <code>SWT.MOVEMENT_WORD</code>,
+ * <code>SWT.MOVEMENT_WORD_END</code> or <code>SWT.MOVEMENT_WORD_START</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getPreviousOffset(int, int)
+ */
+public int getNextOffset (int offset, int movement) {
+ checkLayout();
+ return _getOffset (offset, movement, true);
+}
+
+int _getOffset(int offset, int movement, boolean forward) {
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ if (forward && offset == length) return length;
+ if (!forward && offset == 0) return 0;
+ int step = forward ? 1 : -1;
+ if ((movement & SWT.MOVEMENT_CHAR) != 0) return offset + step;
+ offset = translateOffset(offset);
+ int lineStart = 0, lineIndex;
+ for (lineIndex=0; lineIndex<lines.length; lineIndex++) {
+ int lineLength = OS.TextLine_Length(lines[lineIndex]);
+ if (lineStart + lineLength > offset) break;
+ lineStart += lineLength;
+ }
+ int line = lines[lineIndex];
+ int lineLength = OS.TextLine_Length(line);
+ int lineBreak = OS.TextLine_NewlineLength (line);
+ while (lineStart <= offset && offset <= lineStart + lineLength) {
+ int resultCharHit;
+ int characterHit = OS.gcnew_CharacterHit(offset, 0);
+ if (forward) {
+ resultCharHit = OS.TextLine_GetNextCaretCharacterHit(line, characterHit);
+ } else {
+ resultCharHit = OS.TextLine_GetPreviousCaretCharacterHit(line, characterHit);
+ }
+ int newOffset = OS.CharacterHit_FirstCharacterIndex(resultCharHit);
+ int trailing = OS.CharacterHit_TrailingLength(resultCharHit);
+ OS.GCHandle_Free(resultCharHit);
+ OS.GCHandle_Free(characterHit);
+ if (forward) {
+ if (newOffset + trailing >= lineStart + lineLength - lineBreak) {
+ int lineEnd = lineStart + lineLength;
+ if (trailing != 0) lineEnd -= lineBreak;
+ return untranslateOffset(Math.min(length, lineEnd));
+ }
+ } else {
+ if (newOffset + trailing == lineStart) {
+ if (lineIndex == 0) return 0;
+ int lineEnd = 0;
+ if (newOffset + trailing == offset) lineEnd = OS.TextLine_NewlineLength(lines[lineIndex - 1]);
+ return untranslateOffset(Math.max(0, newOffset + trailing - lineEnd));
+ }
+ }
+ offset = newOffset + trailing;
+
+ switch (movement) {
+ case SWT.MOVEMENT_CLUSTER:
+ return untranslateOffset(offset);
+ case SWT.MOVEMENT_WORD:
+ case SWT.MOVEMENT_WORD_START: {
+ if (offset > 0) {
+ boolean letterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset));
+ boolean previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset - 1));
+ if (letterOrDigit != previousLetterOrDigit || !letterOrDigit) {
+ if (!Compatibility.isWhitespace(segmentsText.charAt(offset))) {
+ return untranslateOffset(offset);
+ }
+ }
+ }
+ break;
+ }
+ case SWT.MOVEMENT_WORD_END: {
+ if (offset > 0) {
+ boolean isLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset));
+ boolean previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset - 1));
+ if (!isLetterOrDigit && previousLetterOrDigit) {
+ return untranslateOffset(offset);
+ }
+ }
+ break;
+ }
+ }
+ }
+ return forward ? length : 0;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param point the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (Point point, int[] trailing) {
+ checkLayout();
+ if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return getOffset (point.x, point.y, trailing) ;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (int x, int y, int[] trailing) {
+ checkLayout();
+ computeRuns();
+ if (trailing != null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ double lineY = 0;
+ int line;
+ for (line=0; line<lines.length; line++) {
+ double lineHeight = OS.TextLine_Length(lines[line]);
+ if (lineY + lineHeight > y) break;
+ lineY += lineHeight;
+ }
+ if (line >= lines.length) line = lines.length - 1;
+ int characterHit = OS.TextLine_GetCharacterHitFromDistance(lines[line], x);
+ int offset = OS.CharacterHit_FirstCharacterIndex(characterHit);
+ if (trailing != null) trailing[0] = OS.CharacterHit_TrailingLength(characterHit);
+ OS.GCHandle_Free(characterHit);
+ return untranslateOffset(offset);
+}
+
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getOrientation () {
+ checkLayout();
+ return orientation;
+}
+
+/**
+ * Returns the previous offset for the specified offset and movement
+ * type. The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code> or <code>SWT.MOVEMENT_WORD</code>,
+ * <code>SWT.MOVEMENT_WORD_END</code> or <code>SWT.MOVEMENT_WORD_START</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the previous offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getNextOffset(int, int)
+ */
+public int getPreviousOffset (int offset, int movement) {
+ checkLayout();
+ return _getOffset (offset, movement, false);
+}
+
+/**
+ * Gets the ranges of text that are associated with a <code>TextStyle</code>.
+ *
+ * @return the ranges, an array of offsets representing the start and end of each
+ * text style.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getStyles()
+ *
+ * @since 3.2
+ */
+public int[] getRanges () {
+ checkLayout();
+ int[] result = new int[styles.length * 2];
+ int count = 0;
+ for (int i=0; i<styles.length - 1; i++) {
+ if (styles[i].style != null) {
+ result[count++] = styles[i].start;
+ result[count++] = styles[i + 1].start - 1;
+ }
+ }
+ if (count != result.length) {
+ int[] newResult = new int[count];
+ System.arraycopy(result, 0, newResult, 0, count);
+ result = newResult;
+ }
+ return result;
+}
+
+/**
+ * Returns the text segments offsets of the receiver.
+ *
+ * @return the text segments offsets
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getSegments () {
+ checkLayout();
+ return segments;
+}
+
+String getSegmentsText() {
+ if (segments == null) return text;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return text;
+ int length = text.length();
+ if (length == 0) return text;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return text;
+ }
+ char[] oldChars = new char[length];
+ text.getChars(0, length, oldChars, 0);
+ char[] newChars = new char[length + nSegments];
+ int charCount = 0, segmentCount = 0;
+ char separator = orientation == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+ while (charCount < length) {
+ if (segmentCount < nSegments && charCount == segments[segmentCount]) {
+ newChars[charCount + segmentCount++] = separator;
+ } else {
+ newChars[charCount + segmentCount] = oldChars[charCount++];
+ }
+ }
+ if (segmentCount < nSegments) {
+ segments[segmentCount] = charCount;
+ newChars[charCount + segmentCount++] = separator;
+ }
+ return new String(newChars, 0, Math.min(charCount + segmentCount, newChars.length));
+}
+
+/**
+ * Returns the line spacing of the receiver.
+ *
+ * @return the line spacing
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getSpacing () {
+ checkLayout();
+ return lineSpacing;
+}
+
+/**
+ * Gets the style of the receiver at the specified character offset.
+ *
+ * @param offset the text offset
+ * @return the style or <code>null</code> if not set
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public TextStyle getStyle (int offset) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset < length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ for (int i=1; i<styles.length; i++) {
+ if (styles[i].start > offset) {
+ return styles[i - 1].style;
+ }
+ }
+ return null;
+}
+
+/**
+ * Gets all styles of the receiver.
+ *
+ * @return the styles
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getRanges()
+ *
+ * @since 3.2
+ */
+public TextStyle[] getStyles () {
+ checkLayout();
+ TextStyle[] result = new TextStyle[styles.length];
+ int count = 0;
+ for (int i=0; i<styles.length; i++) {
+ if (styles[i].style != null) {
+ result[count++] = styles[i].style;
+ }
+ }
+ if (count != result.length) {
+ TextStyle[] newResult = new TextStyle[count];
+ System.arraycopy(result, 0, newResult, 0, count);
+ result = newResult;
+ }
+ return result;
+}
+
+/**
+ * Returns the tab list of the receiver.
+ *
+ * @return the tab list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getTabs () {
+ checkLayout();
+ return tabs;
+}
+
+int GetTextRun(int textSourceCharacterIndex) {
+ if (runs == null) runs = new int[4];
+ int index = 0;
+ while (index < runs.length && runs[index] != 0) index++;
+ if (index == runs.length) {
+ int[] tmpRuns = new int[index + 4];
+ System.arraycopy(runs, 0, tmpRuns, 0, index);
+ runs = tmpRuns;
+ }
+ int length = OS.String_Length(string);
+ if (textSourceCharacterIndex >= length) {
+ runs[index] = OS.gcnew_TextEndOfParagraph(1, defaultTextProperties);
+ } else {
+ int styleIndex = 1;
+ while (styleIndex < styles.length && styles[styleIndex].start <= textSourceCharacterIndex) styleIndex++;
+ TextStyle textStyle = styles[styleIndex - 1].style;
+ int textProperties = styles[styleIndex - 1].textProperties;
+ if (textProperties == 0) textProperties = defaultTextProperties;
+ int end = styles[styleIndex].start;
+ if (textStyle != null && textStyle.metrics != null) {
+ GlyphMetrics metrics = textStyle.metrics;
+ runs[index] = OS.gcnew_SWTTextEmbeddedObject(textProperties, end - textSourceCharacterIndex, metrics.width, metrics.ascent + metrics.descent, metrics.ascent);
+ } else {
+ char ch = segmentsText.charAt(textSourceCharacterIndex);
+ if (ch == '\n' || ch == '\r') {
+ int breakLength = 1;
+ if (ch == '\r' && textSourceCharacterIndex + 1 < end && segmentsText.charAt(textSourceCharacterIndex + 1) == '\n') breakLength++;
+ runs[index] = OS.gcnew_TextEndOfLine(breakLength, textProperties);
+ } else {
+ int i = textSourceCharacterIndex;
+ while (i < end && (ch = segmentsText.charAt(i)) != '\n' && ch != '\r') i++;
+ runs[index] = OS.gcnew_TextCharacters(string, textSourceCharacterIndex, i - textSourceCharacterIndex, textProperties);
+ }
+ }
+ }
+ return runs[index];
+}
+
+int GetPrecedingText(int textSourceCharacterIndexLimit) {
+ return 0;
+}
+
+/**
+ * Gets the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public String getText () {
+ checkLayout();
+ return text;
+}
+
+/**
+ * Returns the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getWidth () {
+ checkLayout();
+ return wrapWidth;
+}
+
+/**
+ * Returns <code>true</code> if the text layout has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the text layout.
+ * When a text layout has been disposed, it is an error to
+ * invoke any other method using the text layout.
+ * </p>
+ *
+ * @return <code>true</code> when the text layout is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+ return device == null;
+}
+
+/**
+ * Sets the text alignment for the receiver. The alignment controls
+ * how a line of text is positioned horizontally. The argument should
+ * be one of <code>SWT.LEFT</code>, <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>.
+ * <p>
+ * The default alignment is <code>SWT.LEFT</code>. Note that the receiver's
+ * width must be set in order to use <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>
+ * alignment.
+ * </p>
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setWidth(int)
+ */
+public void setAlignment (int alignment) {
+ checkLayout();
+ int mask = SWT.LEFT | SWT.CENTER | SWT.RIGHT;
+ alignment &= mask;
+ if (alignment == 0) return;
+ if ((alignment & SWT.LEFT) != 0) alignment = SWT.LEFT;
+ if ((alignment & SWT.RIGHT) != 0) alignment = SWT.RIGHT;
+ if (this.alignment == alignment) return;
+ freeRuns();
+ this.alignment = alignment;
+}
+
+/**
+ * Sets the ascent of the receiver. The ascent is distance in pixels
+ * from the baseline to the top of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * ascent is calculated from the line fonts.
+ *
+ * @param ascent the new ascent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the ascent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setAscent(int ascent) {
+ checkLayout();
+ if (ascent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.ascent == ascent) return;
+ freeRuns();
+ this.ascent = ascent;
+}
+
+/**
+ * Sets the descent of the receiver. The descent is distance in pixels
+ * from the baseline to the bottom of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * descent is calculated from the line fonts.
+ *
+ * @param descent the new descent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the descent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setDescent(int descent) {
+ checkLayout();
+ if (descent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.descent == descent) return;
+ freeRuns();
+ this.descent = descent;
+}
+
+/**
+ * Sets the default font which will be used by the receiver
+ * to draw and measure text. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead. Note that a text
+ * style can override the default font.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setFont (Font font) {
+ checkLayout();
+ if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Font oldFont = this.font;
+ if (oldFont == font) return;
+ this.font = font;
+ if (oldFont != null && oldFont.equals(font)) return;
+ freeRuns();
+}
+
+/**
+ * Sets the indent of the receiver. This indent it applied of the first line of
+ * each paragraph.
+ *
+ * @param indent new indent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setIndent (int indent) {
+ checkLayout();
+ if (indent < 0) return;
+ if (this.indent == indent) return;
+ freeRuns();
+ this.indent = indent;
+}
+
+/**
+ * Sets the justification of the receiver. Note that the receiver's
+ * width must be set in order to use justification.
+ *
+ * @param justify new justify
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setJustify (boolean justify) {
+ checkLayout();
+ if (this.justify == justify) return;
+ freeRuns();
+ this.justify = justify;
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setOrientation (int orientation) {
+ checkLayout();
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ orientation &= mask;
+ if (orientation == 0) return;
+ if ((orientation & SWT.LEFT_TO_RIGHT) != 0) orientation = SWT.LEFT_TO_RIGHT;
+ if (this.orientation == orientation) return;
+ this.orientation = orientation;
+ freeRuns();
+}
+
+/**
+ * Sets the offsets of the receiver's text segments. Text segments are used to
+ * override the default behaviour of the bidirectional algorithm.
+ * Bidirectional reordering can happen within a text segment but not
+ * between two adjacent segments.
+ * <p>
+ * Each text segment is determined by two consecutive offsets in the
+ * <code>segments</code> arrays. The first element of the array should
+ * always be zero and the last one should always be equals to length of
+ * the text.
+ * </p>
+ *
+ * @param segments the text segments offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSegments(int[] segments) {
+ checkLayout();
+ if (this.segments == null && segments == null) return;
+ if (this.segments != null && segments != null) {
+ if (this.segments.length == segments.length) {
+ int i;
+ for (i = 0; i <segments.length; i++) {
+ if (this.segments[i] != segments[i]) break;
+ }
+ if (i == segments.length) return;
+ }
+ }
+ freeRuns();
+ this.segments = segments;
+}
+
+/**
+ * Sets the line spacing of the receiver. The line spacing
+ * is the space left between lines.
+ *
+ * @param spacing the new line spacing
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the spacing is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSpacing (int spacing) {
+ checkLayout();
+ if (spacing < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.lineSpacing == spacing) return;
+ freeRuns();
+ this.lineSpacing = spacing;
+}
+
+/**
+ * Sets the style of the receiver for the specified range. Styles previously
+ * set for that range will be overwritten. The start and end offsets are
+ * inclusive and will be clamped if out of range.
+ *
+ * @param style the style
+ * @param start the start offset
+ * @param end the end offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setStyle (TextStyle style, int start, int end) {
+ checkLayout();
+ int length = text.length();
+ if (length == 0) return;
+ if (start > end) return;
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ int low = -1;
+ int high = styles.length;
+ while (high - low > 1) {
+ int index = (high + low) / 2;
+ if (styles[index + 1].start > start) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ if (0 <= high && high < styles.length) {
+ StyleItem item = styles[high];
+ if (item.start == start && styles[high + 1].start - 1 == end) {
+ if (style == null) {
+ if (item.style == null) return;
+ } else {
+ if (style.equals(item.style)) return;
+ }
+ }
+ }
+ freeRuns();
+ int modifyStart = high;
+ int modifyEnd = modifyStart;
+ while (modifyEnd < styles.length) {
+ if (styles[modifyEnd + 1].start > end) break;
+ modifyEnd++;
+ }
+ if (modifyStart == modifyEnd) {
+ int styleStart = styles[modifyStart].start;
+ int styleEnd = styles[modifyEnd + 1].start - 1;
+ if (styleStart == start && styleEnd == end) {
+ styles[modifyStart].style = style;
+ return;
+ }
+ if (styleStart != start && styleEnd != end) {
+ StyleItem[] newStyles = new StyleItem[styles.length + 2];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ item = new StyleItem();
+ item.start = end + 1;
+ item.style = styles[modifyStart].style;
+ newStyles[modifyStart + 2] = item;
+ System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1);
+ styles = newStyles;
+ return;
+ }
+ }
+ if (start == styles[modifyStart].start) modifyStart--;
+ if (end == styles[modifyEnd + 1].start - 1) modifyEnd++;
+ int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1);
+ StyleItem[] newStyles = new StyleItem[newLength];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ styles[modifyEnd].start = end + 1;
+ System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd);
+ styles = newStyles;
+}
+
+/**
+ * Sets the receiver's tab list. Each value in the tab list specifies
+ * the space in pixels from the origin of the text layout to the respective
+ * tab stop. The last tab stop width is repeated continuously.
+ *
+ * @param tabs the new tab list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setTabs (int[] tabs) {
+ checkLayout();
+ if (this.tabs == null && tabs == null) return;
+ if (this.tabs != null && tabs !=null) {
+ if (this.tabs.length == tabs.length) {
+ int i;
+ for (i = 0; i <tabs.length; i++) {
+ if (this.tabs[i] != tabs[i]) break;
+ }
+ if (i == tabs.length) return;
+ }
+ }
+ freeRuns();
+ this.tabs = tabs;
+}
+
+/**
+ * Sets the receiver's text.
+ *<p>
+ * Note: Setting the text also clears all the styles. This method
+ * returns without doing anything if the new text is the same as
+ * the current text.
+ * </p>
+ *
+ * @param text the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setText (String text) {
+ checkLayout();
+ if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (text.equals(this.text)) return;
+ freeRuns();
+ this.text = text;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ styles[1].start = text.length();
+}
+
+/**
+ * Sets the line width of the receiver, which determines how
+ * text should be wrapped and aligned. The default value is
+ * <code>-1</code> which means wrapping is disabled.
+ *
+ * @param width the new width
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the width is <code>0</code> or less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAlignment(int)
+ */
+public void setWidth (int width) {
+ checkLayout();
+ if (width < -1 || width == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.wrapWidth == width) return;
+ freeRuns();
+ this.wrapWidth = width;
+}
+
+int validadeOffset(int offset, int step) {
+ offset += step;
+ if (segments != null && segments.length > 2) {
+ for (int i = 0; i < segments.length; i++) {
+ if (translateOffset(segments[i]) - 1 == offset) {
+ offset += step;
+ break;
+ }
+ }
+ }
+ return offset;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "TextLayout {*DISPOSED*}";
+ return "TextLayout {}";
+}
+
+int translateOffset(int offset) {
+ if (segments == null) return offset;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return offset;
+ int length = text.length();
+ if (length == 0) return offset;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return offset;
+ }
+ for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) {
+ offset++;
+ }
+ return offset;
+}
+
+int untranslateOffset(int offset) {
+ if (segments == null) return offset;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return offset;
+ int length = text.length();
+ if (length == 0) return offset;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return offset;
+ }
+ for (int i = 0; i < nSegments && offset > segments[i]; i++) {
+ offset--;
+ }
+ return offset;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java
new file mode 100644
index 0000000000..9bd58865f4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent transformation matrices for
+ * points expressed as (x, y) pairs of floating point numbers.
+ * <p>
+ * Application code must explicitly invoke the <code>Transform.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public class Transform extends Resource {
+
+ /**
+ * the OS resource for the Transform
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+
+/**
+ * Constructs a new identity Transform.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the Transform
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform (Device device) {
+ this(device, 1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Constructs a new Transform given an array of elements that represent the
+ * matrix that describes the transformation.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the Transform
+ * @param elements an array of floats that describe the transformation matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device, or the elements array is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the elements array is too small to hold the matrix values</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform(Device device, float[] elements) {
+ this (device, checkTransform(elements)[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
+}
+
+/**
+ * Constructs a new Transform given all of the elements that represent the
+ * matrix that describes the transformation.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the Transform
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform (Device device, float m11, float m12, float m21, float m22, float dx, float dy) {
+ super(device);
+ handle = OS.gcnew_Matrix(m11, m12, m21, m22, dx, dy);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ init();
+}
+
+static float[] checkTransform(float[] elements) {
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return elements;
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Transform. Applications must dispose of all Transforms that
+ * they allocate.
+ */
+void destroy() {
+ OS.GCHandle_Free(handle);
+ handle = 0;
+}
+
+/**
+ * Fills the parameter with the values of the transformation matrix
+ * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}.
+ *
+ * @param elements array to hold the matrix values
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the matrix values</li>
+ * </ul>
+ */
+public void getElements(float[] elements) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ elements[0] = (float)OS.Matrix_M11(handle);
+ elements[1] = (float)OS.Matrix_M12(handle);
+ elements[2] = (float)OS.Matrix_M21(handle);
+ elements[3] = (float)OS.Matrix_M22(handle);
+ elements[4] = (float)OS.Matrix_OffsetX(handle);
+ elements[5] = (float)OS.Matrix_OffsetY(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * identity matrix.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void identity() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_SetIdentity(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes
+ * the mathematical inverse of the matrix it previously represented.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_CANNOT_INVERT_MATRIX - if the matrix is not invertible</li>
+ * </ul>
+ */
+public void invert() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_Invert(handle);
+ //TODO handle matrix invert exception
+ //SWT.error(SWT.ERROR_CANNOT_INVERT_MATRIX);
+}
+
+/**
+ * Returns <code>true</code> if the Transform has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Transform.
+ * When a Transform has been disposed, it is an error to
+ * invoke any other method using the Transform.
+ *
+ * @return <code>true</code> when the Transform is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns <code>true</code> if the Transform represents the identity matrix
+ * and false otherwise.
+ *
+ * @return <code>true</code> if the receiver is an identity Transform, and <code>false</code> otherwise
+ */
+public boolean isIdentity() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Matrix_IsIdentity(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the result of multiplying the matrix it previously represented by the
+ * argument.
+ *
+ * @param matrix the matrix to multiply the receiver by
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ */
+public void multiply(Transform matrix) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (matrix == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (matrix.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int result = OS.Matrix_Multiply(handle, matrix.handle);
+ OS.Matrix_M11(handle, OS.Matrix_M11(result));
+ OS.Matrix_M12(handle, OS.Matrix_M12(result));
+ OS.Matrix_M21(handle, OS.Matrix_M21(result));
+ OS.Matrix_M22(handle, OS.Matrix_M22(result));
+ OS.Matrix_OffsetX(handle, OS.Matrix_OffsetX(result));
+ OS.Matrix_OffsetY(handle, OS.Matrix_OffsetY(result));
+ OS.GCHandle_Free(result);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation rotated by the specified angle.
+ * The angle is specified in degrees and for the identity transform 0 degrees
+ * is at the 3 o'clock position. A positive value indicates a clockwise rotation
+ * while a negative value indicates a counter-clockwise rotation.
+ *
+ * @param angle the angle to rotate the transformation by
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void rotate(float angle) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_RotatePrepend(handle, angle);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation scaled by (scaleX, scaleY).
+ *
+ * @param scaleX the amount to scale in the X direction
+ * @param scaleY the amount to scale in the Y direction
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void scale(float scaleX, float scaleY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_ScalePrepend(handle, scaleX, scaleY);
+}
+
+/**
+ * Modifies the receiver to represent a new transformation given all of
+ * the elements that represent the matrix that describes that transformation.
+ *
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setElements(float m11, float m12, float m21, float m22, float dx, float dy) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_M11(handle, m11);
+ OS.Matrix_M12(handle, m12);
+ OS.Matrix_M21(handle, m21);
+ OS.Matrix_M22(handle, m22);
+ OS.Matrix_OffsetX(handle, dx);
+ OS.Matrix_OffsetY(handle, dy);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation sheared by (shearX, shearY).
+ *
+ * @param shearX the shear factor in the X direction
+ * @param shearY the shear factor in the Y direction
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void shear(float shearX, float shearY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int matrix = OS.gcnew_Matrix(1, shearX, shearY, 1, 0, 0);
+ int result = OS.Matrix_Multiply(handle, matrix);
+ OS.Matrix_M11(handle, OS.Matrix_M11(result));
+ OS.Matrix_M12(handle, OS.Matrix_M12(result));
+ OS.Matrix_M21(handle, OS.Matrix_M21(result));
+ OS.Matrix_M22(handle, OS.Matrix_M22(result));
+ OS.Matrix_OffsetX(handle, OS.Matrix_OffsetX(result));
+ OS.Matrix_OffsetY(handle, OS.Matrix_OffsetY(result));
+ OS.GCHandle_Free(result);
+ OS.GCHandle_Free(matrix);
+}
+
+/**
+ * Given an array containing points described by alternating x and y values,
+ * modify that array such that each point has been replaced with the result of
+ * applying the transformation represented by the receiver to that point.
+ *
+ * @param pointArray an array of alternating x and y values to be transformed
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void transform(float[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ for (int i = 0; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i], pointArray[i + 1]);
+ int result = OS.Matrix_Transform(handle, point);
+ pointArray[i] = (float)OS.Point_X(result);
+ pointArray[i + 1] = (float)OS.Point_Y(result);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(result);
+ }
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation translated by (offsetX, offsetY).
+ *
+ * @param offsetX the distance to translate in the X direction
+ * @param offsetY the distance to translate in the Y direction
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void translate(float offsetX, float offsetY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_TranslatePrepend(handle, offsetX, offsetY);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Transform {*DISPOSED*}";
+ float[] elements = new float[6];
+ getElements(elements);
+ return "Transform {" + elements [0] + "," + elements [1] + "," +elements [2] + "," +elements [3] + "," +elements [4] + "," +elements [5] + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Button.java
new file mode 100644
index 0000000000..99237de68e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Button.java
@@ -0,0 +1,652 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a selectable user interface object that
+ * issues notification when pressed and released.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT</dd>
+ * <dd>UP, DOWN, LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles ARROW, CHECK, PUSH, RADIO, and TOGGLE
+ * may be specified.
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified.
+ * </p><p>
+ * Note: Only one of the styles UP, DOWN, LEFT, and RIGHT may be specified
+ * when the ARROW style is specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#button">Button snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Button extends Control {
+ String text = "";
+ Image image;
+ int textHandle, imageHandle;
+ boolean ignoreSelection, grayed;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#ARROW
+ * @see SWT#CHECK
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#TOGGLE
+ * @see SWT#FLAT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Button (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the user.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ style = checkBits (style, SWT.PUSH, SWT.ARROW, SWT.CHECK, SWT.RADIO, SWT.TOGGLE, 0);
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+ return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
+ }
+ if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
+ return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+ }
+ if ((style & SWT.ARROW) != 0) {
+ style |= SWT.NO_FOCUS;
+ return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0);
+ }
+ return style;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ Point size = computeSize (handle, wHint, hHint, changed);
+ if ((style & SWT.ARROW) == 0) {
+ int border = getBorderWidth ();
+ size.x += border * 2;
+ size.y += border * 2;
+ }
+ return size;
+}
+
+void createArrow () {
+ int geometry = OS.gcnew_StreamGeometry ();
+ int context = OS.StreamGeometry_Open (geometry);
+ int start = 0, point = 0, end = 0;
+ int mask = SWT.RIGHT | SWT.LEFT | SWT.DOWN | SWT.UP;
+ switch (style & mask) {
+ case SWT.RIGHT:
+ start = OS.gcnew_Point (1, 0);
+ point = OS.gcnew_Point (4, 3);
+ end = OS.gcnew_Point (1, 6);
+ break;
+ case SWT.LEFT:
+ start = OS.gcnew_Point (4, 1);
+ point = OS.gcnew_Point (1, 3);
+ end = OS.gcnew_Point (4, 6);
+ break;
+ case SWT.DOWN:
+ start = OS.gcnew_Point (0, 1);
+ point = OS.gcnew_Point (3, 4);
+ end = OS.gcnew_Point (6, 1);
+ break;
+ case SWT.UP:
+ start = OS.gcnew_Point (0, 4);
+ point = OS.gcnew_Point (3, 1);
+ end = OS.gcnew_Point (6, 4);
+ break;
+ }
+ OS.StreamGeometryContext_BeginFigure (context, start, true, true);
+ OS.StreamGeometryContext_LineTo (context, point, true, true);
+ OS.StreamGeometryContext_LineTo (context, end, true, true);
+ OS.StreamGeometryContext_Close (context);
+ int path = OS.gcnew_Path ();
+ OS.Path_Data (path, geometry);
+ int padding = OS.gcnew_Thickness (3, 3, 3, 3);
+ OS.FrameworkElement_Margin (path, padding);
+ int brush = OS.Brushes_Black ();
+ OS.Path_Fill (path, brush);
+ OS.FrameworkElement_Width (path, 6);
+ OS.FrameworkElement_Height (path, 6);
+ OS.FrameworkElement_HorizontalAlignment (path, OS.HorizontalAlignment_Center);
+ OS.FrameworkElement_VerticalAlignment (path, OS.VerticalAlignment_Center);
+ OS.ContentControl_Content (handle, path);
+ OS.GCHandle_Free (padding);
+ OS.GCHandle_Free (start);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (end);
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (path);
+ OS.GCHandle_Free (context);
+ OS.GCHandle_Free (geometry);
+}
+
+void createHandle () {
+ if ((style & SWT.PUSH) == 0) state |= THEME_BACKGROUND;
+ int bits = SWT.TOGGLE | SWT.ARROW | SWT.PUSH | SWT.RADIO | SWT.CHECK;
+ switch (style & bits) {
+ case SWT.TOGGLE:
+ handle = OS.gcnew_ToggleButton ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.ARROW:
+ handle = OS.gcnew_Button ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ createArrow ();
+ break;
+ case SWT.RADIO:
+ handle = OS.gcnew_RadioButton ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.CHECK:
+ handle = OS.gcnew_CheckBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.PUSH:
+ default:
+ handle = OS.gcnew_Button ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ }
+ if ((style & SWT.ARROW) != 0) return;
+ int value = OS.HorizontalAlignment_Left;
+ if ((style & SWT.CENTER) != 0) value = OS.HorizontalAlignment_Center;
+ if ((style & SWT.RIGHT) != 0) value = OS.HorizontalAlignment_Right;
+ OS.Control_HorizontalContentAlignment (handle, value);
+ imageHandle = OS.gcnew_Image ();
+ if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+ textHandle = OS.gcnew_AccessText ();
+ if (textHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_VerticalAlignment (textHandle, OS.VerticalAlignment_Center);
+ int panel = OS.gcnew_StackPanel ();
+ if (panel == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.StackPanel_Orientation (panel, OS.Orientation_Horizontal);
+ int thickness = OS.gcnew_Thickness (1, 1, 1, 1);
+ if (thickness == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (panel, thickness);
+ OS.GCHandle_Free(thickness);
+ int children = OS.Panel_Children (panel);
+ OS.UIElementCollection_Add (children, imageHandle);
+ OS.UIElementCollection_Add (children, textHandle);
+ OS.ContentControl_Content (handle, panel);
+ OS.GCHandle_Free (children);
+ OS.GCHandle_Free (panel);
+}
+
+int defaultBackground () {
+ if ((style & SWT.PUSH) == 0) return OS.SystemColors_ControlColor;
+ return 0;
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is an <code>ARROW</code> button, in
+ * which case, the alignment will indicate the direction of
+ * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>UP</code> or <code>DOWN</code>).
+ *
+ * @return the alignment
+ *
+ * @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 int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.ARROW) != 0) {
+ if ((style & SWT.UP) != 0) return SWT.UP;
+ if ((style & SWT.DOWN) != 0) return SWT.DOWN;
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.UP;
+ }
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the widget does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @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>
+ *
+ * @since 3.4
+ */
+public boolean getGrayed () {
+ checkWidget ();
+ if ((style & SWT.CHECK) == 0) return false;
+ return grayed;
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's 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;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
+ * it is selected when it is pushed in. If the receiver is of any other type,
+ * this method returns false.
+ *
+ * @return the selection 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>
+ */
+public boolean getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return false;
+ if ((style & SWT.CHECK) != 0 && grayed) {
+ int property = OS.ToggleButton_IsCheckedProperty();
+ int value = OS.DependencyObject_GetValue(handle, property);
+ OS.GCHandle_Free(property);
+ if (value == 0) return true;
+ OS.GCHandle_Free(value);
+ }
+ return OS.ToggleButton_IsChecked (handle);
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * an <code>ARROW</code> button.
+ *
+ * @return the receiver's 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 ();
+ if ((style & SWT.ARROW) != 0) return "";
+ return text;
+}
+
+void HandleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if ((style & SWT.CHECK) != 0) {
+ if (grayed) {
+ if (OS.ToggleButton_IsChecked (handle)) {
+ ignoreSelection = true;
+ OS.ToggleButton_IsCheckedNullSetter (handle);
+ ignoreSelection = false;
+ }
+ }
+ }
+ if (!ignoreSelection) postEvent (SWT.Selection);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ if ((style & (SWT.TOGGLE | SWT.RADIO | SWT.CHECK)) != 0) {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ToggleButton_Checked (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ToggleButton_Unchecked (handle, handler);
+ OS.GCHandle_Free (handler);
+ } else {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ButtonBase_Click (handle, handler);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+boolean mnemonicHit (char ch) {
+ //TODO
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ return super.mnemonicMatch (textHandle, key);
+}
+
+void releaseHandle() {
+ super.releaseHandle ();
+ if (textHandle != 0) OS.GCHandle_Free (textHandle);
+ textHandle = 0;
+ if (imageHandle !=0 )OS.GCHandle_Free (imageHandle);
+ imageHandle = 0;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ text = null;
+ image = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Controls how text, images and arrows will be displayed
+ * in the receiver. The argument should be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is an <code>ARROW</code> button, in
+ * which case, the argument indicates the direction of
+ * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>UP</code> or <code>DOWN</code>).
+ *
+ * @param alignment the new alignment
+ *
+ * @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 setAlignment (int alignment) {
+ checkWidget ();
+ if ((style & SWT.ARROW) != 0) {
+ if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) == 0) return;
+ style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+ style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+ createArrow ();
+ return;
+ }
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ int value = OS.HorizontalAlignment_Left;
+ if ((style & SWT.CENTER) != 0) value = OS.HorizontalAlignment_Center;
+ if ((style & SWT.RIGHT) != 0) value = OS.HorizontalAlignment_Right;
+ OS.Control_HorizontalContentAlignment (handle, value);
+}
+
+/**
+ * Sets the grayed state of the receiver. This state change
+ * only applies if the control was created with the SWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed 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>
+ *
+ * @since 3.4
+ */
+public void setGrayed (boolean grayed) {
+ checkWidget ();
+ if ((style & SWT.CHECK) == 0) return;
+ boolean checked = getSelection();
+ this.grayed = grayed;
+ ignoreSelection = true;
+ if (checked){
+ if (grayed) {
+ OS.ToggleButton_IsCheckedNullSetter(handle);
+ } else {
+ OS.ToggleButton_IsChecked(handle, true);
+ }
+ }
+ setSelection (checked);
+ ignoreSelection = false;
+}
+
+void setDefault (boolean value) {
+ if ((style & SWT.PUSH) == 0) return;
+ OS.Button_IsDefault (handle, value);
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * <code>null</code> indicating that no image should be displayed.
+ * <p>
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX. On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ * </p>
+ * @param image the image to display on the receiver (may be <code>null</code>)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if ((style & SWT.ARROW) != 0) return;
+ this.image = image;
+ OS.Image_Source (imageHandle, image != null ? image.handle : 0);
+ OS.UIElement_Visibility (imageHandle, image != null ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ OS.UIElement_Visibility (textHandle, image != null && text.length () == 0 ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = image != null && text.length ()!= 0 ? 3 : 0;
+ int margin = OS.gcnew_Thickness (0, 0, spacing, 0);
+ if (margin == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+
+/**
+ * Sets the selection state of the receiver, if it is of type <code>CHECK</code>,
+ * <code>RADIO</code>, or <code>TOGGLE</code>.
+ *
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
+ * it is selected when it is pushed in.
+ *
+ * @param selected the new selection 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>
+ */
+public void setSelection (boolean selected) {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return;
+ ignoreSelection = true;
+ if ((style & SWT.CHECK) != 0 && grayed) {
+ OS.ToggleButton_IsCheckedNullSetter (handle);
+ } else {
+ OS.ToggleButton_IsChecked (handle, selected);
+ }
+ ignoreSelection = false;
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * This method sets the button label. The label may include
+ * the mnemonic character but must not contain line delimiters.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasized in a platform specific
+ * manner. The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p><p>
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX. On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ * </p>
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if ((style & SWT.ARROW) != 0) return;
+ if (string.equals (text)) return;
+ text = string;
+ int strPtr = createDotNetString (text, true);
+ if (strPtr == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.AccessText_Text (textHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ OS.UIElement_Visibility (textHandle, string.length () == 0 && image != null ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = image != null && text.length () != 0 ? 3 : 0;
+ int margin = OS.gcnew_Thickness (0, 0, spacing, 0);
+ if (margin == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+
+int traversalCode (int key, int event) {
+ int code = super.traversalCode (key, event);
+ if ((style & SWT.ARROW) != 0) code &= ~(SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS);
+ if ((style & SWT.RADIO) != 0) code |= SWT.TRAVERSE_ARROW_NEXT | SWT.TRAVERSE_ARROW_PREVIOUS;
+ return code;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Canvas.java
new file mode 100644
index 0000000000..d662b69410
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Canvas.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class provide a surface for drawing
+ * arbitrary graphics.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are <em>not</em> constructed
+ * from aggregates of other controls. That is, they are either
+ * painted using SWT graphics calls or are handled by native
+ * methods.
+ * </p>
+ *
+ * @see Composite
+ * @see <a href="http://www.eclipse.org/swt/snippets/#canvas">Canvas snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Canvas extends Composite {
+ Caret caret;
+ IME ime;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Canvas () {
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Canvas (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+void clearArea (int x, int y, int width, int height) {
+ checkWidget ();
+// if (OS.IsWindowVisible (handle)) {
+// RECT rect = new RECT ();
+// OS.SetRect (rect, x, y, x + width, y + height);
+// int hDC = OS.GetDCEx (handle, 0, OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS);
+// drawBackground (hDC, rect);
+// OS.ReleaseDC (handle, hDC);
+// }
+}
+
+/**
+ * Returns the caret.
+ * <p>
+ * The caret for the control is automatically hidden
+ * and shown when the control is painted or resized,
+ * when focus is gained or lost and when an the control
+ * is scrolled. To avoid drawing on top of the caret,
+ * the programmer must hide and show the caret when
+ * drawing in the window any other time.
+ * </p>
+ *
+ * @return the caret for the receiver, may be 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 Caret getCaret () {
+ checkWidget ();
+ return caret;
+}
+
+int getCaretHandle () {
+ if (caret != null && !caret.isDisposed()) {
+ return caret.handle;
+ }
+ return 0;
+}
+
+/**
+ * Returns the IME.
+ *
+ * @return the IME
+ *
+ * @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>
+ *
+ * @since 3.4
+ */
+public IME getIME () {
+ checkWidget ();
+ return ime;
+}
+
+void releaseChildren (boolean destroy) {
+ super.releaseChildren (destroy);
+ if (caret != null) {
+ caret.release (false);
+ caret = null;
+ }
+ if (ime != null) {
+ ime.release (false);
+ ime = null;
+ }
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * with the receiver's background.
+ *
+ * @param gc the gc where the rectangle is to be filled
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</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>
+ *
+ * @since 3.2
+ */
+public void drawBackground (GC gc, int x, int y, int width, int height) {
+ checkWidget ();
+ if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ Control control = findBackgroundControl ();
+ if (control != null) {
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ Point pt = display.map (this, control, 0, 0);
+ int transform = OS.gcnew_TranslateTransform (-pt.x, -pt.y);
+ OS.DrawingContext_PushTransform (gc.handle, transform);
+ x += pt.x;
+ y += pt.y;
+ int rect = OS.gcnew_Rect (x, y, width, height);
+ int backgroundHandle = control.backgroundHandle ();
+ int property = backgroundProperty ();
+ int brush = OS.DependencyObject_GetValue (backgroundHandle, property);
+ OS.GCHandle_Free (property);
+ OS.DrawingContext_DrawRectangle (gc.handle, brush, 0, rect);
+ OS.DrawingContext_Pop (gc.handle);
+ OS.GCHandle_Free (transform);
+ OS.GCHandle_Free (rect);
+ OS.GCHandle_Free (brush);
+ } else {
+ gc.fillRectangle (x, y, width, height);
+ }
+
+}
+
+/**
+ * Scrolls a rectangular area of the receiver by first copying
+ * the source area to the destination and then causing the area
+ * of the source which is not covered by the destination to
+ * be repainted. Children that intersect the rectangle are
+ * optionally moved during the operation. In addition, outstanding
+ * paint events are flushed before the source area is copied to
+ * ensure that the contents of the canvas are drawn correctly.
+ *
+ * @param destX the x coordinate of the destination
+ * @param destY the y coordinate of the destination
+ * @param x the x coordinate of the source
+ * @param y the y coordinate of the source
+ * @param width the width of the area
+ * @param height the height of the area
+ * @param all <code>true</code>if children should be scrolled, and <code>false</code> otherwise
+ *
+ * @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 scroll (int destX, int destY, int x, int y, int width, int height, boolean all) {
+ checkWidget ();
+// boolean isFocus = caret != null && caret.isFocusCaret ();
+// if (isFocus) caret.killFocus ();
+ //TODO
+ redraw (false);
+// if (isFocus) caret.setFocus ();
+}
+
+/**
+ * Sets the receiver's caret.
+ * <p>
+ * The caret for the control is automatically hidden
+ * and shown when the control is painted or resized,
+ * when focus is gained or lost and when an the control
+ * is scrolled. To avoid drawing on top of the caret,
+ * the programmer must hide and show the caret when
+ * drawing in the window any other time.
+ * </p>
+ * @param caret the new caret for the receiver, may be null
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the caret has been disposed</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 setCaret (Caret caret) {
+ checkWidget ();
+ if (caret != null && caret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ int children = OS.Panel_Children (handle);
+ if (this.caret != null) {
+ OS.UIElementCollection_Remove (children, this.caret.handle);
+ }
+ this.caret = caret;
+ if (caret != null) {
+ OS.UIElementCollection_Insert (children, 0, caret.handle);
+ if (hasFocus ()) caret.show ();
+ }
+ OS.GCHandle_Free (children);
+}
+
+public void setFont (Font font) {
+ checkWidget ();
+ if (caret != null) caret.setFont (font);
+ super.setFont (font);
+}
+
+/**
+ * Sets the receiver's IME.
+ *
+ * @param ime the new IME for the receiver, may be null
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the IME has been disposed</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>
+ *
+ * @since 3.4
+ */
+public void setIME (IME ime) {
+ checkWidget ();
+ if (ime != null && ime.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ this.ime = ime;
+}
+
+void HandlePreviewGotKeyboardFocus (int sender, int e) {
+ if (!checkEvent (e)) return;
+ super.HandlePreviewGotKeyboardFocus (sender, e);
+ if (caret != null) caret.show ();
+}
+
+void HandleLostKeyboardFocus (int sender, int e) {
+ if (!checkEvent (e)) return;
+ super.HandleLostKeyboardFocus (sender, e);
+ if (caret != null) caret.hide ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Caret.java
new file mode 100644
index 0000000000..f72e2b3cc1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Caret.java
@@ -0,0 +1,530 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class provide an i-beam that is typically used
+ * as the insertion point for text.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#caret">Caret snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Canvas tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Caret extends Widget {
+ Canvas parent;
+ int x, y, width, height;
+ int imageHandle;
+ boolean isVisible;
+ Image image;
+ Font font;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 Caret (Canvas parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ createWidget ();
+}
+
+void createWidget () {
+ createHandle ();
+ if (parent.getCaret () == null) {
+ parent.setCaret (this);
+ }
+}
+
+void createHandle() {
+ handle = OS.gcnew_StackPanel ();
+ //handle = OS.gcnew_ContentControl ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+
+ int animation = OS.gcnew_DoubleAnimationUsingKeyFrames ();
+ if (animation == 0) error (SWT.ERROR_NO_HANDLES);
+ int timespan = OS.gcnew_TimeSpan (6000000);
+ if (timespan == 0) error (SWT.ERROR_NO_HANDLES);
+ int duration = OS.gcnew_Duration (timespan);
+ if (duration == 0) error (SWT.ERROR_NO_HANDLES);
+ int repeatBehavior = OS.RepeatBehavior_Forever();
+
+ OS.Timeline_AutoReverse(animation, true);
+ OS.Timeline_Duration(animation, duration);
+ OS.Timeline_RepeatBehavior(animation, repeatBehavior);
+ int keyFrames = OS.DoubleAnimationUsingKeyFrames_KeyFrames(animation);
+ int keyTime = OS.KeyTime_Uniform();
+ int keyFrame0 = OS.gcnew_DiscreteDoubleKeyFrame(0, keyTime);
+ int keyFrame1 = OS.gcnew_DiscreteDoubleKeyFrame(0, keyTime);
+ OS.DoubleKeyFrameCollection_Add(keyFrames, keyFrame0);
+ OS.DoubleKeyFrameCollection_Add(keyFrames, keyFrame1);
+ int opacityProperty = OS.UIElement_OpacityProperty();
+ OS.UIElement_BeginAnimation(handle, opacityProperty, animation);
+
+ int brush = OS.SystemColors_ControlTextBrush ();
+ OS.Panel_Background(handle, brush);
+
+ imageHandle = OS.gcnew_Image ();
+ if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+
+ int children = OS.Panel_Children (handle);
+ OS.UIElementCollection_Add (children, imageHandle);
+ OS.GCHandle_Free (children);
+ hide ();
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(opacityProperty);
+ OS.GCHandle_Free(keyFrames);
+ OS.GCHandle_Free(keyTime);
+ OS.GCHandle_Free(keyFrame0);
+ OS.GCHandle_Free(keyFrame1);
+ OS.GCHandle_Free(animation);
+ OS.GCHandle_Free(duration);
+ OS.GCHandle_Free(timespan);
+ OS.GCHandle_Free(repeatBehavior);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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 Rectangle getBounds () {
+ checkWidget();
+ if (image != null) {
+ Rectangle rect = image.getBounds ();
+ return new Rectangle (x, y, rect.width, rect.height);
+ }
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @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 Font getFont () {
+ checkWidget();
+ if (font == null) {
+ return parent.display.systemFont;
+ }
+ return font;
+}
+
+/**
+ * Returns the image that the receiver will use to paint the caret.
+ *
+ * @return the receiver's 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;
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's location
+ *
+ * @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 Point getLocation () {
+ checkWidget();
+ return new Point (x, y);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Canvas</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Canvas getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns a point describing the receiver's size.
+ *
+ * @return the receiver's size
+ *
+ * @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 Point getSize () {
+ checkWidget();
+ if (image != null) {
+ Rectangle rect = image.getBounds ();
+ return new Point (rect.width, rect.height);
+ }
+ return new Point (width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible, and
+ * <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's visibility 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>
+ */
+public boolean getVisible () {
+ checkWidget ();
+ return isVisible;
+}
+
+boolean hasFocus () {
+ return OS.UIElement_IsKeyboardFocused (parent.handle);
+}
+
+boolean isFocusCaret () {
+ return parent.caret == this && hasFocus ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility 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 #getVisible
+ */
+public boolean isVisible () {
+ checkWidget();
+ return OS.UIElement_IsVisible (handle) && parent.isVisible () && hasFocus ();
+}
+
+void hide () {
+ OS.UIElement_Visibility (handle, OS.Visibility_Collapsed);
+}
+
+void move (int x, int y) {
+ OS.Canvas_SetLeft (handle, x);
+ OS.Canvas_SetTop (handle, y);
+}
+
+void releaseHandle() {
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ if (imageHandle != 0) OS.GCHandle_Free (imageHandle);
+ imageHandle = 0;
+ super.releaseHandle ();
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (this == parent.getCaret ()) parent.setCaret (null);
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ parent = null;
+ image = null;
+ font = null;
+}
+
+void resize (int width, int height) {
+ if (image != null) {
+ Rectangle rect = image.getBounds();
+ width = rect.width;
+ height = rect.height;
+ }
+ if (width == 0) width = 1;
+ OS.FrameworkElement_Width (handle, width);
+ OS.FrameworkElement_Height (handle, height);
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The <code>x</code> and
+ * <code>y</code> arguments are relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @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 setBounds (int x, int y, int width, int height) {
+ checkWidget();
+ boolean samePosition = this.x == x && this.y == y;
+ boolean sameExtent = this.width == width && this.height == height;
+ if (samePosition && sameExtent) return;
+ this.x = x; this.y = y;
+ this.width = width; this.height = height;
+ if (!sameExtent) resize (width, height);
+ if (!samePosition) move (x, y);
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The <code>x</code> and
+ * <code>y</code> fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @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 setBounds (Rectangle rect) {
+ if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+void show () {
+ OS.UIElement_Visibility (handle, OS.Visibility_Visible);
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * to the font specified by the argument, or to the default font for that
+ * kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</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 setFont (Font font) {
+ checkWidget();
+ if (font != null && font.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.font = font;
+}
+
+/**
+ * Sets the image that the receiver will use to paint the caret
+ * to the image specified by the argument, or to the default
+ * which is a filled rectangle if the argument is null
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.image = image;
+ if (image != null) {
+ OS.Image_Source (imageHandle, image.handle);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Visible);
+ } else {
+ OS.Image_Source (imageHandle, 0);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+ }
+ resize (width, height);
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @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 setLocation (int x, int y) {
+ checkWidget();
+ if (this.x == x && this.y == y) return;
+ this.x = x; this.y = y;
+ move (x, y);
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the argument which is relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param location the new location for the receiver
+ *
+ * @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 setLocation (Point location) {
+ checkWidget();
+ if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @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 setSize (int width, int height) {
+ checkWidget();
+ if (this.width == width && this.height == height) return;
+ this.width = width; this.height = height;
+ resize (width, height);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ *
+ * @param size the new extent for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setSize (Point size) {
+ checkWidget();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+/**
+ * Marks the receiver as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility 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>
+ */
+public void setVisible (boolean visible) {
+ checkWidget();
+ if (visible == isVisible) return;
+ isVisible = visible;
+ if (!hasFocus()) return;
+ OS.UIElement_Visibility(handle, visible ? OS.Visibility_Visible : OS.Visibility_Hidden);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ColorDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ColorDialog.java
new file mode 100644
index 0000000000..a67b2415de
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ColorDialog.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class allow the user to select a color
+ * from a predefined set of available colors.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class ColorDialog extends Dialog {
+ RGB rgb;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a composite control which will be the parent of the new instance
+ *
+ * @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 ColorDialog (Shell parent) {
+ this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 ColorDialog (Shell parent, int style) {
+ super (parent, checkStyle (parent, style));
+ checkSubclass ();
+}
+
+/**
+ * Returns the currently selected color in the receiver.
+ *
+ * @return the RGB value for the selected color, may be null
+ *
+ * @see PaletteData#getRGBs
+ */
+public RGB getRGB () {
+ return rgb;
+}
+
+/**
+ * Makes the receiver visible and brings it to the front
+ * of the display.
+ *
+ * @return the selected color, or null if the dialog was
+ * cancelled, no color was selected, or an error
+ * occurred
+ *
+ * @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 RGB open () {
+ int dialog = OS.gcnew_ColorDialog ();
+ if (rgb != null) {
+ int color = OS.DrawingColor_FromArgb (174, rgb.red, rgb.blue, rgb.green);
+ OS.ColorDialog_Color (dialog, color);
+ OS.GCHandle_Free (color);
+ }
+ Display display = parent.getDisplay ();
+ int customColors = display.customColors;
+ OS.ColorDialog_AnyColor (dialog, true);
+ OS.ColorDialog_CustomColors (dialog, customColors);
+ int result = OS.FormsCommonDialog_ShowDialog (dialog);
+ RGB rgb = null;
+ if (result == OS.DialogResult_OK) {
+ int color = OS.ColorDialog_Color (dialog);
+ int argb = OS.DrawingColor_ToArgb (color);
+ int red = (argb & 0xFF0000) >> 16;
+ int green = (argb & 0xFF00) >> 8;
+ int blue = argb & 0xFF;
+ OS.GCHandle_Free (color);
+ rgb = new RGB (red, green, blue);
+ if (customColors != 0) OS.GCHandle_Free (customColors);
+ display.customColors = OS.ColorDialog_CustomColors (dialog);
+ }
+ OS.GCHandle_Free (dialog);
+ return rgb;
+}
+
+/**
+ * Sets the receiver's selected color to be the argument.
+ *
+ * @param rgb the new RGB value for the selected color, may be
+ * null to let the platform select a default when
+ * open() is called
+ * @see PaletteData#getRGBs
+ */
+public void setRGB (RGB rgb) {
+ this.rgb = rgb;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Combo.java
new file mode 100644
index 0000000000..796bce5b02
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Combo.java
@@ -0,0 +1,1424 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.wpf.OS;
+
+/**
+ * Instances of this class are controls that allow the user
+ * to choose an item from a list of items, or optionally
+ * enter a new value by typing it into an editable text
+ * field. Often, <code>Combo</code>s are used in the same place
+ * where a single selection <code>List</code> widget could
+ * be used but space is limited. A <code>Combo</code> takes
+ * less space than a <code>List</code> widget and shows
+ * similar information.
+ * <p>
+ * Note: Since <code>Combo</code>s can contain both a list
+ * and an editable text field, it is possible to confuse methods
+ * which access one versus the other (compare for example,
+ * <code>clearSelection()</code> and <code>deselectAll()</code>).
+ * The API documentation is careful to indicate either "the
+ * receiver's list" or the "the receiver's text field" to
+ * distinguish between the two cases.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>DROP_DOWN, READ_ONLY, SIMPLE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, Modify, Selection, Verify</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see List
+ * @see <a href="http://www.eclipse.org/swt/snippets/#combo">Combo snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Combo extends Composite {
+ int textHandle;
+ boolean ignoreSelection;
+
+ /**
+ * the operating system limit for the number of characters
+ * that the text field in an instance of this class can hold
+ */
+ public static final int LIMIT;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ static {
+ LIMIT = 0x7FFFFFFF;
+ }
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#DROP_DOWN
+ * @see SWT#READ_ONLY
+ * @see SWT#SIMPLE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Combo (Composite parent, int style) {
+ super (parent, checkStyle (style));
+ /* This code is intentionally commented */
+ //if ((style & SWT.H_SCROLL) != 0) this.style |= SWT.H_SCROLL;
+ this.style |= SWT.H_SCROLL;
+}
+
+Control [] _getChildren () {
+ return new Control [0];
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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>
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int itemHandle = OS.gcnew_ComboBoxItem ();
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content (itemHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int itemCollection = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Add (itemCollection, itemHandle);
+ OS.GCHandle_Free (itemCollection);
+ OS.GCHandle_Free (itemHandle);
+}
+
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ * <p>
+ * Note: To add an item at the end of the list, use the
+ * result of calling <code>getItemCount()</code> as the
+ * index or use <code>add(String)</code>.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</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>
+ *
+ * @see #add(String)
+ */
+public void add (String string, int index) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (index < 0) error (SWT.ERROR_INVALID_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (index > count) error (SWT.ERROR_INVALID_ARGUMENT);
+ int itemHandle = OS.gcnew_ComboBoxItem ();
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content (itemHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int itemCollection = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (itemCollection, index, itemHandle);
+ OS.GCHandle_Free (itemCollection);
+ OS.GCHandle_Free (itemHandle);
+}
+
+void addChild (Control control) {
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the combo's list selection.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #removeVerifyListener
+ *
+ * @since 3.1
+ */
+public void addVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+void addWidget () {
+ super.addWidget ();
+ if ((style & SWT.READ_ONLY) == 0) {
+ updateLayout (handle);
+ int name = createDotNetString ("PART_EditableTextBox", false);
+ int template = OS.Control_Template (handle);
+ textHandle = OS.FrameworkTemplate_FindName (template, name, handle);
+ OS.GCHandle_Free (name);
+ OS.GCHandle_Free (template);
+ }
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ /*
+ * Feature in Windows. It is not possible to create
+ * a combo box that has a border using Windows style
+ * bits. All combo boxes draw their own border and
+ * do not use the standard Windows border styles.
+ * Therefore, no matter what style bits are specified,
+ * clear the BORDER bits so that the SWT style will
+ * match the Windows widget.
+ *
+ * The Windows behavior is currently implemented on
+ * all platforms.
+ */
+ style &= ~SWT.BORDER;
+
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
+ style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
+ if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY;
+ return style;
+}
+
+/**
+ * Sets the selection in the receiver's text field to an empty
+ * selection starting just before the first character. If the
+ * text field is editable, this has the effect of placing the
+ * i-beam at the start of the text.
+ * <p>
+ * Note: To clear the selected items in the receiver's list,
+ * use <code>deselectAll()</code>.
+ * </p>
+ *
+ * @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 #deselectAll
+ */
+public void clearSelection () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) == 0) {
+ OS.TextBox_Select (textHandle, 0, 0);
+ }
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ ignoreSelection = true;
+ int itemCount = getItemCount();
+ int text = 0;
+ if (textHandle != 0) {
+ text = OS.TextBox_Text (textHandle);
+ }
+ int selectedIndex = OS.Selector_SelectedIndex (handle);
+ int width = wHint, height = hHint;
+ if (wHint == SWT.DEFAULT) width = 0x7FFFFFFF;
+ if (hHint == SWT.DEFAULT) height = 0x7FFFFFFF;
+ width = Math.max (0, width);
+ height = Math.max (0, height);
+ int availSize = OS.gcnew_Size ((double) width, (double) height);
+ if (availSize == 0) error (SWT.ERROR_NO_HANDLES);
+ double requestWidth = OS.FrameworkElement_Width (handle);
+ double requestHeight = OS.FrameworkElement_Height (handle);
+ int widthDP = OS.FrameworkElement_WidthProperty ();
+ int heightDP = OS.FrameworkElement_HeightProperty ();
+ OS.DependencyObject_ClearValue (handle, widthDP);
+ OS.DependencyObject_ClearValue (handle, heightDP);
+ OS.UIElement_Measure (handle, availSize);
+ int size = OS.UIElement_DesiredSize (handle);
+ width = (int) OS.Size_Width (size);
+ height = (int) OS.Size_Height (size);
+ OS.GCHandle_Free (size);
+ for (int i = 0; i < itemCount; i++) {
+ OS.Selector_SelectedIndex (handle, i);
+ updateLayout (handle);
+ OS.UIElement_Measure (handle, availSize);
+ size = OS.UIElement_DesiredSize (handle);
+ width = Math.max (width, (int) OS.Size_Width (size));
+ height = Math.max (height, (int) OS.Size_Height (size));
+ OS.GCHandle_Free (size);
+ }
+ OS.GCHandle_Free (availSize);
+ OS.FrameworkElement_Width (handle, requestWidth);
+ OS.FrameworkElement_Height (handle, requestHeight);
+ OS.Selector_SelectedIndex (handle, selectedIndex);
+ if (textHandle != 0) {
+ OS.TextBox_Text (textHandle, text);
+ OS.GCHandle_Free (text);
+ }
+ OS.GCHandle_Free (widthDP);
+ OS.GCHandle_Free (heightDP);
+ if (wHint != SWT.DEFAULT) width = wHint;
+ if (hHint != SWT.DEFAULT) height = hHint;
+ ignoreSelection = false;
+ return new Point (width, height);
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public void copy () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return; //TODO
+ OS.TextBoxBase_Copy (textHandle);
+}
+
+void createHandle () {
+ handle = OS.gcnew_ComboBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.READ_ONLY) == 0) {
+ OS.ComboBox_IsEditable (handle, true);
+ OS.ItemsControl_IsTextSearchEnabled (handle, false);
+ }
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public void cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ OS.TextBoxBase_Cut (textHandle);
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @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 deselect (int index) {
+ checkWidget ();
+ ignoreSelection = true;
+ int selected = OS.Selector_SelectedIndex (handle);
+ if (selected == index) OS.Selector_SelectedIndex (handle, -1);
+ ignoreSelection = false;
+// FIXME: May need to send modify event here.
+// if ((style & SWT.READ_ONLY) == 0) {
+// sendEvent (SWT.Modify);
+// }
+}
+
+/**
+ * Deselects all selected items in the receiver's list.
+ * <p>
+ * Note: To clear the selection in the receiver's text field,
+ * use <code>clearSelection()</code>.
+ * </p>
+ *
+ * @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 #clearSelection
+ */
+public void deselectAll () {
+ checkWidget ();
+ ignoreSelection = true;
+ OS.Selector_SelectedIndex (handle, -1);
+ ignoreSelection = false;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver's list. Throws an exception if the index is out
+ * of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 String getItem (int index) {
+ checkWidget ();
+ int count = getItemCount ();
+ if (index < 0 || index >= count) error (SWT.ERROR_INVALID_RANGE);
+ int itemCollection = OS.ItemsControl_Items (handle);
+ int comboBoxItem = OS.ItemCollection_GetItemAt (itemCollection, index);
+ OS.GCHandle_Free (itemCollection);
+ int content = OS.ContentControl_Content (comboBoxItem);
+ String string = createJavaString(content);
+ OS.GCHandle_Free (comboBoxItem);
+ OS.GCHandle_Free (content);
+ return string;
+}
+
+/**
+ * Returns the number of items contained in the receiver's list.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ int itemCollection = OS.ItemsControl_Items (handle);
+ int count = OS.ItemCollection_Count (itemCollection);
+ OS.GCHandle_Free (itemCollection);
+ return count;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the receiver's list.
+ *
+ * @return the height of one item
+ *
+ * @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 int getItemHeight () {
+ checkWidget ();
+ //todo
+ int result = 0;
+// if (result == OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+ return result;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>String</code>s which are
+ * the items in the receiver's list.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @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 [] getItems () {
+ checkWidget ();
+ int count = getItemCount ();
+ String [] result = new String [count];
+ for (int i=0; i<count; i++) result [i] = getItem (i);
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's list is visible,
+ * and <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's list's visibility 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>
+ *
+ * @since 3.4
+ */
+public boolean getListVisible () {
+ checkWidget ();
+ return OS.ComboBox_IsDropDownOpen (handle);
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @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>
+ *
+ * @since 2.1.2
+ */
+public int getOrientation () {
+ checkWidget ();
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns a <code>Point</code> whose x coordinate is the
+ * character position representing the start of the selection
+ * in the receiver's text field, and whose y coordinate is the
+ * character position representing the end of the selection.
+ * An "empty" selection is indicated by the x and y coordinates
+ * having the same value.
+ * <p>
+ * Indexing is zero based. The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ * </p>
+ *
+ * @return a point representing the selection start and end
+ *
+ * @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 Point getSelection () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return new Point (0,0);
+ int start = OS.TextBox_SelectionStart (textHandle);
+ int length = OS.TextBox_SelectionLength (textHandle);
+ return new Point (start, start + length);
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver's list, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @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 int getSelectionIndex () {
+ checkWidget ();
+ return OS.Selector_SelectedIndex (handle);
+}
+
+/**
+ * Returns a string containing a copy of the contents of the
+ * receiver's text field, or an empty string if there are no
+ * contents.
+ *
+ * @return the receiver's 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 ();
+ String text;
+ if ((style & SWT.READ_ONLY) != 0) {
+ int item = OS.ComboBox_SelectionBoxItem (handle);
+ text = createJavaString (item);
+ OS.GCHandle_Free (item);
+ } else {
+ int content = OS.TextBox_Text (textHandle);
+ text = createJavaString (content);
+ OS.GCHandle_Free (content);
+ }
+ return text;
+}
+
+/**
+ * Returns the height of the receivers's text field.
+ *
+ * @return the text height
+ *
+ * @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 int getTextHeight () {
+ checkWidget ();
+ if (textHandle != 0) {
+ return (int) OS.FrameworkElement_ActualHeight(textHandle);
+ }
+ return 0;
+}
+
+/**
+ * Returns the maximum number of characters that the receiver's
+ * text field is capable of holding. If this has not been changed
+ * by <code>setTextLimit()</code>, it will be the constant
+ * <code>Combo.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @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 #LIMIT
+ */
+public int getTextLimit () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return LIMIT;
+ return OS.TextBox_MaxLength (textHandle);
+}
+
+/**
+ * Gets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @return the number of items that are visible
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public int getVisibleItemCount () {
+ checkWidget ();
+ return 0;
+}
+
+void HandleSelectionChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (!ignoreSelection) postEvent (SWT.Selection);
+}
+
+void HandlePreviewExecutedRoutedEvent (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int command = OS.ExecutedRoutedEventArgs_Command (e);
+ boolean doVerify = false;
+ String input = null;
+ int paste = OS.ApplicationCommands_Paste ();
+ int cut = OS.ApplicationCommands_Cut ();
+ int redo = OS.ApplicationCommands_Redo ();
+ int undo = OS.ApplicationCommands_Undo ();
+ int backspace = OS.EditingCommands_Backspace ();
+ int delete = OS.EditingCommands_Delete ();
+ int deleteNext = OS.EditingCommands_DeleteNextWord ();
+ int deletePrevious = OS.EditingCommands_DeletePreviousWord ();
+ if (OS.Object_Equals (command, paste)) {
+ doVerify = true;
+ int clipboardText = OS.Clipboard_GetText ();
+ input = createJavaString(clipboardText);
+ OS.GCHandle_Free(clipboardText);
+ } else if (OS.Object_Equals (command, cut)){
+ doVerify = true;
+ int content = OS.TextBox_SelectedText (textHandle);
+ input = createJavaString (content);
+ OS.GCHandle_Free (content);
+ } else if (OS.Object_Equals(command, redo)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals(command, undo)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals (command, backspace)) {
+ doVerify = true;
+ input = "";
+ } else if (OS.Object_Equals (command, delete)) {
+ doVerify = true;
+ input = "";
+ } else if (OS.Object_Equals(command, deleteNext)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals(command, deletePrevious)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ }
+ OS.GCHandle_Free (paste);
+ OS.GCHandle_Free (cut);
+ OS.GCHandle_Free (redo);
+ OS.GCHandle_Free (undo);
+ OS.GCHandle_Free (backspace);
+ OS.GCHandle_Free (delete);
+ OS.GCHandle_Free (deleteNext);
+ OS.GCHandle_Free (deletePrevious);
+ OS.GCHandle_Free(command);
+ /*
+ * FIXME - should do this first, but for now we want to swallow
+ * all Redo, Undo, DeleteNextWord and DeletePreviousWord to
+ * prevent those from changing the TextBox w/o Verify events
+ */
+ if (!hooks (SWT.Verify)) return;
+ if (!doVerify) return;
+ String text = verifyText (input);
+ if (text != null && !text.equals (input)) {
+ int strPtr = createDotNetString (text, false);
+ OS.TextBox_SelectedText (textHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int start = OS.TextBox_SelectionStart (textHandle);
+ int length = OS.TextBox_SelectionLength (textHandle);
+ OS.TextBox_Select (textHandle, start+length, 0);
+ OS.TextBox_SelectionLength (textHandle, 0);
+ text = null;
+ }
+ if (text == null) OS.ExecutedRoutedEventArgs_Handled (e, true);
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_Return) postEvent (SWT.DefaultSelection);
+}
+
+void HandlePreviewTextInput (int sender, int e) {
+ super.HandlePreviewTextInput (sender, e);
+ if (!checkEvent (e)) return;
+ int textPtr = OS.TextCompositionEventArgs_Text (e);
+ String input = createJavaString(textPtr);
+ OS.GCHandle_Free (textPtr);
+ String text = verifyText (input);
+ if (text != null && !text.equals (input)) {
+ textPtr = createDotNetString (text, false);
+ OS.TextBox_SelectedText (textHandle, textPtr);
+ OS.GCHandle_Free (textPtr);
+ int start = OS.TextBox_SelectionStart (textHandle);
+ int length = OS.TextBox_SelectionLength (textHandle);
+ OS.TextBox_Select (textHandle, start+length, 0);
+ OS.TextBox_SelectionLength (textHandle, 0);
+ text = null;
+ }
+ if (text == null) OS.TextCompositionEventArgs_Handled (e, true);
+}
+
+void HandleTextChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Modify);
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ int handler = OS.gcnew_SelectionChangedEventHandler (jniRef, "HandleSelectionChanged");
+ OS.Selector_SelectionChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+ if (textHandle != 0) {
+ handler = OS.gcnew_ExecutedRoutedEventHandler (jniRef, "HandlePreviewExecutedRoutedEvent");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.CommandManager_AddPreviewExecutedHandler (textHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_TextChangedEventHandler (jniRef, "HandleTextChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.TextBoxBase_TextChanged (textHandle, handler);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 int indexOf (String string) {
+ return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to begin the search
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 int indexOf (String string, int start) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount ();
+ if (start < 0 || start >= count) return -1;
+ start = Math.max (start, 0);
+ int strPtr = createDotNetString (string, false);
+ int itemCollection = OS.ItemsControl_Items (handle);
+ int index = -1;
+ while (start < count && index == -1) {
+ int item = OS.ItemCollection_GetItemAt (itemCollection, start);
+ int itemContent = OS.ContentControl_Content (item);
+ OS.GCHandle_Free (item);
+ if (itemContent != 0 && OS.Object_Equals (itemContent, strPtr)) index = start;
+ OS.GCHandle_Free (itemContent);
+ start ++;
+ }
+ OS.GCHandle_Free (strPtr);
+ OS.GCHandle_Free (itemCollection);
+ return index;
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public void paste () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ OS.TextBoxBase_Paste (textHandle);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (textHandle != 0) OS.GCHandle_Free (textHandle);
+ textHandle = 0;
+}
+/**
+ * Removes the item from the receiver's list at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int index) {
+ checkWidget ();
+ if (index < 0 || index >= getItemCount ()) error (SWT.ERROR_INVALID_RANGE);
+ int itemCollection = OS.ItemsControl_Items(handle);
+ OS.ItemCollection_RemoveAt(itemCollection, index);
+ OS.GCHandle_Free(itemCollection);
+}
+
+/**
+ * Removes the items from the receiver's list which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int start, int end) {
+ checkWidget ();
+ int count = getItemCount ();
+ if (start < 0 || start >= count) error (SWT.ERROR_INVALID_RANGE);
+ if (end < 0 || end >= count) error (SWT.ERROR_INVALID_RANGE);
+ int itemCollection = OS.ItemsControl_Items(handle);
+ for (int i = end; i >= start; i--) {
+ OS.ItemCollection_RemoveAt(itemCollection, i);
+ }
+ OS.GCHandle_Free(itemCollection);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</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 remove (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = indexOf (string, 0);
+ if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver's list and clear the
+ * contents of receiver's text field.
+ * <p>
+ * @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 removeAll () {
+ checkWidget ();
+ int itemCollection = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ OS.ItemCollection_Clear (itemCollection);
+ ignoreSelection = false;
+ OS.GCHandle_Free (itemCollection);
+}
+
+void removeChild(Control control) {
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ *
+ * @since 3.1
+ */
+public void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 select (int index) {
+ checkWidget ();
+ int itemCollection = OS.ItemsControl_Items(handle);
+ int count = OS.ItemCollection_Count(itemCollection);
+ OS.GCHandle_Free(itemCollection);
+ if (0 <= index && index < count) {
+// int selection = OS.Selector_SelectedIndex (handle);
+ ignoreSelection = true;
+ OS.Selector_SelectedIndex(handle, index);
+ ignoreSelection = false;
+// int code = OS.Selector_SelectedIndex(handle);
+// if (code != -1 && code != selection) {
+// sendEvent (SWT.Modify);
+// }
+ }
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 setItem (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (index < 0 || index >= getItemCount()) error (SWT.ERROR_INVALID_RANGE);
+ int itemCollection = OS.ItemsControl_Items(handle);
+ int item = OS.ItemCollection_GetItemAt(itemCollection, index);
+ OS.GCHandle_Free(itemCollection);
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content(item, strPtr);
+ OS.GCHandle_Free(strPtr);
+ OS.GCHandle_Free(item);
+}
+
+/**
+ * Sets the receiver's list to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if an item in the items array 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 setItems (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<items.length; i++) {
+ if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int itemCollection = OS.ItemsControl_Items(handle);
+ ignoreSelection = true;
+ OS.ItemCollection_Clear(itemCollection);
+ for (int i = 0; i < items.length; i++) {
+ int itemHandle = OS.gcnew_ComboBoxItem ();
+ int strPtr = createDotNetString (items [i], false);
+ OS.ContentControl_Content (itemHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ OS.ItemCollection_Add (itemCollection, itemHandle);
+ OS.GCHandle_Free (itemHandle);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free(itemCollection);
+}
+
+/**
+ * Marks the receiver's list as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility 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>
+ *
+ * @since 3.4
+ */
+public void setListVisible (boolean visible) {
+ checkWidget ();
+ OS.ComboBox_IsDropDownOpen (handle, visible);
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ * <p>
+ *
+ * @param orientation new orientation style
+ *
+ * @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>
+ *
+ * @since 2.1.2
+ */
+public void setOrientation (int orientation) {
+ checkWidget();
+ int flowDirection = orientation == SWT.RIGHT_TO_LEFT ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ OS.FrameworkElement_FlowDirection (handle, flowDirection);
+}
+
+/**
+ * Sets the selection in the receiver's text field to the
+ * range specified by the argument whose x coordinate is the
+ * start of the selection and whose y coordinate is the end
+ * of the selection.
+ *
+ * @param selection a point representing the new selection start and end
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setSelection (Point selection) {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int start = selection.x, length = selection.y - selection.x;
+ OS.TextBox_SelectionLength (textHandle, length);
+ OS.TextBox_SelectionStart (textHandle, start);
+}
+
+/**
+ * Sets the contents of the receiver's text field to the
+ * given string.
+ * <p>
+ * This call is ignored when the receiver is read only and
+ * the given string is not in the receiver's list.
+ * </p>
+ * <p>
+ * Note: The text field in a <code>Combo</code> is typically
+ * only capable of displaying a single line of text. Thus,
+ * setting the text to a string containing line breaks or
+ * other special characters will probably cause it to
+ * display incorrectly.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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);
+ if ((style & SWT.READ_ONLY) != 0) {
+ int index = indexOf (string);
+ if (index != -1) select (index);
+ return;
+ }
+ int strPtr = createDotNetString (string, false);
+ OS.TextBox_Text (textHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * Sets the maximum number of characters that the receiver's
+ * text field is capable of holding to be the argument.
+ * <p>
+ * To reset this value to the default, use <code>setTextLimit(Combo.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Combo.LIMIT</code> sets the
+ * receiver's limit to <code>Combo.LIMIT</code>.
+ * </p>
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</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>
+ *
+ * @see #LIMIT
+ */
+public void setTextLimit (int limit) {
+ checkWidget ();
+ if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+ if ((style & SWT.READ_ONLY) != 0) return;
+ OS.TextBox_MaxLength (textHandle, limit);
+}
+
+/**
+ * Sets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param count the new number of items to be visible
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void setVisibleItemCount (int count) {
+ checkWidget ();
+ return;
+}
+
+String verifyText (String text) {
+ int start = OS.TextBox_SelectionStart (textHandle);
+ int length = OS.TextBox_SelectionLength (textHandle);
+ Event event = new Event ();
+ event.text = text;
+ event.start = start;
+ /*
+ * FIXME: end can be greater than start+length+1
+ * when Deleting special characters.
+ * Note that backspace deletes one character at
+ * a time.
+ */
+ event.end = start+length+1;
+ sendEvent (SWT.Verify, event);
+ if (!event.doit) return null;
+ return event.text;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Composite.java
new file mode 100644
index 0000000000..e7e27d2c5f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Composite.java
@@ -0,0 +1,1157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class are controls which are capable
+ * of containing other controls.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
+ * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
+ * They can be used with <code>Composite</code> if you are drawing your own, but their
+ * behavior is undefined if they are used with subclasses of <code>Composite</code> other
+ * than <code>Canvas</code>.
+ * </p><p>
+ * Note: The <code>CENTER</code> style, although undefined for composites, has the
+ * same value as <code>EMBEDDED</code> which is used to embed widgets from other
+ * widget toolkits into SWT. On some operating systems (GTK, Motif), this may cause
+ * the children of this composite to be obscured.
+ * </p><p>
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are constructed from aggregates
+ * of other controls.
+ * </p>
+ *
+ * @see Canvas
+ * @see <a href="http://www.eclipse.org/swt/snippets/#composite">Composite snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Composite extends Scrollable {
+ Layout layout;
+ Control [] tabList;
+ int layoutCount, backgroundMode;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Composite () {
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget 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>
+ * </ul>
+ *
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_FOCUS
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_RADIO_GROUP
+ * @see SWT#EMBEDDED
+ * @see SWT#DOUBLE_BUFFERED
+ * @see Widget#getStyle
+ */
+public Composite (Composite parent, int style) {
+ super (parent, style);
+}
+
+static int checkStyle (int style) {
+ style &= ~SWT.TRANSPARENT;
+ return style;
+}
+
+int getCaretHandle () {
+ return 0;
+}
+
+Control [] _getChildren () {
+ int parentHandle = parentingHandle ();
+ int elements = OS.Panel_Children (parentHandle);
+ int count = OS.UIElementCollection_Count (elements);
+ int caretHandle = getCaretHandle ();
+ if (caretHandle != 0) count--;
+ Control [] children = new Control [count];
+ int index = count - 1;
+ if (count != 0) {
+ int enumerator = OS.UIElementCollection_GetEnumerator (elements);
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int current = OS.UIElementCollection_Current (enumerator);
+ if (caretHandle != 0 && OS.Object_Equals(caretHandle, current)) {
+ OS.GCHandle_Free (current);
+ continue;
+ }
+ Widget widget = display.getWidget (current);
+ if (widget != null && widget != this) {
+ if (widget instanceof Control) {
+ children [index--] = (Control)widget;
+ }
+ }
+ OS.GCHandle_Free (current);
+ }
+ OS.GCHandle_Free (enumerator);
+ }
+ OS.GCHandle_Free (elements);
+ if (index == -1) return children;
+ Control [] newChildren = new Control [count - index - 1];
+ System.arraycopy (children, index + 1, newChildren, 0, newChildren.length);
+ return newChildren;
+}
+
+Control [] _getTabList () {
+ if (tabList == null) return tabList;
+ int count = 0;
+ for (int i=0; i<tabList.length; i++) {
+ if (!tabList [i].isDisposed ()) count++;
+ }
+ if (count == tabList.length) return tabList;
+ Control [] newList = new Control [count];
+ int index = 0;
+ for (int i=0; i<tabList.length; i++) {
+ if (!tabList [i].isDisposed ()) {
+ newList [index++] = tabList [i];
+ }
+ }
+ tabList = newList;
+ return tabList;
+}
+
+void addChild (Control control) {
+ int parentHandle = parentingHandle ();
+ int children = OS.Panel_Children (parentHandle);
+ int index = 0;
+ if (parentHandle != handle) {
+ if (OS.UIElementCollection_Contains (children, handle)) {
+ index = 1;
+ }
+ }
+ int topHandle = control.topHandle ();
+ OS.UIElementCollection_Insert (children, index, topHandle);
+ OS.GCHandle_Free (children);
+ OS.FrameworkElement_Width (topHandle, 0);
+ OS.FrameworkElement_Height (topHandle, 0);
+}
+
+int backgoundProperty () {
+ return OS.Panel_BackgroundProperty();
+}
+
+/**
+ * Clears any data that has been cached by a Layout for all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver. If an ancestor does not have a layout, it is skipped.
+ *
+ * @param changed an array of controls that changed state and require a recalculation of size
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</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>
+ *
+ * @since 3.1
+ */
+public void changed (Control[] changed) {
+ checkWidget ();
+ if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i<changed.length; i++) {
+ Control control = changed [i];
+ if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ boolean ancestor = false;
+ Composite composite = control.parent;
+ while (composite != null) {
+ ancestor = composite == this;
+ if (ancestor) break;
+ composite = composite.parent;
+ }
+ if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
+ }
+ for (int i=0; i<changed.length; i++) {
+ Control child = changed [i];
+ Composite composite = child.parent;
+ while (child != this) {
+ if (composite.layout == null || !composite.layout.flushCache (child)) {
+ composite.state |= LAYOUT_CHANGED;
+ }
+ child = composite;
+ composite = child.parent;
+ }
+ }
+}
+
+protected void checkSubclass () {
+ /* Do nothing - Subclassing is allowed */
+}
+
+Control [] computeTabList () {
+ Control result [] = super.computeTabList ();
+ if (result.length == 0) return result;
+ Control [] list = tabList != null ? _getTabList () : _getChildren ();
+ for (int i=0; i<list.length; i++) {
+ Control child = list [i];
+ Control [] childList = child.computeTabList ();
+ if (childList.length != 0) {
+ Control [] newResult = new Control [result.length + childList.length];
+ System.arraycopy (result, 0, newResult, 0, result.length);
+ System.arraycopy (childList, 0, newResult, result.length, childList.length);
+ result = newResult;
+ }
+ }
+ return result;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ Point size;
+ if (layout != null) {
+ if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+ changed |= (state & LAYOUT_CHANGED) != 0;
+ state &= ~LAYOUT_CHANGED;
+ size = layout.computeSize (this, wHint, hHint, changed);
+ } else {
+ size = new Point (wHint, hHint);
+ }
+ } else {
+ size = minimumSize (wHint, hHint, changed);
+ }
+ if (size.x == 0) size.x = DEFAULT_WIDTH;
+ if (size.y == 0) size.y = DEFAULT_HEIGHT;
+ if (wHint != SWT.DEFAULT) size.x = wHint;
+ if (hHint != SWT.DEFAULT) size.y = hHint;
+ Rectangle trim = computeTrim (0, 0, size.x, size.y);
+ return new Point (trim.width, trim.height);
+}
+
+void createHandle () {
+ state |= CANVAS;
+ if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
+ state |= THEME_BACKGROUND;
+ }
+ boolean scrolled = (style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0;
+ createHandle (scrolled, false);
+}
+
+void createHandle (boolean scrolled, boolean menubar) {
+ handle = OS.gcnew_SWTCanvas (jniRef);
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_FocusVisualStyle (handle, 0);
+ if ((style & SWT.NO_FOCUS) == 0) {
+ OS.UIElement_Focusable (handle, true);
+ }
+ if (scrolled || menubar) {
+ scrolledHandle = OS.gcnew_Grid ();
+ if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
+
+ /* Create grid definition */
+ int gridLength = OS.gcnew_GridLength (1, OS.GridUnitType_Auto);
+ if (gridLength == 0) error (SWT.ERROR_NO_HANDLES);
+ int columnDefinitions = OS.Grid_ColumnDefinitions (scrolledHandle);
+ int column0 = OS.gcnew_ColumnDefinition ();
+ if (column0 == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ColumnDefinitionCollection_Add (columnDefinitions, column0);
+ int column1 = OS.gcnew_ColumnDefinition ();
+ if (column1 == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ColumnDefinition_Width (column1, gridLength);
+ OS.ColumnDefinitionCollection_Add (columnDefinitions, column1);
+ int rowDefinitions = OS.Grid_RowDefinitions (scrolledHandle);
+ int row0 = OS.gcnew_RowDefinition ();
+ if (row0 == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.RowDefinition_Height (row0, gridLength);
+ OS.RowDefinitionCollection_Add (rowDefinitions, row0);
+ int row1 = OS.gcnew_RowDefinition ();
+ if (row1 == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.RowDefinitionCollection_Add (rowDefinitions, row1);
+ int row2 = OS.gcnew_RowDefinition ();
+ if (row2 == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.RowDefinition_Height (row2, gridLength);
+ OS.RowDefinitionCollection_Add (rowDefinitions, row2);
+ OS.GCHandle_Free (column0);
+ OS.GCHandle_Free (column1);
+ OS.GCHandle_Free (row0);
+ OS.GCHandle_Free (row1);
+ OS.GCHandle_Free (row2);
+ OS.GCHandle_Free (gridLength);
+ OS.GCHandle_Free (columnDefinitions);
+ OS.GCHandle_Free (rowDefinitions);
+
+ /* create children */
+ int children = OS.Panel_Children (scrolledHandle);
+ OS.UIElementCollection_Add (children, handle);
+ OS.Grid_SetRow (handle, 1);
+ OS.Grid_SetColumn (handle, 0);
+ if ((style & SWT.V_SCROLL) != 0) {
+ int vScroll = OS.gcnew_ScrollBar ();
+ if (vScroll == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ScrollBar_Orientation (vScroll, OS.Orientation_Vertical);
+ OS.RangeBase_Maximum(vScroll, 90);
+ OS.RangeBase_LargeChange (vScroll, 10);
+ OS.ScrollBar_ViewportSize (vScroll, 10);
+ OS.Grid_SetRow (vScroll, 1);
+ OS.Grid_SetColumn (vScroll, 1);
+ OS.UIElementCollection_Add (children, vScroll);
+ OS.GCHandle_Free (vScroll);
+ }
+ if ((style & SWT.H_SCROLL) != 0) {
+ int hScroll = OS.gcnew_ScrollBar ();
+ if (hScroll == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ScrollBar_Orientation (hScroll, OS.Orientation_Horizontal);
+ OS.RangeBase_Maximum (hScroll, 90);
+ OS.RangeBase_LargeChange (hScroll, 10);
+ OS.ScrollBar_ViewportSize (hScroll, 10);
+ OS.Grid_SetRow (hScroll, 2);
+ OS.Grid_SetColumn (hScroll, 0);
+ OS.UIElementCollection_Add (children, hScroll);
+ OS.GCHandle_Free (hScroll);
+ }
+ OS.GCHandle_Free (children);
+ }
+}
+
+int defaultBackground () {
+ if ((state & CANVAS) != 0) {
+ return OS.SystemColors_ControlColor;
+ }
+ return 0;
+}
+
+void enableWidget (boolean enabled) {
+ if ((state & CANVAS) != 0) {
+ OS.UIElement_IsHitTestVisible (topHandle (), enabled);
+ } else {
+ OS.UIElement_IsEnabled (handle, enabled);
+ OS.UIElement_IsHitTestVisible (parentingHandle (), enabled);
+ }
+}
+
+Composite findDeferredControl () {
+ return layoutCount > 0 ? this : parent.findDeferredControl ();
+}
+
+Menu [] findMenus (Control control) {
+ if (control == this) return new Menu [0];
+ Menu result [] = super.findMenus (control);
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ Menu [] menuList = child.findMenus (control);
+ if (menuList.length != 0) {
+ Menu [] newResult = new Menu [result.length + menuList.length];
+ System.arraycopy (result, 0, newResult, 0, result.length);
+ System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
+ result = newResult;
+ }
+ }
+ return result;
+}
+
+void fixScrollbarVisibility () {
+}
+
+void fixTabList (Control control) {
+ if (tabList == null) return;
+ int count = 0;
+ for (int i=0; i<tabList.length; i++) {
+ if (tabList [i] == control) count++;
+ }
+ if (count == 0) return;
+ Control [] newList = null;
+ int length = tabList.length - count;
+ if (length != 0) {
+ newList = new Control [length];
+ int index = 0;
+ for (int i=0; i<tabList.length; i++) {
+ if (tabList [i] != control) {
+ newList [index++] = tabList [i];
+ }
+ }
+ }
+ tabList = newList;
+}
+
+/**
+ * Returns the receiver's background drawing mode. This
+ * will be one of the following constants defined in class
+ * <code>SWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERTIT_FORCE</code>.
+ *
+ * @return the background mode
+ *
+ * @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 SWT
+ *
+ * @since 3.2
+ */
+public int getBackgroundMode () {
+ checkWidget ();
+ return backgroundMode;
+}
+
+/**
+ * Returns a (possibly empty) array containing the receiver's children.
+ * Children are returned in the order that they are drawn. The topmost
+ * control appears at the beginning of the array. Subsequent controls
+ * draw beneath this control and appear later in the array.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of children, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return an array of children
+ *
+ * @see Control#moveAbove
+ * @see Control#moveBelow
+ *
+ * @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 Control [] getChildren () {
+ checkWidget ();
+ return _getChildren ();
+}
+
+/**
+ * Returns layout which is associated with the receiver, or
+ * null if one has not been set.
+ *
+ * @return the receiver's layout 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 Layout getLayout () {
+ checkWidget ();
+ return layout;
+}
+
+Point getLocation (Control child) {
+ int topHandle = child.topHandle ();
+ int x = (int) OS.Canvas_GetLeft (topHandle);
+ int y = (int) OS.Canvas_GetTop (topHandle);
+ return new Point (x, y);
+}
+
+/**
+ * Gets the (possibly empty) tabbing order for the control.
+ *
+ * @return tabList the ordered list of controls representing the tab order
+ *
+ * @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 #setTabList
+ */
+public Control [] getTabList () {
+ checkWidget ();
+ Control [] tabList = _getTabList ();
+ if (tabList == null) {
+ int count = 0;
+ Control [] list =_getChildren ();
+ for (int i=0; i<list.length; i++) {
+ if (list [i].isTabGroup ()) count++;
+ }
+ tabList = new Control [count];
+ int index = 0;
+ for (int i=0; i<list.length; i++) {
+ if (list [i].isTabGroup ()) {
+ tabList [index++] = list [i];
+ }
+ }
+ }
+ return tabList;
+}
+
+boolean hooksKeys () {
+ return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
+}
+
+/**
+ * Returns <code>true</code> if the receiver has deferred
+ * the performing of layout, and <code>false</code> otherwise.
+ *
+ * @return the receiver's deferred layout 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 #setLayoutDeferred(boolean)
+ * @see #isLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean getLayoutDeferred () {
+ checkWidget ();
+ return layoutCount > 0 ;
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ /*
+ * In WPF arrows key move the focus around, this
+ * behavior is not expected in SWT.
+ */
+ if ((state & CANVAS) != 0) {
+ int key = OS.KeyEventArgs_Key (e);
+ switch (key) {
+ case OS.Key_Up:
+ case OS.Key_Left:
+ case OS.Key_Down:
+ case OS.Key_Right: {
+ OS.RoutedEventArgs_Handled (e, true);
+ break;
+ }
+ }
+ }
+}
+
+void HandlePreviewMouseDown(int sender, int e) {
+ if (!checkEvent (e)) return;
+ super.HandlePreviewMouseDown (sender, e);
+
+ /* Set focus for a canvas with no children */
+ if ((state & CANVAS) != 0) {
+ if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
+ int children = OS.Panel_Children (handle);
+ int count = OS.UIElementCollection_Count (children);
+ OS.GCHandle_Free (children);
+ int caretHandle = getCaretHandle ();
+ if (caretHandle != 0) count--;
+ if (count == 0) {
+ OS.UIElement_Focus (handle);
+ }
+ }
+ }
+}
+
+void HandlePreviewTextInput(int sender, int e) {
+ super.HandlePreviewTextInput (sender, e);
+ if (!checkEvent (e)) return;
+ if ((state & CANVAS) != 0) {
+ OS.RoutedEventArgs_Handled (e, true);
+ }
+}
+
+/**
+ * Returns <code>true</code> if the receiver or any ancestor
+ * up to and including the receiver's nearest ancestor shell
+ * has deferred the performing of layouts. Otherwise, <code>false</code>
+ * is returned.
+ *
+ * @return the receiver's deferred layout 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 #setLayoutDeferred(boolean)
+ * @see #getLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean isLayoutDeferred () {
+ checkWidget ();
+ return findDeferredControl () != null;
+}
+
+boolean isTabGroup() {
+ if ((state & CANVAS) != 0) return true;
+ return super.isTabGroup();
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * This is equivalent to calling <code>layout(true)</code>.
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @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 layout () {
+ checkWidget ();
+ layout (true);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the argument is <code>true</code> the layout must not rely
+ * on any information it has cached about the immediate children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * If a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child. The layout
+ * will cascade down through all child widgets in the receiver's widget
+ * tree until a child is encountered that does not resize. Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ *
+ * @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 layout (boolean changed) {
+ checkWidget ();
+ if (layout == null) return;
+ layout (changed, false);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the changed argument is <code>true</code> the layout must not rely
+ * on any information it has cached about its children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the all argument is <code>true</code> the layout will cascade down
+ * through all child widgets in the receiver's widget tree, regardless of
+ * whether the child has changed size. The changed argument is applied to
+ * all layouts. If the all argument is <code>false</code>, the layout will
+ * <em>not</em> cascade down through all child widgets in the receiver's widget
+ * tree. However, if a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child. Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public void layout (boolean changed, boolean all) {
+ checkWidget ();
+ if (layout == null && !all) return;
+ markLayout (changed, all);
+ updateLayout (true, all);
+}
+
+/**
+ * Forces a lay out (that is, sets the size and location) of all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver. The layouts in the hierarchy must not rely on any information
+ * cached about the changed control or any of its ancestors. The layout may
+ * (potentially) optimize the work it is doing by assuming that none of the
+ * peers of the changed control have changed state since the last layout.
+ * If an ancestor does not have a layout, skip it.
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed a control that has had a state change which requires a recalculation of its size
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</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>
+ *
+ * @since 3.1
+ */
+public void layout (Control [] changed) {
+ checkWidget ();
+ if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i<changed.length; i++) {
+ Control control = changed [i];
+ if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ boolean ancestor = false;
+ Composite composite = control.parent;
+ while (composite != null) {
+ ancestor = composite == this;
+ if (ancestor) break;
+ composite = composite.parent;
+ }
+ if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
+ }
+ int updateCount = 0;
+ Composite [] update = new Composite [16];
+ for (int i=0; i<changed.length; i++) {
+ Control child = changed [i];
+ Composite composite = child.parent;
+ while (child != this) {
+ if (composite.layout != null) {
+ composite.state |= LAYOUT_NEEDED;
+ if (!composite.layout.flushCache (child)) {
+ composite.state |= LAYOUT_CHANGED;
+ }
+ }
+ if (updateCount == update.length) {
+ Composite [] newUpdate = new Composite [update.length + 16];
+ System.arraycopy (update, 0, newUpdate, 0, update.length);
+ update = newUpdate;
+ }
+ child = update [updateCount++] = composite;
+ composite = child.parent;
+ }
+ }
+ for (int i=updateCount-1; i>=0; i--) {
+ update [i].updateLayout (true, false);
+ }
+}
+
+void OnRender(int drawingContext) {
+ if (isDisposed ()) return;
+ OS.SWTCanvas_Visual (handle, 0);
+ if (display.ignoreRender) {
+ display.addInvalidate (this);
+ return;
+ }
+ if (!hooks (SWT.Paint)) return;
+ int width = (int)OS.FrameworkElement_ActualWidth (handle);
+ int height = (int)OS.FrameworkElement_ActualHeight (handle);
+ if (width != 0 && height != 0) {
+ GCData data = new GCData ();
+ data.device = display;
+ data.drawingContext = drawingContext;
+ GC gc = GC.wpf_new (this, data);
+ Event event = new Event ();
+ event.gc = gc;
+ event.width = width;
+ event.height = height;
+ sendEvent (SWT.Paint, event);
+ event.gc = null;
+ gc.dispose ();
+ }
+}
+
+void markLayout (boolean changed, boolean all) {
+ if (layout != null) {
+ state |= LAYOUT_NEEDED;
+ if (changed) state |= LAYOUT_CHANGED;
+ }
+ if (all) {
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ children [i].markLayout (changed, all);
+ }
+ }
+}
+
+Point minimumSize (int wHint, int hHint, boolean changed) {
+ Control [] children = _getChildren ();
+ int width = 0, height = 0;
+ for (int i=0; i<children.length; i++) {
+ Rectangle rect = children [i].getBounds ();
+ width = Math.max (width, rect.x + rect.width);
+ height = Math.max (height, rect.y + rect.height);
+ }
+ return new Point (width, height);
+}
+
+int parentingHandle () {
+ return handle;
+}
+
+void releaseChildren (boolean destroy) {
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ if (child != null && !child.isDisposed ()) {
+ child.release (false);
+ }
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+// if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+// if (hwndChild != 0) {
+// int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
+// if (threadId != OS.GetCurrentThreadId ()) {
+// OS.ShowWindow (hwndChild, OS.SW_HIDE);
+// OS.SetParent (hwndChild, 0);
+// }
+// }
+// }
+ layout = null;
+ tabList = null;
+}
+
+void removeChild (Control control) {
+ int topHandle = control.topHandle ();
+ int parentHandle = parentingHandle ();
+ int children = OS.Panel_Children (parentHandle);
+ OS.UIElementCollection_Remove (children, topHandle);
+ OS.GCHandle_Free (children);
+}
+
+void removeControl (Control control) {
+ fixTabList (control);
+}
+
+void resized () {
+ super.resized();
+ if (isDisposed ()) return;
+ if (layout != null) {
+ markLayout (false, false);
+ updateLayout (false, false);
+ }
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public void setAlpha(int alpha) {
+ checkWidget ();
+ int backgroundHandle = backgroundHandle ();
+ int property = backgroundProperty ();
+ int brush = OS.DependencyObject_GetValue (backgroundHandle, property);
+ if (brush != 0) {
+ int newBrush = OS.Freezable_Clone(brush);
+ OS.Brush_Opacity (newBrush, (alpha & 0xFF) / (double)0xFF);
+ OS.DependencyObject_SetValue (backgroundHandle, property, newBrush);
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (newBrush);
+ }
+ OS.GCHandle_Free (property);
+// OS.UIElement_Opacity (handle, (alpha & 0xFF) / (double)0xFF);
+}
+
+void setBackgroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Panel_Background (handle, brush);
+ } else {
+ int property = OS.Panel_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the background drawing mode to the argument which should
+ * be one of the following constants defined in class <code>SWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERIT_FORCE</code>.
+ *
+ * @param mode the new background mode
+ *
+ * @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 SWT
+ *
+ * @since 3.2
+ */
+public void setBackgroundMode (int mode) {
+ checkWidget ();
+ backgroundMode = mode;
+ Control [] children = _getChildren ();
+ for (int i = 0; i < children.length; i++) {
+ children [i].updateBackgroundMode ();
+ }
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0 && layout != null) {
+ markLayout (false, false);
+ updateLayout (false, false);
+ }
+ return result;
+}
+
+void setClipping () {
+ OS.UIElement_ClipToBounds (topHandle (), true);
+}
+
+public boolean setFocus () {
+ checkWidget();
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ if (child.getVisible () && child.setFocus ()) return true;
+ }
+ return super.setFocus ();
+}
+
+void setFont (int font, double size) {
+}
+
+void setForegroundBrush (int brush) {
+ OS.UIElement_InvalidateVisual (handle);
+}
+
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ *
+ * @param layout the receiver's new layout 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 setLayout (Layout layout) {
+ checkWidget ();
+ this.layout = layout;
+}
+
+/**
+ * If the argument is <code>true</code>, causes subsequent layout
+ * operations in the receiver or any of its children to be ignored.
+ * No layout of any kind can occur in the receiver or any of its
+ * children until the flag is set to false.
+ * Layout operations that occurred while the flag was
+ * <code>true</code> are remembered and when the flag is set to
+ * <code>false</code>, the layout operations are performed in an
+ * optimized manner. Nested calls to this method are stacked.
+ *
+ * @param defer the new defer 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 #layout(boolean)
+ * @see #layout(Control[])
+ *
+ * @since 3.1
+ */
+public void setLayoutDeferred (boolean defer) {
+ if (!defer) {
+ if (--layoutCount == 0) {
+ if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) {
+ updateLayout (true, true);
+ }
+ }
+ } else {
+ layoutCount++;
+ }
+}
+
+/**
+ * Sets the tabbing order for the specified controls to
+ * match the order that they occur in the argument list.
+ *
+ * @param tabList the ordered list of controls representing the tab order or null
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</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 setTabList (Control [] tabList) {
+ checkWidget ();
+ if (tabList != null) {
+ for (int i=0; i<tabList.length; i++) {
+ Control control = tabList [i];
+ if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != this) error (SWT.ERROR_INVALID_PARENT);
+ }
+ Control [] newList = new Control [tabList.length];
+ System.arraycopy (tabList, 0, newList, 0, tabList.length);
+ tabList = newList;
+ }
+ this.tabList = tabList;
+}
+
+boolean setTabGroupFocus () {
+ if (isTabItem ()) return setTabItemFocus ();
+ boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
+ if ((state & CANVAS) != 0) {
+ takeFocus = hooksKeys ();
+ if ((style & SWT.EMBEDDED) != 0) takeFocus = true;
+ }
+ if (takeFocus && setTabItemFocus ()) return true;
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ if (child.isTabItem () && child.setTabItemFocus ()) return true;
+ }
+ return false;
+}
+
+boolean translateMnemonic (Event event, Control control) {
+ if (super.translateMnemonic (event, control)) return true;
+ if (control != null) {
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ if (child.translateMnemonic (event, control)) return true;
+ }
+ }
+ return false;
+}
+
+int traversalCode(int key, int event) {
+ if ((state & CANVAS) != 0) {
+ if ((style & SWT.NO_FOCUS) != 0) return 0;
+ if (hooksKeys ()) return 0;
+ }
+ return super.traversalCode (key, event);
+}
+
+boolean translateTraversal (int msg) {
+ if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) return false;
+ return super.translateTraversal (msg);
+}
+
+void updateBackgroundColor () {
+ super.updateBackgroundColor ();
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ if ((children [i].state & PARENT_BACKGROUND) != 0) {
+ children [i].updateBackgroundColor ();
+ }
+ }
+}
+
+void updateBackgroundImage () {
+ super.updateBackgroundImage ();
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ if ((children [i].state & PARENT_BACKGROUND) != 0) {
+ children [i].updateBackgroundImage ();
+ }
+ }
+}
+
+void updateBackgroundMode () {
+ super.updateBackgroundMode ();
+ Control [] children = _getChildren ();
+ for (int i = 0; i < children.length; i++) {
+ children [i].updateBackgroundMode ();
+ }
+}
+
+void updateFont (Font oldFont, Font newFont) {
+ super.updateFont (oldFont, newFont);
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ Control control = children [i];
+ if (!control.isDisposed ()) {
+ control.updateFont (oldFont, newFont);
+ }
+ }
+}
+
+void updateLayout (boolean resize, boolean all) {
+ Composite parent = findDeferredControl ();
+ if (parent != null) {
+ parent.state |= LAYOUT_CHILD;
+ return;
+ }
+ if ((state & LAYOUT_NEEDED) != 0) {
+ boolean changed = (state & LAYOUT_CHANGED) != 0;
+ state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
+ layout.layout (this, changed);
+ }
+ if (all) {
+ state &= ~LAYOUT_CHILD;
+ Control [] children = _getChildren ();
+ for (int i=0; i<children.length; i++) {
+ children [i].updateLayout (resize, all);
+ }
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Control.java
new file mode 100644
index 0000000000..1cbda102e8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Control.java
@@ -0,0 +1,3621 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.accessibility.*;
+
+//TEMPORARY CODE
+import org.eclipse.swt.effects.*;
+
+/**
+ * Control is the abstract superclass of all windowed user interface classes.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>BORDER</dd>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * <dt><b>Events:</b>
+ * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
+ * MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse</dd>
+ * </dl>
+ * </p><p>
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public abstract class Control extends Widget implements Drawable {
+ Cursor cursor;
+ Menu menu;
+ String toolTipText;
+ Object layoutData;
+ Accessible accessible;
+ Image backgroundImage;
+ Region region;
+// int drawCount;
+ int foreground, background;
+ int x, y, width, height;
+ Font font;
+ Composite parent;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Control () {
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#BORDER
+ * @see SWT#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Control (Composite parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when a drag gesture occurs, by sending it
+ * one of the messages defined in the <code>DragDetectListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see DragDetectListener
+ * @see #removeDragDetectListener
+ *
+ * @since 3.3
+ */
+public void addDragDetectListener (DragDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.DragDetect,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control gains or loses focus, by sending
+ * it one of the messages defined in the <code>FocusListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see FocusListener
+ * @see #removeFocusListener
+ */
+public void addFocusListener (FocusListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.FocusIn,typedListener);
+ addListener (SWT.FocusOut,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when help events are generated for the control,
+ * by sending it one of the messages defined in the
+ * <code>HelpListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard, by sending
+ * it one of the messages defined in the <code>KeyListener</code>
+ * interface.
+ * <p>
+ * When a key listener is added to a control, the control
+ * will take part in widget traversal. By default, all
+ * traversal keys (such as the tab key and so on) are
+ * delivered to the control. In order for a control to take
+ * part in traversal, it should listen for traversal events.
+ * Otherwise, the user can traverse into a control but not
+ * out. Note that native controls such as table and tree
+ * implement key traversal in the operating system. It is
+ * not necessary to add traversal listeners for these controls,
+ * unless you want to override the default traversal.
+ * </p>
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see KeyListener
+ * @see #removeKeyListener
+ */
+public void addKeyListener (KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.KeyUp,typedListener);
+ addListener (SWT.KeyDown,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the platform-specific context menu trigger
+ * has occurred, by sending it one of the messages defined in
+ * the <code>MenuDetectListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MenuDetectListener
+ * @see #removeMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void addMenuDetectListener (MenuDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MenuDetect, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when mouse buttons are pressed and released, by sending
+ * it one of the messages defined in the <code>MouseListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MouseListener
+ * @see #removeMouseListener
+ */
+public void addMouseListener (MouseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseDown,typedListener);
+ addListener (SWT.MouseUp,typedListener);
+ addListener (SWT.MouseDoubleClick,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls, by sending
+ * it one of the messages defined in the <code>MouseTrackListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MouseTrackListener
+ * @see #removeMouseTrackListener
+ */
+public void addMouseTrackListener (MouseTrackListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseEnter,typedListener);
+ addListener (SWT.MouseExit,typedListener);
+ addListener (SWT.MouseHover,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse moves, by sending it one of the
+ * messages defined in the <code>MouseMoveListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MouseMoveListener
+ * @see #removeMouseMoveListener
+ */
+public void addMouseMoveListener (MouseMoveListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseMove,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse wheel is scrolled, by sending
+ * it one of the messages defined in the
+ * <code>MouseWheelListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MouseWheelListener
+ * @see #removeMouseWheelListener
+ *
+ * @since 3.3
+ */
+public void addMouseWheelListener (MouseWheelListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseWheel, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver needs to be painted, by sending it
+ * one of the messages defined in the <code>PaintListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see PaintListener
+ * @see #removePaintListener
+ */
+public void addPaintListener (PaintListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Paint,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when traversal events occur, by sending it
+ * one of the messages defined in the <code>TraverseListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see TraverseListener
+ * @see #removeTraverseListener
+ */
+public void addTraverseListener (TraverseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Traverse,typedListener);
+}
+
+void addWidget () {
+ parent.addChild (this);
+}
+
+int borderHandle () {
+ return handle;
+}
+
+void checkBackground () {
+ Shell shell = getShell ();
+ if (this == shell) return;
+ state &= ~PARENT_BACKGROUND;
+ Composite composite = parent;
+ do {
+ int mode = composite.backgroundMode;
+ if (mode != 0) {
+ if (mode == SWT.INHERIT_DEFAULT) {
+ Control control = this;
+ do {
+ if ((control.state & THEME_BACKGROUND) == 0) {
+ return;
+ }
+ control = control.parent;
+ } while (control != composite);
+ }
+ state |= PARENT_BACKGROUND;
+ return;
+ }
+ if (composite == shell) break;
+ composite = composite.parent;
+ } while (true);
+}
+
+void checkBorder () {
+ if (getBorderWidth () == 0) style &= ~SWT.BORDER;
+}
+
+void checkBuffered () {
+ style |= SWT.DOUBLE_BUFFERED;
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a control is the size that it would
+ * best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask a control questions such as "Given a particular
+ * width, how high does the control need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @return the preferred size of the control
+ *
+ * @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 Layout
+ * @see #getBorderWidth
+ * @see #getBounds
+ * @see #getSize
+ * @see #pack(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint) {
+ return computeSize (wHint, hHint, true);
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a control is the size that it would
+ * best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask a control questions such as "Given a particular
+ * width, how high does the control need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p><p>
+ * If the changed flag is <code>true</code>, it indicates that the receiver's
+ * <em>contents</em> have changed, therefore any caches that a layout manager
+ * containing the control may have been keeping need to be flushed. When the
+ * control is resized, the changed flag will be <code>false</code>, so layout
+ * manager caches can be retained.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
+ * @return the preferred size of the control.
+ *
+ * @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 Layout
+ * @see #getBorderWidth
+ * @see #getBounds
+ * @see #getSize
+ * @see #pack(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ return computeSize (handle, wHint, hHint, changed);
+}
+
+Point computeSize (int handle, int wHint, int hHint, boolean changed) {
+ int width = wHint, height = hHint;
+ if (wHint == SWT.DEFAULT) width = 0x7FFFFFFF;
+ if (hHint == SWT.DEFAULT) height = 0x7FFFFFFF;
+ width = Math.max (0, width);
+ height = Math.max (0, height);
+ int availSize = OS.gcnew_Size ((double)width, (double)height);
+ if (availSize == 0) error (SWT.ERROR_NO_HANDLES);
+ double requestWidth = OS.FrameworkElement_Width (handle);
+ if (requestWidth >= 0) {
+ int widthDP = OS.FrameworkElement_WidthProperty ();
+ OS.DependencyObject_ClearValue (handle, widthDP);
+ OS.GCHandle_Free (widthDP);
+ }
+ double requestHeight = OS.FrameworkElement_Height (handle);
+ if (requestHeight >= 0) {
+ int heightDP = OS.FrameworkElement_HeightProperty ();
+ OS.DependencyObject_ClearValue (handle, heightDP);
+ OS.GCHandle_Free (heightDP);
+ }
+ OS.UIElement_Measure (handle, availSize);
+ OS.GCHandle_Free (availSize);
+ int size = OS.UIElement_DesiredSize (handle);
+ width = (int) OS.Size_Width (size);
+ height = (int) OS.Size_Height (size);
+ OS.GCHandle_Free (size);
+ if (requestWidth >= 0) OS.FrameworkElement_Width (handle, requestWidth);
+ if (requestHeight >= 0) OS.FrameworkElement_Height (handle, requestHeight);
+ if (wHint != SWT.DEFAULT) width = wHint;
+ if (hHint != SWT.DEFAULT) height = hHint;
+ return new Point (width, height);
+}
+
+Control computeTabGroup () {
+ if (isTabGroup ()) return this;
+ return parent.computeTabGroup ();
+}
+
+Control computeTabRoot () {
+ Control [] tabList = parent._getTabList ();
+ if (tabList != null) {
+ int index = 0;
+ while (index < tabList.length) {
+ if (tabList [index] == this) break;
+ index++;
+ }
+ if (index == tabList.length) {
+ if (isTabGroup ()) return this;
+ }
+ }
+ return parent.computeTabRoot ();
+}
+
+Control [] computeTabList () {
+ if (isTabGroup ()) {
+ if (getVisible () && getEnabled ()) {
+ return new Control [] {this};
+ }
+ }
+ return new Control [0];
+}
+
+void createWidget () {
+ state |= DRAG_DETECT;
+ checkOrientation (parent);
+ super.createWidget ();
+ checkBackground ();
+ checkBuffered ();
+ setClipping ();
+ if (defaultBackground () != 0 || (state & PARENT_BACKGROUND) != 0) {
+ setBackground ();
+ }
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public void setAlpha(int alpha) {
+ checkWidget ();
+ OS.UIElement_Opacity (handle, (alpha & 0xFF) / (double)0xFF);
+}
+
+void setClipping () {
+ //accept default clipping
+}
+
+int defaultBackground () {
+ return 0;
+}
+
+Font defaultFont () {
+ return display.getSystemFont ();
+}
+
+int defaultForeground () {
+ return display.getSystemColor (SWT.COLOR_BLACK).handle;
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.removeChild (this);
+ releaseHandle ();
+}
+
+/**
+ * Detects a drag and drop gesture. This method is used
+ * to detect a drag gesture when called from within a mouse
+ * down listener.
+ *
+ * <p>By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior. In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item. Custom widget writers can use <code>setDragDetect</code>
+ * to disable the default detection, listen for mouse down,
+ * and then call <code>dragDetect()</code> from within the
+ * listener to conditionally detect a drag.
+ * </p>
+ *
+ * @param event the mouse down event
+ *
+ * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT when the event 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>
+ *
+ * @see DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @see #getDragDetect
+ * @see #setDragDetect
+ *
+ * @since 3.3
+ */
+public boolean dragDetect (Event event) {
+ checkWidget ();
+ if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
+}
+
+/**
+ * Detects a drag and drop gesture. This method is used
+ * to detect a drag gesture when called from within a mouse
+ * down listener.
+ *
+ * <p>By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior. In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item. Custom widget writers can use <code>setDragDetect</code>
+ * to disable the default detection, listen for mouse down,
+ * and then call <code>dragDetect()</code> from within the
+ * listener to conditionally detect a drag.
+ * </p>
+ *
+ * @param event the mouse down event
+ *
+ * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT when the event 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>
+ *
+ * @see DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @see #getDragDetect
+ * @see #setDragDetect
+ *
+ * @since 3.3
+ */
+public boolean dragDetect (MouseEvent event) {
+ checkWidget ();
+ if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
+}
+
+boolean dragDetect (int button, int count, int stateMask, int x, int y) {
+ if (button != 1 || count != 1) return false;
+ boolean dragging = dragDetect (x, y, false);
+ if (dragging) return sendDragEvent (button, stateMask, x, y);
+ return false;
+}
+
+void dragHandler () {
+ int frame = display.dragDetectFrame = OS.gcnew_DispatcherFrame ();
+ OS.Dispatcher_PushFrame (frame);
+ OS.GCHandle_Free (frame);
+ OS.GCHandle_Free (display.dragRect);
+ if (display.dragMouseDown != 0) OS.GCHandle_Free (display.dragMouseDown);
+ display.dragMouseDown = display.dragDetectFrame = display.dragRect = 0;
+}
+
+boolean dragDetect (double x, double y, boolean post) {
+ display.dragging = false;
+ double minH = OS.SystemParameters_MinimumHorizontalDragDistance ();
+ double minV = OS.SystemParameters_MinimumVerticalDragDistance ();
+ display.dragRect = OS.gcnew_Rect(x - minH, y - minV, minH * 2, minV * 2);
+ if (post) {
+ int handler = OS.gcnew_NoArgsDelegate (jniRef, "dragHandler");
+ int operation = OS.Dispatcher_BeginInvoke (display.dispatcher, OS.DispatcherPriority_Send, handler);
+ OS.GCHandle_Free (operation);
+ OS.GCHandle_Free (handler);
+ } else {
+ dragHandler ();
+ }
+ return display.dragging;
+}
+
+void enableWidget (boolean enabled) {
+ OS.UIElement_IsEnabled (handle, enabled);
+}
+
+boolean drawGripper (int x, int y, int width, int height, boolean vertical) {
+ return false;
+}
+
+Control findBackgroundControl () {
+ if (background != 0 || backgroundImage != null) return this;
+ return (state & PARENT_BACKGROUND) != 0 ? parent.findBackgroundControl () : null;
+}
+
+Control findThemeControl () {
+ return background == 0 && backgroundImage == null ? parent.findThemeControl () : null;
+}
+
+Control findImageControl () {
+ Control control = findBackgroundControl ();
+ return control != null && control.backgroundImage != null ? control : null;
+}
+
+Menu [] findMenus (Control control) {
+ if (menu != null && this != control) return new Menu [] {menu};
+ return new Menu [0];
+}
+
+char findMnemonic (String string) {
+ int index = 0;
+ int length = string.length ();
+ do {
+ while (index < length && string.charAt (index) != '&') index++;
+ if (++index >= length) return '\0';
+ if (string.charAt (index) != '&') return string.charAt (index);
+ index++;
+ } while (index < length);
+ return '\0';
+}
+
+void fixFocus (Control focusControl) {
+ Shell shell = getShell ();
+ Control control = this;
+ while (control != shell && (control = control.parent) != null) {
+ if (control.setFocus ()) return;
+ }
+ shell.setSavedFocus (focusControl);
+ OS.UIElement_Focus (shell.shellHandle);
+}
+
+/**
+ * Forces the receiver to have the <em>keyboard focus</em>, causing
+ * all keyboard events to be delivered to it.
+ *
+ * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
+ *
+ * @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 #setFocus
+ */
+public boolean forceFocus () {
+ checkWidget ();
+// if (display.focusEvent == SWT.FocusOut) return false;
+ Decorations shell = menuShell ();
+ shell.setSavedFocus (this);
+ if (!isEnabled () || !isVisible () || !isActive ()) return false;
+ if (isFocusControl ()) return true;
+ shell.setSavedFocus (null);
+ OS.UIElement_Focus (handle);
+ if (isDisposed ()) return false;
+ shell.setSavedFocus (this);
+ return isFocusControl ();
+}
+
+/**
+ * Returns the accessible object for the receiver.
+ * If this is the first time this object is requested,
+ * then the object is created and returned.
+ *
+ * @return the accessible object
+ *
+ * @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 Accessible#addAccessibleListener
+ * @see Accessible#addAccessibleControlListener
+ *
+ * @since 2.0
+ */
+public Accessible getAccessible () {
+ checkWidget ();
+ if (accessible == null) accessible = new_Accessible (this);
+ return accessible;
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public int getAlpha () {
+ checkWidget ();
+ return (int) (0XFF * OS.UIElement_Opacity (handle));
+}
+
+/**
+ * Returns the receiver's background color.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on some versions of Windows the background of a TabFolder,
+ * is a gradient rather than a solid color.
+ * </p>
+ * @return the background color
+ *
+ * @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 Color getBackground () {
+ checkWidget ();
+ Control control = findBackgroundControl ();
+ if (control == null) control = this;
+ return Color.wpf_new (display, control.getBackgroundColor ());
+}
+
+/**
+ * Returns the receiver's background image.
+ *
+ * @return the background 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>
+ *
+ * @since 3.2
+ */
+public Image getBackgroundImage () {
+ checkWidget ();
+ Control control = findBackgroundControl ();
+ if (control == null) control = this;
+ return control.backgroundImage;
+}
+
+int getBackgroundColor () {
+ int color = background;
+ if (color == 0) color = defaultBackground ();
+ if (color == 0) color = OS.SystemColors_ControlColor;//TODO
+ return color;
+}
+
+/**
+ * Returns the receiver's border width.
+ *
+ * @return the border width
+ *
+ * @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 int getBorderWidth () {
+ checkWidget ();
+ //FIXME
+ return 2;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null),
+ * unless the receiver is a shell. In this case, the location is
+ * relative to the display.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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 Rectangle getBounds () {
+ checkWidget ();
+ int topHandle = topHandle ();
+ Point location = parent.getLocation (this);
+ int width = (int) OS.FrameworkElement_Width (topHandle);
+ int height = (int) OS.FrameworkElement_Height (topHandle);
+ return new Rectangle (location.x, location.y, width, height);
+}
+
+String getClipboardText () {
+ String string = "";
+ int text = OS.Clipboard_GetText ();
+ if (text != 0) {
+ string = createJavaString (text);
+ OS.GCHandle_Free(text);
+ }
+ return string;
+}
+
+/**
+ * Returns the receiver's cursor, or null if it has not been set.
+ * <p>
+ * When the mouse pointer passes over a control its appearance
+ * is changed to match the control's cursor.
+ * </p>
+ *
+ * @return the receiver's cursor or <code>null</code>
+ *
+ * @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>
+ *
+ * @since 3.3
+ */
+public Cursor getCursor () {
+ checkWidget ();
+ return cursor;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is detecting
+ * drag gestures, and <code>false</code> otherwise.
+ *
+ * @return the receiver's drag detect 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>
+ *
+ * @since 3.3
+ */
+public boolean getDragDetect () {
+ checkWidget ();
+ return (state & DRAG_DETECT) != 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return (state & DISABLED) == 0;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @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 Font getFont () {
+ checkWidget ();
+ return font != null ? font : defaultFont ();
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @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 Color getForeground () {
+ checkWidget ();
+ return Color.wpf_new (display, getForegroundColor ());
+}
+
+int getForegroundColor () {
+ return foreground != 0 ? foreground : defaultForeground ();
+}
+
+/**
+ * Returns layout data which is associated with the receiver.
+ *
+ * @return the receiver's layout data
+ *
+ * @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 Object getLayoutData () {
+ checkWidget ();
+ return layoutData;
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @return the receiver's location
+ *
+ * @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 Point getLocation () {
+ checkWidget ();
+ return parent.getLocation (this);
+}
+
+/**
+ * Returns the receiver's pop up menu if it has one, or null
+ * if it does not. All controls may optionally have a pop up
+ * menu that is displayed when the user requests one for
+ * the control. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pop up
+ * menu is platform specific.
+ *
+ * @return the receiver's menu
+ *
+ * @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 getMenu () {
+ checkWidget ();
+ return menu;
+}
+
+/**
+ * Returns the receiver's monitor.
+ *
+ * @return the receiver's monitor
+ *
+ * @since 3.0
+ */
+public Monitor getMonitor () {
+ checkWidget ();
+ //TODO
+ return display.getPrimaryMonitor ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Composite</code>
+ * or null when the receiver is a shell that was created with null or
+ * a display for a parent.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Composite getParent () {
+ checkWidget ();
+ return parent;
+}
+
+Control [] getPath () {
+ int count = 0;
+ Shell shell = getShell ();
+ Control control = this;
+ while (control != shell) {
+ count++;
+ control = control.parent;
+ }
+ control = this;
+ Control [] result = new Control [count];
+ while (control != shell) {
+ result [--count] = control;
+ control = control.parent;
+ }
+ return result;
+}
+
+/**
+ * Returns the region that defines the shape of the control,
+ * or null if the control has the default shape.
+ *
+ * @return the region that defines the shape of the shell (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>
+ *
+ * @since 3.4
+ */
+public Region getRegion () {
+ checkWidget ();
+ return region;
+}
+
+/**
+ * Returns the receiver's shell. For all controls other than
+ * shells, this simply returns the control's nearest ancestor
+ * shell. Shells return themselves, even if they are children
+ * of other shells.
+ *
+ * @return the receiver's shell
+ *
+ * @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 #getParent
+ */
+public Shell getShell () {
+ checkWidget ();
+ return parent.getShell ();
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @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 Point getSize () {
+ checkWidget ();
+ int topHandle = topHandle ();
+ int width = (int) OS.FrameworkElement_Width (topHandle);
+ int height = (int) OS.FrameworkElement_Height (topHandle);
+ return new Point (width, height);
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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 getToolTipText () {
+ checkWidget ();
+ return toolTipText;
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public Transform getTransform () {
+ int transform = OS.FrameworkElement_RenderTransform (handle);
+ int matrix = OS.MatrixTransform_Matrix (transform);
+ OS.GCHandle_Free (transform);
+ float m11 = (float) OS.Matrix_M11 (matrix);
+ float m12 = (float) OS.Matrix_M12 (matrix);
+ float m21 = (float) OS.Matrix_M21 (matrix);
+ float m22 = (float) OS.Matrix_M22 (matrix);
+ float dx = (float) OS.Matrix_OffsetX (matrix);
+ float dy = (float) OS.Matrix_OffsetY (matrix);
+ OS.GCHandle_Free (matrix);
+ //TODO - leaking
+ return new Transform (display, m11, m12, m21, m22, dx, dy);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible, and
+ * <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's visibility 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>
+ */
+public boolean getVisible () {
+ checkWidget ();
+ return OS.UIElement_Visibility (topHandle ()) == OS.Visibility_Visible;
+}
+
+Control getWidgetControl () {
+ return this;
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_KeyEventHandler (jniRef, "HandlePreviewKeyDown");
+ OS.UIElement_PreviewKeyDown (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_KeyEventHandler (jniRef, "HandlePreviewKeyUp");
+ OS.UIElement_PreviewKeyUp (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_TextCompositionEventHandler (jniRef, "HandlePreviewTextInput");
+ OS.UIElement_PreviewTextInput (handle, handler);
+ OS.GCHandle_Free (handler);
+
+ int topHandle = topHandle ();
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandlePreviewMouseDown");
+ OS.UIElement_PreviewMouseDown (topHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandlePreviewMouseUp");
+ OS.UIElement_PreviewMouseUp (topHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseEventHandler (jniRef, "HandleMouseEnter");
+ OS.UIElement_MouseEnter (topHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseEventHandler (jniRef, "HandleMouseLeave");
+ OS.UIElement_MouseLeave (topHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseEventHandler (jniRef, "HandlePreviewMouseMove");
+ OS.UIElement_PreviewMouseMove (topHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseWheelEventHandler (jniRef, "HandlePreviewMouseWheel");
+ OS.UIElement_PreviewMouseWheel (topHandle, handler);
+ OS.GCHandle_Free (handler);
+
+ handler = OS.gcnew_KeyboardFocusChangedEventHandler (jniRef, "HandlePreviewGotKeyboardFocus");
+ OS.UIElement_PreviewGotKeyboardFocus (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_KeyboardFocusChangedEventHandler (jniRef, "HandleLostKeyboardFocus");
+ OS.UIElement_LostKeyboardFocus (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_ContextMenuEventHandler (jniRef, "HandleContextMenuOpening");
+ OS.FrameworkElement_ContextMenuOpening (handle, handler);
+ OS.GCHandle_Free (handler);
+
+ handler = OS.gcnew_SizeChangedEventHandler(jniRef, "HandleSizeChanged");
+ OS.FrameworkElement_SizeChanged (topHandle, handler);
+ OS.GCHandle_Free (handler);
+
+ int typeid = OS.Canvas_typeid();
+ handler = OS.gcnew_EventHandler(jniRef, "HandleTopChanged");
+ int property = OS.Canvas_TopProperty();
+ int dpd = OS.DependencyPropertyDescriptor_FromProperty(property, typeid);
+ OS.DependencyPropertyDescriptor_AddValueChanged(dpd, topHandle, handler);
+ OS.GCHandle_Free(handler);
+ OS.GCHandle_Free(property);
+ OS.GCHandle_Free(dpd);
+ handler = OS.gcnew_EventHandler(jniRef, "HandleLeftChanged");
+ property = OS.Canvas_LeftProperty();
+ dpd = OS.DependencyPropertyDescriptor_FromProperty(property, typeid);
+ OS.DependencyPropertyDescriptor_AddValueChanged(dpd, topHandle, handler);
+ OS.GCHandle_Free(handler);
+ OS.GCHandle_Free(property);
+ OS.GCHandle_Free(dpd);
+ OS.GCHandle_Free(typeid);
+}
+
+void HandleLeftChanged (int sender, int e) {
+ int topHandle = topHandle();
+ int x = (int)OS.Canvas_GetLeft(topHandle);
+ int y = (int)OS.Canvas_GetTop(topHandle);
+ if (x != this.x || y != this.y) {
+ this.x = x;
+ this.y = y;
+ sendEvent(SWT.Move);
+ }
+}
+
+void HandleTopChanged (int sender, int e) {
+ int topHandle = topHandle();
+ int x = (int)OS.Canvas_GetLeft(topHandle);
+ int y = (int)OS.Canvas_GetTop(topHandle);
+ if (x != this.x || y != this.y) {
+ this.x = x;
+ this.y = y;
+ sendEvent(SWT.Move);
+ }
+}
+
+void HandleContextMenuOpening (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int mouse = OS.Mouse_GetPosition (handle);
+ int x = (int) OS.Point_X (mouse);
+ int y = (int) OS.Point_Y (mouse);
+ OS.GCHandle_Free (mouse);
+ Point point = display.map (this, null, x, y);
+ showMenu (point.x, point.y);
+ OS.RoutedEventArgs_Handled (e, true);
+}
+
+void HandlePreviewGotKeyboardFocus (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (OS.UIElement_IsKeyboardFocusWithin (handle)) return;
+ sendFocusEvent (SWT.FocusIn);
+}
+
+void HandleLostKeyboardFocus (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (OS.UIElement_IsKeyboardFocusWithin (handle)) return;
+ sendFocusEvent (SWT.FocusOut);
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ if (!checkEvent (e)) return;
+
+ if (display.dragDetectFrame != 0) {
+ if (OS.KeyEventArgs_Key (e) == OS.Key_Escape) {
+ OS.DispatcherFrame_Continue (display.dragDetectFrame, false);
+ }
+ }
+
+ /* Let OS handle mnemonics for now */
+// if (translateMnemonic (e)) {
+// OS.RoutedEventArgs_Handled (e, true);
+// return;
+// }
+ if (translateTraversal (e)) {
+ OS.RoutedEventArgs_Handled (e, true);
+ return;
+ }
+ sendKeyEvent (SWT.KeyDown, e, false);
+}
+
+void HandlePreviewKeyUp (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendKeyEvent (SWT.KeyUp, e, false);
+}
+
+void HandlePreviewMouseDown (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if ((state & CANVAS) != 0) {
+ OS.UIElement_CaptureMouse (handle);
+ }
+
+ if (OS.MouseButtonEventArgs_ChangedButton (e) == 0 && OS.MouseButtonEventArgs_ClickCount (e) == 1) {
+ if ((state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect)) {
+ int point = OS.MouseEventArgs_GetPosition (e, handle);
+ double x = OS.Point_X (point);
+ double y = OS.Point_Y (point);
+ OS.GCHandle_Free (point);
+ display.dragMouseDown = OS.GCHandle_Alloc (e);
+ dragDetect (x, y, true);
+ }
+ }
+
+ sendMouseEvent (SWT.MouseDown, e, false);
+}
+
+void HandlePreviewMouseUp (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if ((state & CANVAS) != 0) {
+ OS.UIElement_ReleaseMouseCapture (handle);
+ }
+ if (display.dragDetectFrame != 0) {
+ OS.DispatcherFrame_Continue (display.dragDetectFrame, false);
+ }
+ sendMouseEvent (SWT.MouseUp, e, false);
+}
+
+void HandleMouseEnter (int sender, int e) {
+ if (!checkEvent (e)) return;
+ Control control = display.getCursorControl ();
+ if (control != this) return;
+
+ Control lastMouseControl = display.mouseControl;
+ if (lastMouseControl != null && !lastMouseControl.isDisposed() && lastMouseControl != this) {
+ if (OS.Visual_IsDescendantOf (topHandle (), lastMouseControl.topHandle())) {
+ lastMouseControl.sendMouseEvent (SWT.MouseExit, e, false);
+ }
+ }
+ display.mouseControl = this;
+ sendMouseEvent (SWT.MouseEnter, e, false);
+}
+
+void HandleMouseLeave (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (this != display.mouseControl) return;
+ sendMouseEvent (SWT.MouseExit, e, false);
+}
+
+void HandlePreviewMouseMove (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (display.dragDetectFrame != 0) {
+ OS.RoutedEventArgs_Handled (e, true);
+ int point = OS.MouseEventArgs_GetPosition (e, handle);
+ boolean contains = OS.Rect_Contains (display.dragRect, point);
+ OS.GCHandle_Free (point);
+ if (!contains) {
+ display.dragging = true;
+ OS.DispatcherFrame_Continue (display.dragDetectFrame, false);
+ if (display.dragMouseDown != 0) {
+ sendDragEvent (display.dragMouseDown);
+ OS.GCHandle_Free (display.dragMouseDown);
+ display.dragMouseDown = 0;
+ }
+ }
+ return;
+ }
+ Control lastMouseControl = display.mouseControl;
+ if (lastMouseControl != null && !lastMouseControl.isDisposed() && lastMouseControl != this) {
+ if (OS.Visual_IsAncestorOf (topHandle (), lastMouseControl.topHandle ())) {
+ sendMouseEvent (SWT.MouseEnter, e, false);
+ }
+ }
+ display.mouseControl = this;
+ sendMouseEvent (SWT.MouseMove, e, false);
+}
+
+void HandlePreviewMouseWheel (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendMouseEvent (SWT.MouseWheel, e, false);
+}
+
+void HandlePreviewTextInput(int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendKeyEvent (SWT.KeyDown, e, true);
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int topHandle = topHandle();
+ int width = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ if (this.width != width || this.height != height) {
+ this.width = width;
+ this.height = height;
+ resized ();
+ }
+}
+
+void resized () {
+ sendEvent (SWT.Resize);
+}
+
+boolean hasFocus () {
+// return OS.UIElement_IsFocused (handle);
+// return OS.UIElement_IsKeyboardFocused (handle);
+ return display.getFocusControl() == this;
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Control</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public int internal_new_GC (GCData data) {
+ checkWidget();
+ int drawingContext = data != null ? data.drawingContext : 0;
+ int visual = handle;
+ double width = OS.FrameworkElement_ActualWidth (handle);
+ double height = OS.FrameworkElement_ActualHeight (handle);
+ int rect = OS.gcnew_Rect (0, 0, width, height);
+ int clip = OS.gcnew_RectangleGeometry (rect);
+ if (drawingContext != 0) {
+ OS.DrawingContext_PushClip(drawingContext, clip);
+ } else {
+ if ((state & CANVAS) != 0) {
+ visual = OS.SWTCanvas_Visual (handle);
+ if (visual == 0) {
+ visual = OS.gcnew_DrawingVisual();
+ if (visual == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.SWTCanvas_Visual (handle, visual);
+ }
+ } else {
+ visual = OS.gcnew_DrawingVisual();
+ if (visual == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ }
+ OS.ContainerVisual_Clip (visual, clip);
+ int dc = OS.DrawingVisual_RenderOpen (visual);
+ if (dc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ drawingContext = dc;
+ int drawing = OS.DrawingVisual_Drawing(visual);
+ OS.DrawingContext_DrawDrawing(drawingContext, drawing);
+ OS.GCHandle_Free(drawing);
+ }
+ OS.GCHandle_Free (rect);
+ OS.GCHandle_Free (clip);
+ if (data != null) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) == 0) {
+ data.style |= style & (mask | SWT.MIRRORED);
+ }
+ data.device = display;
+ data.foreground = getForegroundColor ();
+ Control control = findBackgroundControl ();
+ if (control == null) control = this;
+ data.background = control.getBackgroundColor ();
+ data.font = font != null ? font : defaultFont ();
+ data.visual = visual;
+ }
+ return drawingContext;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Control</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (int dc, GCData data) {
+ checkWidget ();
+ if (data != null && data.drawingContext == 0) {
+ OS.DrawingContext_Close (dc);
+ OS.GCHandle_Free (dc);
+ OS.GCHandle_Free (data.visual);
+ }
+}
+
+boolean isActive () {
+// Shell dialogShell = display.getModalDialogShell ();
+// if (dialogShell != null && dialogShell != getShell ()) {
+// return false;
+// }
+ Shell shell = null;
+ Shell [] modalShells = display.modalShells;
+ if (modalShells != null) {
+ int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+ int index = modalShells.length;
+ while (--index >= 0) {
+ Shell modal = modalShells [index];
+ if (modal != null) {
+ if ((modal.style & bits) != 0) {
+ Control control = this;
+ while (control != null) {
+ if (control == modal) break;
+ control = control.parent;
+ }
+ if (control != modal) return false;
+ break;
+ }
+ if ((modal.style & SWT.PRIMARY_MODAL) != 0) {
+ if (shell == null) shell = getShell ();
+ if (modal.parent == shell) return false;
+ }
+ }
+ }
+ }
+ if (shell == null) shell = getShell ();
+ return shell.getEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are enabled. Otherwise, <code>false</code> is returned.
+ * A disabled control is typically not selectable from the user
+ * interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget ();
+ return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver has the user-interface
+ * focus, and <code>false</code> otherwise.
+ *
+ * @return the receiver's focus 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>
+ */
+public boolean isFocusControl () {
+ checkWidget ();
+ return hasFocus ();
+}
+
+boolean isFocusAncestor (Control control) {
+ while (control != null && control != this && !(control instanceof Shell)) {
+ control = control.parent;
+ }
+ return control == this;
+}
+
+/**
+ * Returns <code>true</code> if the underlying operating
+ * system supports this reparenting, otherwise <code>false</code>
+ *
+ * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
+ *
+ * @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 boolean isReparentable () {
+ checkWidget ();
+ return false;
+}
+
+boolean isShowing () {
+ /*
+ * This is not complete. Need to check if the
+ * widget is obscurred by a parent or sibling.
+ */
+ if (!isVisible ()) return false;
+ Control control = this;
+ while (control != null) {
+ Point size = control.getSize ();
+ if (size.x == 0 || size.y == 0) {
+ return false;
+ }
+ control = control.parent;
+ }
+ return true;
+ /*
+ * Check to see if current damage is included.
+ */
+// if (!OS.IsWindowVisible (handle)) return false;
+// int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS;
+// int hDC = OS.GetDCEx (handle, 0, flags);
+// int result = OS.GetClipBox (hDC, new RECT ());
+// OS.ReleaseDC (handle, hDC);
+// return result != OS.NULLREGION;
+}
+
+boolean isTabGroup () {
+ Control [] tabList = parent._getTabList ();
+ if (tabList != null) {
+ for (int i=0; i<tabList.length; i++) {
+ if (tabList [i] == this) return true;
+ }
+ }
+ int code = traversalCode (0, 0);
+ if ((code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0) return false;
+ return (code & (SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_TAB_NEXT)) != 0;
+}
+
+boolean isTabItem () {
+ Control [] tabList = parent._getTabList ();
+ if (tabList != null) {
+ for (int i=0; i<tabList.length; i++) {
+ if (tabList [i] == this) return false;
+ }
+ }
+ int code = traversalCode (0, 0);
+ return (code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are visible. Otherwise, <code>false</code> is returned.
+ *
+ * @return the receiver's visibility 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 #getVisible
+ */
+public boolean isVisible () {
+ checkWidget ();
+ int topHandle = topHandle ();
+ updateLayout (topHandle);
+ return OS.UIElement_IsVisible (topHandle);
+}
+
+void markLayout (boolean changed, boolean all) {
+ /* Do nothing */
+}
+
+Decorations menuShell () {
+ return parent.menuShell ();
+}
+
+boolean mnemonicHit (char key) {
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ return false;
+}
+
+/**
+ * Moves the receiver above the specified control in the
+ * drawing order. If the argument is null, then the receiver
+ * is moved to the top of the drawing order. The control at
+ * the top of the drawing order will not be covered by other
+ * controls even if they occupy intersecting areas.
+ *
+ * @param control the sibling control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</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>
+ *
+ * @see Control#moveBelow
+ * @see Composite#getChildren
+ */
+public void moveAbove (Control control) {
+ checkWidget ();
+ if (parent == null) return; //TODO
+ if (control != null) {
+ if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (parent != control.parent) return;
+ }
+ int index;
+ int parentHandle = parent.parentingHandle ();
+ int children = OS.Panel_Children (parentHandle);
+ if (control != null) {
+ index = OS.UIElementCollection_IndexOf (children, control.topHandle ());
+ } else {
+ index = OS.UIElementCollection_Count (children) - 1;
+ }
+ int topHandle = topHandle ();
+ if (OS.UIElementCollection_IndexOf (children, topHandle) < index) {
+ OS.UIElementCollection_Remove (children, topHandle);
+ OS.UIElementCollection_Insert (children, index, topHandle);
+ }
+ OS.GCHandle_Free (children);
+}
+
+/**
+ * Moves the receiver below the specified control in the
+ * drawing order. If the argument is null, then the receiver
+ * is moved to the bottom of the drawing order. The control at
+ * the bottom of the drawing order will be covered by all other
+ * controls which occupy intersecting areas.
+ *
+ * @param control the sibling control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</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>
+ *
+ * @see Control#moveAbove
+ * @see Composite#getChildren
+ */
+public void moveBelow (Control control) {
+ checkWidget ();
+ if (parent == null) return; //TODO
+ if (control != null) {
+ if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (parent != control.parent) return;
+ }
+ int index;
+ int parentHandle = parent.parentingHandle ();
+ int children = OS.Panel_Children (parentHandle);
+ if (control != null) {
+ index = Math.max (0, OS.UIElementCollection_IndexOf (children, control.topHandle ()) - 1);
+ } else {
+ if (parentHandle != parent.handle) {
+ index = 1;
+ } else {
+ index = 0;
+ }
+ }
+ int topHandle = topHandle ();
+ if (OS.UIElementCollection_IndexOf (children, topHandle) > index) {
+ OS.UIElementCollection_Remove (children, topHandle);
+ OS.UIElementCollection_Insert (children, index, topHandle);
+ }
+ OS.GCHandle_Free (children);
+}
+
+Accessible new_Accessible (Control control) {
+ return Accessible.internal_new_Accessible (this);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @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 #computeSize(int, int, boolean)
+ */
+public void pack () {
+ checkWidget ();
+ pack (true);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ * <p>
+ * If the changed flag is <code>true</code>, it indicates that the receiver's
+ * <em>contents</em> have changed, therefore any caches that a layout manager
+ * containing the control may have been keeping need to be flushed. When the
+ * control is resized, the changed flag will be <code>false</code>, so layout
+ * manager caches can be retained.
+ * </p>
+ *
+ * @param changed whether or not the receiver's contents have changed
+ *
+ * @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 #computeSize(int, int, boolean)
+ */
+public void pack (boolean changed) {
+ checkWidget ();
+ setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
+}
+
+/**
+ * Prints the receiver and all children.
+ *
+ * @param gc the gc where the drawing occurs
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</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>
+ *
+ * @since 3.4
+ */
+public boolean print (GC gc) {
+ checkWidget ();
+ if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ return false;
+}
+
+/**
+ * Causes the entire bounds of the receiver to be marked
+ * as needing to be redrawn. The next time a paint request
+ * is processed, the control will be completely painted,
+ * including the background.
+ *
+ * @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 #update()
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#DOUBLE_BUFFERED
+ */
+public void redraw () {
+ checkWidget ();
+ redraw (false);
+}
+
+void redraw (boolean all) {
+// checkWidget ();
+ //TODO InvalidateVisual invalidates the entire visual tree
+ OS.UIElement_InvalidateVisual (topHandle ());
+ OS.UIElement_InvalidateVisual (handle);
+}
+
+/**
+ * Causes the rectangular area of the receiver specified by
+ * the arguments to be marked as needing to be redrawn.
+ * The next time a paint request is processed, that area of
+ * the receiver will be painted, including the background.
+ * If the <code>all</code> flag is <code>true</code>, any
+ * children of the receiver which intersect with the specified
+ * area will also paint their intersecting areas. If the
+ * <code>all</code> flag is <code>false</code>, the children
+ * will not be painted.
+ *
+ * @param x the x coordinate of the area to draw
+ * @param y the y coordinate of the area to draw
+ * @param width the width of the area to draw
+ * @param height the height of the area to draw
+ * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
+ *
+ * @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 #update()
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#DOUBLE_BUFFERED
+ */
+public void redraw (int x, int y, int width, int height, boolean all) {
+ checkWidget ();
+ if (width <= 0 || height <= 0) return;
+ //TODO redraw only rect
+ redraw(true);
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+void releaseParent () {
+ parent.removeControl (this);
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+// if (toolTipText != null) {
+// setToolTipText (getShell (), null);
+// }
+ toolTipText = null;
+ if (menu != null && !menu.isDisposed ()) {
+ menu.dispose ();
+ }
+ menu = null;
+ cursor = null;
+ layoutData = null;
+ if (accessible != null) {
+ accessible.internal_dispose_Accessible ();
+ }
+ accessible = null;
+ region = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag gesture occurs.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @since 3.3
+ */
+public void removeDragDetectListener(DragDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.DragDetect, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control gains or loses focus.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see FocusListener
+ * @see #addFocusListener
+ */
+public void removeFocusListener(FocusListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.FocusIn, listener);
+ eventTable.unhook (SWT.FocusOut, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.KeyUp, listener);
+ eventTable.unhook (SWT.KeyDown, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the platform-specific context menu trigger has
+ * occurred.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MenuDetectListener
+ * @see #addMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void removeMenuDetectListener (MenuDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MenuDetect, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MouseTrackListener
+ * @see #addMouseTrackListener
+ */
+public void removeMouseTrackListener(MouseTrackListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseEnter, listener);
+ eventTable.unhook (SWT.MouseExit, listener);
+ eventTable.unhook (SWT.MouseHover, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when mouse buttons are pressed and released.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MouseListener
+ * @see #addMouseListener
+ */
+public void removeMouseListener (MouseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseDown, listener);
+ eventTable.unhook (SWT.MouseUp, listener);
+ eventTable.unhook (SWT.MouseDoubleClick, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse moves.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MouseMoveListener
+ * @see #addMouseMoveListener
+ */
+public void removeMouseMoveListener(MouseMoveListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseMove, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse wheel is scrolled.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MouseWheelListener
+ * @see #addMouseWheelListener
+ *
+ * @since 3.3
+ */
+public void removeMouseWheelListener (MouseWheelListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseWheel, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver needs to be painted.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see PaintListener
+ * @see #addPaintListener
+ */
+public void removePaintListener(PaintListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook(SWT.Paint, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when traversal events occur.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see TraverseListener
+ * @see #addTraverseListener
+ */
+public void removeTraverseListener(TraverseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Traverse, listener);
+}
+
+boolean sendFocusEvent (int type) {
+ Shell shell = getShell ();
+
+ Display display = this.display;
+ display.focusControl = this;
+ sendEvent (type);
+ display.focusControl = null;
+
+ /*
+ * It is possible that the shell may be
+ * disposed at this point. If this happens
+ * don't send the activate and deactivate
+ * events.
+ */
+ if (!shell.isDisposed ()) {
+ switch (type) {
+ case SWT.FocusIn:
+ shell.setActiveControl (this);
+ break;
+ case SWT.FocusOut:
+ if (shell != display.getActiveShell ()) {
+ shell.setActiveControl (null);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on Windows the background of a Button cannot be changed.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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 setBackground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ if (background != 0 && OS.Object_Equals (color.handle, background)) return;
+ background = color.handle;
+ } else {
+ if (background == 0) return;
+ background = 0;
+ }
+ setBackground ();
+// updateBackgroundColor ();
+}
+
+int backgroundHandle () {
+ return handle;
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+void setBackground () {
+ int backgroundHandle = backgroundHandle ();
+ int property = backgroundProperty ();
+ int brush = 0;
+ if ((state & PARENT_BACKGROUND) == 0) {
+ if (backgroundImage != null) {
+ int imageHandle = backgroundImage.handle;
+ brush = OS.gcnew_ImageBrush (imageHandle);
+ OS.TileBrush_TileMode (brush, OS.TileMode_Tile);
+ OS.TileBrush_Stretch (brush, OS.Stretch_Fill);
+ OS.TileBrush_ViewportUnits (brush, OS.BrushMappingMode_Absolute);
+ int rect = OS.gcnew_Rect (0, 0, OS.BitmapSource_PixelWidth (imageHandle), OS.BitmapSource_PixelHeight (imageHandle));
+ OS.TileBrush_Viewport (brush, rect);
+ OS.GCHandle_Free (rect);
+ } else {
+ int color = background;
+ if (color == 0) {
+ color = defaultBackground ();
+ if ((state & THEME_BACKGROUND) != 0) {
+ Control themeControl = findThemeControl ();
+ if (themeControl != null) {
+ if (color != 0) {
+ /*
+ * Feature in WPF. If the control does not have a background
+ * brush it does not receive input events.
+ * The fix is to set a transparent background.
+ */
+ color = OS.Colors_Transparent;
+ }
+ }
+ }
+ }
+ if (color != 0) {
+ brush = OS.gcnew_SolidColorBrush (color);
+ }
+ }
+ }
+ if (brush != 0) {
+ OS.DependencyObject_SetValue (backgroundHandle, property, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ OS.DependencyObject_ClearValue (backgroundHandle, property);
+ }
+ OS.GCHandle_Free (property);
+}
+
+/**
+ * Sets the receiver's background image to the image specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null. The background image is tiled to fill
+ * the available space.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on Windows the background of a Button cannot be changed.
+ * </p>
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</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>
+ *
+ * @since 3.2
+ */
+public void setBackgroundImage (Image image) {
+ checkWidget ();
+ if (image != null) {
+ if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (backgroundImage == image) return;
+ backgroundImage = image;
+ setBackground ();
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The <code>x</code> and
+ * <code>y</code> arguments are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the <code>x</code>
+ * and <code>y</code> arguments are relative to the display.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @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 setBounds (int x, int y, int width, int height) {
+ checkWidget ();
+ int flags = MOVED | RESIZED;
+ setBounds (x, y, Math.max (0, width), Math.max (0, height), flags);
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = 0;
+ int topHandle = topHandle ();
+ if ((flags & MOVED) != 0) {
+ int oldX = (int) OS.Canvas_GetLeft (topHandle);
+ int oldY = (int) OS.Canvas_GetTop (topHandle);
+ if (oldX != x) {
+ this.x = x;
+ OS.Canvas_SetLeft (topHandle, x);
+ }
+ if (oldY != y) {
+ this.y = y;
+ OS.Canvas_SetTop (topHandle, y);
+ }
+ if (oldX != x || oldY != y) {
+ sendEvent (SWT.Move);
+ if (isDisposed ()) return 0;
+ result |= MOVED;
+ }
+ }
+ if ((flags & RESIZED) != 0) {
+ int oldWidth = (int) OS.FrameworkElement_Width (topHandle);
+ int oldHeight = (int) OS.FrameworkElement_Height (topHandle);
+ if (oldWidth != width) {
+ this.width = width;
+ OS.FrameworkElement_Width (topHandle, width);
+ }
+ if (oldHeight != height) {
+ this.height = height;
+ OS.FrameworkElement_Height (topHandle, height);
+ }
+ if (oldWidth != width || oldHeight != height) {
+ sendEvent (SWT.Resize);
+ if (isDisposed ()) return 0;
+ result |= RESIZED;
+ }
+ }
+ return result;
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The <code>x</code> and
+ * <code>y</code> fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @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 setBounds (Rectangle rect) {
+ checkWidget ();
+ if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * If the argument is <code>true</code>, causes the receiver to have
+ * all mouse events delivered to it until the method is called with
+ * <code>false</code> as the argument. Note that on some platforms,
+ * a mouse button must currently be down for capture to be assigned.
+ *
+ * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
+ *
+ * @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 setCapture (boolean capture) {
+ checkWidget ();
+ if (capture) {
+ OS.UIElement_CaptureMouse (handle);
+ } else {
+ OS.UIElement_ReleaseMouseCapture (handle);
+ }
+}
+
+/**
+ * Sets the receiver's cursor to the cursor specified by the
+ * argument, or to the default cursor for that kind of control
+ * if the argument is null.
+ * <p>
+ * When the mouse pointer passes over a control its appearance
+ * is changed to match the control's cursor.
+ * </p>
+ *
+ * @param cursor the new cursor (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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 setCursor (Cursor cursor) {
+ checkWidget ();
+ if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.cursor = cursor;
+ if (cursor != null) {
+ OS.FrameworkElement_Cursor (handle, cursor.handle);
+ } else {
+ int property = OS.FrameworkElement_CursorProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the receiver's drag detect state. If the argument is
+ * <code>true</code>, the receiver will detect drag gestures,
+ * otherwise these gestures will be ignored.
+ *
+ * @param dragDetect the new drag detect 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>
+ *
+ * @since 3.3
+ */
+public void setDragDetect (boolean dragDetect) {
+ checkWidget ();
+ if (dragDetect) {
+ state |= DRAG_DETECT;
+ } else {
+ state &= ~DRAG_DETECT;
+ }
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public void setEffect(Effect effect){
+ checkWidget ();
+ if (effect != null && effect.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (effect != null) {
+ OS.UIElement_BitmapEffect (handle, effect.handle);
+ OS.UIElement_ClipToBounds (topHandle (), false);
+ } else {
+ OS.UIElement_BitmapEffect (handle, 0);
+ setClipping();
+ }
+// updateLayout(handle);
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled 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>
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ if (((state & DISABLED) == 0) == enabled) return;
+ /*
+ * Feature in Windows. If the receiver has focus, disabling
+ * the receiver causes no window to have focus. The fix is
+ * to assign focus to the first ancestor window that takes
+ * focus. If no window will take focus, set focus to the
+ * desktop.
+ */
+ Control control = null;
+ boolean fixFocus = false;
+ if (!enabled) {
+// if (display.focusEvent != SWT.FocusOut) {
+ control = display.getFocusControl ();
+ fixFocus = isFocusAncestor (control);
+// }
+ }
+ if (enabled) {
+ state &= ~DISABLED;
+ } else {
+ state |= DISABLED;
+ }
+ enableWidget (enabled);
+ if (fixFocus) fixFocus (control);
+}
+
+/**
+ * Causes the receiver to have the <em>keyboard focus</em>,
+ * such that all keyboard events will be delivered to it. Focus
+ * reassignment will respect applicable platform constraints.
+ *
+ * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
+ *
+ * @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 #forceFocus
+ */
+public boolean setFocus () {
+ checkWidget ();
+ if ((style & SWT.NO_FOCUS) != 0) return false;
+ return forceFocus ();
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * to the font specified by the argument, or to the default font for that
+ * kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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 setFont (Font font) {
+ checkWidget ();
+ if (font != null) {
+ if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.font = font;
+ if (font == null) font = defaultFont();
+ setFont (font.handle, font.size);
+}
+
+void setFont (int font, double size) {
+ if (font != 0) {
+ int fontFamily = OS.Typeface_FontFamily( font);
+ int style = OS.Typeface_Style (font);
+ int weight = OS.Typeface_Weight (font);
+ int stretch = OS.Typeface_Stretch (font);
+ OS.Control_FontFamily (handle, fontFamily);
+ OS.Control_FontStyle (handle, style);
+ OS.Control_FontWeight (handle, weight);
+ OS.Control_FontStretch (handle, stretch);
+ OS.Control_FontSize (handle, size);
+ OS.GCHandle_Free (fontFamily);
+ OS.GCHandle_Free (style);
+ OS.GCHandle_Free (weight);
+ OS.GCHandle_Free (stretch);
+ } else {
+ int property = OS.Control_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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 setForeground (Color color) {
+ checkWidget ();
+ int brush = 0;
+ if (color != null) {
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (foreground != 0 && OS.Object_Equals (color.handle, foreground)) return;
+ foreground = color.handle;
+ brush = OS.gcnew_SolidColorBrush (foreground);
+ } else {
+ if (foreground == 0) return;
+ foreground = 0;
+ }
+ setForegroundBrush (brush);
+ if (brush != 0) OS.GCHandle_Free (brush);
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the layout data associated with the receiver to the argument.
+ *
+ * @param layoutData the new layout data for the receiver.
+ *
+ * @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 setLayoutData (Object layoutData) {
+ checkWidget ();
+ this.layoutData = layoutData;
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @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 setLocation (int x, int y) {
+ checkWidget ();
+ int flags = MOVED;
+ setBounds (x, y, 0, 0, flags);
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @param location the new location for the receiver
+ *
+ * @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 setLocation (Point location) {
+ checkWidget ();
+ if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's pop up menu to the argument.
+ * All controls may optionally have a pop up
+ * menu that is displayed when the user requests one for
+ * the control. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pop up
+ * menu is platform specific.
+ * <p>
+ * Note: Disposing of a control that has a pop up menu will
+ * dispose of the menu. To avoid this behavior, set the
+ * menu to null before the control is disposed.
+ * </p>
+ *
+ * @param menu the new pop up menu
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
+ * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</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 setMenu (Menu menu) {
+ checkWidget ();
+ if (menu != null) {
+ if (menu.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if ((menu.style & SWT.POP_UP) == 0) {
+ error (SWT.ERROR_MENU_NOT_POP_UP);
+ }
+ if (menu.parent != menuShell ()) {
+ error (SWT.ERROR_INVALID_PARENT);
+ }
+ }
+ this.menu = menu;
+ OS.FrameworkElement_ContextMenu(handle, menu != null ? menu.handle : 0);
+}
+
+/**
+ * If the argument is <code>false</code>, causes subsequent drawing
+ * operations in the receiver to be ignored. No drawing of any kind
+ * can occur in the receiver until the flag is set to true.
+ * Graphics operations that occurred while the flag was
+ * <code>false</code> are lost. When the flag is set to <code>true</code>,
+ * the entire widget is marked as needing to be redrawn. Nested calls
+ * to this method are stacked.
+ * <p>
+ * Note: This operation is a hint and may not be supported on some
+ * platforms or for some widgets.
+ * </p>
+ *
+ * @param redraw the new redraw 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 #redraw(int, int, int, int, boolean)
+ * @see #update()
+ */
+public void setRedraw (boolean redraw) {
+ checkWidget ();
+ /*
+ * Feature in Windows. When WM_SETREDRAW is used to turn
+ * off drawing in a widget, it clears the WS_VISIBLE bits
+ * and then sets them when redraw is turned back on. This
+ * means that WM_SETREDRAW will make a widget unexpectedly
+ * visible. The fix is to track the visibility state while
+ * drawing is turned off and restore it when drawing is
+ * turned back on.
+ */
+// if (drawCount == 0) {
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN;
+// }
+// if (redraw) {
+// if (--drawCount == 0) {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// if ((state & HIDDEN) != 0) {
+// state &= ~HIDDEN;
+// OS.ShowWindow (handle, OS.SW_HIDE);
+// } else {
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, null, true);
+// } else {
+// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+// }
+// }
+// } else {
+// if (drawCount++ == 0) {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// }
+ redraw ();
+}
+
+/**
+ * Sets the shape of the control to the region specified
+ * by the argument. When the argument is null, the
+ * default shape of the control is restored.
+ *
+ * @param region the region that defines the shape of the control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</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>
+ *
+ * @since 3.4
+ */
+public void setRegion (Region region) {
+ checkWidget ();
+ if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ OS.UIElement_Clip (topHandle (), region.handle);
+ this.region = region;
+}
+
+boolean setSavedFocus () {
+ return forceFocus ();
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @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 setSize (int width, int height) {
+ checkWidget ();
+ int flags = RESIZED;
+ setBounds (0, 0, Math.max (0, width), Math.max (0, height), flags);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ * </p>
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+boolean setTabGroupFocus () {
+ return setTabItemFocus ();
+}
+
+boolean setTabItemFocus () {
+ if (!isShowing ()) return false;
+ return forceFocus ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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 setToolTipText (String string) {
+ checkWidget ();
+ toolTipText = string;
+ if (string != null && string.length() == 0) string = null;
+ int strPtr = createDotNetString (string, false);
+ OS.FrameworkElement_ToolTip (handle, strPtr);
+ if (strPtr != 0) OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+ */
+public void setTransform (Transform t) {
+ checkWidget ();
+ if (t == null) {
+ OS.FrameworkElement_RenderTransform (handle, 0);
+ return;
+ }
+ int matrixTransform = OS.gcnew_MatrixTransform (t.handle);
+// OS.FrameworkElement_LayoutTransform (handle, matrixTransform);
+ OS.FrameworkElement_RenderTransform (handle, matrixTransform);
+ OS.GCHandle_Free (matrixTransform);
+}
+
+/**
+ * Marks the receiver as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility 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>
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ int topHandle = topHandle ();
+ if ((OS.UIElement_Visibility (topHandle) == OS.Visibility_Visible) == visible) return;
+ if (visible) {
+ sendEvent (SWT.Show);
+ if (isDisposed ()) return;
+ }
+
+ /*
+ * Feature in Windows. If the receiver has focus, hiding
+ * the receiver causes no window to have focus. The fix is
+ * to assign focus to the first ancestor window that takes
+ * focus. If no window will take focus, set focus to the
+ * desktop.
+ */
+ Control control = null;
+ boolean fixFocus = false;
+ if (!visible) {
+// if (display.focusEvent != SWT.FocusOut) {
+ control = display.getFocusControl ();
+ fixFocus = isFocusAncestor (control);
+// }
+ }
+ OS.UIElement_Visibility (topHandle, visible ? OS.Visibility_Visible : OS.Visibility_Hidden);
+ if (isDisposed ()) return;
+ if (!visible) {
+ sendEvent (SWT.Hide);
+ if (isDisposed ()) return;
+ }
+ if (fixFocus) fixFocus (control);
+}
+
+void sort (int [] items) {
+ /* Shell Sort from K&R, pg 108 */
+ int length = items.length;
+ for (int gap=length/2; gap>0; gap/=2) {
+ for (int i=gap; i<length; i++) {
+ for (int j=i-gap; j>=0; j-=gap) {
+ if (items [j] <= items [j + gap]) {
+ int swap = items [j];
+ items [j] = items [j + gap];
+ items [j + gap] = swap;
+ }
+ }
+ }
+ }
+}
+
+void sortAscending (int [] items) {
+ /* Shell Sort from K&R, pg 108 */
+ int length = items.length;
+ for (int gap=length/2; gap>0; gap/=2) {
+ for (int i=gap; i<length; i++) {
+ for (int j=i-gap; j>=0; j-=gap) {
+ if (items [j] >= items [j + gap]) {
+ int swap = items [j];
+ items [j] = items [j + gap];
+ items [j + gap] = swap;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in display relative coordinates,
+ * to coordinates relative to the receiver.
+ * <p>
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public Point toControl (int x, int y) {
+ checkWidget ();
+ return display.map (null, this, x, y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in display relative coordinates,
+ * to coordinates relative to the receiver.
+ * <p>
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 Point toControl (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return toControl (point.x, point.y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in coordinates relative to
+ * the receiver, to display relative coordinates.
+ * <p>
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public Point toDisplay (int x, int y) {
+ checkWidget ();
+ return display.map (this, null, x, y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in coordinates relative to
+ * the receiver, to display relative coordinates.
+ * <p>
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 Point toDisplay (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return toDisplay (point.x, point.y);
+}
+
+boolean translateMnemonic (Event event, Control control) {
+ if (control == this) return false;
+ if (!isVisible () || !isEnabled ()) return false;
+ event.doit = mnemonicMatch (event.character);
+ return traverse (event);
+}
+
+boolean translateMnemonic (int e) {
+ int key = OS.KeyEventArgs_Key(e);
+ if (key < 0x20) return false;
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice(e);
+ int modifiers = OS.KeyboardDevice_Modifiers(keyboardDevice);
+ OS.GCHandle_Free(keyboardDevice);
+ if (modifiers == 0) {
+ int code = traversalCode (key, e);
+ if ((code & SWT.TRAVERSE_MNEMONIC) == 0) return false;
+ } else {
+ if ((modifiers & OS.ModifierKeys_Alt) == 0) return false;
+ }
+ Decorations shell = menuShell ();
+ if (shell.isVisible () && shell.isEnabled ()) {
+ Event event = new Event ();
+ event.detail = SWT.TRAVERSE_MNEMONIC;
+ if (setKeyState (event, SWT.Traverse, e)) {
+ return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
+ }
+ }
+ return false;
+}
+
+int traversalCode (int key, int event) {
+ int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS;
+ Shell shell = getShell ();
+ if (shell.parent != null) code |= SWT.TRAVERSE_ESCAPE;
+ return code;
+}
+
+boolean translateTraversal (int e) {
+ int detail = SWT.TRAVERSE_NONE;
+ int key = OS.KeyEventArgs_Key(e);
+ int code = traversalCode (key, e);
+ boolean all = false;
+ switch (key) {
+ case OS.Key_Escape: {
+ all = true;
+ detail = SWT.TRAVERSE_ESCAPE;
+ break;
+ }
+ case OS.Key_Return: {
+ all = true;
+ detail = SWT.TRAVERSE_RETURN;
+ break;
+ }
+ case OS.Key_Tab: {
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice (e);
+ int modifiers = OS.KeyboardDevice_Modifiers (keyboardDevice);
+ OS.GCHandle_Free (keyboardDevice);
+ boolean next = (modifiers & OS.ModifierKeys_Shift) == 0;
+ detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
+ break;
+ }
+ case OS.Key_Up:
+ case OS.Key_Left:
+ case OS.Key_Down:
+ case OS.Key_Right: {
+ boolean next = key == OS.Key_Down || key == OS.Key_Right;
+ detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
+ break;
+ }
+ case OS.Key_PageUp:
+ case OS.Key_PageDown: {
+ all = true;
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice (e);
+ int modifiers = OS.KeyboardDevice_Modifiers (keyboardDevice);
+ OS.GCHandle_Free (keyboardDevice);
+ if ((modifiers & OS.ModifierKeys_Control) == 0) return false;
+ detail = key == OS.Key_PageDown ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
+ break;
+ }
+ default:
+ return false;
+ }
+ Event event = new Event ();
+ event.doit = (code & detail) != 0;
+ event.detail = detail;
+ event.time = OS.InputEventArgs_Timestamp (e);
+ if (!setKeyState (event, SWT.Traverse, e)) return false;
+ Shell shell = getShell ();
+ Control control = this;
+ do {
+ if (control.traverse (event)) return true;
+ if (!event.doit && control.hooks (SWT.Traverse)) return false;
+ if (control == shell) return false;
+ control = control.parent;
+ } while (all && control != null);
+ return false;
+}
+
+boolean traverse (Event event) {
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in the traverse
+ * event. If this happens, return true to stop further
+ * event processing.
+ */
+ sendEvent (SWT.Traverse, event);
+ if (isDisposed ()) return true;
+ if (!event.doit) return false;
+ switch (event.detail) {
+ case SWT.TRAVERSE_NONE: return true;
+ case SWT.TRAVERSE_ESCAPE: return traverseEscape ();
+ case SWT.TRAVERSE_RETURN: return traverseReturn ();
+ case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
+ case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
+ case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
+ case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
+ case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event.character);
+ case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
+ case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
+ }
+ return false;
+}
+
+/**
+ * Based on the argument, perform one of the expected platform
+ * traversal action. The argument should be one of the constants:
+ * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
+ * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
+ * <code>SWT.TRAVERSE_ARROW_NEXT</code> and <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>.
+ *
+ * @param traversal the type of traversal
+ * @return true if the traversal succeeded
+ *
+ * @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 boolean traverse (int traversal) {
+ checkWidget ();
+ Event event = new Event ();
+ event.doit = true;
+ event.detail = traversal;
+ return traverse (event);
+}
+
+boolean traverseEscape () {
+ return false;
+}
+
+boolean traverseGroup (boolean next) {
+ Control root = computeTabRoot ();
+ Control group = computeTabGroup ();
+ Control [] list = root.computeTabList ();
+ int length = list.length;
+ int index = 0;
+ while (index < length) {
+ if (list [index] == group) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ if (index == length) return false;
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = ((index + offset + length) % length)) != start) {
+ Control control = list [index];
+ if (!control.isDisposed () && control.setTabGroupFocus ()) {
+ return true;
+ }
+ }
+ if (group.isDisposed ()) return false;
+ return group.setTabGroupFocus ();
+}
+
+boolean traverseItem (boolean next) {
+ Control [] children = parent._getChildren ();
+ int length = children.length;
+ int index = 0;
+ while (index < length) {
+ if (children [index] == this) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ if (index == length) return false;
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = (index + offset + length) % length) != start) {
+ Control child = children [index];
+ if (!child.isDisposed () && child.isTabItem ()) {
+ if (child.setTabItemFocus ()) return true;
+ }
+ }
+ return false;
+}
+
+boolean traverseMnemonic (char key) {
+ return mnemonicHit (key);
+}
+
+boolean traversePage (boolean next) {
+ return false;
+}
+
+boolean traverseReturn () {
+ return false;
+}
+
+/**
+ * Forces all outstanding paint requests for the widget
+ * to be processed before this method returns. If there
+ * are no outstanding paint request, this method does
+ * nothing.
+ * <p>
+ * Note: This method does not cause a redraw.
+ * </p>
+ *
+ * @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 #redraw()
+ * @see #redraw(int, int, int, int, boolean)
+ * @see PaintListener
+ * @see SWT#Paint
+ */
+public void update () {
+ checkWidget ();
+ update (false);
+}
+
+void update (boolean all) {
+ checkWidget ();
+ //TODO
+// if (OS.IsWinCE) {
+// OS.UpdateWindow (handle);
+// } else {
+// int flags = OS.RDW_UPDATENOW;
+// if (all) flags |= OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+}
+
+void updateBackgroundColor () {
+// Control control = findBackgroundControl ();
+// if (control == null) control = this;
+// setBackgroundPixel (control.background);
+}
+
+void updateBackgroundImage () {
+// Control control = findBackgroundControl ();
+// Image image = control != null ? control.backgroundImage : backgroundImage;
+// setBackgroundImage (image != null ? image.handle : 0);
+}
+
+void updateBackgroundMode () {
+ int oldState = state & PARENT_BACKGROUND;
+ checkBackground ();
+ if (oldState != (state & PARENT_BACKGROUND)) {
+ setBackground ();
+ }
+}
+
+void updateFont (Font oldFont, Font newFont) {
+ if (getFont ().equals (oldFont)) setFont (newFont);
+}
+
+void updateImages () {
+ /* Do nothing */
+}
+
+void updateLayout (boolean resize, boolean all) {
+ /* Do nothing */
+}
+
+int widgetParent () {
+ return parent.handle;
+}
+
+/**
+ * Changes the parent of the widget to be the one provided if
+ * the underlying operating system supports this feature.
+ * Returns <code>true</code> if the parent is successfully changed.
+ *
+ * @param parent the new parent for the control.
+ * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></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 boolean setParent (Composite parent) {
+ checkWidget ();
+ if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (parent.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.parent == parent) return true;
+ if (!isReparentable ()) return false;
+ return false;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolBar.java
new file mode 100644
index 0000000000..2b35cecfe6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolBar.java
@@ -0,0 +1,709 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class provide an area for dynamically
+ * positioning the items they contain.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>CoolItem</code>.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add <code>Control</code> children to it,
+ * or set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>FLAT, HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#coolbar">CoolBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class CoolBar extends Composite {
+ Control [] children;
+ CoolItem [] items;
+ int parentingHandle;
+ int itemCount, childCount;
+
+ //TEMPORARY CODE
+ static boolean IsVertical;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 SWT#FLAT
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+ if ((style & SWT.VERTICAL) != 0) {
+ this.style |= SWT.VERTICAL;
+ } else {
+ this.style |= SWT.HORIZONTAL;
+ }
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ IsVertical = (style & SWT.V_SCROLL) != 0;
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void addChild (Control widget) {
+ super.addChild (widget);
+ if (childCount == children.length) {
+ Control [] newChildren = new Control [childCount + 4];
+ System.arraycopy (children, 0, newChildren, 0, childCount);
+ children = newChildren;
+ }
+ children [childCount++] = widget;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ return computeSize (handle, wHint, hHint, changed);
+}
+
+void createHandle () {
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_ToolBarTray ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, handle);
+ OS.GCHandle_Free (children);
+ if (IsVertical) OS.ToolBarTray_Orientation (handle, OS.Orientation_Vertical);
+}
+
+void createItem (CoolItem item, int index) {
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int toolbars = OS.ToolBarTray_ToolBars (handle);
+ int itemHandle = item.topHandle ();
+ OS.IList_Insert (toolbars, index, item.topHandle ());
+ int count = OS.ICollection_Count (toolbars);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ int band = 0;
+ int bandIndex = 0;
+ if (index != itemCount) {
+ band = OS.ToolBar_Band (items [index].topHandle ());
+ bandIndex = OS.ToolBar_BandIndex (items [index].topHandle ());
+ for (int i=0; i<count; i++) {
+ int current = OS.IList_default (toolbars, i);
+ int currentBand = OS.ToolBar_Band (current);
+ int currentIndex = OS.ToolBar_BandIndex (current);
+ if (currentBand == band && currentIndex >= bandIndex) {
+ OS.ToolBar_BandIndex (current, currentIndex + 1);
+ }
+ OS.GCHandle_Free (current);
+ }
+ } else {
+ if (itemCount > 0) {
+ int [] log2vis = logicalToVisualIndices ();
+ int lastItem = items [log2vis [itemCount - 1]].topHandle ();
+ band = OS.ToolBar_Band (lastItem);
+ bandIndex = OS.ToolBar_BandIndex (lastItem) + 1;
+ }
+ }
+ OS.ToolBar_Band (itemHandle, band);
+ OS.ToolBar_BandIndex (itemHandle, bandIndex);
+ OS.GCHandle_Free (toolbars);
+ if (itemCount == items.length) {
+ CoolItem [] newItems = new CoolItem [items.length + 4];
+ System.arraycopy (items, 0, newItems, 0, items.length);
+ items = newItems;
+ }
+ System.arraycopy (items, index, items, index + 1, itemCount - index);
+ items [index] = item;
+ itemCount++;
+}
+
+void createWidget () {
+ super.createWidget ();
+ items = new CoolItem [4];
+ children = new Control [4];
+}
+
+int defaultBackground () {
+ return OS.Colors_Transparent;
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+void destroyItem (CoolItem item) {
+ int toolbars = OS.ToolBarTray_ToolBars (handle);
+ int itemHandle = item.topHandle ();
+ int band = OS.ToolBar_Band (itemHandle);
+ int bandIndex = OS.ToolBar_BandIndex (itemHandle);
+ OS.IList_Remove (toolbars, itemHandle);
+ int count = OS.ICollection_Count (toolbars);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemCount--;
+ for (int i=0; i<itemCount; i++) {
+ int current = OS.IList_default (toolbars, i);
+ int currentBand = OS.ToolBar_Band (current);
+ int currentIndex = OS.ToolBar_BandIndex (current);
+ if (currentBand == band && currentIndex >= bandIndex) {
+ OS.ToolBar_BandIndex (current, currentIndex - 1);
+ }
+ OS.GCHandle_Free (current);
+ }
+ OS.GCHandle_Free (toolbars);
+ int index = 0;
+ while (index < items.length) {
+ if (items [index] == item) break;
+ index++;
+ }
+ System.arraycopy (items, index + 1, items, index, itemCount - index);
+ items [itemCount] = null;
+}
+
+Control [] _getChildren () {
+ // return children in reverse order.
+ Control[] result = new Control [childCount];
+ for (int i =0; i < childCount; i++) {
+ result [childCount - i - 1] = children [i];
+ }
+ return result;
+}
+
+int [] logicalToVisualIndices () {
+ int [] bandLengths = new int [4];
+ for (int i = 0; i < itemCount; i++) {
+ int topHandle = items [i].topHandle ();
+ int band = OS.ToolBar_Band (topHandle);
+ int bandIndex = OS.ToolBar_BandIndex (topHandle);
+ if (band >= bandLengths.length) {
+ int [] newLengths = new int [band + 4];
+ System.arraycopy (bandLengths, 0, newLengths, 0, bandLengths.length);
+ bandLengths = newLengths;
+ }
+ if (bandIndex + 1 > bandLengths [band]) bandLengths [band] = bandIndex + 1;
+ }
+ int [] result = new int [itemCount];
+ for (int i = 0; i < itemCount; i++) {
+ int topHandle = items [i].topHandle ();
+ int band = OS.ToolBar_Band (topHandle);
+ int bandIndex = OS.ToolBar_BandIndex (topHandle);
+ int index = bandIndex;
+ for (int j=0; j<band; j++) index += bandLengths [j];
+ result [index] = i;
+ }
+ return result;
+}
+
+/**
+ * Returns the item that is currently displayed at the given,
+ * zero-relative index. Throws an exception if the index is
+ * out of range.
+ *
+ * @param index the visual index of the item to return
+ * @return the item at the given visual index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 CoolItem getItem (int index) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+ int [] log2vis = logicalToVisualIndices ();
+ return items [log2vis [index]];
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns an array of zero-relative ints that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @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 int [] getItemOrder () {
+ checkWidget ();
+ return logicalToVisualIndices ();
+}
+
+/**
+ * Returns an array of <code>CoolItem</code>s in the order
+ * in which they are currently being displayed.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the receiver's items in their current visual order
+ *
+ * @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 CoolItem [] getItems () {
+ checkWidget ();
+ CoolItem [] result = new CoolItem [itemCount];
+ int [] log2vis = logicalToVisualIndices ();
+ for (int i = 0; i < itemCount; i++) {
+ result [i] = items [log2vis [i]];
+ }
+ return result;
+}
+
+/**
+ * Returns an array of points whose x and y coordinates describe
+ * the widths and heights (respectively) of the items in the receiver
+ * in the order in which they are currently being displayed.
+ *
+ * @return the receiver's item sizes in their current visual order
+ *
+ * @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 Point [] getItemSizes () {
+ checkWidget ();
+ int [] log2vis = logicalToVisualIndices ();
+ Point [] result = new Point [itemCount];
+ for (int i = 0; i < itemCount; i++) {
+ result [i] = items [log2vis [i]].getSize ();
+ }
+ return result;
+}
+
+Point getLocation (Control child) {
+ int topHandle = child.topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (topHandle, point, handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ return new Point (x, y);
+}
+
+/**
+ * Returns whether or not the receiver is 'locked'. When a coolbar
+ * is locked, its items cannot be repositioned.
+ *
+ * @return true if the coolbar is locked, false otherwise
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public boolean getLocked () {
+ checkWidget ();
+ return OS.ToolBarTray_IsLocked (handle);
+}
+
+/**
+ * Returns an array of ints that describe the zero-relative
+ * indices of any item(s) in the receiver that will begin on
+ * a new row. The 0th visible item always begins the first row,
+ * therefore it does not count as a wrap index.
+ *
+ * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row
+ *
+ * @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 int [] getWrapIndices () {
+ checkWidget ();
+ int bands = 1;
+ int [] bandLengths = new int [4];
+ for (int i = 0; i < itemCount; i++) {
+ int topHandle = items [i].topHandle ();
+ int band = OS.ToolBar_Band (topHandle);
+ int bandIndex = OS.ToolBar_BandIndex (topHandle);
+ if (band >= bandLengths.length) {
+ int [] newLengths = new int [band + 4];
+ System.arraycopy (bandLengths, 0, newLengths, 0, bandLengths.length);
+ bandLengths = newLengths;
+ }
+ if (band != 0 && bandLengths [band] == 0) bands ++;
+ if (bandIndex + 1 > bandLengths [band]) bandLengths [band] = bandIndex + 1;
+ }
+ if (bands == 1) return new int [0];
+ int [] result = new int [bands-1];
+ int sum = 0;
+ for (int i = 0; i < result.length; i++) {
+ sum += bandLengths [i];
+ result [i] = sum;
+ }
+ return result;
+}
+
+void HandleSizeChanged (int sender, int e) {
+ postEvent (SWT.Resize);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
+ OS.FrameworkElement_SizeChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Searches the receiver's items in the order they are currently
+ * being displayed, starting at the first item (index 0), until
+ * an item is found that is equal to the argument, and returns
+ * the index of that item. If no item is found, returns -1.
+ *
+ * @param item the search item
+ * @return the visual order index of the search item, or -1 if the item is not found
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item is disposed</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 int indexOf (CoolItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i = 0; i < itemCount; i++) {
+ if (item.equals (items [i])) {
+ int [] log2vis = logicalToVisualIndices ();
+ return log2vis [i];
+ }
+ }
+ return -1;
+}
+
+int parentingHandle () {
+ return parentingHandle;
+}
+
+void register () {
+ super.register ();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ for (int i=0; i<itemCount; i++) {
+ CoolItem item = items [i];
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (parentingHandle != 0) OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void removeChild (Control control) {
+ super.removeChild (control);
+ int index = 0;
+ while (index < childCount) {
+ if (children [index] == control) break;
+ index++;
+ }
+ if (index == childCount) return;
+ System.arraycopy (children, index+1, children, index, --childCount - index);
+ children [childCount] = null;
+}
+
+void removeControl (Control control) {
+ super.removeControl (control);
+ for (int i=0; i<itemCount; i++) {
+ CoolItem item = items [i];
+ if (item.control == control) {
+ item.setControl (null);
+ break;
+ }
+ }
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0) {
+ if ((style & SWT.VERTICAL) != 0) {
+ OS.FrameworkElement_Height (handle, height);
+ } else {
+ OS.FrameworkElement_Width (handle, width);
+ }
+ }
+ return result;
+}
+
+/**
+ * Sets the receiver's item order, wrap indices, and item sizes
+ * all at once. This method is typically used to restore the
+ * displayed state of the receiver to a previously stored state.
+ * <p>
+ * The item order is the order in which the items in the receiver
+ * should be displayed, given in terms of the zero-relative ordering
+ * of when the items were added.
+ * </p><p>
+ * The wrap indices are the indices of all item(s) in the receiver
+ * that will begin on a new row. The indices are given in the order
+ * specified by the item order. The 0th item always begins the first
+ * row, therefore it does not count as a wrap index. If wrap indices
+ * is null or empty, the items will be placed on one line.
+ * </p><p>
+ * The sizes are specified in an array of points whose x and y
+ * coordinates describe the new widths and heights (respectively)
+ * of the receiver's items in the order specified by the item order.
+ * </p>
+ *
+ * @param itemOrder an array of indices that describe the new order to display the items in
+ * @param wrapIndices an array of wrap indices, or null
+ * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+ *
+ * @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>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if item order or sizes is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if item order or sizes is not the same length as the number of items</li>
+ * </ul>
+ */
+public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
+ checkWidget ();
+ setItemOrder (itemOrder);
+ setWrapIndices (wrapIndices);
+ setItemSizes (sizes);
+}
+
+/*
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param itemOrder the new order to display the items in
+ *
+ * @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>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ */
+void setItemOrder (int [] itemOrder) {
+ checkWidget ();
+ if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (itemOrder.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ /* Ensure that itemOrder does not contain any duplicates. */
+ boolean [] set = new boolean [itemCount];
+ for (int i=0; i<itemOrder.length; i++) {
+ int index = itemOrder [i];
+ if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+ if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+ set [index] = true;
+ }
+ for (int i=0; i<itemCount; i++) {
+ CoolItem item = items [itemOrder [i]];
+ int itemHandle = item.topHandle ();
+ OS.ToolBar_Band (itemHandle, 0);
+ OS.ToolBar_BandIndex (itemHandle, i);
+ }
+}
+
+/*
+ * Sets the width and height of the receiver's items to the ones
+ * specified by the argument, which is an array of points whose x
+ * and y coordinates describe the widths and heights (respectively)
+ * in the order in which the items are currently being displayed.
+ *
+ * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of sizes is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items</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>
+ */
+void setItemSizes (Point [] sizes) {
+ if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (sizes.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ int [] log2vis = logicalToVisualIndices ();
+ for (int i=0; i<itemCount; i++) {
+ items [log2vis [i]].setSize (sizes [i].x, sizes [i].y);
+ }
+}
+
+/**
+ * Sets whether or not the receiver is 'locked'. When a coolbar
+ * is locked, its items cannot be repositioned.
+ *
+ * @param locked lock the coolbar if true, otherwise unlock the coolbar
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public void setLocked (boolean locked) {
+ checkWidget ();
+ OS.ToolBarTray_IsLocked (handle, locked);
+}
+
+/**
+ * Sets the indices of all item(s) in the receiver that will
+ * begin on a new row. The indices are given in the order in
+ * which they are currently being displayed. The 0th item
+ * always begins the first row, therefore it does not count
+ * as a wrap index. If indices is null or empty, the items
+ * will be placed on one line.
+ *
+ * @param indices an array of wrap indices, 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 setWrapIndices (int [] indices) {
+ checkWidget ();
+ if (indices == null) indices = new int [0];
+ int count = getItemCount ();
+ for (int i=0; i<indices.length; i++) {
+ if (indices [i] < 0 || indices [i] >= count) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ }
+ sortAscending (indices);
+ int [] log2vis = logicalToVisualIndices ();
+ int band = 0;
+ int bandIndex = 0;
+ int wrapIndex = 0;
+ for (int i = 0; i < itemCount; i++) {
+ int wrap = indices.length > wrapIndex ? indices [wrapIndex] : itemCount;
+ if (i == wrap) {
+ if (wrap != 0) {
+ band ++;
+ bandIndex = 0;
+ }
+ wrapIndex ++;
+ }
+ int topHandle = items [log2vis [i]].topHandle ();
+ OS.ToolBar_Band (topHandle, band);
+ OS.ToolBar_BandIndex (topHandle, bandIndex);
+ bandIndex ++;
+ }
+}
+
+int topHandle () {
+ return parentingHandle;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolItem.java
new file mode 100644
index 0000000000..87ac42f7ef
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/CoolItem.java
@@ -0,0 +1,665 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent the dynamically positionable
+ * areas of a <code>CoolBar</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>DROP_DOWN</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class CoolItem extends Item {
+ CoolBar parent;
+ Control control;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CoolBar</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolItem (CoolBar parent, int style) {
+ this (parent, style, parent.itemCount);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CoolBar</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ * @param index the zero-relative index at which to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolItem (CoolBar parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, index);
+ updateLayout (handle);
+ setButtonVisibility (OS.Visibility_Collapsed);
+}
+
+/**
+ * Adds the listener to the collection of listeners that will
+ * be notified when the control is selected by the user, by sending it one
+ * of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * If <code>widgetSelected</code> is called when the mouse is over
+ * the drop-down arrow (or 'chevron') portion of the cool item,
+ * the event object detail field contains the value <code>SWT.ARROW</code>,
+ * and the x and y fields in the event object represent the point at
+ * the bottom left of the chevron, where the menu should be popped up.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ *
+ * @since 2.0
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandle () {
+ handle = OS.gcnew_ToolBar ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+}
+
+void createWidget () {
+ super.createWidget ();
+ int background = OS.Brushes_Transparent ();
+ OS.Control_Background (handle, background);
+ OS.GCHandle_Free (background);
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a <code>CoolItem</code> is the size that
+ * it would best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask the instance questions such as "Given a particular
+ * width, how high does it need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @return the preferred size
+ *
+ * @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 Layout
+ * @see #getBounds
+ * @see #getSize
+ * @see Control#getBorderWidth
+ * @see Scrollable#computeTrim
+ * @see Scrollable#getClientArea
+ */
+public Point computeSize (int wHint, int hHint) {
+ checkWidget ();
+ if (isToolBar (control)) {
+ return control.computeSize (SWT.DEFAULT, SWT.DEFAULT);
+ }
+ int template = OS.Control_Template (handle);
+ int partName = createDotNetString ("PART_ToolBarPanel", false);
+ int part = OS.FrameworkTemplate_FindName (template, partName, handle);
+ int width = wHint, height = hHint;
+ width = Math.max (0, width);
+ height = Math.max (0, height);
+ int margin = OS.FrameworkElement_Margin (part);
+ width += OS.Thickness_Left (margin) + OS.Thickness_Right (margin);
+ height += OS.Thickness_Top (margin) + OS.Thickness_Bottom (margin);
+ OS.GCHandle_Free (partName);
+ OS.GCHandle_Free (part);
+ OS.GCHandle_Free (margin);
+
+ partName = createDotNetString ("ToolBarThumb", false);
+ part = OS.FrameworkTemplate_FindName (template, partName, handle);
+ width += OS.FrameworkElement_Width (part);
+ OS.GCHandle_Free (partName);
+ OS.GCHandle_Free (part);
+ OS.GCHandle_Free (template);
+ return new Point (width, height);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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 Rectangle getBounds () {
+ checkWidget ();
+ int parentHandle = parent.handle;
+ int topHandle = topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (topHandle, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the control that is associated with the receiver.
+ *
+ * @return the control that is contained by the receiver
+ *
+ * @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 Control getControl () {
+ checkWidget ();
+ return control;
+}
+
+/**
+ * Returns the minimum size that the cool item can
+ * be resized to using the cool item's gripper.
+ *
+ * @return a point containing the minimum width and height of the cool item, in pixels
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public Point getMinimumSize () {
+ checkWidget ();
+ int width = (int) OS.FrameworkElement_MinWidth (handle);
+ int height = (int) OS.FrameworkElement_MinHeight (handle);
+ return new Point (width, height);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>CoolBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 CoolBar getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns a point describing the receiver's ideal size.
+ * The x coordinate of the result is the ideal width of the receiver.
+ * The y coordinate of the result is the ideal height of the receiver.
+ *
+ * @return the receiver's ideal size
+ *
+ * @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 Point getPreferredSize () {
+ checkWidget ();
+ return getSize ();
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @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 Point getSize() {
+ checkWidget ();
+ int width = (int) OS.FrameworkElement_Width (handle);
+ int height = (int) OS.FrameworkElement_Height (handle);
+ return new Point (width, height);
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (isToolBar (control)) {
+ ToolBar toolbar = (ToolBar) control;
+ boolean overflow = OS.ToolBar_HasOverflowItems (toolbar.handle);
+ toolbar.setButtonVisibility (overflow ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ } else {
+ boolean overflow = OS.ToolBar_HasOverflowItems (handle);
+ setButtonVisibility (overflow ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ if (control != null) {
+ int template = OS.Control_Template (handle);
+ int partName = createDotNetString ("PART_ToolBarPanel", false);
+ int part = OS.FrameworkTemplate_FindName (template, partName, handle);
+ int width = (int) OS.FrameworkElement_ActualWidth (part);
+ int height = (int) OS.FrameworkElement_ActualHeight (part);
+ control.setSize (width, height);
+ OS.GCHandle_Free (part);
+ OS.GCHandle_Free (partName);
+ OS.GCHandle_Free (template);
+ }
+ }
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
+ OS.FrameworkElement_SizeChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+boolean isToolBar (Control control) {
+ if (control == null || control.isDisposed ()) return false;
+ int type = OS.ToolBar_typeid ();
+ boolean result = OS.Type_IsInstanceOfType (type, control.handle);
+ OS.GCHandle_Free (type);
+ return result;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners that
+ * will be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ *
+ * @since 2.0
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void setButtonVisibility (byte visibility) {
+ int template = OS.Control_Template (handle);
+ int overFlowName = createDotNetString ("OverflowGrid", false);
+ int overFlowGrid = OS.FrameworkTemplate_FindName (template, overFlowName, handle);
+ if (overFlowGrid != 0) {
+ OS.UIElement_Visibility (overFlowGrid, visibility);
+ OS.GCHandle_Free (overFlowGrid);
+ }
+ OS.GCHandle_Free (overFlowName);
+ int borderName = createDotNetString ("MainPanelBorder", false);
+ int border = OS.FrameworkTemplate_FindName (template, borderName, handle);
+ if (border != 0) {
+ int right = visibility == OS.Visibility_Collapsed ? 0 : 11;
+ int margin = OS.gcnew_Thickness (0, 0, right, 0);
+ OS.FrameworkElement_Margin (border, margin);
+ OS.GCHandle_Free (border);
+ OS.GCHandle_Free (margin);
+ }
+ OS.GCHandle_Free (borderName);
+ OS.GCHandle_Free (template);
+}
+
+/**
+ * Sets the control that is associated with the receiver
+ * to the argument.
+ *
+ * @param control the new control that will be contained by the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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 setControl (Control control) {
+ checkWidget ();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (this.control != null && this.control.isDisposed ()) {
+ this.control = null;
+ }
+ int topHandle = topHandle ();
+ int toolbars = OS.ToolBarTray_ToolBars (parent.handle);
+ int index = OS.IList_IndexOf (toolbars, topHandle);
+ int band = OS.ToolBar_Band (topHandle);
+ int bandIndex = OS.ToolBar_BandIndex (topHandle);
+ Control oldControl = this.control, newControl = control;
+ this.control = control;
+ if (oldControl != null) {
+ if (isToolBar (oldControl)) {
+ ToolBar toolbar = (ToolBar) oldControl;
+ toolbar.setThumbVisibility (OS.Visibility_Collapsed);
+ toolbar.setButtonVisibility (OS.Visibility_Collapsed);
+ OS.IList_Remove (toolbars, toolbar.handle);
+ int children = OS.ToolBarTray_ToolBars (toolbar.trayHandle);
+ OS.IList_Add (children, toolbar.handle);
+ OS.GCHandle_Free (children);
+ OS.IList_Insert (toolbars, index, handle);
+ OS.ToolBar_Band (handle, band);
+ OS.ToolBar_BandIndex (handle, bandIndex);
+ } else {
+ int controlHandle = oldControl.topHandle ();
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Remove (items, controlHandle);
+ OS.GCHandle_Free (items);
+ int children = OS.Panel_Children (parent.parentingHandle);
+ OS.UIElementCollection_Add (children, controlHandle);
+ OS.GCHandle_Free (children);
+ }
+ }
+ if (newControl != null) {
+ if (isToolBar (newControl)) {
+ ToolBar toolbar = (ToolBar) newControl;
+ int controlHandle = toolbar.handle;
+ int children = OS.ToolBarTray_ToolBars (toolbar.trayHandle);
+ OS.IList_Remove (children, controlHandle);
+ OS.GCHandle_Free (children);
+ OS.IList_Remove (toolbars, handle);
+ OS.IList_Insert (toolbars, index, controlHandle);
+
+ boolean locked = OS.ToolBarTray_IsLocked (parent.handle);
+ boolean overflow = OS.ToolBar_HasOverflowItems (controlHandle);
+ toolbar.setThumbVisibility (locked ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ toolbar.setButtonVisibility (overflow ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ OS.ToolBar_Band (controlHandle, band);
+ OS.ToolBar_BandIndex (controlHandle, bandIndex);
+ double width = OS.FrameworkElement_Width (handle);
+ if (width > 0) OS.FrameworkElement_Width (controlHandle, width);
+ double height = OS.FrameworkElement_Height (handle);
+ if (height > 0) OS.FrameworkElement_Height (controlHandle, height);
+ double minWidth = OS.FrameworkElement_MinWidth (handle);
+ if (minWidth > 0) OS.FrameworkElement_MinWidth (controlHandle, minWidth);
+ double minHeight = OS.FrameworkElement_MinHeight (handle);
+ if (minHeight > 0) OS.FrameworkElement_MinHeight (controlHandle, minHeight);
+ updateLayout (controlHandle);
+ } else {
+ int controlHandle = newControl.topHandle ();
+ int children = OS.Panel_Children (parent.parentingHandle ());
+ OS.UIElementCollection_Remove (children, controlHandle);
+ OS.GCHandle_Free (children);
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Add (items, controlHandle);
+ OS.GCHandle_Free (items);
+ }
+ }
+ OS.GCHandle_Free (toolbars);
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the arguments.
+ *
+ * @param width the minimum width of the cool item, in pixels
+ * @param height the minimum height of the cool item, in pixels
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public void setMinimumSize (int width, int height) {
+ checkWidget ();
+ width = Math.max (0, width);
+ height = Math.max (0, height);
+ OS.FrameworkElement_MinWidth (handle, width);
+ OS.FrameworkElement_MinHeight (handle, height);
+ if (isToolBar (control)) {
+ OS.FrameworkElement_MinWidth (control.handle, width);
+ OS.FrameworkElement_MinHeight (control.handle, height);
+ }
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the argument.
+ *
+ * @param size a point representing the minimum width and height of the cool item, in pixels
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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>
+ *
+ * @since 2.0
+ */
+public void setMinimumSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setMinimumSize (size.x, size.y);
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the arguments.
+ *
+ * @param width the new ideal width for the receiver
+ * @param height the new ideal height for the receiver
+ *
+ * @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 setPreferredSize (int width, int height) {
+ checkWidget ();
+ setSize (width, height);
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the argument.
+ *
+ * @param size the new ideal size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setPreferredSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setPreferredSize (size.x, size.y);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @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 setSize (int width, int height) {
+ checkWidget ();
+ width = Math.max (0, width);
+ height = Math.max (0, height);
+ OS.FrameworkElement_Width (handle, width);
+ OS.FrameworkElement_Height (handle, height);
+ if (isToolBar (control)) {
+ OS.FrameworkElement_Width (control.handle, width);
+ OS.FrameworkElement_Height (control.handle, height);
+ }
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ * </p>
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setSize (Point size) {
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+int topHandle () {
+ if (isToolBar (control)) return control.handle;
+ return handle;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Decorations.java
new file mode 100644
index 0000000000..95b68840ee
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Decorations.java
@@ -0,0 +1,895 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+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>
+ * IMPORTANT: This class was intended to be abstract and
+ * should <em>never</em> be referenced or instantiated.
+ * Instead, the class <code>Shell</code> should be used.
+ * </p>
+ * <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, ON_TOP, TOOL</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
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Decorations extends Canvas {
+ int shellHandle;
+ Image image;
+// Image image, smallImage, largeImage;
+ Image [] images;
+ Menu menuBar;
+ Menu [] menus;
+ Control savedFocus;
+ Button defaultButton, saveDefault;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#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));
+}
+
+void addMenu (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 () {
+// /*
+// * This code is intentionally commented. On some platforms,
+// * the ON_TOP 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 98 so this code is
+// * commented out until this functionality is specified and
+// * the problems are fixed.
+// */
+//// if ((style & SWT.ON_TOP) != 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);
+// // widget could be disposed at this point
+//// }
+}
+
+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;
+ }
+//
+// /*
+// * If either 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;
+//
+// /*
+// * Both WS_SYSMENU and WS_CAPTION must be set in order
+// * to for the system menu to appear.
+// */
+// if ((style & SWT.CLOSE) != 0) style |= SWT.TITLE;
+//
+// /*
+// * Bug in Windows. The WS_CAPTION style must be
+// * set when the window is resizable or it does not
+// * draw properly.
+// */
+// /*
+// * This code is intentionally commented. It seems
+// * that this problem originally in Windows 3.11,
+// * has been fixed in later versions. Because the
+// * exact nature of the drawing problem is unknown,
+// * keep the commented code around in case it comes
+// * back.
+// */
+//// if ((style & SWT.RESIZE) != 0) style |= SWT.TITLE;
+//
+ return style;
+}
+
+void checkBorder () {
+ /* Do nothing */
+}
+
+void checkOpened () {
+ //TODO - add back
+// if (!opened) resized = false;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void closeWidget () {
+ Event event = new Event ();
+ sendEvent (SWT.Close, event);
+ if (event.doit && !isDisposed ()) dispose ();
+}
+
+int compare (ImageData data1, ImageData data2) {
+ int transparent1 = data1.getTransparencyType ();
+ int transparent2 = data2.getTransparencyType ();
+ if (transparent1 == transparent2) {
+ if (data1.depth != data2.depth) {
+ return data1.depth > data2.depth ? -1 : 1;
+ }
+ if (data1.width * data1.height != data2.width * data2.height) {
+ return (data1.width * data1.height) > (data2.width * data2.height) ? -1 : 1;
+ }
+ }
+ if (transparent1 == SWT.TRANSPARENCY_ALPHA) return -1;
+ if (transparent2 == SWT.TRANSPARENCY_ALPHA) return 1;
+ if (transparent1 == SWT.TRANSPARENCY_MASK) return -1;
+ if (transparent2 == SWT.TRANSPARENCY_MASK) return 1;
+ if (transparent1 == SWT.TRANSPARENCY_PIXEL) return -1;
+ if (transparent2 == SWT.TRANSPARENCY_PIXEL) return 1;
+ return 0;
+}
+
+Control computeTabGroup () {
+ return this;
+}
+
+Control computeTabRoot () {
+ return this;
+}
+
+public void dispose () {
+ if (isDisposed()) return;
+ if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ if (!(this instanceof Shell)) {
+ setVisible (false);
+ if (!traverseDecorations (false)) {
+ Shell shell = getShell ();
+ shell.setFocus ();
+ }
+ }
+ super.dispose ();
+}
+
+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;
+}
+
+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 <menus.length) {
+ if (menus [index] == menu) {
+ control.setMenu (null);
+ return;
+ }
+ index++;
+ }
+ menu.fixMenus (newDecorations);
+// destroyAccelerators ();
+// newDecorations.destroyAccelerators ();
+ }
+}
+
+/**
+ * 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(Button)
+ */
+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;
+}
+
+/**
+ * Returns the receiver's images if they had previously been
+ * set using <code>setImages()</code>. 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.
+ *
+ * <p>
+ * Note: This method will return an empty array if called before
+ * <code>setImages()</code> is called. It does not provide
+ * access to a window manager provided, "default" image
+ * even if one exists.
+ * </p>
+ *
+ * @return the images
+ *
+ * @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>
+ *
+ * @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 <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 ((style & SWT.ON_TOP) != 0) return false;
+ return OS.Window_WindowState (shellHandle) == OS.WindowState_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 () {
+ 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 ((style & SWT.ON_TOP) != 0) return false;
+ return OS.Window_WindowState (shellHandle) == OS.WindowState_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 () {
+ checkWidget ();
+ if ((style & SWT.ON_TOP) != 0) return "";
+ int shellHandle = topHandle ();
+ int str = OS.Window_Title (shellHandle);
+ String string = createJavaString(str);
+ OS.GCHandle_Free (str);
+ return string;
+}
+
+boolean isTabGroup () {
+ /*
+ * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+ */
+ return true;
+}
+
+boolean isTabItem () {
+ /*
+ * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+ */
+ return false;
+}
+
+Decorations menuShell () {
+ return this;
+}
+
+void releaseChildren (boolean destroy) {
+ if (menuBar != null) {
+ menuBar.release (false);
+ menuBar = null;
+ }
+ super.releaseChildren (destroy);
+ if (menus != null) {
+ for (int i=0; i<menus.length; i++) {
+ Menu menu = menus [i];
+ if (menu != null && !menu.isDisposed ()) {
+ menu.dispose ();
+ }
+ }
+ menus = null;
+ }
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ image = null;
+ images = null;
+ savedFocus = null;
+// defaultButton = saveDefault = null;
+}
+
+void removeMenu (Menu menu) {
+ if (menus == null) return;
+ for (int i=0; i<menus.length; i++) {
+ if (menus [i] == menu) {
+ menus [i] = null;
+ return;
+ }
+ }
+}
+
+boolean restoreFocus () {
+// if (display.ignoreRestoreFocus) return true;
+ if (savedFocus != null && savedFocus.isDisposed ()) savedFocus = null;
+ if (savedFocus != null && savedFocus.setSavedFocus ()) return true;
+ /*
+ * This code is intentionally commented. When no widget
+ * has been given focus, some platforms give focus to the
+ * default button. Windows doesn't do this.
+ */
+// if (defaultButton != null && !defaultButton.isDisposed ()) {
+// if (defaultButton.setFocus ()) return true;
+// }
+ return false;
+}
+
+void saveFocus () {
+ Control control = display._getFocusControl ();
+ if (control != null && control != this && this == control.menuShell ()) {
+ setSavedFocus (control);
+ }
+}
+
+/**
+ * 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.
+ * <p>
+ * The default button is the button that is selected when
+ * the receiver is active and the user presses ENTER.
+ * </p>
+ *
+ * @param button the new default button
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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 setDefaultButton (Button button) {
+ checkWidget ();
+ if (button != null) {
+ if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT);
+ }
+ setDefaultButton (button, true);
+}
+
+void setDefaultButton (Button button, boolean save) {
+ if (button == null) {
+ if (defaultButton == saveDefault) {
+ if (save) saveDefault = null;
+ 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 = 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 IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ setImages (image, null);
+}
+
+void setImages (Image image, Image [] images) {
+ if ((style & SWT.ON_TOP) != 0) return;
+ int encoder = OS.gcnew_TiffBitmapEncoder ();
+ int frames = OS.BitmapEncoder_Frames (encoder);
+ if (image != null) {
+ int frame = OS.BitmapFrame_Create (image.handle);
+ OS.BitmapFrameCollection_Add (frames, frame);
+ OS.GCHandle_Free (frame);
+ }
+ if (images != null) {
+ if (images.length > 1) {
+ ImageData [] datas = null;
+ Image [] bestImages = new Image [images.length];
+ System.arraycopy (images, 0, bestImages, 0, images.length);
+ datas = new ImageData [images.length];
+ for (int i=0; i<datas.length; i++) {
+ datas [i] = images [i].getImageData ();
+ }
+ images = bestImages;
+ sort (images, datas);
+ }
+ for (int i = 0; i < images.length; i++) {
+ int frame = OS.BitmapFrame_Create (images [i].handle);
+ OS.BitmapFrameCollection_Add (frames, frame);
+ OS.GCHandle_Free (frame);
+ }
+ }
+ OS.GCHandle_Free (frames);
+ int stream = OS.gcnew_MemoryStream ();
+ OS.BitmapEncoder_Save (encoder, stream);
+ OS.GCHandle_Free (encoder);
+ int decoder = OS.BitmapDecoder_Create (stream, OS.BitmapCreateOptions_None, OS.BitmapCacheOption_Default);
+ OS.GCHandle_Free (stream);
+ frames = OS.BitmapDecoder_Frames (decoder);
+ int icon = OS.BitmapFrameCollection_default (frames, 0);
+ OS.GCHandle_Free (frames);
+ OS.GCHandle_Free (decoder);
+ OS.Window_Icon(shellHandle, icon);
+ OS.GCHandle_Free (icon);
+}
+
+/**
+ * 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 <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</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>
+ *
+ * @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 (null, images);
+}
+
+/**
+ * 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 maximized 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 ();
+ if ((style & SWT.ON_TOP) != 0) return;
+ int state = maximized ? OS.WindowState_Maximized : OS.WindowState_Normal;
+ OS.Window_WindowState (shellHandle, state);
+}
+
+/**
+ * Sets the receiver's menu bar to the argument, which
+ * may be null.
+ *
+ * @param menu the new menu bar
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</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 setMenuBar (Menu menu) {
+ checkWidget ();
+ if (menuBar == menu) return;
+ if (menu != null) {
+ if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
+ if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
+ }
+ int children = OS.Panel_Children (scrolledHandle);
+ if (menuBar != null) {
+ OS.Menu_IsMainMenu (menuBar.handle, false);
+ OS.UIElementCollection_Remove (children, menuBar.handle);
+ }
+ menuBar = menu;
+ if (menuBar != null) {
+ int menuHandle = menuBar.handle;
+ OS.Menu_IsMainMenu (menuHandle, true);
+ OS.Grid_SetRow (menuHandle, 0);
+ OS.Grid_SetColumn (menuHandle, 0);
+ OS.Grid_SetColumnSpan (menuHandle, 2);
+ OS.UIElementCollection_Add (children, menuHandle);
+ }
+ OS.GCHandle_Free (children);
+}
+
+/**
+ * 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 minimized 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 ();
+ if ((style & SWT.ON_TOP) != 0) return;
+ int state = minimized ? OS.WindowState_Minimized : OS.WindowState_Normal;
+ OS.Window_WindowState (shellHandle, state);
+}
+
+void setSavedFocus (Control control) {
+ 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 must not be null.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if ((style & SWT.ON_TOP) != 0) return;
+ int strPtr = createDotNetString (string, false);
+ int shellHandle = topHandle ();
+ OS.Window_Title (shellHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+}
+
+void sort (Image [] images, ImageData [] datas) {
+ /* Shell Sort from K&R, pg 108 */
+ int length = images.length;
+ if (length <= 1) return;
+ for (int gap=length/2; gap>0; gap/=2) {
+ for (int i=gap; i<length; i++) {
+ for (int j=i-gap; j>=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 traverseDecorations (boolean next) {
+ Control [] children = parent._getChildren ();
+ int length = children.length;
+ int index = 0;
+ while (index < length) {
+ if (children [index] == this) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = (index + offset + length) % length) != start) {
+ Control child = children [index];
+ if (!child.isDisposed () && child instanceof Decorations) {
+ if (child.setFocus ()) return true;
+ }
+ }
+ return false;
+}
+
+boolean traverseItem (boolean next) {
+ return false;
+}
+
+boolean traverseReturn () {
+ if (defaultButton == null || defaultButton.isDisposed ()) return false;
+ if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false;
+// defaultButton.click ();
+// TODO
+ defaultButton.sendEvent (SWT.Selection);
+ return true;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/DirectoryDialog.java
new file mode 100644
index 0000000000..3993e0ccf1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/DirectoryDialog.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.wpf.*;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select a directory.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#directorydialog">DirectoryDialog snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class DirectoryDialog extends Dialog {
+ String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @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>
+ */
+public DirectoryDialog (Shell parent) {
+ this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog 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>
+ */
+public DirectoryDialog (Shell parent, int style) {
+ super (parent, checkStyle (parent, style));
+ checkSubclass ();
+}
+
+/**
+ * Returns the path which the dialog will use to filter
+ * the directories it shows.
+ *
+ * @return the filter path
+ *
+ * @see #setFilterPath
+ */
+public String getFilterPath () {
+ return filterPath;
+}
+
+/**
+ * Returns the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+ return message;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the selected directory,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public String open () {
+ int dialog = OS.gcnew_FolderBrowserDialog ();
+ if (dialog == 0) error (SWT.ERROR_NO_HANDLES);
+ int messagePtr = parent.createDotNetString (message, false);
+ OS.FolderBrowserDialog_Description (dialog, messagePtr);
+ OS.GCHandle_Free (messagePtr);
+ //TODO: filter path...
+ String result = null;
+ if (OS.FormsCommonDialog_ShowDialog (dialog) == OS.DialogResult_OK) {
+ int ptr = OS.FolderBrowserDialog_SelectedPath (dialog);
+ result = Widget.createJavaString (ptr);
+ OS.GCHandle_Free (ptr);
+ }
+ OS.GCHandle_Free (dialog);
+ return result;
+}
+
+/**
+ * Sets the path that the dialog will use to filter
+ * the directories it shows to the argument, which may
+ * be null. If the string is null, then the operating
+ * system's default filter path will be used.
+ * <p>
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ * </p>
+ *
+ * @param string the filter path
+ */
+public void setFilterPath (String string) {
+ filterPath = string;
+}
+
+/**
+ * Sets the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @param string the message
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ */
+public void setMessage (String string) {
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Display.java
new file mode 100644
index 0000000000..3ed8cd3446
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Display.java
@@ -0,0 +1,3018 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class are responsible for managing the
+ * connection between SWT and the underlying operating
+ * system. Their most important function is to implement
+ * the SWT event loop in terms of the platform event model.
+ * They also provide various methods for accessing information
+ * about the operating system, and have overall control over
+ * the operating system resources which SWT allocates.
+ * <p>
+ * Applications which are built with SWT will <em>almost always</em>
+ * require only a single display. In particular, some platforms
+ * which SWT supports will not allow more than one <em>active</em>
+ * display. In other words, some platforms do not support
+ * creating a new display if one already exists that has not been
+ * sent the <code>dispose()</code> message.
+ * <p>
+ * In SWT, the thread which creates a <code>Display</code>
+ * instance is distinguished as the <em>user-interface thread</em>
+ * for that display.
+ * </p>
+ * The user-interface thread for a particular display has the
+ * following special attributes:
+ * <ul>
+ * <li>
+ * The event loop for that display must be run from the thread.
+ * </li>
+ * <li>
+ * Some SWT API methods (notably, most of the public methods in
+ * <code>Widget</code> and its subclasses), may only be called
+ * from the thread. (To support multi-threaded user-interface
+ * applications, class <code>Display</code> provides inter-thread
+ * communication methods which allow threads other than the
+ * user-interface thread to request that it perform operations
+ * on their behalf.)
+ * </li>
+ * <li>
+ * The thread is not allowed to construct other
+ * <code>Display</code>s until that display has been disposed.
+ * (Note that, this is in addition to the restriction mentioned
+ * above concerning platform support for multiple displays. Thus,
+ * the only way to have multiple simultaneously active displays,
+ * even on platforms which support it, is to have multiple threads.)
+ * </li>
+ * </ul>
+ * Enforcing these attributes allows SWT to be implemented directly
+ * on the underlying operating system's event model. This has
+ * numerous benefits including smaller footprint, better use of
+ * resources, safer memory management, clearer program logic,
+ * better performance, and fewer overall operating system threads
+ * required. The down side however, is that care must be taken
+ * (only) when constructing multi-threaded applications to use the
+ * inter-thread communication mechanisms which this class provides
+ * when required.
+ * </p><p>
+ * All SWT API methods which may only be called from the user-interface
+ * thread are distinguished in their documentation by indicating that
+ * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
+ * SWT exception.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Close, Dispose, Settings</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * @see #syncExec
+ * @see #asyncExec
+ * @see #wake
+ * @see #readAndDispatch
+ * @see #sleep
+ * @see Device#dispose
+ * @see <a href="http://www.eclipse.org/swt/snippets/#display">Display snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Display extends Device {
+
+ int application, dispatcher, frame, jniRef, nameScope;
+ boolean idle;
+ int sleepOperation, operation;
+ int operationCount;
+
+ /* Windows and Events */
+ Event [] eventQueue;
+ EventTable eventTable, filterTable;
+
+ int lastKey;
+ char lastChar;
+ boolean deadChar;
+
+ /* Track Mouse Control */
+ Control mouseControl;
+
+ /* Focus */
+ Control focusControl;
+
+ /* Menus */
+ Menu [] popups;
+
+ /* Sync/Async Widget Communication */
+ Synchronizer synchronizer = new Synchronizer (this);
+ Thread thread;
+
+ /* Display Shutdown */
+ Runnable [] disposeList;
+
+ /* System Tray */
+ Tray tray;
+
+ /* Timers */
+ int timerHandler;
+ int [] timerHandles;
+ Runnable [] timerList;
+
+// /* System Resources */
+ Font systemFont;
+ Image errorImage, infoImage, questionImage, warningIcon;
+ Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1];
+ Color [] colors;
+
+ /* Sort Indicators */
+// Image upArrow, downArrow;
+
+ /* Color dialog custom dialgos */
+ int customColors;
+
+ /* Display Data */
+ Object data;
+ String [] keys;
+ Object [] values;
+
+ /* DragDetect */
+ boolean dragging;
+ int dragDetectFrame, dragRect, dragMouseDown;
+
+ Control[] invalidate;
+ int invalidateHandler;
+ boolean ignoreRender;
+
+ Shell [] shells;
+
+ /* Key Mappings */
+ static final int [] [] KeyTable = {
+
+ /* Keyboard and Mouse Masks */
+ {OS.Key_LeftAlt, SWT.ALT},
+ {OS.Key_RightAlt, SWT.ALT},
+ {OS.Key_LeftShift, SWT.SHIFT},
+ {OS.Key_RightShift, SWT.SHIFT},
+ {OS.Key_LeftCtrl, SWT.CONTROL},
+ {OS.Key_RightCtrl, SWT.CONTROL},
+// {OS.VK_????, SWT.COMMAND},
+
+ /* NOT CURRENTLY USED */
+// {OS.VK_LBUTTON, SWT.BUTTON1},
+// {OS.VK_MBUTTON, SWT.BUTTON3},
+// {OS.VK_RBUTTON, SWT.BUTTON2},
+
+ /* Non-Numeric Keypad Keys */
+ {OS.Key_Up, SWT.ARROW_UP},
+ {OS.Key_Down, SWT.ARROW_DOWN},
+ {OS.Key_Left, SWT.ARROW_LEFT},
+ {OS.Key_Right, SWT.ARROW_RIGHT},
+ {OS.Key_PageUp, SWT.PAGE_UP},
+ {OS.Key_PageDown, SWT.PAGE_DOWN},
+ {OS.Key_Home, SWT.HOME},
+ {OS.Key_End, SWT.END},
+ {OS.Key_Insert, SWT.INSERT},
+
+ /* Virtual and Ascii Keys */
+ {OS.Key_Back, SWT.BS},
+ {OS.Key_Return, SWT.CR},
+ {OS.Key_Delete, SWT.DEL},
+ {OS.Key_Escape, SWT.ESC},
+ {OS.Key_Return, SWT.LF},
+ {OS.Key_Tab, SWT.TAB},
+
+ /* Functions Keys */
+ {OS.Key_F1, SWT.F1},
+ {OS.Key_F2, SWT.F2},
+ {OS.Key_F3, SWT.F3},
+ {OS.Key_F4, SWT.F4},
+ {OS.Key_F5, SWT.F5},
+ {OS.Key_F6, SWT.F6},
+ {OS.Key_F7, SWT.F7},
+ {OS.Key_F8, SWT.F8},
+ {OS.Key_F9, SWT.F9},
+ {OS.Key_F10, SWT.F10},
+ {OS.Key_F11, SWT.F11},
+ {OS.Key_F12, SWT.F12},
+ {OS.Key_F13, SWT.F13},
+ {OS.Key_F14, SWT.F14},
+ {OS.Key_F15, SWT.F15},
+
+ /* Numeric Keypad Keys */
+ {OS.Key_Multiply, SWT.KEYPAD_MULTIPLY},
+ {OS.Key_Add, SWT.KEYPAD_ADD},
+ {OS.Key_Return, SWT.KEYPAD_CR},
+ {OS.Key_Subtract, SWT.KEYPAD_SUBTRACT},
+ {OS.Key_Decimal, SWT.KEYPAD_DECIMAL},
+ {OS.Key_Divide, SWT.KEYPAD_DIVIDE},
+ {OS.Key_NumPad0, SWT.KEYPAD_0},
+ {OS.Key_NumPad1, SWT.KEYPAD_1},
+ {OS.Key_NumPad2, SWT.KEYPAD_2},
+ {OS.Key_NumPad3, SWT.KEYPAD_3},
+ {OS.Key_NumPad4, SWT.KEYPAD_4},
+ {OS.Key_NumPad5, SWT.KEYPAD_5},
+ {OS.Key_NumPad6, SWT.KEYPAD_6},
+ {OS.Key_NumPad7, SWT.KEYPAD_7},
+ {OS.Key_NumPad8, SWT.KEYPAD_8},
+ {OS.Key_NumPad9, SWT.KEYPAD_9},
+// {OS.VK_????, SWT.KEYPAD_EQUAL},
+
+ /* Other keys */
+ {OS.Key_CapsLock, SWT.CAPS_LOCK},
+ {OS.Key_NumLock, SWT.NUM_LOCK},
+ {OS.Key_Scroll, SWT.SCROLL_LOCK},
+ {OS.Key_Pause, SWT.PAUSE},
+ {OS.Key_Cancel, SWT.BREAK},
+ {OS.Key_PrintScreen, SWT.PRINT_SCREEN},
+// {OS.VK_????, SWT.HELP},
+
+
+ {OS.Key_D0, '0'},
+ {OS.Key_D1, '1'},
+ {OS.Key_D2, '2'},
+ {OS.Key_D3, '3'},
+ {OS.Key_D4, '4'},
+ {OS.Key_D5, '5'},
+ {OS.Key_D6, '6'},
+ {OS.Key_D7, '7'},
+ {OS.Key_D8, '8'},
+ {OS.Key_D9, '9'},
+ {OS.Key_A, 'a'},
+ {OS.Key_B, 'b'},
+ {OS.Key_C, 'c'},
+ {OS.Key_D, 'd'},
+ {OS.Key_E, 'e'},
+ {OS.Key_F, 'f'},
+ {OS.Key_G, 'g'},
+ {OS.Key_H, 'h'},
+ {OS.Key_I, 'i'},
+ {OS.Key_J, 'j'},
+ {OS.Key_K, 'k'},
+ {OS.Key_L, 'l'},
+ {OS.Key_M, 'm'},
+ {OS.Key_N, 'n'},
+ {OS.Key_O, 'o'},
+ {OS.Key_P, 'p'},
+ {OS.Key_Q, 'q'},
+ {OS.Key_R, 'r'},
+ {OS.Key_S, 's'},
+ {OS.Key_T, 't'},
+ {OS.Key_U, 'u'},
+ {OS.Key_V, 'v'},
+ {OS.Key_W, 'w'},
+ {OS.Key_X, 'x'},
+ {OS.Key_Y, 'y'},
+ {OS.Key_Z, 'z'},
+
+ {OS.Key_OemTilde, '`'},
+ {OS.Key_OemMinus, '-'},
+ {OS.Key_OemPlus, '='},
+ {OS.Key_Oem4, '['},
+ {OS.Key_Oem6, ']'},
+ {OS.Key_OemPipe, '\\'},
+ {OS.Key_OemSemicolon, ';'},
+ {OS.Key_Oem7, '\''},
+ {OS.Key_OemComma, ','},
+ {OS.Key_OemPeriod, '.'},
+ {OS.Key_Oem2, '/'},
+
+ };
+
+ /* Multiple Displays */
+ static Display Default;
+ static Display [] Displays = new Display [4];
+
+ /* Multiple Monitors */
+ static Monitor[] monitors = null;
+ static int monitorCount = 0;
+
+ /* Modality */
+ Shell [] modalShells;
+// Shell modalDialogShell;
+
+ /* Package Name */
+ static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$
+ /*
+ * This code is intentionally commented. In order
+ * to support CLDC, .class cannot be used because
+ * it does not compile on some Java compilers when
+ * they are targeted for CLDC.
+ */
+// static {
+// String name = Display.class.getName ();
+// int index = name.lastIndexOf ('.');
+// PACKAGE_PREFIX = name.substring (0, index + 1);
+// }
+
+ /*
+ * TEMPORARY CODE. Install the runnable that
+ * gets the current display. This code will
+ * be removed in the future.
+ */
+ static {
+ DeviceFinder = new Runnable () {
+ public void run () {
+ Device device = getCurrent ();
+ if (device == null) {
+ device = getDefault ();
+ }
+ setDevice (device);
+ }
+ };
+ }
+
+/*
+* TEMPORARY CODE.
+*/
+static void setDevice (Device device) {
+ CurrentDevice = device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * Note: The resulting display is marked as the <em>current</em>
+ * display. If this is the first display which has been
+ * constructed since the application started, it is also
+ * marked as the <em>default</em> display.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see #getCurrent
+ * @see #getDefault
+ * @see Widget#checkSubclass
+ * @see Shell
+ */
+public Display () {
+ this (null);
+}
+
+/**
+ * Constructs a new instance of this class using the parameter.
+ *
+ * @param data the device data
+ */
+public Display (DeviceData data) {
+ super (data);
+}
+
+Control _getFocusControl () {
+ int focusedElement = OS.Keyboard_FocusedElement ();
+ Control control = null;
+ if (focusedElement != 0) {
+ Widget widget = getWidget (focusedElement);
+ if (widget instanceof Menu) {
+ Shell shell = ((Menu)widget).getShell();
+ OS.GCHandle_Free (focusedElement);
+ focusedElement = OS.FocusManager_GetFocusedElement (shell.shellHandle);
+ if (focusedElement == 0) return null;
+ widget = getWidget (focusedElement);
+ }
+ if (widget != null) control = widget.getWidgetControl ();
+ OS.GCHandle_Free (focusedElement);
+ }
+ return control;
+}
+
+void addWidget (int handle, Widget widget) {
+ if (handle == 0) return;
+ int tag = OS.gcnew_IntPtr (widget.jniRef);
+ OS.FrameworkElement_Tag (handle, tag);
+ OS.GCHandle_Free (tag);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an event of the given type occurs anywhere
+ * in a widget. The event type is one of the event constants
+ * defined in class <code>SWT</code>. When the event does occur,
+ * the listener is notified by sending it the <code>handleEvent()</code>
+ * message.
+ * <p>
+ * Setting the type of an event to <code>SWT.None</code> from
+ * within the <code>handleEvent()</code> method can be used to
+ * change the event type and stop subsequent Java listeners
+ * from running. Because event filters run before other listeners,
+ * event filters can both block other listeners and set arbitrary
+ * fields within an event. For this reason, event filters are both
+ * powerful and dangerous. They should generally be avoided for
+ * performance, debugging and code maintenance reasons.
+ * </p>
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeFilter
+ * @see #removeListener
+ *
+ * @since 3.0
+ */
+public void addFilter (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (filterTable == null) filterTable = new EventTable ();
+ filterTable.hook (eventType, listener);
+}
+
+void addInvalidate (Control control) {
+ if (invalidate == null) invalidate = new Control [4];
+ int length = invalidate.length;
+ for (int i=0; i<length; i++) {
+ if (invalidate [i] == control) return;
+ }
+ int index = 0;
+ while (index < length) {
+ if (invalidate [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Control [] temp = new Control [length + 4];
+ System.arraycopy (invalidate, 0, temp, 0, length);
+ invalidate = temp;
+ }
+ invalidate [index] = control;
+ if (invalidateHandler == 0) {
+ int handler = invalidateHandler = OS.gcnew_NoArgsDelegate (jniRef, "invalidateHandler");
+ int operation = OS.Dispatcher_BeginInvoke (dispatcher, OS.DispatcherPriority_Send, handler);
+ OS.GCHandle_Free (operation);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an event of the given type occurs. The event
+ * type is one of the event constants defined in class <code>SWT</code>.
+ * When the event does occur in the display, the listener is notified by
+ * sending it the <code>handleEvent()</code> message.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeListener
+ *
+ * @since 2.0
+ */
+public void addListener (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) eventTable = new EventTable ();
+ eventTable.hook (eventType, listener);
+}
+
+void addPopup (Menu menu) {
+ if (popups == null) popups = new Menu [4];
+ int length = popups.length;
+ for (int i=0; i<length; i++) {
+ if (popups [i] == menu) return;
+ }
+ int index = 0;
+ while (index < length) {
+ if (popups [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Menu [] newPopups = new Menu [length + 4];
+ System.arraycopy (popups, 0, newPopups, 0, length);
+ popups = newPopups;
+ }
+ popups [index] = menu;
+}
+
+void addShell (Shell shell) {
+ if (shells == null) shells = new Shell [4];
+ int length = shells.length;
+ for (int i=0; i<length; i++) {
+ if (shells [i] == shell) return;
+ }
+ int index = 0;
+ while (index < length) {
+ if (shells [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Shell [] temp = new Shell [length + 4];
+ System.arraycopy (shells, 0, temp, 0, length);
+ shells = temp;
+ }
+ shells [index] = shell;
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The caller of this method continues
+ * to run in parallel, and is not notified when the
+ * runnable has completed. Specifying <code>null</code> as the
+ * runnable simply wakes the user-interface thread when run.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param runnable code to run on the user-interface thread or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #syncExec
+ */
+public void asyncExec (Runnable runnable) {
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ synchronizer.asyncExec (runnable);
+ }
+}
+
+/**
+ * Causes the system hardware to emit a short sound
+ * (if it supports this capability).
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void beep () {
+ checkDevice ();
+ OS.Console_Beep ();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ */
+protected void checkSubclass () {
+ if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+protected void checkDevice () {
+ if (thread == null) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+}
+
+static void checkDisplay (Thread thread, boolean multiple) {
+ synchronized (Device.class) {
+ for (int i=0; i<Displays.length; i++) {
+ if (Displays [i] != null) {
+ if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
+ if (Displays [i].thread == thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ }
+ }
+}
+
+void clearModal (Shell shell) {
+ if (modalShells == null) return;
+ int index = 0, length = modalShells.length;
+ while (index < length) {
+ if (modalShells [index] == shell) break;
+ if (modalShells [index] == null) return;
+ index++;
+ }
+ if (index == length) return;
+ System.arraycopy (modalShells, index + 1, modalShells, index, --length - index);
+ modalShells [length] = null;
+ if (index == 0 && modalShells [0] == null) modalShells = null;
+ Shell [] shells = getShells ();
+ for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+/**
+ * Requests that the connection between SWT and the underlying
+ * operating system be closed.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Device#dispose
+ *
+ * @since 2.0
+ */
+public void close () {
+ checkDevice ();
+ Event event = new Event ();
+ sendEvent (SWT.Close, event);
+ if (event.doit) dispose ();
+}
+
+/**
+ * Creates the device in the operating system. If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ * <p>
+ * This method is called before <code>init</code>.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+protected void create (DeviceData data) {
+ checkSubclass ();
+ checkDisplay (thread = Thread.currentThread (), true);
+ createDisplay (data);
+ register (this);
+ if (Default == null) Default = this;
+}
+
+void createDisplay (DeviceData data) {
+ Win32.OleInitialize (0);
+ application = OS.gcnew_Application();
+ if (application == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.Application_ShutdownMode (application, OS.ShutdownMode_OnExplicitShutdown);
+ nameScope = OS.gcnew_NameScope ();
+ if (nameScope == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+}
+
+static void deregister (Display display) {
+ synchronized (Device.class) {
+ for (int i=0; i<Displays.length; i++) {
+ if (display == Displays [i]) Displays [i] = null;
+ }
+ }
+}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle. If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ * <p>
+ * This method is called after <code>release</code>.
+ * </p>
+ * @see Device#dispose
+ * @see #release
+ */
+protected void destroy () {
+ if (this == Default) Default = null;
+ deregister (this);
+ destroyDisplay ();
+}
+
+void destroyDisplay () {
+ OS.GCHandle_Dump();
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread just before the
+ * receiver is disposed. Specifying a <code>null</code> runnable
+ * is ignored.
+ *
+ * @param runnable code to run at dispose time.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void disposeExec (Runnable runnable) {
+ checkDevice ();
+ if (disposeList == null) disposeList = new Runnable [4];
+ for (int i=0; i<disposeList.length; i++) {
+ if (disposeList [i] == null) {
+ disposeList [i] = runnable;
+ return;
+ }
+ }
+ Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
+ System.arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
+ newDisposeList [disposeList.length] = runnable;
+ disposeList = newDisposeList;
+}
+
+/**
+ * Does whatever display specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+ SWT.error (code);
+}
+
+boolean filterEvent (Event event) {
+ if (filterTable != null) filterTable.sendEvent (event);
+ return false;
+}
+
+boolean filters (int eventType) {
+ if (filterTable == null) return false;
+ return filterTable.hooks (eventType);
+}
+
+/**
+ * Given the operating system handle for a widget, returns
+ * the instance of the <code>Widget</code> subclass which
+ * represents it in the currently running application, if
+ * such exists, or null if no matching widget can be found.
+ * <p>
+ * <b>IMPORTANT:</b> This method should not be called from
+ * application code. The arguments are platform-specific.
+ * </p>
+ *
+ * @param handle the handle for the widget
+ * @return the SWT widget that the handle represents
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Widget findWidget (int handle) {
+ checkDevice ();
+ return getWidget (handle);
+}
+
+/**
+ * Given the operating system handle for a widget,
+ * and widget-specific id, returns the instance of
+ * the <code>Widget</code> subclass which represents
+ * the handle/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ * <p>
+ * <b>IMPORTANT:</b> This method should not be called from
+ * application code. The arguments are platform-specific.
+ * </p>
+ *
+ * @param handle the handle for the widget
+ * @param id the id for the subwidget (usually an item)
+ * @return the SWT widget that the handle/id pair represents
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public Widget findWidget (int handle, int id) {
+ checkDevice ();
+ return null;
+}
+
+/**
+ * Given a widget and a widget-specific id, returns the
+ * instance of the <code>Widget</code> subclass which represents
+ * the widget/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ *
+ * @param widget the widget
+ * @param id the id for the subwidget (usually an item)
+ * @return the SWT subwidget (usually an item) that the widget/id pair represents
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public Widget findWidget (Widget widget, int id) {
+ checkDevice ();
+ return null;
+}
+
+/**
+ * Returns the display which the given thread is the
+ * user-interface thread for, or null if the given thread
+ * is not a user-interface thread for any display. Specifying
+ * <code>null</code> as the thread will return <code>null</code>
+ * for the display.
+ *
+ * @param thread the user-interface thread
+ * @return the display for the given thread
+ */
+public static Display findDisplay (Thread thread) {
+ synchronized (Device.class) {
+ for (int i=0; i<Displays.length; i++) {
+ Display display = Displays [i];
+ if (display != null && display.thread == thread) {
+ return display;
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * Returns the currently active <code>Shell</code>, or null
+ * if no shell belonging to the currently running application
+ * is active.
+ *
+ * @return the active shell or null
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Shell getActiveShell () {
+ checkDevice ();
+ int windows = OS.Application_Windows (application);
+ int count = OS.WindowCollection_Count (windows);
+ int activeWindow = 0;
+ if (count != 0) {
+ int enumerator = OS.WindowCollection_GetEnumerator (windows);
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int window = OS.WindowCollection_Current (enumerator);
+ if (OS.Window_IsActive (window)) {
+ activeWindow = window;
+ break;
+ }
+ OS.GCHandle_Free (window);
+ }
+ OS.GCHandle_Free (enumerator);
+ }
+ OS.GCHandle_Free (windows);
+ Shell shell = (Shell)getWidget (activeWindow);
+ if (activeWindow != 0) OS.GCHandle_Free (activeWindow);
+ return shell;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location. Note that
+ * on multi-monitor systems the origin can be negative.
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds () {
+ checkDevice ();
+ int x = (int) OS.SystemParameters_VirtualScreenLeft ();
+ int y = (int) OS.SystemParameters_VirtualScreenTop ();
+ int width = (int) OS.SystemParameters_VirtualScreenWidth ();
+ int height = (int) OS.SystemParameters_VirtualScreenHeight ();
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the display which the currently running thread is
+ * the user-interface thread for, or null if the currently
+ * running thread is not a user-interface thread for any display.
+ *
+ * @return the current display
+ */
+public static Display getCurrent () {
+ return findDisplay (Thread.currentThread ());
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ */
+public Rectangle getClientArea () {
+ checkDevice ();
+// if (true/*OS.GetSystemMetrics (OS.SM_CMONITORS) < 2*/) {
+ int rect = OS.SystemParameters_WorkArea ();
+ int x = (int) OS.Rect_X (rect);
+ int y = (int) OS.Rect_Y (rect);
+ int width = (int) OS.Rect_Width (rect);
+ int height = (int) OS.Rect_Height (rect);
+ OS.GCHandle_Free (rect);
+ return new Rectangle (x, y, width, height);
+// }
+// int x = (int) OS.SystemParameters_VirtualScreenLeft ();
+// int y = (int) OS.SystemParameters_VirtualScreenTop ();
+// int width = (int) OS.SystemParameters_VirtualScreenWidth ();
+// int height = (int) OS.SystemParameters_VirtualScreenHeight ();
+// return new Rectangle (x, y, width, height);
+}
+
+Widget getWidget (int handle) {
+ if (handle == 0) return null;
+ int frameworkElementType = OS.FrameworkElement_typeid ();
+ int frameworkContentElementType = OS.FrameworkContentElement_typeid ();
+ int widget = handle;
+ int jniRef = 0;
+ do {
+ int parent = 0;
+ if (OS.Type_IsInstanceOfType (frameworkElementType, widget)) {
+ int tag = OS.FrameworkElement_Tag (widget);
+ if (tag != 0) {
+ jniRef = OS.IntPtr_ToInt32 (tag);
+ OS.GCHandle_Free (tag);
+ break;
+ }
+ parent = OS.FrameworkElement_Parent (widget);
+ if (parent == 0) {
+ parent = OS.VisualTreeHelper_GetParent (widget);
+ }
+ } else {
+ if (OS.Type_IsInstanceOfType (frameworkContentElementType, widget)) {
+ parent = OS.FrameworkContentElement_Parent (widget);
+ }
+ }
+ if (widget != handle) OS.GCHandle_Free (widget);
+ widget = parent;
+ } while (widget != 0);
+ if (widget != handle && widget != 0) OS.GCHandle_Free (widget);
+ OS.GCHandle_Free (frameworkElementType);
+ OS.GCHandle_Free (frameworkContentElementType);
+ return jniRef != 0 ? (Widget) OS.JNIGetObject (jniRef) : null;
+}
+
+/**
+ * Returns the control which the on-screen pointer is currently
+ * over top of, or null if it is not currently over one of the
+ * controls built by the currently running application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Control getCursorControl () {
+ checkDevice ();
+ int inputElement = 0;
+ int captured = OS.Mouse_Captured ();
+ if (captured != 0) {
+ int sources = OS.PresentationSource_CurrentSources ();
+ int enumerator = OS.IEnumerable_GetEnumerator (sources);
+ while (OS.IEnumerator_MoveNext (enumerator) && inputElement == 0) {
+ int current = OS.IEnumerator_Current (enumerator);
+ int root = OS.PresentationSource_RootVisual (current);
+ if (root != 0) {
+ int pt = OS.Mouse_GetPosition (root);
+ inputElement = OS.UIElement_InputHitTest (root, pt);
+ OS.GCHandle_Free (pt);
+ OS.GCHandle_Free (root);
+ }
+ OS.GCHandle_Free (current);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (sources);
+ OS.GCHandle_Free (captured);
+ } else {
+ inputElement = OS.Mouse_DirectlyOver ();
+ }
+ if (inputElement != 0) {
+ Widget widget = getWidget (inputElement);
+ OS.GCHandle_Free (inputElement);
+ if (widget != null) return widget.getWidgetControl ();
+ }
+ return null;
+}
+
+/**
+ * Returns the location of the on-screen pointer relative
+ * to the top left corner of the screen.
+ *
+ * @return the cursor location
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point getCursorLocation () {
+ checkDevice ();
+ POINT pt = new POINT ();
+ Win32.GetCursorPos (pt);
+ return new Point (pt.x, pt.y);
+}
+
+/**
+ * Returns an array containing the recommended cursor sizes.
+ *
+ * @return the array of cursor sizes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public Point [] getCursorSizes () {
+ checkDevice ();
+// return new Point [] {
+// new Point (OS.GetSystemMetrics (OS.SM_CXCURSOR), OS.GetSystemMetrics (OS.SM_CYCURSOR))};
+ return null;
+}
+
+/**
+ * Returns the default display. One is created (making the
+ * thread that invokes this method its user-interface thread)
+ * if it did not already exist.
+ *
+ * @return the default display
+ */
+public static Display getDefault () {
+ synchronized (Device.class) {
+ if (Default == null) Default = new Display ();
+ return Default;
+ }
+}
+
+static boolean isValidClass (Class clazz) {
+ String name = clazz.getName ();
+ int index = name.lastIndexOf ('.');
+ return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
+}
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility to provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setData(String, Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData (String key) {
+ checkDevice ();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+// return new Boolean (runMessagesInIdle);
+// }
+ if (keys == null) return null;
+ for (int i=0; i<keys.length; i++) {
+ if (keys [i].equals (key)) return values [i];
+ }
+ return null;
+}
+
+/**
+ * Returns the application defined, display specific data
+ * associated with the receiver, or null if it has not been
+ * set. The <em>display specific data</em> is a single,
+ * unnamed field that is stored with every display.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility to provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @return the display specific data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setData(Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData () {
+ checkDevice ();
+ return data;
+}
+
+/**
+ * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
+ * The button dismissal alignment is the ordering that should be used when positioning the
+ * default dismissal button for a dialog. For example, in a dialog that contains an OK and
+ * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
+ * button ordering should be OK/CANCEL. When button dismissal alignment is <code>RIGHT</code>,
+ * the button ordering should be CANCEL/OK.
+ *
+ * @return the button dismissal order
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public int getDismissalAlignment () {
+ checkDevice ();
+ return SWT.LEFT;
+}
+
+
+/**
+ * Returns the longest duration, in milliseconds, between
+ * two mouse button clicks that will be considered a
+ * <em>double click</em> by the underlying operating system.
+ *
+ * @return the double click time
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getDoubleClickTime () {
+ checkDevice ();
+ //TODO
+ return 500;
+}
+
+/**
+ * Returns the control which currently has keyboard focus,
+ * or null if keyboard events are not currently going to
+ * any of the controls built by the currently running
+ * application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Control getFocusControl () {
+ checkDevice ();
+ if (focusControl != null && !focusControl.isDisposed ()) {
+ return focusControl;
+ }
+ return _getFocusControl ();
+}
+
+/**
+ * Returns true when the high contrast mode is enabled.
+ * Otherwise, false is returned.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @return the high contrast mode
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public boolean getHighContrast () {
+ checkDevice ();
+ return OS.SystemParameters_HighContrast ();
+}
+
+/**
+ * Returns the maximum allowed depth of icons on this display, in bits per pixel.
+ * On some platforms, this may be different than the actual depth of the display.
+ *
+ * @return the maximum icon depth
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Device#getDepth
+ */
+public int getIconDepth () {
+ checkDevice ();
+// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+// if (getDepth () >= 24) return 32;
+// }
+//
+// /* Use the character encoding for the default locale */
+// TCHAR buffer1 = new TCHAR (0, "Control Panel\\Desktop\\WindowMetrics", true); //$NON-NLS-1$
+//
+// int [] phkResult = new int [1];
+// int result = OS.RegOpenKeyEx (OS.HKEY_CURRENT_USER, buffer1, 0, OS.KEY_READ, phkResult);
+// if (result != 0) return 4;
+ int depth = 4;
+// int [] lpcbData = new int [1];
+//
+// /* Use the character encoding for the default locale */
+// TCHAR buffer2 = new TCHAR (0, "Shell Icon BPP", true); //$NON-NLS-1$
+// result = OS.RegQueryValueEx (phkResult [0], buffer2, 0, null, (TCHAR) null, lpcbData);
+// if (result == 0) {
+// TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
+// result = OS.RegQueryValueEx (phkResult [0], buffer2, 0, null, lpData, lpcbData);
+// if (result == 0) {
+// try {
+// depth = Integer.parseInt (lpData.toString (0, lpData.strlen ()));
+// } catch (NumberFormatException e) {}
+// }
+// }
+// OS.RegCloseKey (phkResult [0]);
+ return depth;
+}
+
+/**
+ * Returns an array containing the recommended icon sizes.
+ *
+ * @return the array of icon sizes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Decorations#setImages(Image[])
+ *
+ * @since 3.0
+ */
+public Point [] getIconSizes () {
+ checkDevice ();
+ //TODO
+// return new Point [] {
+// new Point (OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON)),
+// new Point (OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON)),
+// };
+ return null;
+}
+
+int getLastEventTime () {
+ //TODO - use OS
+ return (int)System.currentTimeMillis();
+}
+
+int getMessageCount () {
+ return synchronizer.getMessageCount ();
+}
+
+
+Shell getModalShell () {
+ if (modalShells == null) return null;
+ int index = modalShells.length;
+ while (--index >= 0) {
+ Shell shell = modalShells [index];
+ if (shell != null) return shell;
+ }
+ return null;
+}
+
+//Shell getModalDialogShell () {
+// if (modalDialogShell != null && modalDialogShell.isDisposed ()) modalDialogShell = null;
+// return modalDialogShell;
+//}
+
+/**
+ * Returns an array of monitors attached to the device.
+ *
+ * @return the array of monitors
+ *
+ * @since 3.0
+ */
+public Monitor [] getMonitors () {
+ checkDevice ();
+ int screens = OS.Screen_AllScreens ();
+ if (screens == 0) error (SWT.ERROR_NO_HANDLES);
+ int screenCount = OS.ICollection_Count (screens);
+ Monitor [] monitors = new Monitor [screenCount];
+ for (int i=0; i<screenCount; i++) {
+ int screen = OS.IList_default (screens, i);
+ int bounds = OS.Screen_Bounds (screen);
+ int workingArea = OS.Screen_WorkingArea (screen);
+ Monitor monitor = new Monitor ();
+ monitor.x = OS.Rectangle_X (bounds);
+ monitor.y = OS.Rectangle_Y (bounds);
+ monitor.width = OS.Rectangle_Width (bounds);
+ monitor.height = OS.Rectangle_Height (bounds);
+ monitor.clientX = OS.Rectangle_X (workingArea);
+ monitor.clientY = OS.Rectangle_Y (workingArea);
+ monitor.clientWidth = OS.Rectangle_Width (workingArea);
+ monitor.clientHeight = OS.Rectangle_Height (workingArea);
+ monitors [i] = monitor;
+ OS.GCHandle_Free (workingArea);
+ OS.GCHandle_Free (bounds);
+ OS.GCHandle_Free (screen);
+ }
+ OS.GCHandle_Free (screens);
+ return monitors;
+}
+
+/**
+ * Returns the primary monitor for that device.
+ *
+ * @return the primary monitor
+ *
+ * @since 3.0
+ */
+public Monitor getPrimaryMonitor () {
+ checkDevice ();
+ int screen = OS.Screen_PrimaryScreen ();
+ if (screen == 0) error (SWT.ERROR_NO_HANDLES);
+ int bounds = OS.Screen_Bounds (screen);
+ int workingArea = OS.Screen_WorkingArea (screen);
+ Monitor monitor = new Monitor ();
+ monitor.x = OS.Rectangle_X (bounds);
+ monitor.y = OS.Rectangle_Y (bounds);
+ monitor.width = OS.Rectangle_Width (bounds);
+ monitor.height = OS.Rectangle_Height (bounds);
+ monitor.clientX = OS.Rectangle_X (workingArea);
+ monitor.clientY = OS.Rectangle_Y (workingArea);
+ monitor.clientWidth = OS.Rectangle_Width (workingArea);
+ monitor.clientHeight = OS.Rectangle_Height (workingArea);
+ OS.GCHandle_Free (workingArea);
+ OS.GCHandle_Free (bounds);
+ OS.GCHandle_Free (screen);
+ return monitor;
+}
+
+/**
+ * Returns a (possibly empty) array containing all shells which have
+ * not been disposed and have the receiver as their display.
+ *
+ * @return the receiver's shells
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Shell [] getShells () {
+ checkDevice ();
+ if (shells == null) return new Shell [0];
+ int length = 0;
+ for (int i=0; i<shells.length; i++) {
+ if (shells [i] != null) length++;
+ }
+ int index = 0;
+ Shell [] result = new Shell [length];
+ for (int i=0; i<shells.length; i++) {
+ Shell widget = shells [i];
+ if (widget != null) result [index++] = widget;
+ }
+ return result;
+}
+
+/**
+ * Gets the synchronizer used by the display.
+ *
+ * @return the receiver's synchronizer
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public Synchronizer getSynchronizer () {
+ checkDevice ();
+ return synchronizer;
+}
+
+/**
+ * Returns the thread that has invoked <code>syncExec</code>
+ * or null if no such runnable is currently being invoked by
+ * the user-interface thread.
+ * <p>
+ * Note: If a runnable invoked by asyncExec is currently
+ * running, this method will return null.
+ * </p>
+ *
+ * @return the receiver's sync-interface thread
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Thread getSyncThread () {
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ return synchronizer.syncThread;
+ }
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class <code>SWT</code>. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be free'd because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT
+ */
+public Color getSystemColor (int id) {
+ checkDevice ();
+ Color color = null;
+ if (0 <= id && id < colors.length) {
+ color = colors [id];
+ }
+ return color != null ? color : super.getSystemColor (id);
+}
+
+/**
+ * Returns the matching standard platform cursor for the given
+ * constant, which should be one of the cursor constants
+ * specified in class <code>SWT</code>. This cursor should
+ * not be free'd because it was allocated by the system,
+ * not the application. A value of <code>null</code> will
+ * be returned if the supplied constant is not an SWT cursor
+ * constant.
+ *
+ * @param id the SWT cursor constant
+ * @return the corresponding cursor or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ *
+ * @since 3.0
+ */
+public Cursor getSystemCursor (int id) {
+ checkDevice ();
+ if (!(0 <= id && id < cursors.length)) return null;
+ if (cursors [id] == null) {
+ cursors [id] = new Cursor (this, id);
+ }
+ return cursors [id];
+}
+
+/**
+ * Returns the matching standard platform image for the given
+ * constant, which should be one of the icon constants
+ * specified in class <code>SWT</code>. This image should
+ * not be free'd because it was allocated by the system,
+ * not the application. A value of <code>null</code> will
+ * be returned either if the supplied constant is not an
+ * SWT icon constant or if the platform does not define an
+ * image that corresponds to the constant.
+ *
+ * @param id the SWT icon constant
+ * @return the corresponding image or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_QUESTION
+ * @see SWT#ICON_WARNING
+ * @see SWT#ICON_WORKING
+ *
+ * @since 3.0
+ */
+public Image getSystemImage (int id) {
+ checkDevice ();
+ switch (id) {
+ case SWT.ICON_ERROR: {
+ if (errorImage != null) return errorImage;
+ int hIcon = Win32.LoadImage (0, Win32.OIC_HAND, Win32.IMAGE_ICON, 0, 0, Win32.LR_SHARED);
+ int empty = OS.Int32Rect_Empty ();
+ int source = OS.Imaging_CreateBitmapSourceFromHIcon (hIcon, empty, 0);
+ errorImage = Image.wpf_new (this, SWT.BITMAP, source);
+ OS.GCHandle_Free (empty);
+ Win32.DestroyIcon (hIcon);
+ return errorImage;
+ }
+ case SWT.ICON_WORKING:
+ case SWT.ICON_INFORMATION: {
+ if (infoImage != null) return infoImage;
+ int hIcon = Win32.LoadImage (0, Win32.OIC_INFORMATION, Win32.IMAGE_ICON, 0, 0, Win32.LR_SHARED);
+ int empty = OS.Int32Rect_Empty ();
+ int source = OS.Imaging_CreateBitmapSourceFromHIcon (hIcon, empty, 0);
+ infoImage = Image.wpf_new (this, SWT.BITMAP, source);
+ OS.GCHandle_Free (empty);
+ Win32.DestroyIcon (hIcon);
+ return infoImage;
+ }
+ case SWT.ICON_QUESTION: {
+ if (questionImage != null) return questionImage;
+ int hIcon = Win32.LoadImage (0, Win32.OIC_QUES, Win32.IMAGE_ICON, 0, 0, Win32.LR_SHARED);
+ int empty = OS.Int32Rect_Empty ();
+ int source = OS.Imaging_CreateBitmapSourceFromHIcon (hIcon, empty, 0);
+ questionImage = Image.wpf_new (this, SWT.BITMAP, source);
+ OS.GCHandle_Free (empty);
+ Win32.DestroyIcon (hIcon);
+ return questionImage;
+ }
+ case SWT.ICON_WARNING: {
+ if (warningIcon != null) return warningIcon;
+ int hIcon = Win32.LoadImage (0, Win32.OIC_BANG, Win32.IMAGE_ICON, 0, 0, Win32.LR_SHARED);
+ int empty = OS.Int32Rect_Empty ();
+ int source = OS.Imaging_CreateBitmapSourceFromHIcon (hIcon, empty, 0);
+ warningIcon = Image.wpf_new (this, SWT.BITMAP, source);
+ OS.GCHandle_Free (empty);
+ Win32.DestroyIcon (hIcon);
+ return warningIcon;
+ }
+ }
+ return null;
+}
+
+/**
+ * Returns the single instance of the system tray or null
+ * when there is no system tray available for the platform.
+ *
+ * @return the system tray or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public Tray getSystemTray () {
+ checkDevice ();
+ if (tray != null) return tray;
+ tray = new Tray (this, SWT.NONE);
+ return tray;
+}
+
+/**
+ * Returns the user-interface thread for the receiver.
+ *
+ * @return the receiver's user-interface thread
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Thread getThread () {
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ return thread;
+ }
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Display</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
+ * </ul>
+ */
+public int internal_new_GC (GCData data) {
+ if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+ //TODO - for now, return a drawing context that can measure text
+ if (data == null) return 0;
+ int visual = OS.gcnew_DrawingVisual();
+ if (visual == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int dc = OS.DrawingVisual_RenderOpen (visual);
+ if (dc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ data.visual = visual;
+ data.font = getSystemFont ();
+ return dc;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ * <p>
+ * This method is called after <code>create</code>.
+ * </p>
+ *
+ * @see #create
+ */
+protected void init () {
+ super.init ();
+
+ dispatcher = OS.Application_Dispatcher (application);
+ if (dispatcher == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ frame = OS.gcnew_DispatcherFrame ();
+ if (frame == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ jniRef = OS.NewGlobalRef (this);
+ if (jniRef == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ int hooks = OS.Dispatcher_Hooks (dispatcher);
+ int handler = OS.gcnew_EventHandler (jniRef, "HandleDispatcherInactive");
+ OS.DispatcherHooks_DispatcherInactive (hooks, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_DispatcherHookEventHandler (jniRef, "HandleOperationCompleted");
+ OS.DispatcherHooks_OperationCompleted (hooks, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_DispatcherHookEventHandler (jniRef, "HandleOperationPosted");
+ OS.DispatcherHooks_OperationPosted (hooks, handler);
+ OS.GCHandle_Free (handler);
+ OS.GCHandle_Free (hooks);
+ timerHandler = OS.gcnew_TimerHandler(jniRef, "timerProc");
+
+
+ /* Create the standard colors */
+ colors = new Color [SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT + 1];
+ colors [SWT.COLOR_WIDGET_DARK_SHADOW] = Color.wpf_new( this, OS.SystemColors_ControlDarkDarkColor ());
+ colors [SWT.COLOR_WIDGET_NORMAL_SHADOW] = Color.wpf_new (this, OS.SystemColors_ControlDarkColor ());
+ colors [SWT.COLOR_WIDGET_LIGHT_SHADOW] = Color.wpf_new (this, OS.SystemColors_ControlLightColor ());
+ colors [SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW] = Color.wpf_new (this, OS.SystemColors_ControlLightLightColor ());
+ colors [SWT.COLOR_WIDGET_FOREGROUND] = Color.wpf_new (this, OS.SystemColors_ControlTextColor ());
+ colors [SWT.COLOR_WIDGET_BACKGROUND] = Color.wpf_new (this, OS.SystemColors_ControlColor ());
+ colors [SWT.COLOR_WIDGET_BORDER] = Color.wpf_new (this, OS.SystemColors_ActiveBorderColor ());
+ colors [SWT.COLOR_LIST_FOREGROUND] = Color.wpf_new (this, OS.SystemColors_WindowTextColor ());
+ colors [SWT.COLOR_LIST_BACKGROUND] = Color.wpf_new (this, OS.SystemColors_WindowColor ());
+ colors [SWT.COLOR_LIST_SELECTION] = Color.wpf_new (this, OS.SystemColors_HighlightColor ());
+ colors [SWT.COLOR_LIST_SELECTION_TEXT] = Color.wpf_new (this, OS.SystemColors_HighlightTextColor ());
+ colors [SWT.COLOR_INFO_FOREGROUND] = Color.wpf_new (this, OS.SystemColors_InfoTextColor ());
+ colors [SWT.COLOR_INFO_BACKGROUND] = Color.wpf_new (this, OS.SystemColors_InfoColor ());
+ colors [SWT.COLOR_TITLE_FOREGROUND] = Color.wpf_new (this, OS.SystemColors_ActiveCaptionTextColor ());
+ colors [SWT.COLOR_TITLE_BACKGROUND] = Color.wpf_new (this, OS.SystemColors_ActiveCaptionColor ());
+ colors [SWT.COLOR_TITLE_BACKGROUND_GRADIENT] = Color.wpf_new (this, OS.SystemColors_GradientActiveCaptionColor ());
+ colors [SWT.COLOR_TITLE_INACTIVE_FOREGROUND] = Color.wpf_new (this, OS.SystemColors_InactiveCaptionTextColor ());
+ colors [SWT.COLOR_TITLE_INACTIVE_BACKGROUND] = Color.wpf_new (this, OS.SystemColors_InactiveCaptionColor ());
+ colors [SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT] = Color.wpf_new (this, OS.SystemColors_GradientInactiveCaptionColor ());
+
+}
+
+void invalidateHandler () {
+ invalidateHandler = 0;
+ if (invalidate != null) {
+ Control[] invalidate = this.invalidate;
+ this.invalidate = null;
+ for (int i = 0; i < invalidate.length; i++) {
+ Control control = invalidate [i];
+ if (control != null && !control.isDisposed()) {
+ control.redraw (true);
+ }
+ }
+ }
+}
+
+void HandleDispatcherInactive (int sender, int e) {
+ if (runAsyncMessages (false)) wakeThread ();
+}
+
+void HandleOperationCompleted (int sender, int e) {
+ if (operation != 0) {
+ int current = OS.DispatcherHookEventArgs_Operation(e);
+ int priority = OS.DispatcherOperation_Priority(current);
+ if (priority == 5) OS.DispatcherOperation_Abort(operation);
+ OS.GCHandle_Free(current);
+ }
+}
+
+void HandleOperationPosted (int sender, int e) {
+ if (sleepOperation != 0) OS.DispatcherOperation_Priority(sleepOperation, OS.DispatcherPriority_Send);
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Display</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (int dc, GCData data) {
+ //TODO - the wrong drawing context was created
+ if (data != null && data.drawingContext == 0) {
+ OS.DrawingContext_Close (dc);
+ OS.GCHandle_Free (dc);
+ OS.GCHandle_Free (data.visual);
+ }
+}
+
+boolean isValidThread () {
+ return thread == Thread.currentThread ();
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param point to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public Point map (Control from, Control to, Point point) {
+ checkDevice ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return map (from, to, point.x, point.y);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public Point map (Control from, Control to, int x, int y) {
+ checkDevice ();
+ if (from != null && from.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (to != null && to.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (from == to) return new Point (x, y);
+ int newX, newY;
+ if (from != null && to != null) {
+ int point = OS.gcnew_Point (x, y);
+ int newPoint = OS.UIElement_TranslatePoint (from.handle, point, to.handle);
+ newX = (int) (OS.Point_X (newPoint) + 0.5);
+ newY = (int) (OS.Point_Y (newPoint) + 0.5);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (newPoint);
+ } else {
+ if (from == null) {
+ int toHandle = to.handle;
+ to.updateLayout (toHandle);
+ int source = OS.PresentationSource_FromVisual (toHandle);
+ int window = OS.PresentationSource_RootVisual (source);
+ OS.GCHandle_Free (source);
+ int point = OS.gcnew_Point (x, y);
+ int temp = OS.Visual_PointFromScreen (window, point);
+ int newPoint = OS.UIElement_TranslatePoint (window, temp, toHandle);
+ newX = (int) OS.Point_X (newPoint);
+ newY = (int) OS.Point_Y (newPoint);
+ OS.GCHandle_Free (temp);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (newPoint);
+ OS.GCHandle_Free (window);
+ } else {
+ int fromHandle = from.handle;
+ from.updateLayout (fromHandle);
+ int source = OS.PresentationSource_FromVisual (fromHandle);
+ int window = OS.PresentationSource_RootVisual (source);
+ OS.GCHandle_Free (source);
+ int point = OS.gcnew_Point (x, y);
+ int temp = OS.UIElement_TranslatePoint (fromHandle, point, window);
+ int newPoint = OS.Visual_PointToScreen (window, temp);
+ newX = (int) OS.Point_X (newPoint);
+ newY = (int) OS.Point_Y (newPoint);
+ OS.GCHandle_Free (temp);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (newPoint);
+ OS.GCHandle_Free (window);
+ }
+ }
+ return new Point (newX, newY);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param rectangle to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public Rectangle map (Control from, Control to, Rectangle rectangle) {
+ checkDevice ();
+ if (rectangle == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @param width coordinates to be mapped
+ * @param height coordinates to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
+ checkDevice ();
+ if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (from == to) return new Rectangle (x, y, width, height);
+ //TODO
+ Point point = map (from, to, x, y);
+ return new Rectangle (point.x, point.y, width, height);
+}
+
+/**
+ * Generate a low level system event.
+ *
+ * <code>post</code> is used to generate low level keyboard
+ * and mouse events. The intent is to enable automated UI
+ * testing by simulating the input from the user. Most
+ * SWT applications should never need to call this method.
+ * <p>
+ * Note that this operation can fail when the operating system
+ * fails to generate the event for any reason. For example,
+ * this can happen when there is no such key or mouse button
+ * or when the system event queue is full.
+ * </p>
+ * <p>
+ * <b>Event Types:</b>
+ * <p>KeyDown, KeyUp
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type KeyDown or KeyUp</li>
+ * <p> Either one of:
+ * <li>(in) character a character that corresponds to a keyboard key</li>
+ * <li>(in) keyCode the key code of the key that was typed,
+ * as defined by the key code constants in class <code>SWT</code></li>
+ * </ul>
+ * <p>MouseDown, MouseUp</p>
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type MouseDown or MouseUp
+ * <li>(in) button the button that is pressed or released
+ * </ul>
+ * <p>MouseMove</p>
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type MouseMove
+ * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
+ * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
+ * </ul>
+ * <p>MouseWheel</p>
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type MouseWheel
+ * <li>(in) detail either SWT.SCROLL_LINE or SWT.SCROLL_PAGE
+ * <li>(in) count the number of lines or pages to scroll
+ * </ul>
+ * </dl>
+ *
+ * @param event the event to be generated
+ *
+ * @return true if the event was generated or false otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the event is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ *
+ */
+public boolean post (Event event) {
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+// int type = event.type;
+// switch (type){
+// case SWT.KeyDown:
+// case SWT.KeyUp: {
+// KEYBDINPUT inputs = new KEYBDINPUT ();
+// inputs.wVk = (short) untranslateKey (event.keyCode);
+// if (inputs.wVk == 0) {
+// char key = event.character;
+// switch (key) {
+// case SWT.BS: inputs.wVk = (short) OS.VK_BACK; break;
+// case SWT.CR: inputs.wVk = (short) OS.VK_RETURN; break;
+// case SWT.DEL: inputs.wVk = (short) OS.VK_DELETE; break;
+// case SWT.ESC: inputs.wVk = (short) OS.VK_ESCAPE; break;
+// case SWT.TAB: inputs.wVk = (short) OS.VK_TAB; break;
+// /*
+// * Since there is no LF key on the keyboard, do not attempt
+// * to map LF to CR or attempt to post an LF key.
+// */
+// // case SWT.LF: inputs.wVk = (short) OS.VK_RETURN; break;
+// case SWT.LF: return false;
+// default: {
+// if (OS.IsWinCE) {
+// inputs.wVk = OS.CharUpper ((short) key);
+// } else {
+// inputs.wVk = OS.VkKeyScan ((short) wcsToMbcs (key, 0));
+// if (inputs.wVk == -1) return false;
+// inputs.wVk &= 0xFF;
+// }
+// }
+// }
+// }
+// inputs.dwFlags = type == SWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
+// int hHeap = OS.GetProcessHeap ();
+// int pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+// OS.MoveMemory(pInputs, new int[] {OS.INPUT_KEYBOARD}, 4);
+// OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
+// boolean result = OS.SendInput (1, pInputs, INPUT.sizeof) != 0;
+// OS.HeapFree (hHeap, 0, pInputs);
+// return result;
+// }
+// case SWT.MouseDown:
+// case SWT.MouseMove:
+// case SWT.MouseUp: {
+// MOUSEINPUT inputs = new MOUSEINPUT ();
+// if (type == SWT.MouseMove){
+// inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
+// inputs.dx = event.x * 65535 / (OS.GetSystemMetrics (OS.SM_CXSCREEN) - 1);
+// inputs.dy = event.y * 65535 / (OS.GetSystemMetrics (OS.SM_CYSCREEN) - 1);
+// } else {
+// switch (event.button) {
+// case 1: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
+// case 2: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
+// case 3: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
+// default: return false;
+// }
+// }
+// int hHeap = OS.GetProcessHeap ();
+// int pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+// OS.MoveMemory(pInputs, new int[] {OS.INPUT_MOUSE}, 4);
+// OS.MoveMemory (pInputs + 4, inputs, MOUSEINPUT.sizeof);
+// boolean result = OS.SendInput (1, pInputs, INPUT.sizeof) != 0;
+// OS.HeapFree (hHeap, 0, pInputs);
+// return result;
+// }
+// }
+ return false;
+ }
+}
+
+void postEvent (Event event) {
+ /*
+ * Place the event at the end of the event queue.
+ * This code is always called in the Display's
+ * thread so it must be re-enterant but does not
+ * need to be synchronized.
+ */
+ if (eventQueue == null) eventQueue = new Event [4];
+ int index = 0;
+ int length = eventQueue.length;
+ while (index < length) {
+ if (eventQueue [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Event [] newQueue = new Event [length + 4];
+ System.arraycopy (eventQueue, 0, newQueue, 0, length);
+ eventQueue = newQueue;
+ }
+ eventQueue [index] = event;
+}
+
+void removePopup (Menu menu) {
+ if (popups == null) return;
+ for (int i=0; i<popups.length; i++) {
+ if (popups [i] == menu) {
+ popups [i] = null;
+ return;
+ }
+ }
+}
+
+void removeShell (Shell shell) {
+ if (shells == null) return;
+ for (int i=0; i<shells.length; i++) {
+ if (shells [i] == shell) {
+ shells [i] = null;
+ return;
+ }
+ }
+}
+
+/**
+ * Reads an event from the operating system's event queue,
+ * dispatches it appropriately, and returns <code>true</code>
+ * if there is potentially more work to do, or <code>false</code>
+ * if the caller can sleep until another event is placed on
+ * the event queue.
+ * <p>
+ * In addition to checking the system event queue, this method also
+ * checks if any inter-thread messages (created by <code>syncExec()</code>
+ * or <code>asyncExec()</code>) are waiting to be processed, and if
+ * so handles them before returning.
+ * </p>
+ *
+ * @return <code>false</code> if the caller can sleep upon return from this method
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
+ * </ul>
+ *
+ * @see #sleep
+ * @see #wake
+ */
+public boolean readAndDispatch () {
+ checkDevice ();
+ runPopups ();
+ idle = false;
+ int handler = OS.gcnew_NoArgsDelegate(jniRef, "setIdleHandler");
+ operation = OS.Dispatcher_BeginInvoke(dispatcher, 2, handler);
+ OS.DispatcherOperation_Wait(operation);
+ OS.GCHandle_Free(handler);
+ OS.GCHandle_Free(operation);
+ operation = 0;
+ if (!idle) {
+ runDeferredEvents();
+ return true;
+ }
+ return isDisposed () || runAsyncMessages(false);
+}
+
+static void register (Display display) {
+ synchronized (Device.class) {
+ for (int i=0; i<Displays.length; i++) {
+ if (Displays [i] == null) {
+ Displays [i] = display;
+ return;
+ }
+ }
+ Display [] newDisplays = new Display [Displays.length + 4];
+ System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
+ newDisplays [Displays.length] = display;
+ Displays = newDisplays;
+ }
+}
+
+/**
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the device handle.
+ * <p>
+ * Disposes all shells which are currently open on the display.
+ * After this method has been invoked, all related related shells
+ * will answer <code>true</code> when sent the message
+ * <code>isDisposed()</code>.
+ * </p><p>
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in <code>release</code>. Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by <code>destroy</code>.
+ * </p>
+ * This method is called before <code>destroy</code>.
+ *
+ * @see Device#dispose
+ * @see #destroy
+ */
+protected void release () {
+ sendEvent (SWT.Dispose, new Event ());
+ Shell [] shells = getShells ();
+ for (int i=0; i<shells.length; i++) {
+ Shell shell = shells [i];
+ if (!shell.isDisposed ()) shell.dispose ();
+ }
+ if (tray != null) tray.dispose ();
+ tray = null;
+
+ //hack... readAndDispatch Always returns true right now, prevents apps from shutting down.
+ //while (readAndDispatch ()) {}
+
+ if (disposeList != null) {
+ for (int i=0; i<disposeList.length; i++) {
+ if (disposeList [i] != null) disposeList [i].run ();
+ }
+ }
+ disposeList = null;
+ synchronizer.releaseSynchronizer ();
+ synchronizer = null;
+ releaseDisplay ();
+ super.release ();
+}
+
+void releaseDisplay () {
+ /* Release the timers */
+ OS.GCHandle_Free (timerHandler);
+ timerHandler = 0;
+ if (timerHandles != null) {
+ for (int i = 0; i < timerHandles.length; i++) {
+ int timer = timerHandles [i];
+ if (timer != 0) {
+ OS.DispatcherTimer_Stop (timer);
+ OS.GCHandle_Free (timer);
+ }
+ }
+ }
+ timerHandles = null;
+ timerList = null;
+ if (nameScope != 0) OS.GCHandle_Free (nameScope);
+ nameScope = 0;
+ if (application != 0) {
+ OS.Application_Shutdown (application);
+ OS.GCHandle_Free (application);
+ }
+ application = 0;
+ if (dispatcher != 0) OS.GCHandle_Free (dispatcher);
+ dispatcher = 0;
+ if (frame != 0) OS.GCHandle_Free (frame);
+ frame = 0;
+ if (jniRef != 0) OS.DeleteGlobalRef (jniRef);
+ jniRef = 0;
+
+ for (int i = 0; i < colors.length; i++) {
+ if (colors [i] != null) colors [i].dispose ();
+ }
+ colors = null;
+
+// /* Release the System fonts */
+// if (systemFont != null) systemFont.dispose ();
+// systemFont = null;
+// lfSystemFont = null;
+
+ /* Release the System Images */
+ if (errorImage != null) errorImage.dispose ();
+ if (infoImage != null) infoImage.dispose ();
+ if (questionImage != null) questionImage.dispose ();
+ if (warningIcon != null) warningIcon.dispose ();
+ errorImage = infoImage = questionImage = warningIcon = null;
+
+ /* Release the System Cursors */
+ for (int i = 0; i < cursors.length; i++) {
+ if (cursors [i] != null) cursors [i].dispose ();
+ }
+ cursors = null;
+
+// /* Release Acquired Resources */
+// if (resources != null) {
+// for (int i=0; i<resources.length; i++) {
+// if (resources [i] != null) resources [i].dispose ();
+// }
+// resources = null;
+// }
+//
+ /* Release Custom Colors for ChooseColor */
+ if (customColors != 0) OS.GCHandle_Free (customColors);
+ customColors = 0;
+
+ /* Release references */
+ thread = null;
+// modalDialogShell = null;
+ modalShells = null;
+ data = null;
+ keys = null;
+ values = null;
+ popups = null;
+ mouseControl = null;
+ shells = null;
+ eventTable = filterTable = null;
+
+ /* Uninitialize OLE */
+ Win32.OleUninitialize ();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs anywhere in
+ * a widget. The event type is one of the event constants defined
+ * in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addFilter
+ * @see #addListener
+ *
+ * @since 3.0
+ */
+public void removeFilter (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (filterTable == null) return;
+ filterTable.unhook (eventType, listener);
+ if (filterTable.size () == 0) filterTable = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs. The event type
+ * is one of the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addListener
+ *
+ * @since 2.0
+ */
+public void removeListener (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+Widget removeWidget (int handle) {
+ if (handle == 0) return null;
+ int tag = OS.FrameworkElement_Tag (handle), ref = 0;
+ if (tag != 0) {
+ ref = OS.IntPtr_ToInt32(tag);
+ OS.GCHandle_Free(tag);
+ }
+ Widget widget = null;
+ if (ref != 0) {
+ OS.FrameworkElement_Tag (handle, 0);
+ widget = (Widget) OS.JNIGetObject (ref);
+ }
+ return widget;
+}
+
+boolean runAsyncMessages (boolean all) {
+ return synchronizer.runAsyncMessages (all);
+}
+
+boolean runDeferredEvents () {
+ boolean run = false;
+ /*
+ * Run deferred events. This code is always
+ * called in the Display's thread so it must
+ * be re-enterant but need not be synchronized.
+ */
+ while (eventQueue != null) {
+
+ /* Take an event off the queue */
+ Event event = eventQueue [0];
+ if (event == null) break;
+ int length = eventQueue.length;
+ System.arraycopy (eventQueue, 1, eventQueue, 0, --length);
+ eventQueue [length] = null;
+
+ /* Run the event */
+ Widget widget = event.widget;
+ if (widget != null && !widget.isDisposed ()) {
+ Widget item = event.item;
+ if (item == null || !item.isDisposed ()) {
+ run = true;
+ widget.sendEvent (event);
+ }
+ }
+
+ /*
+ * At this point, the event queue could
+ * be null due to a recursive invokation
+ * when running the event.
+ */
+ }
+
+ /* Clear the queue */
+ eventQueue = null;
+ return run;
+}
+
+boolean runPopups () {
+ if (popups == null) return false;
+ boolean result = false;
+ while (popups != null) {
+ Menu menu = popups [0];
+ if (menu == null) break;
+ int length = popups.length;
+ System.arraycopy (popups, 1, popups, 0, --length);
+ popups [length] = null;
+ runDeferredEvents ();
+ if (!menu.isDisposed()) menu._setVisible (true);
+ result = true;
+ }
+ popups = null;
+ return result;
+}
+
+void runSettings () {
+ Font oldFont = getSystemFont ();
+ saveResources ();
+// updateImages ();
+ sendEvent (SWT.Settings, null);
+ Font newFont = getSystemFont ();
+ boolean sameFont = oldFont.equals (newFont);
+ Shell [] shells = getShells ();
+ for (int i=0; i<shells.length; i++) {
+ Shell shell = shells [i];
+ if (!shell.isDisposed ()) {
+ if (!sameFont) {
+ shell.updateFont (oldFont, newFont);
+ }
+ /* This code is intentionally commented */
+ //shell.redraw (true);
+ shell.layout (true, true);
+ }
+ }
+}
+
+void saveResources () {
+// int resourceCount = 0;
+// if (resources == null) {
+// resources = new Resource [RESOURCE_SIZE];
+// } else {
+// resourceCount = resources.length;
+// Resource [] newResources = new Resource [resourceCount + RESOURCE_SIZE];
+// System.arraycopy (resources, 0, newResources, 0, resourceCount);
+// resources = newResources;
+// }
+// if (systemFont != null) {
+// if (!OS.IsWinCE) {
+// NONCLIENTMETRICS info = OS.IsUnicode ? (NONCLIENTMETRICS) new NONCLIENTMETRICSW () : new NONCLIENTMETRICSA ();
+// info.cbSize = NONCLIENTMETRICS.sizeof;
+// if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+// LOGFONT logFont = OS.IsUnicode ? (LOGFONT) ((NONCLIENTMETRICSW)info).lfMessageFont : ((NONCLIENTMETRICSA)info).lfMessageFont;
+// if (lfSystemFont == null ||
+// logFont.lfCharSet != lfSystemFont.lfCharSet ||
+// logFont.lfHeight != lfSystemFont.lfHeight ||
+// logFont.lfWidth != lfSystemFont.lfWidth ||
+// logFont.lfEscapement != lfSystemFont.lfEscapement ||
+// logFont.lfOrientation != lfSystemFont.lfOrientation ||
+// logFont.lfWeight != lfSystemFont.lfWeight ||
+// logFont.lfItalic != lfSystemFont.lfItalic ||
+// logFont.lfUnderline != lfSystemFont.lfUnderline ||
+// logFont.lfStrikeOut != lfSystemFont.lfStrikeOut ||
+// logFont.lfCharSet != lfSystemFont.lfCharSet ||
+// logFont.lfOutPrecision != lfSystemFont.lfOutPrecision ||
+// logFont.lfClipPrecision != lfSystemFont.lfClipPrecision ||
+// logFont.lfQuality != lfSystemFont.lfQuality ||
+// logFont.lfPitchAndFamily != lfSystemFont.lfPitchAndFamily ||
+// !getFontName (logFont).equals (getFontName (lfSystemFont))) {
+// resources [resourceCount++] = systemFont;
+// lfSystemFont = logFont;
+// systemFont = null;
+// }
+// }
+// }
+// }
+// if (errorImage != null) resources [resourceCount++] = errorImage;
+// if (infoImage != null) resources [resourceCount++] = infoImage;
+// if (questionImage != null) resources [resourceCount++] = questionImage;
+// if (warningIcon != null) resources [resourceCount++] = warningIcon;
+// errorImage = infoImage = questionImage = warningIcon = null;
+// for (int i=0; i<cursors.length; i++) {
+// if (cursors [i] != null) resources [resourceCount++] = cursors [i];
+// cursors [i] = null;
+// }
+// if (resourceCount < RESOURCE_SIZE) {
+// Resource [] newResources = new Resource [resourceCount];
+// System.arraycopy (resources, 0, newResources, 0, resourceCount);
+// resources = newResources;
+// }
+}
+
+void sendEvent (int eventType, Event event) {
+ if (eventTable == null && filterTable == null) {
+ return;
+ }
+ if (event == null) event = new Event ();
+ event.display = this;
+ event.type = eventType;
+ if (event.time == 0) event.time = getLastEventTime ();
+ if (!filterEvent (event)) {
+ if (eventTable != null) eventTable.sendEvent (event);
+ }
+}
+
+/**
+ * Sets the location of the on-screen pointer relative to the top left corner
+ * of the screen. <b>Note: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.</b>
+ *
+ * @param x the new x coordinate for the cursor
+ * @param y the new y coordinate for the cursor
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setCursorLocation (int x, int y) {
+ checkDevice ();
+ Win32.SetCursorPos (x, y);
+}
+
+/**
+ * Sets the location of the on-screen pointer relative to the top left corner
+ * of the screen. <b>Note: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.</b>
+ *
+ * @param point new position
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.0
+ */
+public void setCursorLocation (Point point) {
+ checkDevice ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setCursorLocation (point.x, point.y);
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given argument.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getData(String)
+ * @see #disposeExec(Runnable)
+ */
+public void setData (String key, Object value) {
+ checkDevice ();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+
+// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+// Boolean data = (Boolean) value;
+// runMessagesInIdle = data != null && data.booleanValue ();
+// return;
+// }
+
+ /* Remove the key/value pair */
+ if (value == null) {
+ if (keys == null) return;
+ int index = 0;
+ while (index < keys.length && !keys [index].equals (key)) index++;
+ if (index == keys.length) return;
+ if (keys.length == 1) {
+ keys = null;
+ values = null;
+ } else {
+ String [] newKeys = new String [keys.length - 1];
+ Object [] newValues = new Object [values.length - 1];
+ System.arraycopy (keys, 0, newKeys, 0, index);
+ System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
+ System.arraycopy (values, 0, newValues, 0, index);
+ System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
+ keys = newKeys;
+ values = newValues;
+ }
+ return;
+ }
+
+ /* Add the key/value pair */
+ if (keys == null) {
+ keys = new String [] {key};
+ values = new Object [] {value};
+ return;
+ }
+ for (int i=0; i<keys.length; i++) {
+ if (keys [i].equals (key)) {
+ values [i] = value;
+ return;
+ }
+ }
+ String [] newKeys = new String [keys.length + 1];
+ Object [] newValues = new Object [values.length + 1];
+ System.arraycopy (keys, 0, newKeys, 0, keys.length);
+ System.arraycopy (values, 0, newValues, 0, values.length);
+ newKeys [keys.length] = key;
+ newValues [values.length] = value;
+ keys = newKeys;
+ values = newValues;
+}
+
+/**
+ * Sets the application defined, display specific data
+ * associated with the receiver, to the argument.
+ * The <em>display specific data</em> is a single,
+ * unnamed field that is stored with every display.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param data the new display specific data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getData()
+ * @see #disposeExec(Runnable)
+ */
+public void setData (Object data) {
+ checkDevice ();
+ this.data = data;
+}
+
+/**
+ * On platforms which support it, sets the application name
+ * to be the argument. On Motif, for example, this can be used
+ * to set the name used for resource lookup. Specifying
+ * <code>null</code> for the name clears it.
+ *
+ * @param name the new app name or <code>null</code>
+ */
+public static void setAppName (String name) {
+ /* Do nothing */
+}
+
+//void setModalDialogShell (Shell modalDailog) {
+// if (modalDialogShell != null && modalDialogShell.isDisposed ()) modalDialogShell = null;
+// this.modalDialogShell = modalDailog;
+// Shell [] shells = getShells ();
+// for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+//}
+
+void setIdleHandler () {
+ idle = true;
+}
+
+void setModalShell (Shell shell) {
+ if (modalShells == null) modalShells = new Shell [4];
+ int index = 0, length = modalShells.length;
+ while (index < length) {
+ if (modalShells [index] == shell) return;
+ if (modalShells [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Shell [] newModalShells = new Shell [length + 4];
+ System.arraycopy (modalShells, 0, newModalShells, 0, length);
+ modalShells = newModalShells;
+ }
+ modalShells [index] = shell;
+ Shell [] shells = getShells ();
+ for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+/**
+ * Sets the synchronizer used by the display to be
+ * the argument, which can not be null.
+ *
+ * @param synchronizer the new synchronizer for the display (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
+ * </ul>
+ */
+public void setSynchronizer (Synchronizer synchronizer) {
+ checkDevice ();
+ if (synchronizer == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (synchronizer == this.synchronizer) return;
+ Synchronizer oldSynchronizer;
+ synchronized (Device.class) {
+ oldSynchronizer = this.synchronizer;
+ this.synchronizer = synchronizer;
+ }
+ if (oldSynchronizer != null) {
+ oldSynchronizer.runAsyncMessages(true);
+ }
+}
+
+/**
+ * Causes the user-interface thread to <em>sleep</em> (that is,
+ * to be put in a state where it does not consume CPU cycles)
+ * until an event is received or it is otherwise awakened.
+ *
+ * @return <code>true</code> if an event requiring dispatching was placed on the queue.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #wake
+ */
+public boolean sleep () {
+ checkDevice ();
+ int handler = OS.gcnew_NoArgsDelegate (jniRef, "sleep_noop");
+ sleepOperation = OS.Dispatcher_BeginInvoke(dispatcher, OS.DispatcherPriority_Inactive, handler);
+ OS.DispatcherOperation_Wait(sleepOperation);
+ OS.GCHandle_Free(handler);
+ OS.GCHandle_Free(sleepOperation);
+ sleepOperation = 0;
+ return true;
+}
+
+void sleep_noop() {
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The thread which calls this method
+ * is suspended until the runnable completes. Specifying <code>null</code>
+ * as the runnable simply wakes the user-interface thread.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param runnable code to run on the user-interface thread or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #asyncExec
+ */
+public void syncExec (Runnable runnable) {
+ Synchronizer synchronizer;
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ synchronizer = this.synchronizer;
+ }
+ synchronizer.syncExec (runnable);
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread after the specified
+ * number of milliseconds have elapsed. If milliseconds is less
+ * than zero, the runnable is not executed.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param milliseconds the delay before running the runnable
+ * @param runnable code to run on the user-interface thread
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #asyncExec
+ */
+public void timerExec (int milliseconds, Runnable runnable) {
+ checkDevice ();
+ if (runnable == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (timerList == null) timerList = new Runnable [4];
+ if (timerHandles == null) timerHandles = new int [4];
+ int index = 0;
+ while (index < timerList.length) {
+ if (timerList [index] == runnable) break;
+ index++;
+ }
+ int timer = 0;
+ if (index != timerList.length) {
+ timer = timerHandles [index];
+ if (milliseconds < 0) {
+ OS.DispatcherTimer_Stop (timer);
+ timerList [index] = null;
+ OS.GCHandle_Free (timer);
+ timerHandles [index] = 0;
+ return;
+ }
+ } else {
+ if (milliseconds < 0) return;
+ index = 0;
+ while (index < timerList.length) {
+ if (timerList [index] == null) break;
+ index++;
+ }
+ if (index == timerList.length) {
+ Runnable [] newTimerList = new Runnable [timerList.length + 4];
+ System.arraycopy (timerList, 0, newTimerList, 0, timerList.length);
+ timerList = newTimerList;
+ int [] newTimerHandles = new int [timerHandles.length + 4];
+ System.arraycopy (timerHandles, 0, newTimerHandles, 0, timerHandles.length);
+ timerHandles = newTimerHandles;
+ }
+ }
+ if (timer == 0) timer = OS.gcnew_DispatcherTimer();
+ if (timer != 0) {
+ OS.DispatcherTimer_Tag (timer, index);
+ int timeSpan = OS.TimeSpan_FromMilliseconds (milliseconds);
+ OS.DispatcherTimer_Interval(timer, timeSpan);
+ OS.DispatcherTimer_Tick (timer, timerHandler);
+ OS.DispatcherTimer_Start (timer);
+ timerList [index] = runnable;
+ timerHandles [index] = timer;
+ OS.GCHandle_Free (timeSpan);
+ }
+}
+
+void timerProc (int index, int e) {
+ if (0 <= index && index < timerHandles.length) {
+ int timer = timerHandles [index];
+ if (timer != 0) {
+ OS.DispatcherTimer_Stop (timer);
+ OS.GCHandle_Free (timer);
+ timerHandles [index] = 0;
+ Runnable runnable = timerList [index];
+ timerList [index] = null;
+ runnable.run ();
+ }
+ }
+}
+
+static int translateKey (int key) {
+ for (int i=0; i<KeyTable.length; i++) {
+ if (KeyTable [i] [0] == key) return KeyTable [i] [1];
+ }
+ return 0;
+}
+
+static int untranslateKey (int key) {
+ for (int i=0; i<KeyTable.length; i++) {
+ if (KeyTable [i] [1] == key) return KeyTable [i] [0];
+ }
+ return 0;
+}
+
+/**
+ * Forces all outstanding paint requests for the display
+ * to be processed before this method returns.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Control#update()
+ */
+public void update() {
+ checkDevice ();
+ Shell[] shells = getShells ();
+ for (int i=0; i<shells.length; i++) {
+ Shell shell = shells [i];
+ if (!shell.isDisposed ()) shell.update (true);
+ }
+}
+
+/**
+ * If the receiver's user-interface thread was <code>sleep</code>ing,
+ * causes it to be awakened and start running again. Note that this
+ * method may be called from any thread.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #sleep
+ */
+public void wake () {
+ synchronized (Device.class) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ if (thread == Thread.currentThread ()) return;
+ wakeThread ();
+ }
+}
+
+void wakeThreadHandler () {
+}
+
+void wakeThread () {
+ int handler = OS.gcnew_NoArgsDelegate (jniRef, "wakeThreadHandler");
+ int operation = OS.Dispatcher_BeginInvoke (dispatcher, OS.DispatcherPriority_Normal, handler);
+ OS.GCHandle_Free (operation);
+ OS.GCHandle_Free (handler);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandBar.java
new file mode 100644
index 0000000000..b6cfac15bc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandBar.java
@@ -0,0 +1,459 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class support the layout of selectable
+ * expand bar items.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>ExpandItem</code>.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>V_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Expand, Collapse</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ExpandItem
+ * @see ExpandEvent
+ * @see ExpandListener
+ * @see ExpandAdapter
+ * @see <a href="http://www.eclipse.org/swt/snippets/#expandbar">ExpandBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ExpandBar extends Composite {
+ int parentingHandle;
+ Control [] children;
+ int itemCount, childCount;
+ int spacing;
+
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#V_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+Control [] _getChildren () {
+ // return children in reverse order.
+ Control[] result = new Control [childCount];
+ for (int i = 0; i < childCount; i++) {
+ result [childCount - i - 1] = children [i];
+ }
+ return result;
+}
+
+void addChild (Control control) {
+ super.addChild (control);
+ if (childCount == children.length) {
+ Control [] newChildren = new Control [childCount + 4];
+ System.arraycopy (children, 0, newChildren, 0, childCount);
+ children = newChildren;
+ }
+ children [childCount++] = control;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the <code>ExpandListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ExpandListener
+ * @see #removeExpandListener
+ */
+public void addExpandListener (ExpandListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Expand, typedListener);
+ addListener (SWT.Collapse, typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ style &= ~SWT.H_SCROLL;
+ return style;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ Point size = computeSize (handle, wHint, hHint, changed);
+ Rectangle trim = computeTrim (0, 0, size.x, size.y);
+ return new Point (trim.width, trim.height);
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ scrolledHandle = OS.gcnew_ScrollViewer ();
+ if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_StackPanel ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, scrolledHandle);
+ OS.GCHandle_Free (children);
+ OS.ContentControl_Content (scrolledHandle, handle);
+}
+
+void createItem (ExpandItem item, int style, int index) {
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int items = OS.Panel_Children (handle);
+ OS.UIElementCollection_Insert (items, index, item.topHandle ());
+ int count = OS.UIElementCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ itemCount++;
+}
+
+void createWidget () {
+ super.createWidget ();
+ children = new Control [4];
+}
+
+int defaultBackground () {
+ return OS.SystemColors_ControlColor;
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+void destroyItem (ExpandItem item) {
+ int items = OS.Panel_Children (handle);
+ OS.UIElementCollection_Remove (items, item.topHandle ());
+ int count = OS.UIElementCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemCount--;
+}
+
+void fixScrollbarVisibility () {
+ OS.ScrollViewer_SetHorizontalScrollBarVisibility (scrolledHandle, OS.ScrollBarVisibility_Hidden);
+ if ((style & SWT.V_SCROLL) == 0) {
+ OS.ScrollViewer_SetVerticalScrollBarVisibility (scrolledHandle, OS.ScrollBarVisibility_Hidden);
+ } else {
+ OS.ScrollViewer_SetVerticalScrollBarVisibility (scrolledHandle, OS.ScrollBarVisibility_Auto);
+ }
+}
+
+Point getLocation (Control child) {
+ int topHandle = child.topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (topHandle, point, handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ return new Point (x, y);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 ExpandItem getItem (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.Panel_Children (handle);
+ ExpandItem item = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return item;
+}
+
+ExpandItem getItem (int items, int index) {
+ int item = OS.UIElementCollection_default (items, index);
+ ExpandItem result = (ExpandItem) display.getWidget (item);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns an array of <code>ExpandItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 ExpandItem [] getItems () {
+ checkWidget ();
+ ExpandItem [] result = new ExpandItem [itemCount];
+ int items = OS.Panel_Children (handle);
+ for (int i=0; i<itemCount; i++) {
+ result [i] = getItem (items, i);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+int getScrollBarHandle (int style) {
+ if ((style & SWT.H_SCROLL) != 0) return 0;
+ updateLayout (handle);
+ int template = OS.Control_Template (scrolledHandle);
+ int part = createDotNetString ("PART_VerticalScrollBar", false);
+ int scrollbar = OS.FrameworkTemplate_FindName (template, part, scrolledHandle);
+ OS.GCHandle_Free (part);
+ OS.GCHandle_Free (template);
+ return scrollbar;
+}
+
+/**
+ * Returns the receiver's spacing.
+ *
+ * @return the spacing
+ *
+ * @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 int getSpacing () {
+ checkWidget ();
+ return spacing;
+}
+
+boolean hasItems () {
+ return true;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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 int indexOf (ExpandItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int items = OS.Panel_Children (handle);
+ int index = OS.UIElementCollection_IndexOf (items, item.topHandle ());
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+int parentingHandle() {
+ return parentingHandle;
+}
+
+void register () {
+ super.register ();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.Panel_Children (handle);
+ for (int i=0; i<itemCount; i++) {
+ ExpandItem item = getItem (items, i);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (parentingHandle != 0) OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void removeChild (Control control) {
+ super.removeChild (control);
+ int index = 0;
+ while (index < childCount) {
+ if (children [index] == control) break;
+ index++;
+ }
+ if (index == childCount) return;
+ System.arraycopy (children, index+1, children, index, --childCount - index);
+ children [childCount] = null;
+}
+
+void removeControl (Control control) {
+ super.removeControl (control);
+ int items = OS.Panel_Children (handle);
+ for (int i=0; i<itemCount; i++) {
+ ExpandItem item = getItem (items, i);
+ if (item.control == control) {
+ item.setControl (null);
+ break;
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ExpandListener
+ * @see #addExpandListener
+ */
+public void removeExpandListener (ExpandListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Expand, listener);
+ eventTable.unhook (SWT.Collapse, listener);
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0) {
+ OS.FrameworkElement_Height (scrolledHandle, height);
+ OS.FrameworkElement_Width (scrolledHandle, width);
+ }
+ return result;
+}
+
+/**
+ * Sets the receiver's spacing. Spacing specifies the number of pixels allocated around
+ * each item.
+ *
+ * @param spacing the spacing around each item
+ *
+ * @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 setSpacing (int spacing) {
+ checkWidget ();
+ if (spacing < 0) return;
+ if (spacing == this.spacing) return;
+ this.spacing = spacing;
+ int thickness = OS.gcnew_Thickness (spacing, spacing, spacing, spacing);
+ int items = OS.Panel_Children (handle);
+ for (int i = 0; i < itemCount; i++) {
+ ExpandItem item = getItem (items, i);
+ OS.FrameworkElement_Margin (item.handle, thickness);
+ }
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (thickness);
+}
+
+int topHandle () {
+ return parentingHandle;
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandItem.java
new file mode 100644
index 0000000000..b7b55c596c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ExpandItem.java
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a expandable item in a expand bar.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ExpandBar
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ExpandItem extends Item {
+ ExpandBar parent;
+ Control control;
+ int imageHandle, textHandle, contentHandle;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandItem (ExpandBar parent, int style) {
+ this (parent, style, checkNull (parent).getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent, a
+ * style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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 Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandItem (ExpandBar parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, style, index);
+}
+
+static ExpandBar checkNull (ExpandBar control) {
+ if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return control;
+}
+
+void createHandle () {
+ handle = OS.gcnew_Expander ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int spacing = parent.spacing;
+ int thickness = OS.gcnew_Thickness (spacing, spacing, spacing, spacing);
+ OS.FrameworkElement_Margin (handle, thickness);
+ OS.GCHandle_Free (thickness);
+ imageHandle = OS.gcnew_Image ();
+ if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+ textHandle = OS.gcnew_TextBlock ();
+ if (textHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ int panel = OS.gcnew_StackPanel ();
+ if (panel == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.StackPanel_Orientation (panel, OS.Orientation_Horizontal);
+ thickness = OS.gcnew_Thickness (1, 1, 1, 1);
+ if (thickness == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (panel, thickness);
+ OS.GCHandle_Free (thickness);
+ int children = OS.Panel_Children (panel);
+ OS.UIElementCollection_Add (children, imageHandle);
+ OS.UIElementCollection_Add (children, textHandle);
+ OS.GCHandle_Free (children);
+ OS.HeaderedContentControl_Header (handle, panel);
+ OS.GCHandle_Free (panel);
+ contentHandle = OS.gcnew_Canvas ();
+ if (contentHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ContentControl_Content (handle, contentHandle);
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns the control that is shown when the item is expanded.
+ * If no control has been set, return <code>null</code>.
+ *
+ * @return the control
+ *
+ * @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 Control getControl () {
+ checkWidget ();
+ return control;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is expanded,
+ * and false otherwise.
+ *
+ * @return the expanded 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>
+ */
+public boolean getExpanded () {
+ checkWidget ();
+ return OS.Expander_IsExpanded (handle);
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header
+ *
+ * @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 int getHeaderHeight () {
+ checkWidget ();
+ int panel = OS.HeaderedContentControl_Header (handle);
+ return (int) OS.FrameworkElement_ActualHeight (panel);
+}
+
+/**
+ * Gets the height of the receiver.
+ *
+ * @return the height
+ *
+ * @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 int getHeight () {
+ checkWidget ();
+ return (int) OS.FrameworkElement_Height (contentHandle);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>ExpandBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 ExpandBar getParent () {
+ checkWidget ();
+ return parent;
+}
+
+Control getWidgetControl () {
+ return parent;
+}
+
+void HandleExpanded (int sender, int e) {
+ if (!checkEvent (e)) return;
+ Event event = new Event ();
+ event.item = this;
+ parent.notifyListeners (SWT.Expand, event);
+}
+
+void HandleCollapsed (int sender, int e) {
+ if (!checkEvent (e)) return;
+ Event event = new Event ();
+ event.item = this;
+ parent.notifyListeners (SWT.Collapse, event);
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ resizeControl ();
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleExpanded");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Expander_Expanded (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleCollapsed");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Expander_Collapsed (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_SizeChanged (contentHandle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+ if (textHandle != 0) OS.GCHandle_Free (textHandle);
+ textHandle = 0;
+ if (imageHandle !=0 )OS.GCHandle_Free (imageHandle);
+ imageHandle = 0;
+ if (contentHandle != 0) OS.GCHandle_Free (contentHandle);
+ contentHandle = 0;
+}
+
+void resizeControl () {
+ if (control != null) {
+ int width = (int) OS.FrameworkElement_ActualWidth (contentHandle);
+ int height = (int) OS.FrameworkElement_Height (contentHandle);
+ control.setSize (width, height);
+ }
+}
+
+/**
+ * Sets the control that is shown when the item is expanded.
+ *
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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 setControl (Control control) {
+ checkWidget ();
+ if (control != null) {
+ if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ Control oldControl = this.control, newControl = control;
+ this.control = control;
+ int children = OS.Panel_Children (contentHandle);
+ int parentHandle = parent.parentingHandle ();
+ int parentChildren = OS.Panel_Children (parentHandle);
+ if (newControl != null) {
+ int topHandle = newControl.topHandle ();
+ OS.UIElementCollection_Remove (parentChildren, topHandle);
+ OS.UIElementCollection_Add (children, topHandle);
+ }
+ if (oldControl != null) {
+ int topHandle = oldControl.topHandle ();
+ OS.UIElementCollection_Remove (children, topHandle);
+ OS.UIElementCollection_Add (parentChildren, topHandle);
+ }
+ OS.GCHandle_Free (children);
+ OS.GCHandle_Free (parentChildren);
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ *
+ * @param expanded the new expanded 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>
+ */
+public void setExpanded (boolean expanded) {
+ checkWidget ();
+ OS.Expander_IsExpanded(handle, expanded);
+}
+
+/**
+ * Sets the height of the receiver. This is height of the item when it is expanded,
+ * excluding the height of the header.
+ *
+ * @param height the new height
+ *
+ * @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 setHeight (int height) {
+ checkWidget ();
+ if (height < 0) return;
+ OS.FrameworkElement_Height (contentHandle, height);
+}
+
+public void setImage (Image image) {
+ super.setImage (image);
+ if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ OS.Image_Source (imageHandle, image != null ? image.handle : 0);
+ OS.UIElement_Visibility (imageHandle, image != null ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ OS.UIElement_Visibility (textHandle, image != null && text.length () == 0 ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = image != null && text.length () != 0 ? 3 : 0;
+ int margin = OS.gcnew_Thickness (0, 0, spacing, 0);
+ if (margin == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ text = string;
+ int ptr = createDotNetString (text, false);
+ if (ptr == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.TextBlock_Text (textHandle, ptr);
+ OS.GCHandle_Free (ptr);
+ OS.UIElement_Visibility (textHandle, text.length() == 0 && image != null ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = image != null && text.length () != 0 ? 3 : 0;
+ int margin = OS.gcnew_Thickness (0, 0, spacing, 0);
+ if (margin == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FileDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FileDialog.java
new file mode 100644
index 0000000000..af8aa3c078
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FileDialog.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select or enter a file name.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SAVE, OPEN, MULTI</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles SAVE and OPEN may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#filedialog">FileDialog snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class FileDialog extends Dialog {
+ String [] filterNames = new String [0];
+ String [] filterExtensions = new String [0];
+ String [] fileNames = new String [0];
+ String filterPath = "", fileName = ""; //$NON-NLS-1$//$NON-NLS-2$
+ int filterIndex = -1;
+ boolean overwrite = false;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @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>
+ */
+public FileDialog (Shell parent) {
+ this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog 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#SAVE
+ * @see SWT#OPEN
+ * @see SWT#MULTI
+ */
+public FileDialog (Shell parent, int style) {
+ super (parent, checkStyle (parent, style));
+ checkSubclass ();
+}
+
+/**
+ * Returns the path of the first file that was
+ * selected in the dialog relative to the filter path, or an
+ * empty string if no such file has been selected.
+ *
+ * @return the relative path of the file
+ */
+public String getFileName () {
+ return fileName;
+}
+
+/**
+ * Returns a (possibly empty) array with the paths of all files
+ * that were selected in the dialog relative to the filter path.
+ *
+ * @return the relative paths of the files
+ */
+public String [] getFileNames () {
+ return fileNames;
+}
+
+/**
+ * Returns the file extensions which the dialog will
+ * use to filter the files it shows.
+ *
+ * @return the file extensions filter
+ */
+public String [] getFilterExtensions () {
+ return filterExtensions;
+}
+
+/**
+ * Get the 0-based index of the file extension filter
+ * which was selected by the user, or -1 if no filter
+ * was selected.
+ * <p>
+ * This is an index into the FilterExtensions array and
+ * the FilterNames array.
+ * </p>
+ *
+ * @return index the file extension filter index
+ *
+ * @see #getFilterExtensions
+ * @see #getFilterNames
+ *
+ * @since 3.4
+ */
+public int getFilterIndex () {
+ return filterIndex;
+}
+
+/**
+ * Returns the names that describe the filter extensions
+ * which the dialog will use to filter the files it shows.
+ *
+ * @return the list of filter names
+ */
+public String [] getFilterNames () {
+ return filterNames;
+}
+
+/**
+ * Returns the directory path that the dialog will use, or an empty
+ * string if this is not set. File names in this path will appear
+ * in the dialog, filtered according to the filter extensions.
+ *
+ * @return the directory path string
+ *
+ * @see #setFilterExtensions
+ */
+public String getFilterPath () {
+ return filterPath;
+}
+
+/**
+ * Returns the flag that the dialog will use to
+ * determine whether to prompt the user for file
+ * overwrite if the selected file already exists.
+ *
+ * @return true if the dialog will prompt for file overwrite, false otherwise
+ *
+ * @since 3.4
+ */
+public boolean getOverwrite () {
+ return overwrite;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the first selected file,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public String open () {
+ int dialog;
+ if ((style & SWT.SAVE) != 0) {
+ dialog = OS.gcnew_SaveFileDialog ();
+ } else {
+ dialog = OS.gcnew_OpenFileDialog ();
+ if ((style & SWT.MULTI) != 0) OS.OpenFileDialog_Multiselect (dialog, true);
+ }
+ int titlePtr = parent.createDotNetString (title, false);
+ OS.FileDialog_Title (dialog, titlePtr);
+ OS.GCHandle_Free (titlePtr);
+ int fileNamePtr = parent.createDotNetString (fileName, false);
+ OS.FileDialog_FileName (dialog, fileNamePtr);
+ OS.GCHandle_Free (fileNamePtr);
+
+ if (filterExtensions != null && filterExtensions.length > 0) {
+ StringBuffer strFilter = new StringBuffer();
+ for (int i=0; i<filterExtensions.length; i++) {
+ if (i > 0) strFilter.append("|");
+ if (filterNames != null && i < filterNames.length) {
+ strFilter.append(filterNames [i]);
+ } else {
+ strFilter.append(filterExtensions [i]);
+ }
+ strFilter.append("|");
+ strFilter.append(filterExtensions [i]);
+ }
+ int filterPtr = parent.createDotNetString(strFilter.toString (), false);
+ OS.FileDialog_Filter (dialog, filterPtr);
+ OS.GCHandle_Free (filterPtr);
+ if (filterIndex != -1) OS.FileDialog_FilterIndex (dialog, filterIndex + 1);
+ }
+
+ int filterPathPtr = parent.createDotNetString (filterPath, false);
+ OS.FileDialog_InitialDirectory (dialog, filterPathPtr);
+ OS.GCHandle_Free (filterPathPtr);
+
+ if ((style & SWT.SAVE) != 0) OS.SaveFileDialog_OverwritePrompt (dialog, overwrite);
+
+ int parentHandle = (parent.style & SWT.ON_TOP) == 0 ? parent.shellHandle : 0;
+ boolean success = OS.CommonDialog_ShowDialog (dialog, parentHandle);
+
+ /* Set the new path, file name and filter */
+ String fullPath = null;
+ if (success) {
+ int strings = OS.FileDialog_FileNames (dialog);
+ int length = OS.ICollection_Count (strings);
+ fileNames = new String [length];
+ for (int i = 0; i < length; i++) {
+ int str = OS.IList_default (strings, i);
+ int fileInfo = OS.gcnew_FileInfo (str);
+ int name = OS.FileInfo_Name (fileInfo);
+ fileNames [i] = Widget.createJavaString (name);
+ if (i == 0) {
+ int dir = OS.FileInfo_DirectoryName (fileInfo);
+ filterPath = Widget.createJavaString (dir);
+ OS.GCHandle_Free (dir);
+ }
+ OS.GCHandle_Free (name);
+ OS.GCHandle_Free (fileInfo);
+ OS.GCHandle_Free (str);
+ }
+ OS.GCHandle_Free (strings);
+ fullPath = filterPath + "\\" + fileNames [0];
+ fileName = fileNames [0];
+ } else {
+ fileNames = new String [0];
+ }
+ filterIndex = OS.FileDialog_FilterIndex (dialog) - 1;
+
+ OS.GCHandle_Free (dialog);
+ /* Answer the full path or null */
+ return fullPath;
+}
+
+/**
+ * Set the initial filename which the dialog will
+ * select by default when opened to the argument,
+ * which may be null. The name will be prefixed with
+ * the filter path when one is supplied.
+ *
+ * @param string the file name
+ */
+public void setFileName (String string) {
+ fileName = string;
+}
+
+/**
+ * Set the file extensions which the dialog will
+ * use to filter the files it shows to the argument,
+ * which may be null.
+ * <p>
+ * The strings are platform specific. For example, on
+ * some platforms, an extension filter string is typically
+ * of the form "*.extension", where "*.*" matches all files.
+ * For filters with multiple extensions, use semicolon as
+ * a separator, e.g. "*.jpg;*.png".
+ * </p>
+ *
+ * @param extensions the file extension filter
+ *
+ * @see #setFilterNames to specify the user-friendly
+ * names corresponding to the extensions
+ */
+public void setFilterExtensions (String [] extensions) {
+ filterExtensions = extensions;
+}
+
+/**
+ * Set the 0-based index of the file extension filter
+ * which the dialog will use initially to filter the files
+ * it shows to the argument.
+ * <p>
+ * This is an index into the FilterExtensions array and
+ * the FilterNames array.
+ * </p>
+ *
+ * @param index the file extension filter index
+ *
+ * @see #setFilterExtensions
+ * @see #setFilterNames
+ *
+ * @since 3.4
+ */
+public void setFilterIndex (int index) {
+ filterIndex = index;
+}
+
+/**
+ * Sets the names that describe the filter extensions
+ * which the dialog will use to filter the files it shows
+ * to the argument, which may be null.
+ * <p>
+ * Each name is a user-friendly short description shown for
+ * its corresponding filter. The <code>names</code> array must
+ * be the same length as the <code>extensions</code> array.
+ * </p>
+ *
+ * @param names the list of filter names, or null for no filter names
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterNames (String [] names) {
+ filterNames = names;
+}
+
+/**
+ * Sets the directory path that the dialog will use
+ * to the argument, which may be null. File names in this
+ * path will appear in the dialog, filtered according
+ * to the filter extensions. If the string is null,
+ * then the operating system's default filter path
+ * will be used.
+ * <p>
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ * </p>
+ *
+ * @param string the directory path
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterPath (String string) {
+ filterPath = string;
+}
+
+/**
+ * Sets the flag that the dialog will use to
+ * determine whether to prompt the user for file
+ * overwrite if the selected file already exists.
+ *
+ * @param overwrite true if the dialog will prompt for file overwrite, false otherwise
+ *
+ * @since 3.4
+ */
+public void setOverwrite (boolean overwrite) {
+ this.overwrite = overwrite;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FontDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FontDialog.java
new file mode 100644
index 0000000000..345524ec7c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/FontDialog.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.OS;
+
+/**
+ * Instances of this class allow the user to select a font
+ * from all available fonts in the system.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class FontDialog extends Dialog {
+ FontData fontData;
+ RGB rgb;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @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>
+ */
+public FontDialog (Shell parent) {
+ this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog 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>
+ */
+public FontDialog (Shell parent, int style) {
+ super (parent, checkStyle (parent, style));
+ checkSubclass ();
+}
+
+/**
+ * Returns a FontData object describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @deprecated use #getFontList ()
+ */
+public FontData getFontData () {
+ return fontData;
+}
+
+/**
+ * Returns a FontData set describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @since 2.1.1
+ */
+public FontData [] getFontList () {
+ if (fontData == null) return null;
+ FontData [] result = new FontData [1];
+ result [0] = fontData;
+ return result;
+}
+
+/**
+ * Returns an RGB describing the color that was selected
+ * in the dialog, or null if none is available.
+ *
+ * @return the RGB value for the selected color, or null
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public RGB getRGB () {
+ return rgb;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a FontData object describing the font that was selected,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public FontData open () {
+ int dialog = OS.gcnew_FontDialog ();
+ OS.FontDialog_ShowColor (dialog, true);
+ if (fontData != null) {
+ int fontFamily = parent.createDotNetString (fontData.fontFamily, false);
+ int fontStyle = 0;
+ int fontWeight = OS.FontWeight_ToOpenTypeWeight (OS.FontWeights_Bold);
+ if (fontWeight == fontData.weight) fontStyle |= OS.FontStyle_Bold;
+ if (fontData.style == OS.FontStyles_Italic) fontStyle |= OS.FontStyle_Italic;
+ if (fontData.style == OS.FontStyles_Normal) fontStyle |= OS.FontStyle_Regular;
+ //TODO strikethrough/underline
+ int font = OS.gcnew_Font (fontFamily, fontData.height, fontStyle);
+ OS.FontDialog_Font (dialog, font);
+ OS.GCHandle_Free (font);
+ OS.GCHandle_Free (fontFamily);
+ }
+ if (rgb != null) {
+ int color = OS.DrawingColor_FromArgb (174, rgb.red, rgb.blue, rgb.green);
+ OS.FontDialog_Color (dialog, color);
+ OS.GCHandle_Free (color);
+ }
+ int result = OS.FormsCommonDialog_ShowDialog (dialog);
+ boolean success = result == OS.DialogResult_OK;
+ if (success) {
+ int font = OS.FontDialog_Font (dialog);
+ int fontFamilyPtr = OS.Font_FontFamily (font);
+ int fontFamilyName = OS.DrawingFontFamily_Name (fontFamilyPtr);
+ String fontFamily = Widget.createJavaString (fontFamilyName);
+ int fontStyle = OS.Font_Style (font);
+ int fontDataStyle;
+ if ((fontStyle & OS.FontStyle_Italic) != 0) {
+ fontDataStyle = OS.FontStyles_Italic;
+ } else {
+ fontDataStyle = OS.FontStyles_Normal;
+ }
+ int weight;
+ if ((fontStyle & OS.FontStyle_Bold) != 0) {
+ weight = OS.FontWeight_ToOpenTypeWeight (OS.FontWeights_Bold);
+ } else {
+ weight = OS.FontWeight_ToOpenTypeWeight (OS.FontWeights_Normal);
+ }
+ int height = OS.Font_Size (font);
+ OS.GCHandle_Free(fontFamilyName);
+ OS.GCHandle_Free(fontFamilyPtr);
+ OS.GCHandle_Free(font);
+ fontData = FontData.wpf_new (fontFamily, fontDataStyle, weight, 1, height);
+
+ int color = OS.FontDialog_Color (dialog);
+ int argb = OS.DrawingColor_ToArgb (color);
+ int red = (argb & 0xFF0000) >> 16;
+ int green = (argb & 0xFF00) >> 8;
+ int blue = argb & 0xFF;
+ OS.GCHandle_Free (color);
+ rgb = new RGB (red, green, blue);
+ }
+ OS.GCHandle_Free (dialog);
+ return success ? fontData : null;
+}
+
+/**
+ * Sets a FontData object describing the font to be
+ * selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the FontData to use initially, or null
+ * @deprecated use #setFontList (FontData [])
+ */
+public void setFontData (FontData fontData) {
+ this.fontData = fontData;
+}
+
+/**
+ * Sets the set of FontData objects describing the font to
+ * be selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the set of FontData objects to use initially, or null
+ * to let the platform select a default when open() is called
+ *
+ * @see Font#getFontData
+ *
+ * @since 2.1.1
+ */
+public void setFontList (FontData [] fontData) {
+ if (fontData != null && fontData.length > 0) {
+ this.fontData = fontData [0];
+ } else {
+ this.fontData = null;
+ }
+}
+
+/**
+ * Sets the RGB describing the color to be selected by default
+ * in the dialog, or null to let the platform choose one.
+ *
+ * @param rgb the RGB value to use initially, or null to let
+ * the platform select a default when open() is called
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public void setRGB (RGB rgb) {
+ this.rgb = rgb;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Group.java
new file mode 100644
index 0000000000..5877f27207
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Group.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class provide an etched border
+ * with an optional title.
+ * <p>
+ * Shadow styles are hints and may not be honoured
+ * by the platform. To create a group with the
+ * default shadow style for the platform, do not
+ * specify a shadow style.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the above styles may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Group extends Composite {
+ int parentingHandle;
+ String text;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SHADOW_ETCHED_IN
+ * @see SWT#SHADOW_ETCHED_OUT
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Group (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+int clientHandle () {
+ return parentingHandle;
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ handle = OS.gcnew_GroupBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ContentControl_Content (handle, parentingHandle);
+}
+
+public Rectangle computeTrim (int x, int y, int width, int height) {
+ int topHandle = topHandle ();
+ int clientHandle = clientHandle();
+ if (clientHandle != topHandle) {
+ double currentWidth = OS.FrameworkElement_Width (topHandle);
+ double currentHeight = OS.FrameworkElement_Height (topHandle);
+ OS.FrameworkElement_Width (topHandle, 100);
+ OS.FrameworkElement_Height (topHandle, 100);
+ updateLayout (topHandle);
+ int w = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int h = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ int clientWidth = (int) OS.FrameworkElement_ActualWidth (clientHandle);
+ int clientHeight = (int) OS.FrameworkElement_ActualHeight (clientHandle);
+ int point = OS.gcnew_Point (0, 0);
+ int result = OS.UIElement_TranslatePoint (clientHandle, point, topHandle);
+ x -= (int) OS.Point_X (result);
+ y -= (int) OS.Point_Y (result);
+ width += (w - clientWidth);
+ height += (h - clientHeight);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (result);
+ OS.FrameworkElement_Width (topHandle, currentWidth);
+ OS.FrameworkElement_Height (topHandle, currentHeight);
+ }
+ return new Rectangle (x, y, width, height);
+}
+
+int defaultBackground () {
+ return OS.SystemColors_ControlColor;
+}
+
+void enableWidget (boolean enabled) {
+ OS.UIElement_IsHitTestVisible (handle, enabled);
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * is used as the <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 ();
+ return text;
+}
+
+boolean mnemonicHit (char key) {
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ int accessText = OS.HeaderedContentControl_Header (handle);
+ boolean result = super.mnemonicMatch (accessText, key);
+ OS.GCHandle_Free (accessText);
+ return result;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the receiver's text, which is the string that will
+ * be displayed as the receiver's <em>title</em>, to the argument,
+ * which may not be null. The string may include the mnemonic character.
+ * </p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the first child of the group. On most platforms, the
+ * mnemonic appears underlined but may be emphasised in a
+ * platform specific manner. The mnemonic indicator character
+ * '&amp;' can be escaped by doubling it in the string, causing
+ * a single '&amp;' to be displayed.
+ * </p>
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if (string.equals (text)) return;
+ text = string;
+ int ptr = createDotNetString (text, true);
+ int accessText = OS.gcnew_AccessText ();
+ if (ptr != 0) OS.AccessText_Text (accessText, ptr);
+ OS.HeaderedContentControl_Header (handle, accessText);
+ if (ptr != 0) OS.GCHandle_Free (ptr);
+ OS.GCHandle_Free (accessText);
+}
+
+int parentingHandle () {
+ return parentingHandle;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Label.java
new file mode 100644
index 0000000000..d3bc102840
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Label.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class represent a non-selectable
+ * user interface object that displays a string or image.
+ * When SEPARATOR is specified, displays a single
+ * vertical or horizontal line.
+ * <p>
+ * Shadow styles are hints and may not be honored
+ * by the platform. To create a separator label
+ * with the default shadow style for the platform,
+ * do not specify a shadow style.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SEPARATOR, HORIZONTAL, VERTICAL</dd>
+ * <dd>SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dd>CENTER, LEFT, RIGHT, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified.
+ * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified.
+ * Only one of CENTER, LEFT and RIGHT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#label">Label snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Label extends Control {
+ String text = "";
+ Image image;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SEPARATOR
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see SWT#CENTER
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Label (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ if ((style & SWT.SEPARATOR) != 0) {
+ style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0);
+ return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0);
+ }
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ if ((style & SWT.SEPARATOR) != 0) {
+ handle = OS.gcnew_UserControl ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int separator = OS.gcnew_Label ();
+ if (separator == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ContentControl_Content (handle, separator);
+ if ((style & SWT.VERTICAL) != 0) {
+ OS.FrameworkElement_Width (separator, OS.SystemParameters_ThinVerticalBorderWidth ());
+ OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Center);
+ OS.Control_VerticalContentAlignment (handle, OS.VerticalAlignment_Stretch);
+ } else {
+ OS.FrameworkElement_Height (separator, OS.SystemParameters_ThinHorizontalBorderHeight ());
+ OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Stretch);
+ OS.Control_VerticalContentAlignment (handle, OS.VerticalAlignment_Center);
+ }
+ int brush = OS.SystemColors_ActiveBorderBrush ();
+ OS.Control_Background (separator, brush);
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (separator);
+ } else {
+ handle = OS.gcnew_Label ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int value = OS.HorizontalAlignment_Left;
+ if ((style & SWT.CENTER) != 0) value = OS.HorizontalAlignment_Center;
+ if ((style & SWT.RIGHT) != 0) value = OS.HorizontalAlignment_Right;
+ OS.Control_HorizontalContentAlignment (handle, value);
+ int margin = OS.gcnew_Thickness (0, 0, 0, 0);
+ OS.Control_Padding (handle, margin);
+ OS.GCHandle_Free (margin);
+ }
+}
+
+int defaultBackground () {
+ //TEMPORARY CODE
+// return OS.SystemColors_ControlColor;
+ return 0;
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is a <code>SEPARATOR</code> label, in
+ * which case, <code>NONE</code> is returned.
+ *
+ * @return the alignment
+ *
+ * @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 int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return 0;
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's 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;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * a <code>SEPARATOR</code> label.
+ *
+ * @return the receiver's 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 ();
+ if ((style & SWT.SEPARATOR) != 0) return "";
+ return text;
+}
+
+boolean mnemonicHit (char key) {
+ //TODO
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ int accessText = OS.ContentControl_Content (handle);
+ boolean result = super.mnemonicMatch (accessText, key);
+ OS.GCHandle_Free (accessText);
+ return result;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ text = null;
+ image = null;
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
+ * or <code>CENTER</code>. If the receiver is a <code>SEPARATOR</code>
+ * label, the argument is ignored and the alignment is not changed.
+ *
+ * @param alignment the new alignment
+ *
+ * @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 setAlignment (int alignment) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ int value = OS.HorizontalAlignment_Left;
+ if ((style & SWT.CENTER) != 0) value = OS.HorizontalAlignment_Center;
+ if ((style & SWT.RIGHT) != 0) value = OS.HorizontalAlignment_Right;
+ OS.Control_HorizontalContentAlignment (handle, value);
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (Image image) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ int imageHandle = OS.gcnew_Image ();
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ OS.Image_Source (imageHandle, image != null ? image.handle : 0);
+ OS.ContentControl_Content (handle, imageHandle);
+ OS.GCHandle_Free (imageHandle);
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * This method sets the widget label. The label may include
+ * the mnemonic character and line delimiters.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the control that follows the label. On most platforms,
+ * the mnemonic appears underlined but may be emphasised in a
+ * platform specific manner. The mnemonic indicator character
+ * '&amp;' can be escaped by doubling it in the string, causing
+ * a single '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (string.equals (text)) return;
+ text = string;
+ int ptr = createDotNetString (text, true);
+ int accessText = OS.gcnew_AccessText ();
+ if (accessText == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.WRAP) != 0) {
+ OS.AccessText_TextWrapping (accessText, OS.TextWrapping_WrapWithOverflow);
+ }
+ OS.AccessText_Text (accessText, ptr);
+ OS.ContentControl_Content (handle, accessText);
+ OS.GCHandle_Free (ptr);
+ OS.GCHandle_Free (accessText);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Link.java
new file mode 100644
index 0000000000..4a6895c4c8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Link.java
@@ -0,0 +1,461 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a selectable
+ * user interface object that displays a text with
+ * links.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#link">Link snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Link extends Control {
+ Point [] offsets;
+ Point selection;
+ String [] ids;
+ String text;
+ private int[] mnemonics;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Link (Composite parent, int style) {
+ super (parent, style);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the user.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+int backgroundProperty () {
+ return OS.TextBlock_BackgroundProperty ();
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ handle = OS.gcnew_TextBlock ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+}
+
+int defaultBackground () {
+ return OS.SystemColors_ControlColor;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's 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 ();
+ return text;
+}
+
+void HandleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ int i = OS.FrameworkContentElement_Tag (source);
+ OS.GCHandle_Free (source);
+ Event event = new Event ();
+ event.text = ids [i];
+ sendEvent (SWT.Selection, event);
+}
+
+String parse (String string) {
+ int length = string.length ();
+ offsets = new Point [length / 4];
+ ids = new String [length / 4];
+ mnemonics = new int [length / 4 + 1];
+ StringBuffer result = new StringBuffer ();
+ char [] buffer = new char [length];
+ string.getChars (0, string.length (), buffer, 0);
+ int index = 0, state = 0, linkIndex = 0;
+ int start = 0, tagStart = 0, linkStart = 0, endtagStart = 0, refStart = 0;
+ while (index < length) {
+ char c = Character.toLowerCase (buffer [index]);
+ switch (state) {
+ case 0:
+ if (c == '<') {
+ tagStart = index;
+ state++;
+ }
+ break;
+ case 1:
+ if (c == 'a') state++;
+ break;
+ case 2:
+ switch (c) {
+ case 'h':
+ state = 7;
+ break;
+ case '>':
+ linkStart = index + 1;
+ state++;
+ break;
+ default:
+ if (Character.isWhitespace(c)) break;
+ else state = 13;
+ }
+ break;
+ case 3:
+ if (c == '<') {
+ endtagStart = index;
+ state++;
+ }
+ break;
+ case 4:
+ state = c == '/' ? state + 1 : 3;
+ break;
+ case 5:
+ state = c == 'a' ? state + 1 : 3;
+ break;
+ case 6:
+ if (c == '>') {
+ mnemonics [linkIndex] = parseMnemonics (buffer, start, tagStart, result);
+ int offset = result.length ();
+ parseMnemonics (buffer, linkStart, endtagStart, result);
+ offsets [linkIndex] = new Point (offset, result.length () - 1);
+ if (ids [linkIndex] == null) {
+ ids [linkIndex] = new String (buffer, linkStart, endtagStart - linkStart);
+ }
+ linkIndex++;
+ start = tagStart = linkStart = endtagStart = refStart = index + 1;
+ state = 0;
+ } else {
+ state = 3;
+ }
+ break;
+ case 7:
+ state = c == 'r' ? state + 1 : 0;
+ break;
+ case 8:
+ state = c == 'e' ? state + 1 : 0;
+ break;
+ case 9:
+ state = c == 'f' ? state + 1 : 0;
+ break;
+ case 10:
+ state = c == '=' ? state + 1 : 0;
+ break;
+ case 11:
+ if (c == '"') {
+ state++;
+ refStart = index + 1;
+ } else {
+ state = 0;
+ }
+ break;
+ case 12:
+ if (c == '"') {
+ ids[linkIndex] = new String (buffer, refStart, index - refStart);
+ state = 2;
+ }
+ break;
+ case 13:
+ if (Character.isWhitespace (c)) {
+ state = 0;
+ } else if (c == '='){
+ state++;
+ }
+ break;
+ case 14:
+ state = c == '"' ? state + 1 : 0;
+ break;
+ case 15:
+ if (c == '"') state = 2;
+ break;
+ default:
+ state = 0;
+ break;
+ }
+ index++;
+ }
+ if (start < length) {
+ int tmp = parseMnemonics (buffer, start, tagStart, result);
+ int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length, result);
+ if (mnemonic == -1) mnemonic = tmp;
+ mnemonics [linkIndex] = mnemonic;
+ } else {
+ mnemonics [linkIndex] = -1;
+ }
+ if (offsets.length != linkIndex) {
+ Point [] newOffsets = new Point [linkIndex];
+ System.arraycopy (offsets, 0, newOffsets, 0, linkIndex);
+ offsets = newOffsets;
+ String [] newIDs = new String [linkIndex];
+ System.arraycopy (ids, 0, newIDs, 0, linkIndex);
+ ids = newIDs;
+ int [] newMnemonics = new int [linkIndex + 1];
+ System.arraycopy (mnemonics, 0, newMnemonics, 0, linkIndex + 1);
+ mnemonics = newMnemonics;
+ }
+ return result.toString ();
+}
+
+int parseMnemonics (char [] buffer, int start, int end, StringBuffer result) {
+ int mnemonic = -1, index = start;
+ while (index < end) {
+ if (buffer [index] == '&') {
+ if (index + 1 < end && buffer [index + 1] == '&') {
+ result.append (buffer [index]);
+ index++;
+ } else {
+ mnemonic = result.length();
+ }
+ } else {
+ result.append (buffer [index]);
+ }
+ index++;
+ }
+ return mnemonic;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+void setFont (int font, double size) {
+ if (font != 0) {
+ int fontFamily = OS.Typeface_FontFamily( font);
+ int style = OS.Typeface_Style (font);
+ int weight = OS.Typeface_Weight (font);
+ int stretch = OS.Typeface_Stretch (font);
+ OS.TextBlock_FontFamily (handle, fontFamily);
+ OS.TextBlock_FontStyle (handle, style);
+ OS.TextBlock_FontWeight (handle, weight);
+ OS.TextBlock_FontStretch (handle, stretch);
+ OS.TextBlock_FontSize (handle, size);
+ OS.GCHandle_Free (fontFamily);
+ OS.GCHandle_Free (style);
+ OS.GCHandle_Free (weight);
+ OS.GCHandle_Free (stretch);
+ } else {
+ int property = OS.TextBlock_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+void setForegroundBrush (int brush) {
+//TODO
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * The string can contain both regular text and hyperlinks. A hyperlink
+ * is delimited by an anchor tag, &lt;A&gt; and &lt;/A&gt;. Within an
+ * anchor, a single HREF attribute is supported. When a hyperlink is
+ * selected, the text field of the selection event contains either the
+ * text of the hyperlink or the value of its HREF, if one was specified.
+ * In the rare case of identical hyperlinks within the same string, the
+ * HREF attribute can be used to distinguish between them. The string may
+ * include the mnemonic character and line delimiters. The only delimiter
+ * the HREF attribute supports is the quotation mark (").
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if (string.equals (text)) return;
+ text = string;
+ String parsed = parse (string);
+ int inlines = OS.TextBlock_Inlines (handle);
+ OS.InlineCollection_Clear (inlines);
+ int start = 0, end = parsed.length ();
+ int offsetIndex = 0;
+ while (start < end) {
+ Point point = offsetIndex < offsets.length ? offsets [offsetIndex] : null;
+ if (point == null) {
+ String substring = parsed.substring (start, end);
+ int stringPtr = createDotNetString (substring, false);
+ if (stringPtr == 0) error(SWT.ERROR_NO_HANDLES);
+ int run = OS.gcnew_Run ();
+ if (run == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.Run_Text (run, stringPtr);
+ OS.InlineCollection_Add (inlines, run);
+ OS.GCHandle_Free (stringPtr);
+ OS.GCHandle_Free (run);
+ start = end;
+ } else {
+ if (start < point.x) {
+ String substring = parsed.substring (start, point.x);
+ int stringPtr = createDotNetString (substring, false);
+ if (stringPtr == 0) error(SWT.ERROR_NO_HANDLES);
+ int run = OS.gcnew_Run ();
+ if (run == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.Run_Text (run, stringPtr);
+ OS.InlineCollection_Add (inlines, run);
+ OS.GCHandle_Free (stringPtr);
+ OS.GCHandle_Free (run);
+ start = point.x;
+ } else {
+ String substring = parsed.substring (point.x, point.y+1);
+ int stringPtr = createDotNetString (substring, false);
+ if (stringPtr == 0) error(SWT.ERROR_NO_HANDLES);
+ int run = OS.gcnew_Run ();
+ if (run == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.Run_Text (run, stringPtr);
+ int hyperlink = OS.gcnew_Hyperlink (run);
+ OS.FrameworkContentElement_Tag (hyperlink, offsetIndex);
+ OS.InlineCollection_Add (inlines, hyperlink);
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ OS.Hyperlink_Click (hyperlink, handler);
+ OS.GCHandle_Free (handler);
+ OS.GCHandle_Free (stringPtr);
+ OS.GCHandle_Free (run);
+ OS.GCHandle_Free (hyperlink);
+ start = point.y+1;
+ offsetIndex++;
+ }
+ }
+ }
+ OS.GCHandle_Free (inlines);
+}
+
+int traversalCode (int key, int event) {
+// if (offsets.length == 0) return 0;
+ int bits = super.traversalCode (key, event);
+// if (key == OS.Key_Tab && focusIndex < offsets.length - 1) {
+// return bits & ~SWT.TRAVERSE_TAB_NEXT;
+// }
+// if (key == OS.GDK_ISO_Left_Tab && focusIndex > 0) {
+// return bits & ~SWT.TRAVERSE_TAB_PREVIOUS;
+// }
+ //TODO
+ return bits;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/List.java
new file mode 100644
index 0000000000..6040ec4ab1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/List.java
@@ -0,0 +1,1186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a selectable user interface
+ * object that displays a list of strings and issues notification
+ * when a string is selected. A list may be single or multi select.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SINGLE, MULTI</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of SINGLE and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#list">List snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class List extends Scrollable {
+ boolean ignoreSelection;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SINGLE
+ * @see SWT#MULTI
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public List (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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>
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int item = OS.gcnew_ListBoxItem ();
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content (item, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Add (items, item);
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (item);
+}
+
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ * <p>
+ * Note: To add an item at the end of the list, use the
+ * result of calling <code>getItemCount()</code> as the
+ * index or use <code>add(String)</code>.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</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>
+ *
+ * @see #add(String)
+ */
+public void add (String string, int index) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (index < 0 || index > getItemCount ()) error (SWT.ERROR_INVALID_RANGE);
+ int item = OS.gcnew_ListBoxItem ();
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content (item, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (items, index, item);
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (item);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the selection changes.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+void createHandle () {
+ handle = OS.gcnew_ListBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Selector_IsSynchronizedWithCurrentItem (handle, true);
+ if ((style & SWT.MULTI) != 0) OS.ListBox_SelectionMode (handle, OS.SelectionMode_Extended);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int count = getItemCount ();
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i = 0; i < indices.length; i++) {
+ int index = indices [i];
+ if (0 <= index && index < count) {
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ OS.ListBoxItem_IsSelected (item, false);
+ OS.GCHandle_Free (item);
+ }
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @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 deselect (int index) {
+ checkWidget ();
+ if (index == -1) return;
+ if (0 <= index && index < getItemCount ()) {
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ OS.GCHandle_Free (items);
+ ignoreSelection = true;
+ OS.ListBoxItem_IsSelected (item, false);
+ ignoreSelection = false;
+ OS.GCHandle_Free (item);
+ }
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @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 deselect (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ int count = getItemCount ();
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i = end; i >= start; i--) {
+ if (0 <= i && i < count) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ OS.ListBoxItem_IsSelected (item, false);
+ OS.GCHandle_Free (item);
+ }
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @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 deselectAll () {
+ checkWidget ();
+ ignoreSelection = true;
+ OS.ListBox_UnselectAll (handle);
+ ignoreSelection = false;
+}
+
+/**
+ * Returns the zero-relative index of the item which currently
+ * has the focus in the receiver, or -1 if no item has focus.
+ *
+ * @return the index of the selected item
+ *
+ * @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 int getFocusIndex () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int index = OS.ItemCollection_CurrentPosition (items);
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 String getItem (int index) {
+ checkWidget ();
+ int count = getItemCount ();
+ if (index < 0 || index >= count) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ int content = OS.ContentControl_Content (item);
+ String string = createJavaString (content);
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (content);
+ return string;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ return count;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the list.
+ *
+ * @return the height of one item
+ *
+ * @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 int getItemHeight () {
+ checkWidget ();
+ //FIXME what is the default size?
+ if (!OS.ItemsControl_HasItems (handle)) return 16;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, 0);
+ double height = OS.FrameworkElement_ActualHeight (item);
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+ return height != 0 ? (int) height : 16;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>String</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @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 [] getItems () {
+ checkWidget ();
+ int count = getItemCount ();
+ String [] result = new String [count];
+ for (int i=0; i<count; i++) result [i] = getItem (i);
+ return result;
+}
+
+/**
+ * Returns an array of <code>String</code>s that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @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 [] getSelection () {
+ checkWidget ();
+ int [] indices = getSelectionIndices ();
+ String [] result = new String [indices.length];
+ for (int i=0; i<indices.length; i++) {
+ result [i] = getItem (indices [i]);
+ }
+ return result;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @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 int getSelectionCount () {
+ checkWidget ();
+ int selectedItems = OS.ListBox_SelectedItems (handle);
+ int result = OS.ICollection_Count (selectedItems);
+ OS.GCHandle_Free (selectedItems);
+ return result;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item or -1
+ *
+ * @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 int getSelectionIndex () {
+ checkWidget ();
+ return OS.Selector_SelectedIndex (handle);
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return the array of indices of the selected items
+ *
+ * @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 int [] getSelectionIndices () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int list = OS.ListBox_SelectedItems (handle);
+ int enumerator = OS.IList_GetEnumerator (list);
+ int count = OS.ICollection_Count (list);
+ int [] indices = new int [count];
+ int index = 0;
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int item = OS.IEnumerator_Current (enumerator);
+ indices [index++] = OS.ItemCollection_IndexOf (items, item);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (list);
+ OS.GCHandle_Free (items);
+ sortAscending (indices);
+ return indices;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @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 int getTopIndex () {
+ checkWidget ();
+ int topIndex = 0;
+ if (OS.ItemsControl_HasItems (handle)) {
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, 0);
+ OS.GCHandle_Free (items);
+ int virtualizingStackPanel = OS.VisualTreeHelper_GetParent (item);
+ OS.GCHandle_Free (item);
+ if (virtualizingStackPanel != 0) {
+ topIndex = (int) OS.VirtualizingStackPanel_VerticalOffset (virtualizingStackPanel);
+ OS.GCHandle_Free (virtualizingStackPanel);
+ }
+ }
+ return topIndex;
+}
+
+void HandleMouseDoubleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ postEvent (SWT.DefaultSelection);
+}
+
+void HandleSelectionChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (!ignoreSelection) postEvent(SWT.Selection);
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_Return) {
+ postEvent (SWT.DefaultSelection);
+ }
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SelectionChangedEventHandler (jniRef, "HandleSelectionChanged");
+ OS.Selector_SelectionChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandleMouseDoubleClick");
+ OS.Control_MouseDoubleClick (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Gets the index of an item.
+ * <p>
+ * The list is searched starting at 0 until an
+ * item is found that is equal to the search item.
+ * If no item is found, -1 is returned. Indexing
+ * is zero based.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 int indexOf (String string) {
+ return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to start the search
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 int indexOf (String string, int start) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount ();
+ if (start >= count) return -1;
+ start = Math.max (start, 0);
+ int strPtr = createDotNetString (string, false);
+ int items = OS.ItemsControl_Items (handle);
+ int index = -1;
+ while (start < count && index == -1) {
+ int item = OS.ItemCollection_GetItemAt (items, start);
+ int content = OS.ContentControl_Content (item);
+ OS.GCHandle_Free (item);
+ if (content != 0) {
+ if (OS.Object_Equals (content, strPtr)) index = start;
+ OS.GCHandle_Free (content);
+ }
+ start++;
+ }
+ OS.GCHandle_Free (strPtr);
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+/**
+ * Returns <code>true</code> if the item is selected,
+ * and <code>false</code> otherwise. Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the selection state of the item at the index
+ *
+ * @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 boolean isSelected (int index) {
+ checkWidget ();
+ boolean selected = false;
+ if (index >= 0 && index < getItemCount ()) {
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ selected = OS.ListBoxItem_IsSelected (item);
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (item);
+ }
+ return selected;
+}
+
+/**
+ * Removes the items from the receiver at the given
+ * zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the indices array 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 remove (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int [] newIndices = new int [indices.length];
+ System.arraycopy (indices, 0, newIndices, 0, indices.length);
+ sort (newIndices);
+ int start = newIndices [newIndices.length - 1], end = newIndices [0];
+ int count = getItemCount ();
+ if (!(0 <= start && start <= end && end < count)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = newIndices.length-1; i >= 0; i--) {
+ OS.ItemCollection_RemoveAt (items, indices [i]);
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the item from the receiver at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int index) {
+ checkWidget ();
+ if (index < 0 || index >= getItemCount ()) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_RemoveAt (items, index);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ int count = getItemCount ();
+ if (!(0 <= start && start <= end && end < count)) error (SWT.ERROR_INVALID_RANGE);
+ if (start == 0 && end == count - 1) {
+ removeAll ();
+ return;
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = end; i >= start; i--) {
+ OS.ItemCollection_RemoveAt (items, i);
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</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 remove (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = indexOf (string, 0);
+ if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver.
+ * <p>
+ * @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 removeAll () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ OS.ItemCollection_Clear (items);
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices 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>
+ *
+ * @see List#setSelection(int[])
+ */
+public void select (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ select (indices, false);
+}
+
+void select (int [] indices, boolean scroll) {
+ int i = 0;
+ while (i < indices.length) {
+ int index = indices [i];
+ if (index != -1) {
+ select (index, false);
+ }
+ i++;
+ }
+ if (scroll) showSelection ();
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 select (int index) {
+ checkWidget ();
+ select (index, false);
+}
+
+void select (int index, boolean scroll) {
+ if (index < 0) return;
+ int count = getItemCount ();
+ if (index >= count) return;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ OS.GCHandle_Free (items);
+ ignoreSelection = true;
+ OS.ListBoxItem_IsSelected (item, true);
+ ignoreSelection = false;
+ if (scroll) OS.FrameworkElement_BringIntoView (item);
+ OS.GCHandle_Free (item);
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @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 List#setSelection(int,int)
+ */
+public void select (int start, int end) {
+ checkWidget ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ int count = getItemCount ();
+ if (count == 0 || start >= count) return;
+ start = Math.max (0, start);
+ end = Math.min (end, count - 1);
+ ignoreSelection = true;
+ if ((style & SWT.SINGLE) != 0) {
+ select (start, false);
+ } else {
+ select (start, end, false);
+ }
+ ignoreSelection = false;
+}
+
+void select (int start, int end, boolean scroll) {
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i = start; i<=end; i++) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ OS.ListBoxItem_IsSelected (item, true);
+ OS.GCHandle_Free (item);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+ if (scroll) showSelection ();
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ *
+ * @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 selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ ignoreSelection = true;
+ OS.ListBox_SelectAll (handle);
+ ignoreSelection = false;
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 setItem (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int topIndex = getTopIndex ();
+ boolean isSelected = isSelected (index);
+ remove (index);
+ add (string, index);
+ if (isSelected) select (index, false);
+ setTopIndex (topIndex);
+}
+
+/**
+ * Sets the receiver's items to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if an item in the items array 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 setItems (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<items.length; i++) {
+ if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int itemCollection = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ OS.ItemCollection_Clear (itemCollection);
+ for (int i = 0; i < items.length; i++) {
+ String string = items [i];
+ int item = OS.gcnew_ListBoxItem ();
+ int strPtr = createDotNetString (string, false);
+ OS.ContentControl_Content (item, strPtr);
+ OS.GCHandle_Free (strPtr);
+ OS.ItemCollection_Add (itemCollection, item);
+ OS.GCHandle_Free (item);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (itemCollection);
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices 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>
+ *
+ * @see List#deselectAll()
+ * @see List#select(int[])
+ */
+public void setSelection (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ select (indices, true);
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of items 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>
+ *
+ * @see List#deselectAll()
+ * @see List#select(int[])
+ * @see List#setSelection(int[])
+ */
+public void setSelection (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = items.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ for (int i=length-1; i>=0; --i) {
+ String string = items [i];
+ int index = 0;
+ if (string != null) {
+ while ((index = indexOf (string, index)) != -1) {
+ select (index, false);
+ if ((style & SWT.SINGLE) != 0 && isSelected (index)) {
+ showSelection ();
+ return;
+ }
+ index++;
+ }
+ }
+ }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new item is selected.
+ * Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 List#deselectAll()
+ * @see List#select(int)
+ */
+public void setSelection (int index) {
+ checkWidget ();
+ deselectAll ();
+ select (index, true);
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @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 List#deselectAll()
+ * @see List#select(int,int)
+ */
+public void setSelection (int start, int end) {
+ checkWidget ();
+ deselectAll ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ int count = getItemCount ();
+ if (count == 0 || start >= count) return;
+ start = Math.max (0, start);
+ end = Math.min (end, count - 1);
+ if ((style & SWT.SINGLE) != 0) {
+ select (start, true);
+ } else {
+ select (start, end, true);
+ }
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @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 setTopIndex (int index) {
+ checkWidget ();
+ //FIXME: VirtualizingStackPanel.VerticalIndex cannot be set.
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @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 showSelection () {
+ //TODO: does this scroll the first selected item into view if
+ // part of the selection is visible already???
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int selectedItems = OS.ListBox_SelectedItems (handle);
+ int enumerator = OS.IList_GetEnumerator (selectedItems);
+ if (OS.IEnumerator_MoveNext (enumerator)) {
+ int item = OS.IEnumerator_Current (enumerator);
+ OS.ListBox_ScrollIntoView (handle, item);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (selectedItems);
+ OS.GCHandle_Free (items);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Menu.java
new file mode 100644
index 0000000000..b6462e7c77
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Menu.java
@@ -0,0 +1,916 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are user interface objects that contain
+ * menu items.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP</dd>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Help, Hide, Show </dd>
+ * </dl>
+ * <p>
+ * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#menu">Menu snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Menu extends Widget {
+ int itemCount;
+ MenuItem cascade, selected;
+ Decorations parent;
+
+/**
+ * Constructs a new instance of this class given its parent,
+ * and sets the style for the instance so that the instance
+ * will be a popup menu on the given parent's shell.
+ * <p>
+ * After constructing a menu, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code>. In this case, the parent may
+ * be any control in the same widget tree as the parent.
+ * </p>
+ *
+ * @param parent a control which will be the parent of the new instance (cannot be null)
+ *
+ * @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#POP_UP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Control parent) {
+ this (checkNull (parent).menuShell (), SWT.POP_UP);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Decorations</code>) 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p><p>
+ * After constructing a menu or menuBar, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code> or <code>parent.setMenuBar(menuBar)</code>.
+ * </p>
+ *
+ * @param parent a decorations control which will be the parent of the new instance (cannot be null)
+ * @param style the style of menu 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#BAR
+ * @see SWT#DROP_DOWN
+ * @see SWT#POP_UP
+ * @see SWT#NO_RADIO_GROUP
+ * @see SWT#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Decorations parent, int style) {
+ this (parent, checkStyle (style), 0);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Menu</code>) and sets the style
+ * for the instance so that the instance will be a drop-down
+ * menu on the given parent's parent.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentMenu
+ * using <code>parentMenu.setMenu(menu)</code>.
+ * </p>
+ *
+ * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
+ *
+ * @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#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Menu parentMenu) {
+ this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>MenuItem</code>) and sets the style
+ * for the instance so that the instance will be a drop-down
+ * menu on the given parent's parent menu.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentItem
+ * using <code>parentItem.setMenu(menu)</code>.
+ * </p>
+ *
+ * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
+ *
+ * @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#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (MenuItem parentItem) {
+ this (checkNull (parentItem).parent);
+}
+
+Menu (Decorations parent, int style, int handle) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ this.handle = handle;
+ createWidget ();
+}
+
+void _setVisible (boolean visible) {
+ if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+ OS.ContextMenu_IsOpen (handle, visible);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when help events are generated for the control,
+ * by sending it one of the messages defined in the
+ * <code>HelpListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when menus are hidden or shown, by sending it
+ * one of the messages defined in the <code>MenuListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MenuListener
+ * @see #removeMenuListener
+ */
+public void addMenuListener (MenuListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Hide,typedListener);
+ addListener (SWT.Show,typedListener);
+}
+
+static Control checkNull (Control control) {
+ if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return control;
+}
+
+static Menu checkNull (Menu menu) {
+ if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return menu;
+}
+
+static MenuItem checkNull (MenuItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return item;
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
+}
+
+void createHandle () {
+ int bits = SWT.BAR | SWT.DROP_DOWN | SWT.POP_UP;
+ switch (style & bits) {
+ case SWT.BAR:
+ handle = OS.gcnew_Menu ();
+ if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.POP_UP:
+ handle = OS.gcnew_ContextMenu ();
+ if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ OS.ContextMenu_Placement (handle, OS.PlacementMode_MousePoint);
+ break;
+ case SWT.DROP_DOWN:
+ handle = OS.gcnew_CompositeCollection ();
+ if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ int defaultItem = OS.gcnew_MenuItem ();
+ OS.CompositeCollection_Insert (handle, 0, defaultItem);
+ OS.GCHandle_Free (defaultItem);
+ break;
+ }
+}
+
+void createItem (MenuItem item, int index) {
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ if ((style & SWT.DROP_DOWN) != 0) {
+ if (itemCount == 0) OS.CompositeCollection_RemoveAt (handle, 0);
+ OS.CompositeCollection_Insert (handle, index, item.handle);
+ } else {
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (items, index, item.handle);
+ OS.GCHandle_Free (items);
+ }
+ itemCount++;
+}
+
+void createWidget () {
+ checkOrientation (parent);
+ super.createWidget ();
+ parent.addMenu (this);
+}
+
+void deregister () {
+ if ((style & SWT.DROP_DOWN) != 0) return;
+ display.removeWidget (handle);
+}
+
+void destroyItem (MenuItem item) {
+ if ((style & SWT.DROP_DOWN) != 0) {
+ OS.CompositeCollection_Remove (handle, item.handle);
+ if (itemCount == 1) {
+ int defaultItem = OS.gcnew_MenuItem ();
+ OS.CompositeCollection_Insert (handle, 0, defaultItem);
+ OS.GCHandle_Free (defaultItem);
+ }
+ } else {
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Remove (items, item.handle);
+ OS.GCHandle_Free (items);
+ }
+ itemCount--;
+}
+
+void fixMenus (Decorations newParent) {
+ MenuItem [] items = getItems ();
+ for (int i=0; i<items.length; i++) {
+ items [i].fixMenus (newParent);
+ }
+ parent.removeMenu (this);
+ newParent.addMenu (this);
+ this.parent = newParent;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null),
+ * unless the receiver is a menu or a shell. In this case, the
+ * location is relative to the display.
+ * <p>
+ * Note that the bounds of a menu or menu item are undefined when
+ * the menu is not visible. This is because most platforms compute
+ * the bounds of a menu dynamically just before it is displayed.
+ * </p>
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+/*public*/ Rectangle getBounds () {
+ checkWidget ();
+ if ((style & SWT.DROP_DOWN) != 0) return new Rectangle (0, 0, 0, 0);
+ if (!OS.UIElement_IsVisible (handle)) return new Rectangle (0, 0, 0, 0);
+ int point = OS.gcnew_Point (0, 0);
+ int location = OS.UIElement_TranslatePoint (handle, point, parent.handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (handle);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the default menu item or null if none has
+ * been previously set.
+ *
+ * @return the default menu item.
+ *
+ * </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 MenuItem getDefaultItem () {
+ checkWidget ();
+ return null;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return (state & DISABLED) == 0;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 MenuItem getItem (int index) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) error(SWT.ERROR_INVALID_RANGE);
+ if ((style & SWT.DROP_DOWN) != 0) return getItem (handle, index);
+ int items = OS.ItemsControl_Items (handle);
+ MenuItem result = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+MenuItem getItem (int items, int index) {
+ int item;
+ if ((style & SWT.DROP_DOWN) != 0) {
+ item = OS.IList_default (handle, index);
+ } else {
+ item = OS.ItemCollection_GetItemAt (items, index);
+ }
+ MenuItem result = (MenuItem) display.getWidget (item);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>MenuItem</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 MenuItem [] getItems () {
+ checkWidget ();
+ MenuItem [] result = new MenuItem [itemCount];
+ int items = (style & SWT.DROP_DOWN) == 0 ? OS.ItemsControl_Items (handle) : handle;
+ for (int i = 0; i < itemCount; i++) {
+ result [i] = getItem (items, i);
+ }
+ if (items != handle) OS.GCHandle_Free (items);
+ return result;
+}
+
+String getNameText () {
+ String result = "";
+ MenuItem [] items = getItems ();
+ int length = items.length;
+ if (length > 0) {
+ for (int i=0; i<length-1; i++) {
+ result = result + items [i].getNameText() + ", ";
+ }
+ result = result + items [length-1].getNameText ();
+ }
+ return result;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Decorations</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Decorations getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>MenuItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @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 MenuItem getParentItem () {
+ checkWidget ();
+ return cascade;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>Menu</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @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 getParentMenu () {
+ checkWidget ();
+ if (cascade != null) return cascade.parent;
+ return null;
+}
+
+/**
+ * Returns the receiver's shell. For all controls other than
+ * shells, this simply returns the control's nearest ancestor
+ * shell. Shells return themselves, even if they are children
+ * of other shells.
+ *
+ * @return the receiver's shell
+ *
+ * @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 #getParent
+ */
+public Shell getShell () {
+ checkWidget ();
+ return parent.getShell ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible, and
+ * <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's visibility 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>
+ */
+public boolean getVisible () {
+ checkWidget ();
+ if ((style & SWT.BAR) != 0) {
+ return this == parent.menuShell ().menuBar;
+ }
+ if ((style & SWT.POP_UP) != 0) {
+ Menu [] popups = display.popups;
+ if (popups == null) return false;
+ for (int i=0; i<popups.length; i++) {
+ if (popups [i] == this) return true;
+ }
+ }
+// Shell shell = getShell ();
+// Menu menu = shell.activeMenu;
+// while (menu != null && menu != this) {
+// menu = menu.getParentMenu ();
+// }
+// return this == menu;
+ return OS.UIElement_Visibility (handle) == OS.Visibility_Visible;
+}
+
+void HandleClosed (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Hide);
+}
+
+void HandleOpened (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Show);
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ if ((style & SWT.POP_UP) != 0) {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClosed");
+ OS.ContextMenu_Closed (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleOpened");
+ OS.ContextMenu_Opened (handle, handler);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item 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 int indexOf (MenuItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ int index = -1;
+ if ((style & SWT.DROP_DOWN) != 0) {
+ index = OS.CompositeCollection_IndexOf (handle, item.handle);
+ } else {
+ int items = OS.ItemsControl_Items (handle);
+ index = OS.ItemCollection_IndexOf (items, item.handle);
+ OS.GCHandle_Free (items);
+ }
+ return index;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled menu is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget ();
+ Menu parentMenu = getParentMenu ();
+ if (parentMenu == null) return getEnabled ();
+ return getEnabled () && parentMenu.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility 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 #getVisible
+ */
+public boolean isVisible () {
+ checkWidget ();
+ return getVisible ();
+}
+
+void register() {
+ if ((style & SWT.DROP_DOWN) != 0) return;
+ display.addWidget (handle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ MenuItem [] items = getItems ();
+ for (int i=0; i<items.length; i++) {
+ MenuItem item = items [i];
+ if (item != null && !item.isDisposed ()) {
+ item.release (false);
+ }
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (cascade != null) cascade.releaseMenu ();
+ if ((style & SWT.BAR) != 0) {
+ if (this == parent.menuBar) {
+ parent.setMenuBar (null);
+ }
+ } else {
+ if ((style & SWT.POP_UP) != 0) {
+ display.removePopup (this);
+ }
+ }
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ if (parent != null) parent.removeMenu (this);
+ parent = null;
+ cascade = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the menu events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MenuListener
+ * @see #addMenuListener
+ */
+public void removeMenuListener (MenuListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Hide, listener);
+ eventTable.unhook (SWT.Show, listener);
+}
+
+/**
+ * Sets the default menu item to the argument or removes
+ * the default emphasis when the argument is <code>null</code>.
+ *
+ * @param item the default menu item or null
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu item has been disposed</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 setDefaultItem (MenuItem item) {
+ checkWidget ();
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled 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>
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ state &= ~DISABLED;
+ if (!enabled) state |= DISABLED;
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the arguments which are relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p><p>
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ * </p>
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @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 setLocation (int x, int y) {
+ checkWidget ();
+ if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+ OS.ContextMenu_Placement (handle, OS.PlacementMode_AbsolutePoint);
+ OS.ContextMenu_HorizontalOffset (handle, x);
+ OS.ContextMenu_VerticalOffset (handle, y);
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the argument which is relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p><p>
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ * </p>
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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>
+ *
+ * @since 2.1
+ */
+public void setLocation (Point location) {
+ checkWidget ();
+ if (location == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+void setNameScope() {
+ // DO NOTHING
+}
+
+/**
+ * Marks the receiver as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility 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>
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+ if (visible) {
+ display.addPopup (this);
+ } else {
+ display.removePopup (this);
+ _setVisible (false);
+ }
+}
+
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MenuItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MenuItem.java
new file mode 100644
index 0000000000..cc5a802a22
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MenuItem.java
@@ -0,0 +1,739 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that issues notification when pressed and released.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>CHECK, CASCADE, PUSH, RADIO, SEPARATOR</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Arm, Help, Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
+ * may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class MenuItem extends Item {
+ Menu parent, menu;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Menu</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a menu 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#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public MenuItem (Menu parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Menu</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a menu control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public MenuItem (Menu parent, int style, int index) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the arm events are generated for the control, by sending
+ * it one of the messages defined in the <code>ArmListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ArmListener
+ * @see #removeArmListener
+ */
+public void addArmListener (ArmListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Arm, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the help events are generated for the control, by sending
+ * it one of the messages defined in the <code>HelpListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the menu item is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the stateMask field of the event object is valid.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the menu item is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.CASCADE, 0);
+}
+
+void createHandle () {
+ if ((style & SWT.SEPARATOR) != 0) {
+ handle = OS.gcnew_Separator ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ } else {
+ handle = OS.gcnew_MenuItem ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & (SWT.CHECK | SWT.RADIO)) != 0) OS.MenuItem_IsCheckable (handle, true);
+ }
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+void fixMenus (Decorations newParent) {
+ if (menu != null) menu.fixMenus (newParent);
+}
+
+/**
+ * Returns the widget accelerator. An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @return the accelerator or 0
+ *
+ * </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 int getAccelerator () {
+ checkWidget ();
+ //FIXME
+ return 0;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+/*public*/ Rectangle getBounds () {
+ checkWidget ();
+ if (!OS.UIElement_IsVisible(handle)) return new Rectangle (0, 0, 0, 0);
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error(SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (handle, point, parent.handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (handle);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return OS.UIElement_IsEnabled (handle);
+
+}
+
+/**
+ * Returns the receiver's cascade menu if it has one or null
+ * if it does not. Only <code>CASCADE</code> menu items can have
+ * a pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ *
+ * @return the receiver's menu
+ *
+ * @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 getMenu () {
+ checkWidget ();
+ return menu;
+}
+
+String getNameText () {
+ if ((style & SWT.SEPARATOR) != 0) return "|";
+ return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Menu</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked.
+ *
+ * @return the selection 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>
+ */
+public boolean getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+ return OS.MenuItem_IsChecked (handle);
+}
+
+void HandleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if ((style & SWT.RADIO) != 0 && (parent.style & SWT.NO_RADIO_GROUP) == 0) {
+ if (parent.selected == this) {
+ OS.MenuItem_IsChecked (handle, true);
+ return;
+ }
+ if (parent.selected != null) OS.MenuItem_IsChecked (parent.selected.handle, false);
+ parent.selected = this;
+ }
+ Event event = new Event ();
+ setInputState (event, SWT.Selection, 0, 0);
+ postEvent (SWT.Selection, event);
+}
+
+void HandleSubmenuOpened (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (menu != null) {
+ menu.sendEvent (SWT.Show);
+ }
+}
+
+void HandleSubmenuClosed (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (menu != null) {
+ menu.sendEvent (SWT.Hide);
+ }
+}
+
+void hookEvents() {
+ if ((style & SWT.SEPARATOR) != 0) return;
+ super.hookEvents();
+ if ((style & SWT.CASCADE) == 0) {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.MenuItem_Click (handle, handler);
+ OS.GCHandle_Free (handler);
+ } else {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleSubmenuOpened");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.MenuItem_SubmenuOpened (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleSubmenuClosed");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.MenuItem_SubmenuClosed (handle, handler);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled menu item is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #getEnabled
+ */
+public boolean isEnabled () {
+ return getEnabled () && parent.isEnabled ();
+}
+
+void register() {
+ display.addWidget (handle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ if (menu != null) {
+ menu.release (false);
+ menu = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+void releaseMenu () {
+ setMenu (null);
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (menu != null) menu.dispose ();
+ menu = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the arm events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ArmListener
+ * @see #addArmListener
+ */
+public void removeArmListener (ArmListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Arm, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the widget accelerator. An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * <code>SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2</code>.
+ * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @param accelerator an integer that is the bit-wise OR of masks and a key
+ *
+ * </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 setAccelerator (int accelerator) {
+ checkWidget ();
+ //FIXME
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled 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>
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ OS.UIElement_IsEnabled (handle, enabled);
+}
+
+/**
+ * Sets the image the receiver will display to the argument.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept (for example, Windows NT).
+ * Furthermore, some platforms (such as GTK), cannot display both
+ * a check box and an image at the same time. Instead, they hide
+ * the image and display the check box.
+ * </p>
+ *
+ * @param image the image to display
+ *
+ * @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 ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ if (image != null) {
+ int img = OS.gcnew_Image ();
+ if (img == 0) error(SWT.ERROR_NO_HANDLES);
+ OS.Image_Source (img, image.handle);
+ OS.Image_Stretch (img, OS.Stretch_None);
+ OS.MenuItem_Icon (handle, img);
+ OS.GCHandle_Free (img);
+ } else {
+ OS.MenuItem_Icon (handle, 0);
+ }
+}
+
+/**
+ * Sets the receiver's pull down menu to the argument.
+ * Only <code>CASCADE</code> menu items can have a
+ * pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ * <p>
+ * Note: Disposing of a menu item that has a pull down menu
+ * will dispose of the menu. To avoid this behavior, set the
+ * menu to null before the menu item is disposed.
+ * </p>
+ *
+ * @param menu the new pull down menu
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu</li>
+ * <li>ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a <code>CASCADE</code></li>
+ * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</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 setMenu (Menu menu) {
+ checkWidget ();
+ if ((style & SWT.CASCADE) == 0) error (SWT.ERROR_MENUITEM_NOT_CASCADE);
+ if (menu != null) {
+ if (menu.cascade != null) {
+// FIXME: Change this error type, or fix the javadoc.
+ error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (menu.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if ((menu.style & SWT.DROP_DOWN) == 0) {
+ error (SWT.ERROR_MENU_NOT_DROP_DOWN);
+ }
+ if (menu.parent != parent.parent) {
+ error (SWT.ERROR_INVALID_PARENT);
+ }
+ Menu oldMenu = this.menu;
+ if (oldMenu == menu) return;
+ if (oldMenu != null) oldMenu.cascade = null;
+ this.menu = menu;
+ OS.ItemsControl_ItemsSource (handle, menu.handle);
+ menu.cascade = this;
+ } else {
+ OS.ItemsControl_ItemsSource (handle, 0);
+ if (this.menu != null) this.menu.cascade = null;
+ }
+}
+
+/**
+ * Sets the selection state of the receiver.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked.
+ *
+ * @param selected the new selection 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>
+ */
+public void setSelection (boolean selected) {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+ OS.MenuItem_IsChecked (handle, selected);
+}
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character and accelerator text.
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ * <p>
+ * Accelerator text is indicated by the '\t' character.
+ * On platforms that support accelerator text, the text
+ * that follows the '\t' character is displayed to the user,
+ * typically indicating the key stroke that will cause
+ * the item to become selected. On most platforms, the
+ * accelerator text appears right aligned in the menu.
+ * Setting the accelerator text does not install the
+ * accelerator key sequence. The accelerator key sequence
+ * is installed using #setAccelerator.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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>
+ *
+ * @see #setAccelerator
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (text.equals (string)) return;
+ super.setText (string);
+ String accelString = null;
+ int index = string.indexOf ('\t');
+ if (index != -1) {
+ accelString = string.substring (index+1, string.length());
+ string = string.substring (0, index);
+ }
+ int ptr = createDotNetString (string, true);
+ OS.HeaderedItemsControl_Header (handle, ptr);
+ OS.GCHandle_Free (ptr);
+ if (accelString != null) {
+ ptr = createDotNetString (accelString, false);
+ OS.MenuItem_InputGestureText (handle, ptr);
+ OS.GCHandle_Free (ptr);
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MessageBox.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MessageBox.java
new file mode 100644
index 0000000000..1f870e8f36
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/MessageBox.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class are used to inform or warn the user.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING, ICON_WORKING</dd>
+ * <dd>OK, OK | CANCEL</dd>
+ * <dd>YES | NO, YES | NO | CANCEL</dd>
+ * <dd>RETRY | CANCEL</dd>
+ * <dd>ABORT | RETRY | IGNORE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION, ICON_QUESTION,
+ * ICON_WARNING and ICON_WORKING may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class MessageBox extends Dialog {
+ String message;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @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>
+ */
+public MessageBox (Shell parent) {
+ this (parent, SWT.OK | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog 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#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_QUESTION
+ * @see SWT#ICON_WARNING
+ * @see SWT#ICON_WORKING
+ * @see SWT#OK
+ * @see SWT#CANCEL
+ * @see SWT#YES
+ * @see SWT#NO
+ * @see SWT#ABORT
+ * @see SWT#RETRY
+ * @see SWT#IGNORE
+ */
+public MessageBox (Shell parent, int style) {
+ super (parent, checkStyle (parent, checkStyle (style)));
+ checkSubclass ();
+ message = "";
+}
+
+static int checkStyle (int style) {
+ int mask = (SWT.YES | SWT.NO | SWT.OK | SWT.CANCEL | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
+ int bits = style & mask;
+ if (bits == SWT.OK || bits == SWT.CANCEL || bits == (SWT.OK | SWT.CANCEL)) return style;
+ if (bits == SWT.YES || bits == SWT.NO || bits == (SWT.YES | SWT.NO) || bits == (SWT.YES | SWT.NO | SWT.CANCEL)) return style;
+ if (bits == (SWT.RETRY | SWT.CANCEL) || bits == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) return style;
+ style = (style & ~mask) | SWT.OK;
+ return style;
+}
+
+/**
+ * Returns the dialog's message, or an empty string if it does not have one.
+ * The message is a description of the purpose for which the dialog was opened.
+ * This message will be visible in the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+ return message;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return the ID of the button that was selected to dismiss the
+ * message box (e.g. SWT.OK, SWT.CANCEL, etc.)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public int open () {
+
+ /* Compute the MessageBox style */
+ int buttonBits = 0;
+ if ((style & SWT.OK) == SWT.OK) buttonBits = OS.MessageBoxButton_OK;
+ if ((style & (SWT.OK | SWT.CANCEL)) == (SWT.OK | SWT.CANCEL)) buttonBits = OS.MessageBoxButton_OKCancel;
+ if ((style & (SWT.YES | SWT.NO)) == (SWT.YES | SWT.NO)) buttonBits = OS.MessageBoxButton_YesNo;
+ if ((style & (SWT.YES | SWT.NO | SWT.CANCEL)) == (SWT.YES | SWT.NO | SWT.CANCEL)) buttonBits = OS.MessageBoxButton_YesNoCancel;
+ /*
+ * Feature in WPF. MessageBoxButton does not define Retry, Abort, or
+ * Ignore buttons. The work around is to use OK/Cancel instead and map
+ * OK to Retry for Retry/Cancel, and Abort for Abort/Retry/Cancel message
+ * boxes.
+ */
+ if ((style & (SWT.RETRY | SWT.CANCEL)) == (SWT.RETRY | SWT.CANCEL)) buttonBits = OS.MessageBoxButton_OKCancel;
+ if ((style & (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) buttonBits = OS.MessageBoxButton_OKCancel;
+ if (buttonBits == 0) buttonBits = OS.MessageBoxButton_OK;
+
+ int iconBits = 0;
+ if ((style & SWT.ICON_ERROR) != 0) iconBits = OS.MessageBoxImage_Error;
+ if ((style & SWT.ICON_INFORMATION) != 0) iconBits = OS.MessageBoxImage_Information;
+ if ((style & SWT.ICON_QUESTION) != 0) iconBits = OS.MessageBoxImage_Question;
+ if ((style & SWT.ICON_WARNING) != 0) iconBits = OS.MessageBoxImage_Warning;
+ if ((style & SWT.ICON_WORKING) != 0) iconBits = OS.MessageBoxImage_Information;
+
+ int messagePtr = parent.createDotNetString (message, false);
+ int titlePtr = parent.createDotNetString (title, false);
+ int code = OS.MessageBox_Show (messagePtr, titlePtr, buttonBits, iconBits, 0);
+ OS.GCHandle_Free (titlePtr);
+ OS.GCHandle_Free (messagePtr);
+
+ /* Compute and return the result */
+ switch (code) {
+ case OS.MessageBoxResult_No: return SWT.NO;
+ case OS.MessageBoxResult_OK:
+ if ((style & (SWT.RETRY | SWT.CANCEL)) == (SWT.RETRY | SWT.CANCEL)) return SWT.RETRY;
+ if ((style & (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) return SWT.ABORT;
+ return SWT.OK;
+ case OS.MessageBoxResult_Yes: return SWT.YES;
+ case OS.MessageBoxResult_Cancel:
+ default:
+ return SWT.CANCEL;
+ }
+}
+
+/**
+ * Sets the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @param string the message
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ */
+public void setMessage (String string) {
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ProgressBar.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ProgressBar.java
new file mode 100644
index 0000000000..98ca83622a
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ProgressBar.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of the receiver represent an unselectable
+ * user interface object that is used to display progress,
+ * typically in the form of a bar.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SMOOTH, HORIZONTAL, VERTICAL, INDETERMINATE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#progressbar">ProgressBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ProgressBar extends Control {
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SMOOTH
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see SWT#INDETERMINATE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ProgressBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ int border = getBorderWidth ();
+ int width = border * 2, height = border * 2;
+ if ((style & SWT.HORIZONTAL) != 0) {
+ width += OS.SystemParameters_HorizontalScrollBarButtonWidth () * 10;
+ height += OS.SystemParameters_HorizontalScrollBarHeight ();
+ } else {
+ width += OS.SystemParameters_VerticalScrollBarWidth ();
+ height += OS.SystemParameters_VerticalScrollBarButtonHeight () * 10;
+ }
+ if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
+ if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
+ return new Point (width, height);
+}
+
+void createHandle () {
+ handle = OS.gcnew_ProgressBar();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.VERTICAL) != 0) OS.ProgressBar_Orientation (handle, OS.Orientation_Vertical);
+ if ((style & SWT.INDETERMINATE) != 0) {
+ OS.ProgressBar_IsIndeterminate (handle, true) ;
+ }
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @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 int getMaximum () {
+ checkWidget ();
+ return (int) OS.RangeBase_Maximum (handle);
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @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 int getMinimum () {
+ checkWidget ();
+ return (int) OS.RangeBase_Minimum (handle);
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @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 int getSelection () {
+ checkWidget ();
+ return (int) OS.RangeBase_Value (handle);
+}
+
+/**
+ * Returns the state of the receiver. The value will be one of:
+ * <ul>
+ * <li>{@link SWT#NORMAL}</li>
+ * <li>{@link SWT#ERROR}</li>
+ * <li>{@link SWT#PAUSED}</li>
+ * </ul>
+ *
+ * @return the 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>
+ *
+ * @since 3.4
+ */
+public int getState () {
+ checkWidget ();
+ return SWT.NORMAL;
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @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 setMaximum (int value) {
+ checkWidget ();
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ if (0 <= minimum && minimum < value) {
+ OS.RangeBase_Maximum (handle, value);
+ }
+
+ //FIXME - If the new maximum is applied then the receiver's
+ // selection value will be adjusted if necessary to fall within its new range.
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is negative or is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the current maximum
+ *
+ * @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 setMinimum (int value) {
+ checkWidget ();
+ int maximum = (int) OS.RangeBase_Maximum (handle);
+ if (0 <= maximum && value < maximum) {
+ OS.RangeBase_Minimum (handle, value);
+ }
+
+ //FIXME - If the new minimum is applied then the receiver's
+ //selection value will be adjusted if necessary to fall within its new range
+}
+
+/**
+ * Sets the single 'selection' that is the receiver's
+ * position to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @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 setSelection (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ OS.RangeBase_Value (handle, value);
+}
+
+/**
+ * Sets the state of the receiver. The state must be one of these values:
+ * <ul>
+ * <li>{@link SWT#NORMAL}</li>
+ * <li>{@link SWT#ERROR}</li>
+ * <li>{@link SWT#PAUSED}</li>
+ * </ul>
+ *
+ * @param state the new 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>
+ *
+ * @since 3.4
+ */
+public void setState (int state) {
+ checkWidget ();
+ //NOT IMPLEMENTED
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Sash.java
new file mode 100644
index 0000000000..9aeb38b1ea
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Sash.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of the receiver represent a selectable user interface object
+ * that allows the user to drag a rubber banded outline of the sash within
+ * the parent control.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL, SMOOTH</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#sash">Sash snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Sash extends Control {
+ boolean dragging;
+ int startX, startY, lastX, lastY;
+ final static int INCREMENT = 1;
+ final static int PAGE_INCREMENT = 9;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see SWT#SMOOTH
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Sash (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the x, y, width, and height fields of the event object are valid.
+ * If the receiver is being dragged, the event object detail field contains the value <code>SWT.DRAG</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ handle = OS.gcnew_Canvas ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.UIElement_Focusable (handle, true);
+ int newCursor = (style & SWT.VERTICAL)!= 0 ? OS.Cursors_SizeWE () : OS.Cursors_SizeNS ();
+ OS.FrameworkElement_Cursor (handle, newCursor);
+ OS.GCHandle_Free (newCursor);
+}
+
+int defaultBackground () {
+ return OS.SystemColors_ControlColor;
+}
+
+void HandlePreviewGotKeyboardFocus (int sender, int e) {
+ super.HandlePreviewGotKeyboardFocus (sender, e);
+ if (!checkEvent (e)) return;
+ Point location = getLocation();
+ lastX = location.x;
+ lastY = location.y;
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ switch (key) {
+ case OS.Key_Left:
+ case OS.Key_Right:
+ case OS.Key_Up:
+ case OS.Key_Down:
+ int xChange = 0, yChange = 0;
+ int stepSize = PAGE_INCREMENT;
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice(e);
+ int modifiers = OS.KeyboardDevice_Modifiers(keyboardDevice);
+ OS.GCHandle_Free(keyboardDevice);
+ if ((modifiers & OS.ModifierKeys_Control) != 0) stepSize = INCREMENT;
+ if ((style & SWT.VERTICAL) != 0) {
+ if (key == OS.Key_Up || key == OS.Key_Down) break;
+ xChange = key == OS.Key_Left ? -stepSize : stepSize;
+ } else {
+ if (key == OS.Key_Left || key == OS.Key_Right) break;
+ yChange = key == OS.Key_Up ? -stepSize : stepSize;
+ }
+
+ Rectangle bounds = getBounds ();
+ int width = bounds.width, height = bounds.height;
+ Rectangle parentBounds = parent.getBounds ();
+ int parentWidth = parentBounds.width;
+ int parentHeight = parentBounds.height;
+ int newX = lastX, newY = lastY;
+ if ((style & SWT.VERTICAL) != 0) {
+ newX = Math.min (Math.max (0, lastX + xChange), parentWidth - width);
+ } else {
+ newY = Math.min (Math.max (0, lastY + yChange), parentHeight - height);
+ }
+ if (newX == lastX && newY == lastY) return;
+ Event event = new Event ();
+ event.x = newX;
+ event.y = newY;
+ event.width = width;
+ event.height = height;
+ sendEvent (SWT.Selection, event);
+ if (isDisposed ()) break;
+ if (event.doit) {
+ setBounds (event.x, event.y, width, height);
+ if (isDisposed ()) break;
+ lastX = event.x;
+ lastY = event.y;
+ if (isDisposed ()) return;
+ int cursorX = event.x, cursorY = event.y;
+ if ((style & SWT.VERTICAL) != 0) {
+ cursorY += height / 2;
+ } else {
+ cursorX += width / 2;
+ }
+ display.setCursorLocation (parent.toDisplay (cursorX, cursorY));
+ }
+ OS.RoutedEventArgs_Handled(e, true);
+ break;
+ }
+}
+
+void HandlePreviewMouseDown (int sender, int e) {
+ super.HandlePreviewMouseDown (sender, e);
+ int eventPos = OS.MouseEventArgs_GetPosition (e, handle);
+ startX = (int) OS.Point_X (eventPos);
+ startY = (int) OS.Point_Y (eventPos);
+ OS.GCHandle_Free (eventPos);
+ Point location = parent.getLocation (this);
+ int x = location.x;
+ int y = location.y;
+ int width = (int) OS.FrameworkElement_ActualWidth (handle);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ lastX = x;
+ lastY = y;
+ Event event = new Event ();
+ event.x = lastX;
+ event.y = lastY;
+ event.width = width;
+ event.height = height;
+ sendEvent (SWT.Selection, event);
+ if (event.doit) {
+ dragging = true;
+ lastX = event.x;
+ lastY = event.y;
+ OS.UIElement_CaptureMouse (handle);
+ }
+}
+
+void HandlePreviewMouseUp (int sender, int e) {
+ super.HandlePreviewMouseUp (sender, e);
+ if (!dragging) return;
+ OS.UIElement_ReleaseMouseCapture (handle);
+ dragging = false;
+ int width = (int) OS.FrameworkElement_ActualWidth (handle);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ Event event = new Event ();
+ event.x = lastX;
+ event.y = lastY;
+ event.width = width;
+ event.height = height;
+ sendEvent (SWT.Selection, event);
+}
+
+void HandlePreviewMouseMove (int sender, int e) {
+ super.HandlePreviewMouseMove (sender, e);
+ if (!dragging) return;
+ int eventPos = OS.MouseEventArgs_GetPosition (e, handle);
+ int eventX = (int) OS.Point_X (eventPos);
+ int eventY = (int) OS.Point_Y (eventPos);
+ OS.GCHandle_Free (eventPos);
+ Point location = parent.getLocation (this);
+ int x = location.x;
+ int y = location.y;
+ int width = (int) OS.FrameworkElement_ActualWidth (handle);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ int parentWidth = (int) OS.FrameworkElement_ActualWidth (parent.handle);
+ int parentHeight = (int) OS.FrameworkElement_ActualHeight (parent.handle);
+ int newX = lastX, newY = lastY;
+ if ((style & SWT.VERTICAL) != 0) {
+ newX = Math.min (Math.max (0, eventX + x - startX), parentWidth - width);
+ } else {
+ newY = Math.min (Math.max (0, eventY + y - startY), parentHeight - height);
+ }
+ if (newX == lastX && newY == lastY) return;
+ Event event = new Event ();
+ event.x = newX;
+ event.y = newY;
+ event.width = width;
+ event.height = height;
+ sendEvent (SWT.Selection, event);
+ if (isDisposed ()) return;
+ if (event.doit) {
+ lastX = event.x;
+ lastY = event.y;
+ }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+int traversalCode (int key, int event) {
+ return 0;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scale.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scale.java
new file mode 100644
index 0000000000..776a370903
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scale.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of the receiver represent a selectable user
+ * interface object that present a range of continuous
+ * numeric values.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#scale">Scale snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Scale extends Control {
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Scale (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the receiver's value.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ int border = getBorderWidth ();
+ int width = border * 2, height = border * 2;
+ if ((style & SWT.HORIZONTAL) != 0) {
+ width += OS.SystemParameters_HorizontalScrollBarButtonWidth () * 10;
+ height += OS.SystemParameters_HorizontalScrollBarHeight () * 2;
+ } else {
+ width += OS.SystemParameters_VerticalScrollBarWidth () * 2;
+ height += OS.SystemParameters_VerticalScrollBarButtonHeight () * 10;
+ }
+ if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
+ if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
+ return new Point (width, height);
+}
+
+void createHandle () {
+ state |= THEME_BACKGROUND;
+ handle = OS.gcnew_Slider ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.VERTICAL) != 0) OS.Slider_Orientation (handle, OS.Orientation_Vertical);
+ OS.RangeBase_Maximum (handle, 100);
+ OS.RangeBase_LargeChange (handle, 10);
+ OS.RangeBase_SmallChange (handle, 1);
+ OS.Slider_TickFrequency (handle, 10);
+ OS.Slider_TickPlacement (handle, OS.TickPlacement_Both);
+}
+
+int defaultBackground () {
+ return OS.SystemColors_ControlColor;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @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 int getIncrement () {
+ checkWidget ();
+ return (int) OS.RangeBase_SmallChange (handle);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @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 int getMaximum () {
+ checkWidget ();
+ return (int) OS.RangeBase_Maximum (handle);
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @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 int getMinimum () {
+ checkWidget ();
+ return (int) OS.RangeBase_Minimum (handle);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @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 int getPageIncrement () {
+ checkWidget ();
+ return (int) OS.RangeBase_LargeChange(handle);
+}
+
+/**
+ * Returns the 'selection', which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @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 int getSelection () {
+ checkWidget ();
+ return (int) OS.RangeBase_Value (handle);
+}
+
+void HandleValueChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ postEvent (SWT.Selection);
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ int handler = OS.gcnew_RoutedPropertyChangedEventHandler (jniRef, "HandleValueChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.RangeBase_ValueChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param increment the new increment (must be greater than zero)
+ *
+ * @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 setIncrement (int increment) {
+ checkWidget ();
+ if (increment < 1) return;
+ int minimum = (int) OS.RangeBase_Minimum(handle);
+ int maximum = (int) OS.RangeBase_Maximum(handle);
+ if (increment > maximum - minimum) return;
+ OS.RangeBase_SmallChange(handle, increment);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @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 setMaximum (int value) {
+ checkWidget ();
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ if (0 <= minimum && minimum < value) OS.RangeBase_Maximum (handle, value);
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is negative or is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the current maximum
+ *
+ * @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 setMinimum (int value) {
+ checkWidget ();
+ int maximum = (int) OS.RangeBase_Maximum (handle);
+ if (0 <= value && value < maximum) OS.RangeBase_Minimum (handle, value);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param pageIncrement the page increment (must be greater than zero)
+ *
+ * @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 setPageIncrement (int pageIncrement) {
+ checkWidget ();
+ if (pageIncrement < 1) return;
+ int minimum = (int) OS.RangeBase_Minimum(handle);
+ int maximum = (int) OS.RangeBase_Maximum(handle);
+ if (pageIncrement > maximum - minimum) return;
+ OS.RangeBase_LargeChange(handle, pageIncrement);
+ OS.Slider_TickFrequency(handle, pageIncrement);
+}
+
+/**
+ * Sets the 'selection', which is the receiver's value,
+ * to the argument which must be greater than or equal to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @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 setSelection (int value) {
+ checkWidget ();
+ OS.RangeBase_Value (handle, value);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ScrollBar.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ScrollBar.java
new file mode 100644
index 0000000000..db6026d2b5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ScrollBar.java
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ * <p>
+ * At any given moment, a given scroll bar will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the scroll bar represents (that is, between its
+ * <em>minimum</em> and <em>maximum</em> values).
+ * </p><p>
+ * Typically, scroll bars will be made up of five areas:
+ * <ol>
+ * <li>an arrow button for decrementing the value</li>
+ * <li>a page decrement area for decrementing the value by a larger amount</li>
+ * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
+ * <li>a page increment area for incrementing the value by a larger amount</li>
+ * <li>an arrow button for incrementing the value</li>
+ * </ol>
+ * Based on their style, scroll bars are either <code>HORIZONTAL</code>
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or <code>VERTICAL</code>
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ * </p><p>
+ * On some platforms, the size of the scroll bar's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the scroll bar will not change.
+ * </p><p>
+ * Scroll bars are created by specifying either <code>H_SCROLL</code>,
+ * <code>V_SCROLL</code> or both when creating a <code>Scrollable</code>.
+ * They are accessed from the <code>Scrollable</code> using
+ * <code>getHorizontalBar</code> and <code>getVerticalBar</code>.
+ * </p><p>
+ * Note: Scroll bars are not Controls. On some platforms, scroll bars
+ * that appear as part of some standard controls such as a text or list
+ * have no operating system resources and are not children of the control.
+ * For this reason, scroll bars are treated specially. To create a control
+ * that looks like a scroll bar but has operating system resources, use
+ * <code>Slider</code>.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see Slider
+ * @see Scrollable
+ * @see Scrollable#getHorizontalBar
+ * @see Scrollable#getVerticalBar
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class ScrollBar extends Widget {
+ Scrollable parent;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+ScrollBar (Scrollable parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
+ * <code>SWT.NONE</code> - for the end of a drag.
+ * <code>SWT.DRAG</code>.
+ * <code>SWT.HOME</code>.
+ * <code>SWT.END</code>.
+ * <code>SWT.ARROW_DOWN</code>.
+ * <code>SWT.ARROW_UP</code>.
+ * <code>SWT.PAGE_DOWN</code>.
+ * <code>SWT.PAGE_UP</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's value
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createHandle () {
+ handle = parent.getScrollBarHandle (style);
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ int topHandle = topHandle ();
+ OS.UIElement_Visibility (topHandle, OS.Visibility_Collapsed);
+ if (parent.scrolledHandle != 0) {
+ int parentHandle = parent.handle;
+ int children = OS.Panel_Children (parentHandle);
+ OS.UIElementCollection_Remove (children, topHandle);
+ }
+ releaseHandle ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget();
+ return OS.UIElement_IsEnabled (topHandle ());
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @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 int getIncrement () {
+ checkWidget();
+ return (int) OS.RangeBase_SmallChange (handle);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @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 int getMaximum () {
+ checkWidget();
+ int maximum = (int) OS.RangeBase_Maximum (handle);
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ return maximum + viewSize;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @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 int getMinimum () {
+ checkWidget();
+ return (int) OS.RangeBase_Minimum (handle);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @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 int getPageIncrement () {
+ checkWidget();
+ return (int) OS.RangeBase_LargeChange (handle);
+}
+
+/**
+ * Returns the receiver's parent, which must be a Scrollable.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Scrollable getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @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 int getSelection () {
+ checkWidget();
+ return (int) OS.RangeBase_Value (handle);
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @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 Point getSize () {
+ checkWidget();
+ int topHandle = topHandle ();
+ int width = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ return new Point (width, height);
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @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 ScrollBar
+ */
+public int getThumb () {
+ checkWidget();
+ return (int) OS.ScrollBar_ViewportSize (handle);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible, and
+ * <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's visibility 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>
+ */
+public boolean getVisible () {
+ checkWidget();
+ return OS.UIElement_Visibility (handle) == OS.Visibility_Visible;
+}
+
+void HandleScroll (int sender, int e) {
+ if (!checkEvent (e)) return;
+ Event event = new Event ();
+ switch (OS.ScrollEventArgs_ScrollEventType (e)) {
+ case OS.ScrollEventType_EndScroll: return;
+ case OS.ScrollEventType_ThumbPosition: event.detail = SWT.NONE; break;
+ case OS.ScrollEventType_ThumbTrack: event.detail = SWT.DRAG; break;
+ case OS.ScrollEventType_First: event.detail = SWT.HOME; break;
+ case OS.ScrollEventType_Last: event.detail = SWT.END; break;
+ case OS.ScrollEventType_LargeIncrement: event.detail = SWT.PAGE_DOWN; break;
+ case OS.ScrollEventType_LargeDecrement: event.detail = SWT.PAGE_UP; break;
+ case OS.ScrollEventType_SmallIncrement: event.detail = SWT.ARROW_DOWN; break;
+ case OS.ScrollEventType_SmallDecrement: event.detail = SWT.ARROW_UP; break;
+ }
+ postEvent (SWT.Selection, event);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_ScrollEventHandler (jniRef, "HandleScroll");
+ OS.ScrollBar_Scroll (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled control is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget();
+ return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility 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 #getVisible
+ */
+public boolean isVisible () {
+ checkWidget();
+ return getVisible () && parent.isVisible ();
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (parent.horizontalBar == this) parent.horizontalBar = null;
+ if (parent.verticalBar == this) parent.verticalBar = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled 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>
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget();
+ OS.UIElement_IsEnabled (handle, enabled);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @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 setIncrement (int value) {
+ checkWidget();
+ if (value < 1) return;
+ OS.RangeBase_SmallChange (handle, value);
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum
+ *
+ * @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 setMaximum (int value) {
+ checkWidget();
+ if (value < 0) return;
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ if (value <= minimum) return;
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ if (value - minimum < viewSize) {
+ viewSize = value - minimum;
+ OS.ScrollBar_ViewportSize (handle, viewSize);
+ }
+ OS.RangeBase_Maximum (handle, value - viewSize);
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @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 setMinimum (int value) {
+ checkWidget();
+ if (value < 0) return;
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ int maximum = (int) OS.RangeBase_Maximum (handle) + viewSize;
+ if (value >= maximum) return;
+ if (maximum - value < viewSize) {
+ viewSize = maximum - value;
+ OS.RangeBase_Maximum (handle, maximum - viewSize);
+ OS.ScrollBar_ViewportSize (handle, viewSize);
+ }
+ OS.RangeBase_Minimum (handle, value);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @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 setPageIncrement (int value) {
+ checkWidget();
+ if (value < 1) return;
+ OS.RangeBase_LargeChange (handle, value);
+}
+
+/**
+ * Sets the single <em>selection</em> that is the receiver's
+ * value to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param selection the new selection (must be zero or greater)
+ *
+ * @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 setSelection (int selection) {
+ checkWidget();
+ OS.RangeBase_Value (handle, selection);
+}
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values. This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @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 setThumb (int value) {
+ checkWidget();
+ if (value < 1) return;
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ int maximum = (int) OS.RangeBase_Maximum (handle) + viewSize;
+ value = Math.min (value, maximum - minimum);
+ OS.RangeBase_Maximum (handle, maximum - value);
+ OS.ScrollBar_ViewportSize (handle, value);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @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 setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+ checkWidget();
+ if (minimum < 0) return;
+ if (maximum < 0) return;
+ if (thumb < 1) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ thumb = Math.min (thumb, maximum - minimum);
+ OS.RangeBase_Minimum (handle, minimum);
+ OS.RangeBase_Maximum (handle, maximum - thumb);
+ OS.ScrollBar_ViewportSize (handle, thumb);
+ OS.RangeBase_Value (handle, selection);
+ OS.RangeBase_LargeChange (handle, pageIncrement);
+ OS.RangeBase_SmallChange (handle, increment);
+}
+
+/**
+ * Marks the receiver as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility 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>
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ int topHandle = topHandle ();
+ if ((OS.UIElement_Visibility (topHandle) == OS.Visibility_Visible) == visible) return;
+ if (visible) {
+ sendEvent (SWT.Show);
+ if (isDisposed ()) return;
+ }
+ OS.UIElement_Visibility (topHandle, visible ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ if (isDisposed ()) return;
+ if (!visible) {
+ sendEvent (SWT.Hide);
+ if (isDisposed ()) return;
+ }
+}
+
+int topHandle () {
+ return handle;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scrollable.java
new file mode 100644
index 0000000000..2176dd0efb
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Scrollable.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * This class is the abstract superclass of all classes which
+ * represent controls that have standard scroll bars.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>H_SCROLL, V_SCROLL</dd>
+ * <dt><b>Events:</b>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public abstract class Scrollable extends Control {
+ ScrollBar horizontalBar, verticalBar;
+ int scrolledHandle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Scrollable () {
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#H_SCROLL
+ * @see SWT#V_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Scrollable (Composite parent, int style) {
+ super (parent, style);
+}
+
+int clientHandle () {
+ return handle;
+}
+
+/**
+ * Given a desired <em>client area</em> for the receiver
+ * (as described by the arguments), returns the bounding
+ * rectangle which would be required to produce that client
+ * area.
+ * <p>
+ * In other words, it returns a rectangle such that, if the
+ * receiver's bounds were set to that rectangle, the area
+ * of the receiver which is capable of displaying data
+ * (that is, not covered by the "trimmings") would be the
+ * rectangle described by the arguments (relative to the
+ * receiver's parent).
+ * </p>
+ *
+ * @param x the desired x coordinate of the client area
+ * @param y the desired y coordinate of the client area
+ * @param width the desired width of the client area
+ * @param height the desired height of the client area
+ * @return the required bounds to produce the given client area
+ *
+ * @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 #getClientArea
+ */
+public Rectangle computeTrim (int x, int y, int width, int height) {
+ checkWidget ();
+ if (verticalBar != null) width += OS.SystemParameters_VerticalScrollBarWidth ();
+ if (horizontalBar != null) height += OS.SystemParameters_HorizontalScrollBarHeight ();
+ return new Rectangle (x, y, width, height);
+}
+
+ScrollBar createScrollBar (int type) {
+ return new ScrollBar (this, type);
+}
+
+void createWidget () {
+ super.createWidget ();
+ if ((style & SWT.H_SCROLL) != 0) horizontalBar = createScrollBar (SWT.H_SCROLL);
+ if ((style & SWT.V_SCROLL) != 0) verticalBar = createScrollBar (SWT.V_SCROLL);
+ fixScrollbarVisibility ();
+}
+
+void deregister () {
+ super.deregister ();
+ if (scrolledHandle != 0) display.removeWidget (scrolledHandle);
+}
+
+int findScrollViewer (int current, int scrollViewerType) {
+ int type = OS.Object_GetType (current);
+ boolean found = OS.Object_Equals (scrollViewerType, type);
+ OS.GCHandle_Free (type);
+ if (found) return current;
+ int childCount = OS.VisualTreeHelper_GetChildrenCount (current);
+ for (int i = 0; i < childCount; i++) {
+ int child = OS.VisualTreeHelper_GetChild (current, i);
+ int result = findScrollViewer (child, scrollViewerType);
+ if (child != result) OS.GCHandle_Free (child);
+ if (result != 0) return result;
+ }
+ return 0;
+}
+
+void fixScrollbarVisibility () {
+ if ((style & SWT.H_SCROLL) == 0) {
+ OS.ScrollViewer_SetHorizontalScrollBarVisibility (handle, OS.ScrollBarVisibility_Hidden);
+ }
+ if ((style & SWT.V_SCROLL) == 0) {
+ OS.ScrollViewer_SetVerticalScrollBarVisibility (handle, OS.ScrollBarVisibility_Hidden);
+ }
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data (that is,
+ * not covered by the "trimmings").
+ *
+ * @return the client area
+ *
+ * @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 #computeTrim
+ */
+public Rectangle getClientArea () {
+ checkWidget ();
+ int clientHandle = clientHandle ();
+ int topHandle = topHandle ();
+ updateLayout (topHandle);
+ int width = (int) OS.FrameworkElement_ActualWidth (clientHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (clientHandle);
+ return new Rectangle (0, 0, width, height);
+}
+
+/**
+ * Returns the receiver's horizontal scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the horizontal scroll 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 ScrollBar getHorizontalBar () {
+ checkWidget ();
+ return horizontalBar;
+}
+
+int getScrollBarHandle (int style) {
+ int scrollbar = 0;
+ if (scrolledHandle != 0) {
+ int children = OS.Panel_Children (scrolledHandle);
+ int enumerator = OS.UIElementCollection_GetEnumerator (children);
+ int scrollType = OS.ScrollBar_typeid ();
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int current = OS.IEnumerator_Current (enumerator);
+ if (OS.Type_IsInstanceOfType (scrollType, current)) {
+ int orientation = OS.ScrollBar_Orientation (current);
+ if ((style & SWT.H_SCROLL) != 0 && orientation == OS.Orientation_Horizontal) {
+ scrollbar = current;
+ break;
+ }
+ if ((style & SWT.V_SCROLL) != 0 && orientation == OS.Orientation_Vertical) {
+ scrollbar = current;
+ break;
+ }
+ }
+ OS.GCHandle_Free (current);
+ }
+ OS.GCHandle_Free (scrollType);
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (children);
+ } else {
+ updateLayout (handle);
+ int scrollViewerType = OS.ScrollViewer_typeid ();
+ int scrollViewer = findScrollViewer (handle, scrollViewerType);
+ int template = OS.Control_Template (scrollViewer);
+ int part;
+ if ((style & SWT.H_SCROLL) != 0) {
+ part = createDotNetString ("PART_HorizontalScrollBar", false);
+ } else {
+ part = createDotNetString ("PART_VerticalScrollBar", false);
+ }
+ scrollbar = OS.FrameworkTemplate_FindName (template, part, scrollViewer);
+ OS.GCHandle_Free (part);
+ OS.GCHandle_Free (template);
+ OS.GCHandle_Free (scrollViewer);
+ OS.GCHandle_Free (scrollViewerType);
+ }
+ return scrollbar;
+}
+
+/**
+ * Returns the receiver's vertical scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the vertical scroll 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 ScrollBar getVerticalBar () {
+ checkWidget ();
+ return verticalBar;
+}
+
+void HandlePreviewMouseWheel (int sender, int e) {
+ super.HandlePreviewMouseWheel (sender, e);
+ if (!checkEvent (e)) return;
+ if ((state & CANVAS) != 0) {
+ if (verticalBar != null) {
+ int vHandle = verticalBar.handle;
+ int delta = OS.MouseWheelEventArgs_Delta (e);
+ int lines = OS.SystemParameters_WheelScrollLines ();
+ double value = OS.RangeBase_Value (vHandle);
+ double newValue = value;
+ Event event = new Event ();
+ if (lines != -1) {
+ double smallIncrement = OS.RangeBase_SmallChange (vHandle);
+ newValue += smallIncrement * (-delta/120) * lines;
+ event.detail = delta < 0 ? SWT.ARROW_DOWN : SWT.ARROW_UP;
+ } else {
+ double largeIncrement = OS.RangeBase_LargeChange (vHandle);
+ newValue += largeIncrement * (-delta/120);
+ event.detail = delta < 0 ? SWT.PAGE_DOWN : SWT.PAGE_UP;
+ }
+ OS.RangeBase_Value (vHandle, newValue);
+ newValue = OS.RangeBase_Value (vHandle);
+ if (value != newValue) {
+ verticalBar.postEvent (SWT.Selection, event);
+ }
+ }
+ }
+}
+
+void register () {
+ super.register ();
+ if (scrolledHandle != 0) display.addWidget (scrolledHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ if (horizontalBar != null) {
+ horizontalBar.release (false);
+ horizontalBar = null;
+ }
+ if (verticalBar != null) {
+ verticalBar.release (false);
+ verticalBar = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (scrolledHandle != 0) OS.GCHandle_Free (scrolledHandle);
+ scrolledHandle = 0;
+}
+
+int topHandle () {
+ return scrolledHandle != 0 ? scrolledHandle : super.topHandle ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Shell.java
new file mode 100644
index 0000000000..6ec9c27532
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Shell.java
@@ -0,0 +1,1536 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent the "windows"
+ * which the desktop or "window manager" is managing.
+ * Instances that do not have a parent (that is, they
+ * are built using the constructor, which takes a
+ * <code>Display</code> as the argument) are described
+ * as <em>top level</em> shells. Instances that do have
+ * a parent are described as <em>secondary</em> or
+ * <em>dialog</em> shells.
+ * <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><p>
+ * The <em>modality</em> of an instance may be specified using
+ * style bits. The modality style bits are used to determine
+ * whether input is blocked for other shells on the display.
+ * The <code>PRIMARY_MODAL</code> style allows an instance to block
+ * input to its parent. The <code>APPLICATION_MODAL</code> style
+ * allows an instance to block input to every other shell in the
+ * display. The <code>SYSTEM_MODAL</code> style allows an instance
+ * to block input to all shells, including shells belonging to
+ * different applications.
+ * </p><p>
+ * Note: The styles supported by this class are 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
+ * and modality. For example, some window managers only
+ * support resizable windows and will always assume the
+ * RESIZE style, even if it is not set. In addition, if a
+ * modality style is not supported, it is "upgraded" to a
+ * more restrictive modality style that is supported. For
+ * example, if <code>PRIMARY_MODAL</code> is not supported,
+ * it would be upgraded to <code>APPLICATION_MODAL</code>.
+ * A modality style may also be "downgraded" to a less
+ * restrictive style. For example, most operating systems
+ * no longer support <code>SYSTEM_MODAL</code> because
+ * it can freeze up the desktop, so this is typically
+ * downgraded to <code>APPLICATION_MODAL</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET</dd>
+ * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Activate, Close, Deactivate, Deiconify, Iconify</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>
+ * <p>
+ * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
+ * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is not intended to be subclassed.
+ * </p>
+ *
+ * @see Decorations
+ * @see SWT
+ * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Shell extends Decorations {
+ Control lastActive;
+ boolean closing;
+ boolean moved, resized, opened, fullScreen, modified, center;
+ int oldX, oldY, oldWidth, oldHeight;
+ int oldWindowStyle, oldWindowState;
+
+/**
+ * Constructs a new instance of this class. This is equivalent
+ * to calling <code>Shell((Display) null)</code>.
+ *
+ * @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>
+ */
+public Shell () {
+ this ((Display) null);
+}
+
+/**
+ * Constructs a new instance of this class given only the style
+ * value describing its behavior and appearance. This is equivalent
+ * to calling <code>Shell((Display) null, style)</code>.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param style the style of control to construct
+ *
+ * @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#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#TOOL
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ * @see SWT#SHEET
+ */
+public Shell (int style) {
+ this ((Display) null, style);
+}
+
+/**
+ * Constructs a new instance of this class given only the display
+ * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
+ * <p>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the shell on
+ *
+ * @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>
+ */
+public Shell (Display display) {
+ this (display, SWT.SHELL_TRIM);
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p><p>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the shell on
+ * @param style the style of control to construct
+ *
+ * @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#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#TOOL
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ * @see SWT#SHEET
+ */
+public Shell (Display display, int style) {
+ this (display, null, style, 0, false);
+}
+
+Shell (Display display, Shell parent, int style, int handle, boolean embedded) {
+ super ();
+ checkSubclass ();
+ if (display == null) display = Display.getCurrent ();
+ if (display == null) display = Display.getDefault ();
+ if (!display.isValidThread ()) {
+ error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ if (parent != null && parent.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.center = parent != null && (style & SWT.SHEET) != 0;
+ this.style = checkStyle (parent, style);
+ this.parent = parent;
+ this.display = display;
+ if (handle != 0) {
+ if (embedded) {
+ this.handle = handle;
+ } else {
+ shellHandle = handle;
+ }
+ }
+ createWidget ();
+}
+
+/**
+ * Constructs a new instance of this class given only its
+ * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
+ * <p>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</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>
+ */
+public Shell (Shell parent) {
+ this (parent, SWT.DIALOG_TRIM);
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p><p>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</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#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 SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ * @see SWT#SHEET
+ */
+public Shell (Shell parent, int style) {
+ this (parent != null ? parent.display : null, parent, style, 0, false);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new shell.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Shell</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ */
+public static Shell wpf_new (Display display, int handle) {
+ return new Shell (display, null, SWT.NO_TRIM, handle, true);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new shell
+ * that is not embedded.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Shell</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ *
+ * @since 3.3
+ */
+public static Shell internal_new (Display display, int handle) {
+ handle = OS.GCHandle_ToHandle (handle);
+ return new Shell (display, null, SWT.NO_TRIM, handle, false);
+}
+
+static int checkStyle (Shell parent, int style) {
+ style = Decorations.checkStyle (style);
+ style &= ~SWT.TRANSPARENT;
+ int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
+ if ((style & SWT.SHEET) != 0) {
+ style &= ~SWT.SHEET;
+ style |= parent == null ? SWT.SHELL_TRIM : SWT.DIALOG_TRIM;
+ if ((style & mask) == 0) {
+ style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
+ }
+ }
+ int bits = style & ~mask;
+ if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
+ if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
+ if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
+ return bits;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when operations are performed on the receiver,
+ * by sending the listener one of the messages defined in the
+ * <code>ShellListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ShellListener
+ * @see #removeShellListener
+ */
+public void addShellListener (ShellListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Close,typedListener);
+ addListener (SWT.Iconify,typedListener);
+ addListener (SWT.Deiconify,typedListener);
+ addListener (SWT.Activate, typedListener);
+ addListener (SWT.Deactivate, typedListener);
+}
+
+void addWidget () {
+ if ((style & SWT.ON_TOP) != 0) return;
+ if (parent != null) {
+ if ((parent.style & SWT.ON_TOP) != 0) return;
+ OS.Window_Owner (shellHandle, ((Shell)parent).shellHandle);
+ }
+}
+
+void bringToTop () {
+ if ((style & SWT.ON_TOP) != 0) return;
+ OS.Window_Activate (shellHandle);
+}
+
+void center () {
+ if (parent == null) return;
+ Rectangle rect = getBounds ();
+ Rectangle parentRect = display.map (parent, null, parent.getClientArea());
+ int x = Math.max (parentRect.x, parentRect.x + (parentRect.width - rect.width) / 2);
+ int y = Math.max (parentRect.y, parentRect.y + (parentRect.height - rect.height) / 2);
+ Rectangle monitorRect = parent.getMonitor ().getClientArea();
+ if (x + rect.width > monitorRect.x + monitorRect.width) {
+ x = Math.max (monitorRect.x, monitorRect.x + monitorRect.width - rect.width);
+ } else {
+ x = Math.max (x, monitorRect.x);
+ }
+ if (y + rect.height > monitorRect.y + monitorRect.height) {
+ y = Math.max (monitorRect.y, monitorRect.y + monitorRect.height - rect.height);
+ } else {
+ y = Math.max (y, monitorRect.y);
+ }
+ setLocation (x, y);
+}
+
+void checkOpened () {
+ if (!opened) resized = false;
+}
+
+/**
+ * Requests that the window manager close the receiver in
+ * the same way it would be closed when the user clicks on
+ * the "close box" or performs some other platform specific
+ * key or mouse combination that indicates the window
+ * should be removed.
+ *
+ * @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 SWT#Close
+ * @see #dispose
+ */
+public void close () {
+ checkWidget ();
+ closeWidget ();
+}
+
+void createHandle () {
+ if (shellHandle != 0) {
+ scrolledHandle = OS.ContentControl_Content (shellHandle);
+ if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ int children = OS.Panel_Children (scrolledHandle);
+ handle = OS.UIElementCollection_default (children, 0);
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (children);
+ return;
+ }
+ state |= CANVAS;
+ if ((style & SWT.ON_TOP) != 0) {
+ shellHandle = OS.gcnew_Popup ();
+ if (shellHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.NO_TRIM) != 0) OS.Popup_AllowsTransparency (shellHandle, true);
+ OS.KeyboardNavigation_SetTabNavigation (shellHandle, OS.KeyboardNavigationMode_None);
+ boolean scrolled = (style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0;
+ createHandle (scrolled, true);
+ OS.Popup_Child (shellHandle, super.topHandle());
+ OS.Popup_IsOpen (shellHandle, true);
+ OS.Popup_IsOpen (shellHandle, false);
+ return;
+ }
+ shellHandle = OS.gcnew_Window();
+ if (shellHandle == 0) error(SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.NO_TRIM) != 0) OS.Window_AllowsTransparency (shellHandle, true);
+
+ /*
+ * Feature in WPF. ...
+ */
+ OS.Window_ShowInTaskbar (shellHandle, false);
+ OS.Window_ResizeMode (shellHandle, OS.ResizeMode_NoResize);
+ OS.Window_WindowStyle (shellHandle, OS.WindowStyle_None);
+ OS.FrameworkElement_Width (shellHandle, 0);
+ OS.FrameworkElement_Height (shellHandle, 0);
+ OS.Window_Show (shellHandle);
+ OS.Window_Hide (shellHandle);
+ Rectangle bounds = getMonitor ().getBounds ();
+ OS.FrameworkElement_Width (shellHandle, bounds.width * 5 / 8);
+ OS.FrameworkElement_Height (shellHandle, bounds.height * 5 / 8);
+
+ int windowStyle = OS.WindowStyle_None, resizeMode = OS.ResizeMode_NoResize;
+ if ((style & SWT.NO_TRIM) == 0) {
+ if ((style & SWT.TOOL) != 0) {
+ windowStyle = OS.WindowStyle_ToolWindow;
+ } else if ((style & SWT.SHELL_TRIM) != 0) {
+ windowStyle = OS.WindowStyle_SingleBorderWindow;
+ }
+ if ((style & SWT.RESIZE) != 0) {
+ resizeMode |= OS.ResizeMode_CanResize;
+ }
+ }
+ OS.Window_ShowInTaskbar (shellHandle, parent == null);
+ OS.Window_ResizeMode (shellHandle, resizeMode);
+ OS.Window_WindowStyle (shellHandle, windowStyle);
+ OS.KeyboardNavigation_SetTabNavigation (shellHandle, OS.KeyboardNavigationMode_None);
+
+ boolean scrolled = (style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0;
+ createHandle (scrolled, true);
+ OS.ContentControl_Content (shellHandle, super.topHandle());
+}
+
+void createWidget() {
+ super.createWidget ();
+ display.addShell (this);
+}
+
+public Rectangle computeTrim (int x, int y, int width, int height) {
+ checkWidget ();
+ if ((style & SWT.ON_TOP) != 0) return new Rectangle (x, y, width, height);
+ updateLayout (shellHandle);
+ int clientX = (int) OS.Window_Left (shellHandle);
+ int clientY = (int) OS.Window_Top (shellHandle);
+ int w = (int) OS.FrameworkElement_ActualWidth (shellHandle);
+ int h = (int) OS.FrameworkElement_ActualHeight (shellHandle);
+ int clientWidth = (int) OS.FrameworkElement_ActualWidth (handle);
+ int clientHeight = (int) OS.FrameworkElement_ActualHeight (handle);
+ int point = OS.gcnew_Point (clientX, clientY);
+ int result = OS.Visual_PointFromScreen (shellHandle, point);
+ OS.GCHandle_Free (point);
+ clientX = -(int) OS.Point_X (result);
+ clientY = -(int) OS.Point_Y (result);
+ OS.GCHandle_Free (result);
+ x -= clientX;
+ y -= clientY;
+ width += (w - clientWidth);
+ height += (h - clientHeight);
+ return new Rectangle (x, y, width, height);
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (shellHandle);
+}
+
+
+void destroyWidget () {
+ if (shellHandle != 0 && !closing) {
+ if ((style & SWT.ON_TOP) != 0) {
+ OS.Popup_IsOpen (shellHandle, false);
+ } else {
+ OS.Window_Close (shellHandle);
+ }
+ }
+ releaseHandle ();
+}
+
+public void dispose () {
+ /*
+ * This code is intentionally commented. On some
+ * platforms, the owner window is repainted right
+ * away when a dialog window exits. This behavior
+ * is currently unspecified.
+ */
+// /*
+// * Note: It is valid to attempt to dispose a widget
+// * more than once. If this happens, fail silently.
+// */
+// if (!isValidWidget ()) return;
+// if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+// Display oldDisplay = display;
+ super.dispose ();
+ // widget is disposed at this point
+// if (oldDisplay != null) oldDisplay.update ();
+}
+
+Control findBackgroundControl () {
+ return background != -1 || backgroundImage != null ? this : null;
+}
+
+Control findThemeControl () {
+ return null;
+}
+
+/**
+ * If the receiver is visible, moves it to the top of the
+ * drawing order for the display on which it was created
+ * (so that all other shells on that display, which are not
+ * the receiver's children will be drawn behind it) and forces
+ * the window manager to make the shell active.
+ *
+ * @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>
+ *
+ * @since 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void forceActive () {
+ checkWidget ();
+ if(!isVisible()) return;
+ if ((style & SWT.ON_TOP) != 0) return;
+// OS.SetForegroundWindow (handle);
+ OS.Window_Activate (shellHandle);
+}
+
+/**
+ * Returns the receiver's alpha value. The alpha value
+ * is between 0 (transparent) and 255 (opaque).
+ *
+ * @return the alpha value
+ *
+ * @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>
+ *
+ * @since 3.4
+ */
+public int getAlpha () {
+ checkWidget ();
+ return 255;
+}
+
+public Rectangle getBounds () {
+ checkWidget ();
+ int x, y;
+ if ((style & SWT.ON_TOP) != 0) {
+ x = (int) OS.Popup_HorizontalOffset (shellHandle);
+ y = (int) OS.Popup_VerticalOffset (shellHandle);
+ } else {
+ x = (int) OS.Window_Left (shellHandle);
+ y = (int) OS.Window_Top (shellHandle);
+ }
+ int renderSize = OS.UIElement_RenderSize (shellHandle);
+ int width = (int) OS.Size_Width (renderSize);
+ int height = (int) OS.Size_Height (renderSize);
+ OS.GCHandle_Free (renderSize);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is currently
+ * in fullscreen state, and false otherwise.
+ * <p>
+ *
+ * @return the fullscreen 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>
+ *
+ * @since 3.4
+ */
+public boolean getFullScreen() {
+ checkWidget ();
+ return fullScreen;
+}
+
+/**
+ * Returns the receiver's input method editor mode. This
+ * will be the result of bitwise OR'ing together one or
+ * more of the following constants defined in class
+ * <code>SWT</code>:
+ * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
+ * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
+ *
+ * @return the IME mode
+ *
+ * @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 SWT
+ */
+public int getImeInputMode () {
+ checkWidget ();
+ //TODO
+ return SWT.ROMAN;
+}
+
+public Point getLocation () {
+ checkWidget ();
+ int x, y;
+ if ((style & SWT.ON_TOP) != 0) {
+ x = (int) OS.Popup_HorizontalOffset (shellHandle);
+ y = (int) OS.Popup_VerticalOffset (shellHandle);
+ } else {
+ x = (int) OS.Window_Left (shellHandle);
+ y = (int) OS.Window_Top (shellHandle);
+ }
+ return new Point (x, y);
+}
+
+public boolean getMaximized () {
+ checkWidget ();
+ return !fullScreen && super.getMaximized ();
+}
+
+/**
+ * Returns a point describing the minimum receiver's size. The
+ * x coordinate of the result is the minimum width of the receiver.
+ * The y coordinate of the result is the minimum height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Point getMinimumSize () {
+ checkWidget ();
+// int width = Math.max (0, minWidth);
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+// }
+// int height = Math.max (0, minHeight);
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// if ((style & SWT.RESIZE) != 0) {
+// height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+// } else {
+// RECT rect = new RECT ();
+// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits1, false, bits2);
+// height = Math.max (height, rect.bottom - rect.top);
+// }
+// }
+ int width = (int) OS.FrameworkElement_MinWidth (shellHandle);
+ int height = (int) OS.FrameworkElement_MinHeight (shellHandle);
+ return new Point (width, height);
+}
+
+/**
+ * Gets the receiver's modified state.
+ *
+ * </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>
+ *
+ * @since 3.5
+ */
+public boolean getModified () {
+ checkWidget ();
+ return modified;
+}
+
+/**
+ * Returns the region that defines the shape of the shell,
+ * or null if the shell has the default shape.
+ *
+ * @return the region that defines the shape of the shell (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>
+ *
+ * @since 3.0
+ *
+ */
+public Region getRegion () {
+ /* This method is needed for the @since 3.0 Javadoc tag*/
+ checkWidget ();
+ return region;
+}
+
+public Shell getShell () {
+ checkWidget ();
+ return this;
+}
+
+public boolean getVisible () {
+ checkWidget ();
+ if ((style & SWT.ON_TOP) != 0)return OS.Popup_IsOpen (shellHandle);
+ return super.getVisible ();
+}
+
+/**
+ * Returns an array containing all shells which are
+ * descendants of the receiver.
+ * <p>
+ * @return the dialog shells
+ *
+ * @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 Shell [] getShells () {
+ checkWidget ();
+ int count = 0;
+ Shell [] shells = display.getShells ();
+ for (int i=0; i<shells.length; i++) {
+ Control shell = shells [i];
+ do {
+ shell = shell.parent;
+ } while (shell != null && shell != this);
+ if (shell == this) count++;
+ }
+ int index = 0;
+ Shell [] result = new Shell [count];
+ for (int i=0; i<shells.length; i++) {
+ Control shell = shells [i];
+ do {
+ shell = shell.parent;
+ } while (shell != null && shell != this);
+ if (shell == this) {
+ result [index++] = shells [i];
+ }
+ }
+ return result;
+}
+
+Composite findDeferredControl () {
+ return layoutCount > 0 ? this : null;
+}
+
+public boolean isEnabled () {
+ checkWidget ();
+ return getEnabled ();
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
+ OS.FrameworkElement_SizeChanged (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ if ((style & SWT.ON_TOP) != 0) {
+ handler = OS.gcnew_EventHandler (jniRef, "HandleClosed");
+ OS.Popup_Closed (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_KeyboardFocusChangedEventHandler (jniRef, "HandlePreviewGotKeyboardFocusActivate");
+ OS.UIElement_PreviewGotKeyboardFocus (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_KeyboardFocusChangedEventHandler (jniRef, "HandleLostKeyboardFocusDeactivate");
+ OS.UIElement_LostKeyboardFocus (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ } else {
+ handler = OS.gcnew_CancelEventHandler (jniRef, "HandleClosing");
+ OS.Window_Closing (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_EventHandler (jniRef, "HandleActivated");
+ OS.Window_Activated (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_EventHandler (jniRef, "HandleDeactivated");
+ OS.Window_Deactivated (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_EventHandler (jniRef, "HandleLocationChanged");
+ OS.Window_LocationChanged (shellHandle, handler);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+void HandleActivated (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Activate);
+ if (isDisposed ()) return;
+ restoreFocus ();
+}
+
+void HandleClosed (int sender, int e) {
+ if (!checkEvent (e)) return;
+ closing = true;
+ sendEvent (SWT.Close);
+ closing = false;
+}
+
+void HandleClosing (int sender, int e) {
+ if (!checkEvent (e)) return;
+ closing = true;
+ boolean doit = false;
+ if (isEnabled ()) {
+ Event event = new Event ();
+ sendEvent (SWT.Close, event);
+ doit = event.doit || isDisposed ();
+ }
+ if (doit) {
+ /**
+ * Bug in WPF. When a window has more than
+ * two child windows, and all the the child
+ * windows are closed, the parent window is not
+ * brought to the front. The work around is to
+ * null out the Owner property of the child window
+ * before disposing it.
+ */
+ if (shellHandle != 0) OS.Window_Owner (shellHandle, 0);
+ if (!isDisposed ()) release (false);
+ } else {
+ OS.CancelEventArgs_Cancel (e, true);
+ }
+ closing = false;
+}
+
+void HandleDeactivated (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Deactivate);
+ if (isDisposed ()) return;
+ saveFocus ();
+}
+
+void HandleLocationChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int x = (int) OS.Window_Left (shellHandle);
+ int y = (int) OS.Window_Top (shellHandle);
+ if (!moved || oldX != x || oldY != y) {
+ moved = true;
+ oldX = x;
+ oldY = y;
+ sendEvent (SWT.Move);
+ }
+}
+
+void HandleLostKeyboardFocusDeactivate (int sender, int e) {
+ if (isDisposed ()) return;
+ if (OS.UIElement_IsKeyboardFocusWithin (handle)) return;
+ sendEvent (SWT.Deactivate);
+}
+
+void HandleMouseLeave (int sender, int e) {
+ super.HandleMouseLeave (sender, e);
+ if (!checkEvent (e)) return;
+ display.mouseControl = null;
+}
+
+void HandlePreviewGotKeyboardFocusActivate (int sender, int e) {
+ if (isDisposed ()) return;
+ if (!OS.UIElement_IsKeyboardFocusWithin (handle)) return;
+ sendEvent (SWT.Activate);
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int width = (int) OS.FrameworkElement_ActualWidth (shellHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (shellHandle);
+ if (!resized || oldWidth != width || oldHeight != height) {
+ resized = true;
+ oldWidth = width;
+ oldHeight = height;
+ sendEvent (SWT.Resize);
+ if (isDisposed ()) return;
+ if (layout != null) {
+ markLayout (false, false);
+ updateLayout (false, false);
+ }
+ }
+}
+
+/**
+ * Moves the receiver to the top of the drawing order for
+ * the display on which it was created (so that all other
+ * shells on that display, which are not the receiver's
+ * children will be drawn behind it), marks it visible,
+ * sets the focus and asks the window manager to make the
+ * shell active.
+ *
+ * @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 Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#setActive
+ * @see Shell#forceActive
+ */
+public void open () {
+ checkWidget ();
+ bringToTop ();
+ if (isDisposed ()) return;
+ setVisible (true);
+ if (isDisposed ()) return;
+ if (!restoreFocus () && !traverseGroup (true)) setFocus ();
+}
+
+public boolean print (GC gc) {
+ checkWidget ();
+ if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ return false;
+}
+
+void register () {
+ super.register ();
+ display.addWidget (shellHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ Shell [] shells = getShells ();
+ for (int i=0; i<shells.length; i++) {
+ Shell shell = shells [i];
+ if (shell != null && !shell.isDisposed ()) {
+ shell.release ((style & SWT.ON_TOP) != 0);
+ }
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (shellHandle != 0) OS.GCHandle_Free (shellHandle);
+ shellHandle = 0;
+}
+
+void releaseParent () {
+ /* Do nothing */
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ display.clearModal (this);
+ display.removeShell (this);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when operations are performed on the receiver.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ShellListener
+ * @see #addShellListener
+ */
+public void removeShellListener (ShellListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Close, listener);
+ eventTable.unhook (SWT.Iconify,listener);
+ eventTable.unhook (SWT.Deiconify,listener);
+ eventTable.unhook (SWT.Activate, listener);
+ eventTable.unhook (SWT.Deactivate, listener);
+}
+
+/**
+ * If the receiver is visible, moves it to the top of the
+ * drawing order for the display on which it was created
+ * (so that all other shells on that display, which are not
+ * the receiver's children will be drawn behind it) and asks
+ * the window manager to make the shell active
+ *
+ * @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>
+ *
+ * @since 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void setActive () {
+ checkWidget ();
+ if(!isVisible()) return;
+ bringToTop ();
+ // widget could be disposed at this point
+}
+
+void setActiveControl (Control control) {
+ if (control != null && control.isDisposed ()) control = null;
+ if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
+ if (lastActive == control) return;
+
+ /*
+ * Compute the list of controls to be activated and
+ * deactivated by finding the first common parent
+ * control.
+ */
+ Control [] activate = (control == null) ? new Control [0] : control.getPath ();
+ Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
+ lastActive = control;
+ int index = 0, length = Math.min (activate.length, deactivate.length);
+ while (index < length) {
+ if (activate [index] != deactivate [index]) break;
+ index++;
+ }
+
+ /*
+ * It is possible (but unlikely), that application
+ * code could have destroyed some of the widgets. If
+ * this happens, keep processing those widgets that
+ * are not disposed.
+ */
+ for (int i=deactivate.length-1; i>=index; --i) {
+ if (!deactivate [i].isDisposed ()) {
+ deactivate [i].sendEvent (SWT.Deactivate);
+ }
+ }
+ for (int i=activate.length-1; i>=index; --i) {
+ if (!activate [i].isDisposed ()) {
+ activate [i].sendEvent (SWT.Activate);
+ }
+ }
+}
+
+/**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <p>
+ * This operation requires the operating system's advanced
+ * widgets subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param alpha the alpha value
+ *
+ * @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>
+ *
+ * @since 3.4
+ */
+public void setAlpha (int alpha) {
+ checkWidget ();
+ /* Not implemented */
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ if (fullScreen) setFullScreen (false);
+ int result = 0;
+ if ((flags & MOVED) != 0) {
+ int currentX, currentY;
+ if ((style & SWT.ON_TOP) != 0) {
+ currentX = (int) OS.Popup_HorizontalOffset (shellHandle);
+ currentY = (int) OS.Popup_VerticalOffset (shellHandle);
+ } else {
+ currentX = (int) OS.Window_Left (shellHandle);
+ currentY = (int) OS.Window_Top (shellHandle);
+ }
+ if (currentX != x || currentY != y) {
+ moved = true;
+ oldX = x;
+ oldY = currentY;
+ if ((style & SWT.ON_TOP) != 0) {
+ OS.Popup_HorizontalOffset (shellHandle, x);
+ oldY = y;
+ OS.Popup_VerticalOffset (shellHandle, y);
+ } else {
+ OS.Window_Left (shellHandle, x);
+ oldY = y;
+ OS.Window_Top (shellHandle, y);
+ }
+ sendEvent (SWT.Move);
+ if (isDisposed ()) return 0;
+ result |= MOVED;
+ }
+ }
+ if ((flags & RESIZED) != 0) {
+ int currentWidth = (int) OS.FrameworkElement_ActualWidth (shellHandle);
+ int currentHeight = (int) OS.FrameworkElement_ActualHeight (shellHandle);
+ if (currentWidth != width || currentHeight != height) {
+ resized = true;
+ oldWidth = width;
+ oldHeight = currentHeight;
+ OS.FrameworkElement_Width (shellHandle, width);
+ oldHeight = height;
+ OS.FrameworkElement_Height (shellHandle, height);
+ sendEvent (SWT.Resize);
+ if (isDisposed ()) return 0;
+ result |= RESIZED;
+ if (layout != null) {
+ markLayout (false, false);
+ updateLayout (false, false);
+ }
+ }
+ }
+ return result;
+}
+
+void setClipping () {
+
+}
+
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ if (enabled == getEnabled ()) return;
+ super.setEnabled (enabled);
+ if ((style & SWT.ON_TOP) != 0) return;
+ if (enabled && OS.Window_IsActive (shellHandle)) {
+ if (!restoreFocus ()) traverseGroup (true);
+ }
+}
+
+/**
+ * Sets the full screen state of the receiver.
+ * If the argument is <code>true</code> causes the receiver
+ * to switch to the full screen state, and if the argument is
+ * <code>false</code> and the receiver was previously switched
+ * into full screen state, causes the receiver to switch back
+ * to either the maximized or normal states.
+ * <p>
+ * Note: The result of intermixing calls to <code>setFullScreen(true)</code>,
+ * <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 fullScreen the new fullscreen 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>
+ *
+ * @since 3.4
+ */
+public void setFullScreen (boolean fullScreen) {
+ checkWidget ();
+ if (this.fullScreen == fullScreen) return;
+ if(fullScreen) {
+ oldWindowStyle = OS.Window_WindowStyle (shellHandle);
+ oldWindowState = OS.Window_WindowState (shellHandle);
+ boolean visible = getVisible ();
+ OS.Window_Hide (shellHandle);
+ OS.Window_WindowStyle (shellHandle, OS.WindowStyle_None);
+ if (visible) OS.Window_Show (shellHandle);
+ OS.Window_WindowState (shellHandle, OS.WindowState_Maximized);
+ } else {
+ OS.Window_WindowStyle (shellHandle, oldWindowStyle);
+ OS.Window_WindowState (shellHandle, oldWindowState);
+ oldWindowState = 0;
+ oldWindowStyle = 0;
+ }
+ this.fullScreen = fullScreen;
+}
+
+/**
+ * Sets the input method editor mode to the argument which
+ * should be the result of bitwise OR'ing together one or more
+ * of the following constants defined in class <code>SWT</code>:
+ * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
+ * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
+ *
+ * @param mode the new IME mode
+ *
+ * @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 SWT
+ */
+public void setImeInputMode (int mode) {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the arguments.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param width the new minimum width for the receiver
+ * @param height the new minimum height for the receiver
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public void setMinimumSize (int width, int height) {
+ checkWidget ();
+ int widthLimit = 0, heightLimit = 0;
+ int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+ if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
+// if ((style & SWT.RESIZE) != 0) {
+// heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
+// } else {
+// RECT rect = new RECT ();
+// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits1, false, bits2);
+// heightLimit = rect.bottom - rect.top;
+// }
+ }
+ int minWidth = Math.max (widthLimit, width);
+ int minHeight = Math.max (heightLimit, height);
+ OS.FrameworkElement_MinWidth(shellHandle, minWidth);
+ OS.FrameworkElement_MinHeight(shellHandle, minHeight);
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the argument.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param size the new minimum size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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>
+ *
+ * @since 3.1
+ */
+public void setMinimumSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setMinimumSize (size.x, size.y);
+}
+
+/**
+ * Sets the receiver's modified state as specified by the argument.
+ *
+ * @param modified the new modified state for the receiver
+ *
+ * </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>
+ *
+ * @since 3.5
+ */
+public void setModified (boolean modified) {
+ checkWidget ();
+ this.modified = modified;
+}
+
+void setParent () {
+ /* Do nothing. Not necessary for Shells */
+}
+
+/**
+ * Sets the shape of the shell to the region specified
+ * by the argument. When the argument is null, the
+ * default shape of the shell is restored. The shell
+ * must be created with the style SWT.NO_TRIM in order
+ * to specify a region.
+ *
+ * @param region the region that defines the shape of the shell (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</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>
+ *
+ * @since 3.0
+ *
+ */
+public void setRegion (Region region) {
+ checkWidget ();
+ if ((style & SWT.NO_TRIM) == 0) return;
+ super.setRegion (region);
+}
+
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if (getVisible () == visible) return;
+
+ int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+ if ((style & mask) != 0) {
+ if (visible) {
+ display.setModalShell (this);
+// Control control = display._getFocusControl ();
+// if (control != null && !control.isActive ()) {
+// bringToTop ();
+// if (isDisposed ()) return;
+// }
+// int hwndShell = OS.GetActiveWindow ();
+// if (hwndShell == 0) {
+// if (parent != null) hwndShell = parent.handle;
+// }
+// if (hwndShell != 0) {
+// OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
+// }
+// OS.ReleaseCapture ();
+ } else {
+ display.clearModal (this);
+ }
+ } else {
+ updateModal ();
+ }
+
+ if (visible) {
+ if (center && !moved) {
+ center ();
+ if (isDisposed ()) return;
+ }
+ if ((style & SWT.ON_TOP) != 0) {
+ OS.Popup_IsOpen (shellHandle, visible);
+ } else {
+ OS.Window_Show (shellHandle);
+ }
+
+ opened = true;
+ if (!moved) {
+ moved = true;
+ Point location = getLocation();
+ oldX = location.x;
+ oldY = location.y;
+ sendEvent (SWT.Move);
+ if (isDisposed ()) return;
+ }
+ if (!resized) {
+ resized = true;
+ Point size = getSize ();
+ oldWidth = size.x;// - trimWidth ();
+ oldHeight = size.y;// - trimHeight ();
+ sendEvent (SWT.Resize);
+ if (isDisposed ()) return;
+ if (layout != null) {
+ markLayout (false, false);
+ updateLayout (false, false);
+ }
+ }
+
+ } else {
+ if (!closing) {
+ if ((style & SWT.ON_TOP) != 0) {
+ OS.Popup_IsOpen (shellHandle, visible);
+ } else {
+ OS.Window_Hide (shellHandle);
+ }
+ }
+ }
+}
+
+int topHandle () {
+ return shellHandle;
+}
+
+//boolean translateAccelerator (MSG msg) {
+// if (!isEnabled () || !isActive ()) return false;
+// if (menuBar != null && !menuBar.isEnabled ()) return false;
+// return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
+//}
+
+boolean traverseEscape () {
+ if (parent == null) return false;
+ if (!isVisible () || !isEnabled ()) return false;
+ close ();
+ return true;
+}
+
+void updateModal () {
+ int source = OS.PresentationSource_FromVisual (handle);
+ if (source != 0) {
+ int hwnd = OS.HwndSource_Handle (source);
+ Win32.EnableWindow (OS.IntPtr_ToInt32 (hwnd), isActive ());
+ OS.GCHandle_Free (hwnd);
+ OS.GCHandle_Free (source);
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Slider.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Slider.java
new file mode 100644
index 0000000000..c806643d73
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Slider.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ * <p>
+ * At any given moment, a given slider will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the slider represents (that is, between its
+ * <em>minimum</em> and <em>maximum</em> values).
+ * </p><p>
+ * Typically, sliders will be made up of five areas:
+ * <ol>
+ * <li>an arrow button for decrementing the value</li>
+ * <li>a page decrement area for decrementing the value by a larger amount</li>
+ * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
+ * <li>a page increment area for incrementing the value by a larger amount</li>
+ * <li>an arrow button for incrementing the value</li>
+ * </ol>
+ * Based on their style, sliders are either <code>HORIZONTAL</code>
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or <code>VERTICAL</code>
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ * </p><p>
+ * On some platforms, the size of the slider's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the slider will not change.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ScrollBar
+ * @see <a href="http://www.eclipse.org/swt/snippets/#slider">Slider snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Slider extends Control {
+ boolean ignoreFocus;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Slider (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
+ * <code>SWT.NONE</code> - for the end of a drag.
+ * <code>SWT.DRAG</code>.
+ * <code>SWT.HOME</code>.
+ * <code>SWT.END</code>.
+ * <code>SWT.ARROW_DOWN</code>.
+ * <code>SWT.ARROW_UP</code>.
+ * <code>SWT.PAGE_DOWN</code>.
+ * <code>SWT.PAGE_UP</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's value
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ int border = getBorderWidth ();
+ int width = border * 2, height = border * 2;
+ if ((style & SWT.HORIZONTAL) != 0) {
+ width += OS.SystemParameters_HorizontalScrollBarButtonWidth () * 10;
+ height += OS.SystemParameters_HorizontalScrollBarHeight ();
+ } else {
+ width += OS.SystemParameters_VerticalScrollBarWidth ();
+ height += OS.SystemParameters_VerticalScrollBarButtonHeight () * 10;
+ }
+ if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
+ if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
+ return new Point (width, height);
+}
+
+void createHandle () {
+ handle = OS.gcnew_ScrollBar ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.HORIZONTAL) != 0) OS.ScrollBar_Orientation (handle, OS.Orientation_Horizontal);
+ OS.RangeBase_Maximum (handle, 100);
+ OS.RangeBase_LargeChange (handle, 10);
+ OS.RangeBase_SmallChange (handle, 1);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @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 int getIncrement () {
+ checkWidget ();
+ return (int) OS.RangeBase_SmallChange (handle);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @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 int getMaximum () {
+ checkWidget ();
+ int maximum = (int) OS.RangeBase_Maximum (handle);
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ return maximum + viewSize;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @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 int getMinimum () {
+ checkWidget ();
+ return (int) OS.RangeBase_Minimum (handle);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @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 int getPageIncrement () {
+ checkWidget ();
+ return (int) OS.RangeBase_LargeChange (handle);
+}
+
+/**
+ * Returns the 'selection', which is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @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 int getSelection () {
+ checkWidget ();
+ return (int) OS.RangeBase_Value (handle);
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @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 int getThumb () {
+ checkWidget ();
+ return (int) OS.ScrollBar_ViewportSize (handle);
+}
+
+void HandleScroll (int sender, int e) {
+ if (!checkEvent (e)) return;
+ Event event = new Event ();
+ switch (OS.ScrollEventArgs_ScrollEventType (e)) {
+ case OS.ScrollEventType_EndScroll: return;
+ case OS.ScrollEventType_ThumbPosition: event.detail = SWT.NONE; break;
+ case OS.ScrollEventType_ThumbTrack: event.detail = SWT.DRAG; break;
+ case OS.ScrollEventType_First: event.detail = SWT.HOME; break;
+ case OS.ScrollEventType_Last: event.detail = SWT.END; break;
+ case OS.ScrollEventType_LargeIncrement: event.detail = SWT.PAGE_DOWN; break;
+ case OS.ScrollEventType_LargeDecrement: event.detail = SWT.PAGE_UP; break;
+ case OS.ScrollEventType_SmallIncrement: event.detail = SWT.ARROW_DOWN; break;
+ case OS.ScrollEventType_SmallDecrement: event.detail = SWT.ARROW_UP; break;
+ }
+ postEvent (SWT.Selection, event);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_ScrollEventHandler (jniRef, "HandleScroll");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ScrollBar_Scroll (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @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 setIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ OS.RangeBase_SmallChange (handle, value);
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @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 setMaximum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ if (value <= minimum) return;
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ if (value - minimum < viewSize) {
+ viewSize = value - minimum;
+ OS.ScrollBar_ViewportSize (handle, viewSize);
+ }
+ OS.RangeBase_Maximum (handle, value - viewSize);
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @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 setMinimum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ int maximum = (int) OS.RangeBase_Maximum (handle) + viewSize;
+ if (value >= maximum) return;
+ if (maximum - value < viewSize) {
+ viewSize = maximum - value;
+ OS.RangeBase_Maximum (handle, maximum - viewSize);
+ OS.ScrollBar_ViewportSize (handle, viewSize);
+ }
+ OS.RangeBase_Minimum (handle, value);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @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 setPageIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ OS.RangeBase_LargeChange (handle, value);
+}
+
+/**
+ * Sets the 'selection', which is the receiver's
+ * value, to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @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 setSelection (int value) {
+ checkWidget ();
+ OS.RangeBase_Value (handle, value);
+}
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values. This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @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 setThumb (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ int minimum = (int) OS.RangeBase_Minimum (handle);
+ int viewSize = (int) OS.ScrollBar_ViewportSize (handle);
+ int maximum = (int) OS.RangeBase_Maximum (handle) + viewSize;
+ value = Math.min (value, maximum - minimum);
+ OS.RangeBase_Maximum (handle, maximum - value);
+ OS.ScrollBar_ViewportSize (handle, value);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @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 setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+ checkWidget();
+ if (minimum < 0) return;
+ if (maximum < 0) return;
+ if (thumb < 1) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ thumb = Math.min (thumb, maximum - minimum);
+ OS.RangeBase_Minimum (handle, minimum);
+ OS.RangeBase_Maximum (handle, maximum - thumb);
+ OS.ScrollBar_ViewportSize (handle, thumb);
+ OS.RangeBase_Value (handle, selection);
+ OS.RangeBase_LargeChange (handle, pageIncrement);
+ OS.RangeBase_SmallChange (handle, increment);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Spinner.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Spinner.java
new file mode 100644
index 0000000000..96a1f83c29
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Spinner.java
@@ -0,0 +1,991 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that allow the user to enter and modify numeric
+ * values.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, Modify, Verify</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#spinner">Spinner snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Spinner extends Composite {
+ int textHandle, upHandle, downHandle;
+ int increment, pageIncrement, digits, max, min, value;
+
+ /**
+ * the operating system limit for the number of characters
+ * that the text field in an instance of this class can hold
+ *
+ * @since 3.4
+ */
+ public static final int LIMIT;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ static {
+ LIMIT = 0x7FFFFFFF;
+ }
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#READ_ONLY
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Spinner (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+Control [] _getChildren () {
+ return new Control [0];
+}
+
+static int checkStyle (int style) {
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+int backgroundHandle () {
+ return textHandle;
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ return super.computeSize (handle, wHint, hHint, changed);
+}
+
+int createArrow (int direction) {
+ int geometry = OS.gcnew_StreamGeometry ();
+ int context = OS.StreamGeometry_Open (geometry);
+ int start = 0, point = 0, end = 0;
+ switch (direction) {
+ case SWT.DOWN:
+ start = OS.gcnew_Point (0, 0);
+ point = OS.gcnew_Point (3, 3);
+ end = OS.gcnew_Point (6, 0);
+ break;
+ case SWT.UP:
+ start = OS.gcnew_Point (0, 3);
+ point = OS.gcnew_Point (3, 0);
+ end = OS.gcnew_Point (6, 3);
+ break;
+ }
+ OS.StreamGeometryContext_BeginFigure (context, start, true, true);
+ OS.StreamGeometryContext_LineTo (context, point, true, true);
+ OS.StreamGeometryContext_LineTo (context, end, true, true);
+ OS.StreamGeometryContext_Close (context);
+ int path = OS.gcnew_Path ();
+ OS.Path_Data (path, geometry);
+ int padding = OS.gcnew_Thickness (3, 0, 3, 0);
+ OS.FrameworkElement_Margin (path, padding);
+ int brush = OS.Brushes_Black ();
+ OS.Path_Fill (path, brush);
+ OS.FrameworkElement_HorizontalAlignment (path, OS.HorizontalAlignment_Center);
+ OS.FrameworkElement_VerticalAlignment (path, OS.VerticalAlignment_Center);
+ OS.GCHandle_Free (padding);
+ OS.GCHandle_Free (start);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (end);
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (context);
+ OS.GCHandle_Free (geometry);
+ return path;
+}
+
+void createHandle () {
+ handle = OS.gcnew_Grid ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ int row0 = OS.gcnew_RowDefinition ();
+ int row1 = OS.gcnew_RowDefinition ();
+ int rows = OS.Grid_RowDefinitions (handle);
+ OS.RowDefinitionCollection_Add (rows, row0);
+ OS.RowDefinitionCollection_Add (rows, row1);
+ int col0 = OS.gcnew_ColumnDefinition ();
+ int col1 = OS.gcnew_ColumnDefinition ();
+ int columns = OS.Grid_ColumnDefinitions (handle);
+ OS.ColumnDefinitionCollection_Add (columns, col0);
+ OS.ColumnDefinitionCollection_Add (columns, col1);
+ int gridChildren = OS.Panel_Children (handle);
+ textHandle = OS.gcnew_TextBox ();
+ if (textHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Grid_SetRowSpan (textHandle, 2);
+ OS.UIElementCollection_Add (gridChildren, textHandle);
+ if ((style & SWT.READ_ONLY) != 0) OS.TextBoxBase_IsReadOnly (textHandle, true);
+ upHandle = OS.gcnew_RepeatButton ();
+ if (upHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ int upArrow = createArrow (SWT.UP);
+ OS.ContentControl_Content (upHandle, upArrow);
+ OS.Grid_SetColumn (upHandle, 1);
+ OS.UIElementCollection_Add (gridChildren, upHandle);
+ downHandle = OS.gcnew_RepeatButton ();
+ if (downHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ int downArrow = createArrow (SWT.DOWN);
+ OS.ContentControl_Content (downHandle, downArrow);
+ OS.Grid_SetColumn (downHandle, 1);
+ OS.Grid_SetRow (downHandle, 1);
+ OS.UIElementCollection_Add (gridChildren, downHandle);
+ int colWidth0 = OS.gcnew_GridLength (10, OS.GridUnitType_Star);
+ OS.ColumnDefinition_Width(col0, colWidth0);
+ int colWidth1 = OS.gcnew_GridLength (1, OS.GridUnitType_Auto);
+ OS.ColumnDefinition_Width (col1, colWidth1);
+ OS.GCHandle_Free (colWidth0);
+ OS.GCHandle_Free (colWidth1);
+ OS.GCHandle_Free (upArrow);
+ OS.GCHandle_Free (downArrow);
+ OS.GCHandle_Free (row0);
+ OS.GCHandle_Free (row1);
+ OS.GCHandle_Free (rows);
+ OS.GCHandle_Free (col0);
+ OS.GCHandle_Free (col1);
+ OS.GCHandle_Free (columns);
+ OS.GCHandle_Free (gridChildren);
+}
+
+void createWidget () {
+ super.createWidget();
+ increment = 1;
+ pageIncrement = 10;
+ digits = 0;
+ max = 100;
+ value = 0;
+ int ptr = createDotNetString ("0", false);
+ OS.TextBox_Text (textHandle, ptr);
+ OS.GCHandle_Free (ptr);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is not called for texts.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #removeVerifyListener
+ */
+void addVerifyListener (VerifyListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @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 copy () {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @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 cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ //TODO
+}
+
+/**
+ * Returns the number of decimal places used by the receiver.
+ *
+ * @return the digits
+ *
+ * @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 int getDigits () {
+ checkWidget ();
+ return digits;
+}
+
+String getDecimalSeparator () {
+ return ".";
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed.
+ *
+ * @return the increment
+ *
+ * @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 int getIncrement () {
+ checkWidget ();
+ return increment;
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @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 int getMaximum () {
+ checkWidget ();
+ return max;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @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 int getMinimum () {
+ checkWidget ();
+ return min;
+}
+
+/**
+ * Returns the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed.
+ *
+ * @return the page increment
+ *
+ * @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 int getPageIncrement () {
+ checkWidget ();
+ return pageIncrement;
+}
+
+/**
+ * Returns the <em>selection</em>, which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @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 int getSelection () {
+ checkWidget ();
+ return value;
+}
+
+int getSelectionText (boolean [] parseFail) {
+ int textPtr = OS.TextBox_Text (textHandle);
+ String string = createJavaString (textPtr);
+ OS.GCHandle_Free (textPtr);
+ try {
+ int value;
+ if (digits > 0) {
+ String decimalSeparator = getDecimalSeparator ();
+ int index = string.indexOf (decimalSeparator);
+ if (index != -1) {
+ int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0;
+ String wholePart = startIndex != index ? string.substring (startIndex, index) : "0";
+ String decimalPart = string.substring (index + 1);
+ if (decimalPart.length () > digits) {
+ decimalPart = decimalPart.substring (0, digits);
+ } else {
+ int i = digits - decimalPart.length ();
+ for (int j = 0; j < i; j++) {
+ decimalPart = decimalPart + "0";
+ }
+ }
+ int wholeValue = Integer.parseInt (wholePart);
+ int decimalValue = Integer.parseInt (decimalPart);
+ for (int i = 0; i < digits; i++) wholeValue *= 10;
+ value = wholeValue + decimalValue;
+ if (string.startsWith ("-")) value = -value;
+ } else {
+ value = Integer.parseInt (string);
+ for (int i = 0; i < digits; i++) value *= 10;
+ }
+ } else {
+ value = Integer.parseInt (string);
+ }
+ if (min <= value && value <= max) return value;
+ } catch (NumberFormatException e) {
+ }
+ parseFail [0] = true;
+ return -1;
+}
+
+/**
+ * Returns a string containing a copy of the contents of the
+ * receiver's text field, or an empty string if there are no
+ * contents.
+ *
+ * @return the receiver's 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>
+ *
+ * @since 3.4
+ */
+public String getText () {
+ checkWidget ();
+ int text = OS.TextBox_Text (textHandle);
+ String string = createJavaString (text);
+ OS.GCHandle_Free (text);
+ return string;
+}
+
+/**
+ * Returns the maximum number of characters that the receiver's
+ * text field is capable of holding. If this has not been changed
+ * by <code>setTextLimit()</code>, it will be the constant
+ * <code>Spinner.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @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 #LIMIT
+ *
+ * @since 3.4
+ */
+public int getTextLimit () {
+ checkWidget ();
+ return OS.TextBox_MaxLength (textHandle);
+}
+
+void HandleDownClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ updateSelection (-increment);
+}
+
+void HandleLostKeyboardFocus (int sender, int e) {
+ if (!checkEvent (e)) return;
+ boolean [] parseFail = new boolean [1];
+ getSelectionText (parseFail);
+ if (parseFail [0]) {
+ setSelection (value, false, true, false);
+ }
+ super.HandleLostKeyboardFocus (sender, e);
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ int delta = 0;
+ switch (key) {
+ case OS.Key_Return:
+ postEvent (SWT.DefaultSelection);
+ break;
+ case OS.Key_Down: delta -= increment; break;
+ case OS.Key_Up: delta += increment; break;
+ case OS.Key_PageDown: delta -= pageIncrement; break;
+ case OS.Key_PageUp: delta += pageIncrement; break;
+ }
+ if (delta != 0) {
+ updateSelection (delta);
+ }
+}
+
+void HandlePreviewTextInput (int sender, int e) {
+ super.HandlePreviewTextInput (sender, e);
+ if (!checkEvent (e)) return;
+ int textPtr = OS.TextCompositionEventArgs_Text (e);
+ String input = createJavaString(textPtr);
+ OS.GCHandle_Free (textPtr);
+ int start = OS.TextBox_SelectionStart (textHandle);
+ int end = start + OS.TextBox_SelectionLength (textHandle);
+ String text = verifyText (input, start, end);
+ if (text != null && !text.equals (input)) {
+ textPtr = createDotNetString (text, false);
+ OS.TextBox_SelectedText (textHandle, textPtr);
+ OS.GCHandle_Free (textPtr);
+ start = OS.TextBox_SelectionStart (textHandle);
+ int length = OS.TextBox_SelectionLength (textHandle);
+ OS.TextBox_Select (textHandle, start+length, 0);
+ OS.TextBox_SelectionLength (textHandle, 0);
+ text = null;
+ }
+ if (text == null) OS.TextCompositionEventArgs_Handled (e, true);
+}
+
+void HandleTextChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ boolean [] parseFail = new boolean [1];
+ int value = getSelectionText (parseFail);
+ if (!parseFail [0]) {
+ if (this.value != value) setSelection(value, true, false, true);
+ }
+ sendEvent (SWT.Modify);
+}
+
+void HandleUpClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ updateSelection (increment);
+}
+
+void hookEvents () {
+ super.hookEvents();
+ //TEXT
+ int handler = OS.gcnew_TextCompositionEventHandler (jniRef, "HandlePreviewTextInput");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.UIElement_PreviewTextInput (textHandle, handler);
+ OS.GCHandle_Free (handler);
+// handler = OS.gcnew_ExecutedRoutedEventHandler(jniRef, "HandlePreviewExecutedRoutedEvent");
+// if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+// OS.CommandManager_AddPreviewExecutedHandler(handle, handler);
+// OS.GCHandle_Free(handler);
+ handler = OS.gcnew_TextChangedEventHandler (jniRef, "HandleTextChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.TextBoxBase_TextChanged (textHandle, handler);
+ OS.GCHandle_Free (handler);
+
+ //BUTTON
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleDownClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ButtonBase_Click (downHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleUpClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ButtonBase_Click (upHandle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @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 paste () {
+ checkWidget ();
+ //TODO
+}
+
+void releaseHandle () {
+ super.releaseHandle();
+ OS.GCHandle_Free (textHandle);
+ OS.GCHandle_Free (upHandle);
+ OS.GCHandle_Free (downHandle);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ */
+void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+/**
+ * Sets the number of decimal places used by the receiver.
+ * <p>
+ * The digit setting is used to allow for floating point values in the receiver.
+ * For example, to set the selection to a floating point value of 1.37 call setDigits() with
+ * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value
+ * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all
+ * numeric APIs.
+ * </p>
+ *
+ * @param value the new digits (must be greater than or equal to zero)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the value is less than zero</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 setDigits (int value) {
+ checkWidget ();
+ if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT);
+ digits = value;
+ setSelection (this.value, false, true, false);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed to
+ * the argument, which must be at least one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @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 setIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ increment = value;
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @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 setMaximum (int value) {
+ checkWidget ();
+ if (value <= min) return;
+ max = value;
+ if (this.value > value) setSelection (value, true, true, false);
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be less than the current maximum
+ *
+ * @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 setMinimum (int value) {
+ checkWidget ();
+ if (value >= max) return;
+ min = value;
+ if (this.value < value) setSelection (value, true, true, false);
+}
+
+/**
+ * Sets the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed
+ * to the argument, which must be at least one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @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 setPageIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ pageIncrement = value;
+}
+
+/**
+ * Sets the <em>selection</em>, which is the receiver's
+ * position, to the argument. If the argument is not within
+ * the range specified by minimum and maximum, it will be
+ * adjusted to fall within this range.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @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 setSelection (int value) {
+ checkWidget ();
+ value = Math.min (Math.max (min, value), max);
+ setSelection (value, true, true, false);
+}
+
+void setSelection (int value, boolean setPos, boolean setText, boolean notify) {
+ if (setPos) {
+ this.value = value;
+ }
+ if (setText) {
+ String string;
+ if (digits == 0) {
+ string = String.valueOf (value);
+ } else {
+ string = String.valueOf (Math.abs (value));
+ String decimalSeparator = getDecimalSeparator ();
+ int index = string.length () - digits;
+ StringBuffer buffer = new StringBuffer ();
+ if (value < 0) buffer.append ("-");
+ if (index > 0) {
+ buffer.append (string.substring (0, index));
+ buffer.append (decimalSeparator);
+ buffer.append (string.substring (index));
+ } else {
+ buffer.append ("0");
+ buffer.append (decimalSeparator);
+ while (index++ < 0) buffer.append ("0");
+ buffer.append (string);
+ }
+ string = buffer.toString ();
+ }
+// if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+// int length = OS.GetWindowTextLength (hwndText);
+// string = verifyText (string, 0, length, null);
+// if (string == null) return;
+// }
+ int ptr = createDotNetString (string, false);
+ OS.TextBox_Text (textHandle, ptr);
+ OS.GCHandle_Free (ptr);
+ }
+ if (notify) postEvent (SWT.Selection);
+}
+
+/**
+ * Sets the maximum number of characters that the receiver's
+ * text field is capable of holding to be the argument.
+ * <p>
+ * To reset this value to the default, use <code>setTextLimit(Spinner.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Spinner.LIMIT</code> sets the
+ * receiver's limit to <code>Spinner.LIMIT</code>.
+ * </p>
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</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>
+ *
+ * @see #LIMIT
+ *
+ * @since 3.4
+ */
+public void setTextLimit (int limit) {
+ checkWidget ();
+ if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+ OS.TextBox_MaxLength (textHandle, limit);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, digits, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param digits the new digits value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
+ checkWidget ();
+ if (maximum <= minimum) return;
+ if (digits < 0) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ selection = Math.min (Math.max (minimum, selection), maximum);
+ this.pageIncrement = pageIncrement;
+ this.increment = increment;
+ this.digits = digits;
+ this.min = minimum;
+ this.max = maximum;
+ setSelection (selection, true, true, false);
+}
+
+void updateSelection (int delta) {
+ boolean [] parseFail = new boolean [1];
+ int value = getSelectionText (parseFail);
+ if (parseFail [0]) value = this.value;
+ int newValue = value + delta;
+ if ((style & SWT.WRAP) != 0) {
+ if (newValue < min) newValue = max;
+ if (newValue > max) newValue = min;
+ }
+ newValue = Math.min (Math.max (min, newValue), max);
+ if (value != newValue) setSelection (newValue, true, true, true);
+}
+
+String verifyText (String string, int start, int end) {
+ Event event = new Event ();
+ event.text = string;
+ event.start = start;
+ event.end = end;
+ if (string.length () == 1) {
+ event.character = string.charAt (0);
+ setInputState (event, SWT.KeyDown, 0, 0);
+ }
+ int index = 0;
+ if (digits > 0) {
+ String decimalSeparator = getDecimalSeparator ();
+ index = string.indexOf (decimalSeparator);
+ if (index != -1) {
+ string = string.substring (0, index) + string.substring (index + 1);
+ }
+ index = 0;
+ }
+ if (string.length() > 0) {
+ if (min < 0 && string.charAt (0) == '-') index++;
+ }
+ while (index < string.length ()) {
+ if (!Character.isDigit (string.charAt (index))) break;
+ index++;
+ }
+ event.doit = index == string.length ();
+ sendEvent (SWT.Verify, event);
+ if (!event.doit || isDisposed ()) return null;
+ return event.text;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabFolder.java
new file mode 100644
index 0000000000..9100ff47f0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabFolder.java
@@ -0,0 +1,731 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class implement the notebook user interface
+ * metaphor. It allows the user to select a notebook page from
+ * set of pages.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TabItem</code>.
+ * <code>Control</code> children are created and then set into a
+ * tab item using <code>TabItem#setControl</code>.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>TOP, BOTTOM</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles TOP and BOTTOM may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tabfolder">TabFolder, TabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TabFolder extends Composite {
+ int parentingHandle;
+ int itemCount;
+ Control [] children;
+ int childCount;
+ boolean ignoreSelection;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 SWT#TOP
+ * @see SWT#BOTTOM
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TabFolder (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+void addChild (Control widget) {
+ super.addChild (widget);
+ if (childCount == children.length) {
+ Control [] newChildren = new Control [childCount + 4];
+ System.arraycopy (children, 0, newChildren, 0, childCount);
+ children = newChildren;
+ }
+ children [childCount++] = widget;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ /*
+ * When the SWT.TOP style has not been set, force the
+ * tabs to be on the bottom for tab folders on PPC.
+ */
+// if (OS.IsPPC) {
+// if ((style & SWT.TOP) == 0) style |= SWT.BOTTOM;
+// }
+ style = checkBits (style, SWT.TOP, SWT.BOTTOM, 0, 0, 0, 0);
+
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+int clientHandle () {
+ int index = OS.Selector_SelectedIndex (handle);
+ if (index != -1) {
+ int items = OS.ItemsControl_Items (handle);
+ TabItem item = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return item.contentHandle;
+ }
+ return handle;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ Point size = super.computeSize (wHint, hHint, changed);
+ Point sizeTabFolder = computeSize (handle, wHint, hHint, changed);
+ return new Point (Math.max(sizeTabFolder.x + 1, size.x + 10), size.y + sizeTabFolder.y + 10);
+}
+
+void createItem (TabItem item, int index) {
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (items, index, item.topHandle ());
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ itemCount++;
+}
+
+void createHandle () {
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_TabControl ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.BOTTOM) != 0) OS.TabControl_TabStripPlacement (handle, OS.Dock_Bottom);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, handle);
+ OS.GCHandle_Free (children);
+ OS.Canvas_SetLeft (handle, 0);
+ OS.Canvas_SetTop (handle, 0);
+}
+
+void createWidget () {
+ super.createWidget ();
+ children = new Control [4];
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+void destroyItem (TabItem item) {
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Remove (items, item.topHandle ());
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemCount--;
+}
+
+Control findThemeControl () {
+ return this;
+}
+
+Control [] _getChildren () {
+ // return children in reverse order.
+ Control[] result = new Control [childCount];
+ for (int i =0; i < childCount; i++) {
+ result [childCount - i - 1] = children [i];
+ }
+ return result;
+}
+
+public Rectangle getClientArea () {
+ checkWidget ();
+ Rectangle rect = super.getClientArea ();
+ int clientHandle = clientHandle ();
+ int topHandle = topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ int result = OS.UIElement_TranslatePoint (clientHandle, point, topHandle);
+ rect.x = (int) OS.Point_X (result);
+ rect.y = (int) OS.Point_Y (result);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (result);
+ return rect;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 TabItem getItem (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ TabItem item = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return item;
+}
+
+TabItem getItem (int items, int index) {
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ TabItem result = (TabItem) display.getWidget (item);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+/**
+ * Returns the tab item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the tab item at the given point, or null if the point is not in a tab item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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>
+ *
+ * @since 3.4
+ */
+public TabItem getItem (Point point) {
+ checkWidget();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ for (int index = 0; index < itemCount; index++) {
+ TabItem item = getItem (items, index);
+ Rectangle bounds = item.getBounds();
+ if (bounds.contains(point)) {
+ OS.GCHandle_Free (items);
+ return item;
+ }
+ }
+ OS.GCHandle_Free (items);
+ return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ return itemCount;
+}
+
+/**
+ * Returns an array of <code>TabItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 TabItem [] getItems () {
+ checkWidget ();
+ TabItem [] result = new TabItem [itemCount];
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ result [i] = getItem (items, i);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+/**
+ * Returns an array of <code>TabItem</code>s that are currently
+ * selected in the receiver. An empty array indicates that no
+ * items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @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 TabItem [] getSelection () {
+ checkWidget ();
+ int index = OS.Selector_SelectedIndex (handle);
+ if (index == -1) return new TabItem [0];
+ int items = OS.ItemsControl_Items (handle);
+ TabItem item = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return new TabItem [] {item};
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @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 int getSelectionIndex () {
+ checkWidget ();
+ return OS.Selector_SelectedIndex (handle);
+}
+
+boolean hasItems () {
+ return true;
+}
+
+void HandleSelectionChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int removed = OS.SelectionChangedEventArgs_RemovedItems (e);
+ if (OS.ICollection_Count (removed) > 0) {
+ int oldSelection = OS.IList_default (removed, 0);
+ TabItem item = (TabItem) display.getWidget (oldSelection);
+ OS.GCHandle_Free (oldSelection);
+ Control control = item.getControl();
+ if (control != null && !control.isDisposed ()) {
+ control.setVisible (false);
+ }
+ }
+ OS.GCHandle_Free (removed);
+ int selectedItem = OS.Selector_SelectedItem (handle);
+ if (selectedItem == 0) return;
+ TabItem item = (TabItem) display.getWidget (selectedItem);
+ OS.GCHandle_Free (selectedItem);
+
+ Control control = item.getControl();
+ if (control != null && !control.isDisposed ()) {
+ control.setVisible (true);
+ }
+ if (ignoreSelection) return;
+ Event event = new Event ();
+ event.item = item;
+ postEvent (SWT.Selection, event);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SelectionChangedEventHandler (jniRef, "HandleSelectionChanged");
+ OS.Selector_SelectionChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item 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 int indexOf (TabItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ int index = OS.ItemCollection_IndexOf (items, item.topHandle ());
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+Point minimumSize (int wHint, int hHint, boolean flushCache) {
+ Control [] children = _getChildren ();
+ int width = 0, height = 0;
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<children.length; i++) {
+ Control child = children [i];
+ int index = 0;
+ while (index < itemCount) {
+ TabItem item = getItem (items, index);
+ if (item.control == child) break;
+ index++;
+ }
+ if (index == itemCount) {
+ Rectangle rect = child.getBounds ();
+ width = Math.max (width, rect.x + rect.width);
+ height = Math.max (height, rect.y + rect.height);
+ } else {
+ Point size = child.computeSize (wHint, hHint, flushCache);
+ width = Math.max (width, size.x);
+ height = Math.max (height, size.y);
+ }
+ }
+ OS.GCHandle_Free (items);
+ return new Point (width, height);
+}
+
+boolean mnemonicHit (char key) {
+ //TODO
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ boolean found = false;
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TabItem item = getItem (items, i);
+ if (mnemonicMatch (item.textHandle, key)) {
+ found = true;
+ break;
+ }
+ }
+ OS.GCHandle_Free (items);
+ return found;
+}
+
+int parentingHandle() {
+ return parentingHandle;
+}
+
+void register () {
+ super.register ();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TabItem item = getItem (items, i);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ super.releaseChildren (destroy);
+}
+
+void removeChild (Control control) {
+ super.removeChild (control);
+ int index = 0;
+ while (index < childCount) {
+ if (children [index] == control) break;
+ index++;
+ }
+ if (index == childCount) return;
+ System.arraycopy (children, index+1, children, index, --childCount - index);
+ children [childCount] = null;
+}
+
+void releaseHandle() {
+ super.releaseHandle ();
+ if (parentingHandle != 0) OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void removeControl (Control control) {
+ super.removeControl (control);
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TabItem item = getItem (items, i);
+ if (item.control == control) {
+ item.setControl (null);
+ break;
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0) {
+ OS.FrameworkElement_Height (handle, height);
+ OS.FrameworkElement_Width (handle, width);
+ int selectedItem = OS.Selector_SelectedItem (handle);
+ if (selectedItem != 0) {
+ TabItem item = (TabItem) display.getWidget (selectedItem);
+ OS.GCHandle_Free (selectedItem);
+ Control control = item.control;
+ if (control != null && !control.isDisposed ()) {
+ control.setBounds (getClientArea ());
+ }
+ }
+ }
+ return result;
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selected is first cleared, then the new item is
+ * selected.
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item 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>
+ *
+ * @since 3.2
+ */
+public void setSelection (TabItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TabItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selected is first cleared, then the new items are
+ * selected.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the items array 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 setSelection (TabItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (items.length == 0) {
+ setSelection (-1, false);
+ } else {
+ for (int i=items.length-1; i>=0; --i) {
+ int index = indexOf (items [i]);
+ if (index != -1) setSelection (index, false);
+ }
+ }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new items are
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 setSelection (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) return;
+ setSelection (index, false);
+}
+
+void setSelection (int index, boolean notify) {
+ int oldIndex = OS.Selector_SelectedIndex (handle);
+ if (oldIndex != -1) {
+ int items = OS.ItemsControl_Items (handle);
+ TabItem item = getItem (items, oldIndex);
+ OS.GCHandle_Free (items);
+ Control control = item.control;
+ if (control != null && !control.isDisposed ()) {
+ control.setVisible (false);
+ }
+ }
+ ignoreSelection = true;
+ OS.Selector_SelectedIndex (handle, index);
+ ignoreSelection = false;
+ int newIndex = OS.Selector_SelectedIndex (handle);
+ if (newIndex != -1) {
+ int items = OS.ItemsControl_Items (handle);
+ TabItem item = getItem (items, newIndex);
+ OS.GCHandle_Free (items);
+ Control control = item.control;
+ if (control != null && !control.isDisposed ()) {
+// control.setBounds (getClientArea ());
+ control.setVisible (true);
+ }
+ if (notify) {
+ Event event = new Event ();
+ event.item = item;
+ sendEvent (SWT.Selection, event);
+ }
+ }
+}
+
+int topHandle() {
+ return parentingHandle;
+}
+
+boolean traversePage (boolean next) {
+// GTK: OS.g_signal_emit_by_name (handle, OS.change_current_page, next ? 1 : -1);
+ int count = getItemCount ();
+ if (count <= 1) return false;
+ int index = getSelectionIndex ();
+ if (index == -1) {
+ index = 0;
+ } else {
+ int offset = (next) ? 1 : -1;
+ index = (index + offset + count) % count;
+ }
+ setSelection (index, true);
+ if (index == getSelectionIndex ()) {
+// OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+ return true;
+ }
+ return false;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabItem.java
new file mode 100644
index 0000000000..2a87cd4f2f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TabItem.java
@@ -0,0 +1,406 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * corresponding to a tab for a page in a tab folder.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tabfolder">TabFolder, TabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class TabItem extends Item {
+ TabFolder parent;
+ Control control;
+ String toolTipText;
+ int imageHandle, textHandle, contentHandle;
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TabFolder</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 TabItem (TabFolder parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TabFolder</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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 TabItem (TabFolder parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandle () {
+ handle = OS.gcnew_TabItem ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ imageHandle = OS.gcnew_Image ();
+ if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ int thickness = OS.gcnew_Thickness (0, 0, 3, 0);
+ if (thickness == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, thickness);
+ OS.GCHandle_Free (thickness);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+ textHandle = OS.gcnew_AccessText ();
+ if (textHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_VerticalAlignment (textHandle, OS.VerticalAlignment_Center);
+ int panel = OS.gcnew_StackPanel ();
+ if (panel == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.StackPanel_Orientation (panel, OS.Orientation_Horizontal);
+ thickness = OS.gcnew_Thickness (1, 1, 1, 1);
+ if (thickness == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (panel, thickness);
+ OS.GCHandle_Free(thickness);
+ int children = OS.Panel_Children (panel);
+ OS.UIElementCollection_Add (children, imageHandle);
+ OS.UIElementCollection_Add (children, textHandle);
+ OS.HeaderedContentControl_Header (handle, panel);
+ OS.GCHandle_Free (children);
+ OS.GCHandle_Free (panel);
+ contentHandle = OS.gcnew_Canvas ();
+ if (contentHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ContentControl_Content (handle, contentHandle);
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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>
+ *
+ * @since 3.4
+ */
+public Rectangle getBounds () {
+ checkWidget ();
+ int topHandle = handle;
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (topHandle, point, parent.handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item. If no
+ * control has been set, return <code>null</code>.
+ * <p>
+ * @return the control
+ *
+ * @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 Control getControl () {
+ checkWidget();
+ return control;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>TabFolder</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 TabFolder getParent () {
+ checkWidget();
+ return parent;
+}
+
+Control getWidgetControl () {
+ return parent;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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 getToolTipText () {
+ checkWidget();
+ return toolTipText;
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (control == null) return;
+ control.setBounds (parent.getClientArea ());
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
+ OS.FrameworkElement_SizeChanged (contentHandle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+void register() {
+ display.addWidget (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+ if (textHandle != 0) OS.GCHandle_Free (textHandle);
+ textHandle = 0;
+ if (imageHandle !=0 )OS.GCHandle_Free (imageHandle);
+ imageHandle = 0;
+ if (contentHandle != 0) OS.GCHandle_Free (contentHandle);
+ contentHandle = 0;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ int index = parent.indexOf (this);
+ if (index == parent.getSelectionIndex ()) {
+ if (control != null) control.setVisible (false);
+ }
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ control = null;
+ toolTipText = null;
+}
+
+/**
+ * Sets the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item.
+ * <p>
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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 setControl (Control control) {
+ checkWidget();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (this.control != null && this.control.isDisposed ()) {
+ this.control = null;
+ }
+ Control oldControl = this.control, newControl = control;
+ this.control = control;
+ int index = parent.indexOf (this), selectionIndex = parent.getSelectionIndex();
+ if (index != selectionIndex) {
+ if (newControl != null) {
+ if (selectionIndex != -1) {
+ Control selectedControl = parent.getItem(selectionIndex).getControl();
+ if (selectedControl == newControl) return;
+ }
+ newControl.setVisible(false);
+ return;
+ }
+ }
+ if (newControl != null) {
+ newControl.setBounds (parent.getClientArea ());
+ newControl.setVisible (true);
+ }
+ if (oldControl != null) oldControl.setVisible (false);
+}
+
+public void setImage (Image image) {
+ checkWidget();
+ super.setImage (image);
+ OS.Image_Source (imageHandle, image != null ? image.handle : 0);
+ OS.UIElement_Visibility (imageHandle, image != null ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if (string.equals (text)) return;
+ super.setText (string);
+ int strPtr = createDotNetString (string, true);
+ if (strPtr == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.AccessText_Text (textHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+// OS.UIElement_Visibility (textHandle, string.length() == 0 ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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 setToolTipText (String string) {
+ checkWidget();
+ toolTipText = string;
+ if (string != null && string.length() == 0) string = null;
+ int strPtr = createDotNetString (string, false);
+ int header = OS.HeaderedContentControl_Header (handle);
+ OS.FrameworkElement_ToolTip (header, strPtr);
+ if (strPtr != 0) OS.GCHandle_Free (strPtr);
+ OS.GCHandle_Free (header);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Table.java
new file mode 100644
index 0000000000..068104d290
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Table.java
@@ -0,0 +1,2417 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.wpf.OS;
+
+/**
+ * Instances of this class implement a selectable user interface
+ * object that displays a list of images and strings and issues
+ * notification when selected.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TableItem</code>.
+ * </p><p>
+ * Style <code>VIRTUAL</code> is used to create a <code>Table</code> whose
+ * <code>TableItem</code>s are to be populated by the client on an on-demand basis
+ * instead of up-front. This can provide significant performance improvements for
+ * tables that are very large or for which <code>TableItem</code> population is
+ * expensive (for example, retrieving values from an external source).
+ * </p><p>
+ * Here is an example of using a <code>Table</code> with style <code>VIRTUAL</code>:
+ * <code><pre>
+ * final Table table = new Table (parent, SWT.VIRTUAL | SWT.BORDER);
+ * table.setItemCount (1000000);
+ * table.addListener (SWT.SetData, new Listener () {
+ * public void handleEvent (Event event) {
+ * TableItem item = (TableItem) event.item;
+ * int index = table.indexOf (item);
+ * item.setText ("Item " + index);
+ * System.out.println (item.getText ());
+ * }
+ * });
+ * </pre></code>
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL, NO_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles SINGLE, and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Table extends Composite {
+ int gridViewHandle, parentingHandle;
+ int columnCount, itemCount;
+ boolean ignoreSelection;
+ TableColumn [] columns;
+ boolean linesVisible;
+
+ static final String CHECKBOX_PART_NAME = "SWT_PART_CHECKBOX";
+ static final String IMAGE_PART_NAME = "SWT_PART_IMAGE";
+ static final String TEXT_PART_NAME = "SWT_PART_TEXT";
+ static final String CONTENTPANEL_PART_NAME = "SWT_PART_CONTENTPANEL";
+ static final String RENDER_PANEL_NAME = "SWT_PART_RENDERPANEL";
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see SWT#HIDE_SELECTION
+ * @see SWT#VIRTUAL
+ * @see SWT#NO_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Table (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+void _addListener (int eventType, Listener listener) {
+ super._addListener (eventType, listener);
+ switch (eventType) {
+ case SWT.MeasureItem:
+ case SWT.EraseItem:
+ case SWT.PaintItem:
+ //TODO
+ break;
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has the <code>SWT.CHECK</code> style and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+boolean checkData (TableItem item) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ if (!item.cached) {
+ item.cached = true;
+ Event event = new Event ();
+ event.item = item;
+ event.index = indexOf (item);
+ sendEvent (SWT.SetData, event);
+ //widget could be disposed at this point
+ if (isDisposed () || item.isDisposed ()) return false;
+ }
+ return true;
+}
+
+static int checkStyle (int style) {
+ /*
+ * Feature in Windows. Even when WS_HSCROLL or
+ * WS_VSCROLL is not specified, Windows creates
+ * trees and tables with scroll bars. The fix
+ * is to set H_SCROLL and V_SCROLL.
+ *
+ * NOTE: This code appears on all platforms so that
+ * applications have consistent scroll bar behavior.
+ */
+ if ((style & SWT.NO_SCROLL) == 0) {
+ style |= SWT.H_SCROLL | SWT.V_SCROLL;
+ }
+ /* WPF is always FULL_SELECTION */
+ style |= SWT.FULL_SELECTION;
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ TableItem item = getItem (items, index, false);
+ OS.GCHandle_Free (items);
+ if (item != null) item.clear ();
+}
+
+/**
+ * Removes the items from the receiver which are between the given
+ * zero-relative start and end indices (inclusive). The text, icon
+ * and other attributes of the items are set to their default values.
+ * If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param start the start index of the item to clear
+ * @param end the end index of the item to clear
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int start, int end) {
+ checkWidget ();
+ checkWidget ();
+ if (start > end) return;
+ if (!(0 <= start && start <= end && end < itemCount)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ if (start == 0 && end == itemCount - 1) {
+ clearAll ();
+ } else {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=start; i<=end; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null) item.clear ();
+ }
+ OS.GCHandle_Free (items);
+ }
+}
+
+/**
+ * Clears the items at the given zero-relative indices in the receiver.
+ * The text, icon and other attributes of the items are set to their default
+ * values. If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the indices array 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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ for (int i=0; i<indices.length; i++) {
+ if (!(0 <= indices [i] && indices [i] < itemCount)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<indices.length; i++) {
+ int index = indices [i];
+ TableItem item = getItem (items, index, false);
+ if (item != null) item.clear ();
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * table was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clearAll () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null) item.clear ();
+ }
+ OS.GCHandle_Free (items);
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ updateLayout (parent.handle);
+ if (columnCount == 0) { // pack the default column
+ double width = 0;
+ int columns = OS.GridView_Columns (gridViewHandle);
+ int column = OS.GridViewColumnCollection_default (columns, 0);
+ OS.GCHandle_Free (columns);
+ int columnHeader = OS.GridViewColumn_Header (column);
+ if (columnHeader != 0) {
+ int size = OS.UIElement_DesiredSize (columnHeader);
+ width = OS.Size_Width (size);
+ OS.GCHandle_Free (size);
+ OS.GCHandle_Free (columnHeader);
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null) width = Math.max (width, item.computeWidth (0));
+ }
+ OS.GCHandle_Free (items);
+ OS.GridViewColumn_Width (column, width);
+ OS.GCHandle_Free (column);
+ }
+ Point size = computeSize (handle, wHint, hHint, changed);
+ if (size.x == 0) size.x = DEFAULT_WIDTH;
+ if (size.y == 0) size.y = DEFAULT_HEIGHT;
+ if (wHint != SWT.DEFAULT) size.x = wHint;
+ if (hHint != SWT.DEFAULT) size.y = hHint;
+ Rectangle trim = computeTrim (0, 0, size.x, size.y);
+ return new Point (trim.width, trim.height);
+}
+
+int createCellTemplate (int index) {
+ int template = OS.gcnew_DataTemplate ();
+ int renderPanelType = OS.SWTDockPanel_typeid ();
+ int renderPanelName = createDotNetString(RENDER_PANEL_NAME, false);
+ int onRenderNode = OS.gcnew_FrameworkElementFactory (renderPanelType, renderPanelName);
+ OS.GCHandle_Free(renderPanelName);
+ OS.GCHandle_Free (renderPanelType);
+ int jniRefProperty = OS.SWTDockPanel_JNIRefProperty ();
+ OS.FrameworkElementFactory_SetValueInt (onRenderNode, jniRefProperty, jniRef);
+ OS.GCHandle_Free (jniRefProperty);
+ int contentPanelName = createDotNetString (CONTENTPANEL_PART_NAME, false);
+ int contentPanelType = OS.StackPanel_typeid ();
+ int cellContentNode = OS.gcnew_FrameworkElementFactory (contentPanelType, contentPanelName);
+ OS.GCHandle_Free (contentPanelType);
+ OS.GCHandle_Free (contentPanelName);
+ int clipProperty = OS.UIElement_ClipToBoundsProperty ();
+ OS.FrameworkElementFactory_SetValue (cellContentNode, clipProperty, true);
+ OS.GCHandle_Free (clipProperty);
+ int orientationProperty = OS.StackPanel_OrientationProperty ();
+ OS.FrameworkElementFactory_SetValueOrientation (cellContentNode, orientationProperty, OS.Orientation_Horizontal);
+ OS.GCHandle_Free (orientationProperty);
+ if (index == 0 && (style & SWT.CHECK) != 0) {
+ int checkBoxType = OS.CheckBox_typeid ();
+ int checkBoxName = createDotNetString (CHECKBOX_PART_NAME, false);
+ int checkBoxNode = OS.gcnew_FrameworkElementFactory (checkBoxType, checkBoxName);
+ int verticalAlignmentProperty = OS.FrameworkElement_VerticalAlignmentProperty ();
+ OS.FrameworkElementFactory_SetValueVerticalAlignment (checkBoxNode, verticalAlignmentProperty, OS.VerticalAlignment_Center);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (checkBoxNode, marginProperty, thickness);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, checkBoxNode);
+ OS.GCHandle_Free (thickness);
+ OS.GCHandle_Free (marginProperty);
+ OS.GCHandle_Free (verticalAlignmentProperty);
+ OS.GCHandle_Free (checkBoxName);
+ OS.GCHandle_Free (checkBoxNode);
+ OS.GCHandle_Free (checkBoxType);
+ }
+ int textType = OS.TextBlock_typeid ();
+ int textName = createDotNetString (TEXT_PART_NAME, false);
+ int textNode = OS.gcnew_FrameworkElementFactory (textType, textName);
+ OS.GCHandle_Free (textName);
+ OS.GCHandle_Free (textType);
+ int verticalAlignmentProperty = OS.FrameworkElement_VerticalAlignmentProperty ();
+ OS.FrameworkElementFactory_SetValueVerticalAlignment (textNode, verticalAlignmentProperty, OS.VerticalAlignment_Center);
+ OS.GCHandle_Free (verticalAlignmentProperty);
+ int imageType = OS.Image_typeid ();
+ int imageName = createDotNetString (IMAGE_PART_NAME, false);
+ int imageNode = OS.gcnew_FrameworkElementFactory (imageType, imageName);
+ OS.GCHandle_Free (imageName);
+ OS.GCHandle_Free (imageType);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (imageNode, marginProperty, thickness);
+ OS.GCHandle_Free (marginProperty);
+ OS.GCHandle_Free (thickness);
+ int stretchProperty = OS.Image_StretchProperty ();
+ OS.FrameworkElementFactory_SetValueStretch(imageNode, stretchProperty, OS.Stretch_None);
+ OS.GCHandle_Free(stretchProperty);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, imageNode);
+ OS.GCHandle_Free (imageNode);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, textNode);
+ OS.GCHandle_Free (textNode);
+ OS.FrameworkElementFactory_AppendChild (onRenderNode, cellContentNode);
+ OS.GCHandle_Free (cellContentNode);
+ OS.FrameworkTemplate_VisualTree (template, onRenderNode);
+ OS.GCHandle_Free (onRenderNode);
+ return template;
+}
+
+void createDefaultColumn () {
+ int column = OS.gcnew_GridViewColumn ();
+ int columnCollection = OS.GridView_Columns (gridViewHandle);
+ int headerHandle = OS.gcnew_GridViewColumnHeader ();
+ OS.GridViewColumn_Header (column, headerHandle);
+ OS.GCHandle_Free (headerHandle);
+ OS.GridViewColumnCollection_Insert (columnCollection, 0, column);
+ int cellTemplate = createCellTemplate (0);
+ OS.GridViewColumn_CellTemplate (column, cellTemplate);
+ OS.GCHandle_Free (columnCollection);
+ OS.GCHandle_Free (column);
+ OS.GCHandle_Free (cellTemplate);
+}
+
+void createHandle () {
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_ListView ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ gridViewHandle = OS.gcnew_GridView ();
+ if (gridViewHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ListView_View (handle, gridViewHandle);
+ if ((style & SWT.MULTI) == 0) OS.ListBox_SelectionMode (handle, OS.SelectionMode_Single);
+ createDefaultColumn ();
+ setHeaderVisible (false);
+ OS.Selector_IsSynchronizedWithCurrentItem (handle, true);
+ OS.GridView_AllowsColumnReorder (gridViewHandle, false);
+ OS.Canvas_SetLeft (handle, 0);
+ OS.Canvas_SetTop (handle, 0);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, handle);
+ OS.GCHandle_Free (children);
+}
+
+int createHeaderTemplate (int columnJniRef) {
+ int template = OS.gcnew_DataTemplate ();
+ int stackPanelType = OS.StackPanel_typeid ();
+ int stackPanelName = createDotNetString (CONTENTPANEL_PART_NAME, false);
+ int stackPanelNode = OS.gcnew_FrameworkElementFactory (stackPanelType, stackPanelName);
+ int textType = OS.TextBlock_typeid ();
+ int textName = createDotNetString(TEXT_PART_NAME, false);
+ int textNode = OS.gcnew_FrameworkElementFactory (textType, textName);
+ int verticalAlignmentProperty = OS.FrameworkElement_VerticalAlignmentProperty ();
+ OS.FrameworkElementFactory_SetValueVerticalAlignment (textNode, verticalAlignmentProperty, OS.VerticalAlignment_Center);
+ int imageType = OS.Image_typeid ();
+ int imageName = createDotNetString(IMAGE_PART_NAME, false);
+ int imageNode = OS.gcnew_FrameworkElementFactory (imageType, imageName);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (imageNode, marginProperty, thickness);
+ int orientationProperty = OS.StackPanel_OrientationProperty ();
+ OS.FrameworkElementFactory_SetValueOrientation (stackPanelNode, orientationProperty, OS.Orientation_Horizontal);
+ OS.FrameworkElementFactory_AppendChild (stackPanelNode, imageNode);
+ OS.FrameworkElementFactory_AppendChild (stackPanelNode, textNode);
+ OS.FrameworkTemplate_VisualTree (template, stackPanelNode);
+ OS.GCHandle_Free (stackPanelName);
+ OS.GCHandle_Free (imageType);
+ OS.GCHandle_Free (imageName);
+ OS.GCHandle_Free (marginProperty);
+ OS.GCHandle_Free (thickness);
+ OS.GCHandle_Free (textType);
+ OS.GCHandle_Free (textName);
+ OS.GCHandle_Free (stackPanelType);
+ OS.GCHandle_Free (stackPanelNode);
+ OS.GCHandle_Free (textNode);
+ OS.GCHandle_Free (imageNode);
+ OS.GCHandle_Free (orientationProperty);
+ OS.GCHandle_Free (verticalAlignmentProperty);
+ return template;
+}
+
+void createItem (TableColumn column, int index) {
+ if (index == -1) index = columnCount;
+ if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE);
+ column.createWidget ();
+ int template = createHeaderTemplate (column.jniRef);
+ OS.GridViewColumn_HeaderTemplate (column.handle, template);
+ OS.GCHandle_Free (template);
+ template = createCellTemplate (index);
+ OS.GridViewColumn_CellTemplate (column.handle, template);
+ OS.GCHandle_Free (template);
+ int gvColumns = OS.GridView_Columns (gridViewHandle);
+ if (columnCount == 0) OS.GridViewColumnCollection_Clear (gvColumns);
+ OS.GridViewColumnCollection_Insert (gvColumns, index, column.handle);
+ OS.GCHandle_Free (gvColumns);
+ // When columnCount is 0, a "default column" is created in
+ // the WPF control, therefore there is no need to manipulate
+ // the item's array the first time a TableColumn is created
+ // because the number of columns in the OS control is still one.
+ if (columnCount != 0) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null) item.columnAdded (index);
+ }
+ OS.GCHandle_Free (items);
+ }
+ if (columns == null) columns = new TableColumn [4];
+ if (columns.length == columnCount) {
+ TableColumn [] newColumns = new TableColumn [columnCount + 4];
+ System.arraycopy(columns, 0, newColumns, 0, columnCount);
+ columns = newColumns;
+ }
+ columns [columnCount] = column;
+ columnCount++;
+}
+
+void createItem (TableItem item, int index) {
+ if (index == -1) index = itemCount;
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (items, index, item.handle);
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ itemCount++;
+}
+
+int defaultBackground () {
+ return display.getSystemColor (SWT.COLOR_LIST_BACKGROUND).handle;
+}
+
+int defaultForeground () {
+ return display.getSystemColor (SWT.COLOR_LIST_FOREGROUND).handle;
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i=0; i<indices.length; i++) {
+ int index = indices [i];
+ if (!(0 <= index && index < itemCount)) continue;
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ OS.ListBoxItem_IsSelected (item, false);
+ OS.GCHandle_Free (item);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @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 deselect (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) return;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ ignoreSelection = true;
+ OS.ListBoxItem_IsSelected (item, false);
+ ignoreSelection = false;
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @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 deselect (int start, int end) {
+ checkWidget ();
+ if (start <= 0 && end >= itemCount - 1) {
+ deselectAll ();
+ } else {
+ start = Math.max (0, start);
+ end = Math.min (end, itemCount - 1);
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i=start; i<=end; i++) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ OS.ListBoxItem_IsSelected (item, false);
+ OS.GCHandle_Free (item);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+ }
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @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 deselectAll () {
+ checkWidget ();
+ ignoreSelection = true;
+ OS.ListBox_UnselectAll(handle);
+ ignoreSelection = false;
+}
+
+void destroyItem (TableColumn column) {
+ int gvColumns = OS.GridView_Columns (gridViewHandle);
+ int index = OS.GridViewColumnCollection_IndexOf (gvColumns, column.handle);
+ boolean removed = OS.GridViewColumnCollection_Remove (gvColumns, column.handle);
+ OS.GCHandle_Free (gvColumns);
+ if (!removed) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ int arrayIndex = -1;
+ for (int i = 0; i < columnCount; i++) {
+ TableColumn tc = columns [i];
+ if (tc.equals(column)) {
+ arrayIndex = i;
+ break;
+ }
+ }
+ columnCount--;
+ columns [arrayIndex] = null;
+ if (arrayIndex < columnCount) System.arraycopy (columns, arrayIndex+1, columns, arrayIndex, columnCount - arrayIndex);
+ if (columnCount == 0) {
+ createDefaultColumn ();
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null) item.columnRemoved (index);
+ }
+ OS.GCHandle_Free (items);
+}
+
+void destroyItem (TableItem item) {
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ OS.ItemCollection_Remove (items, item.handle);
+ ignoreSelection = false;
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemCount--;
+}
+
+int findPartByType (int source, int type) {
+ if (OS.Type_IsInstanceOfType (type, source)) return source;
+ int parent = OS.VisualTreeHelper_GetParent(source);
+ if (parent == 0) return 0;
+ int result = findPartByType(parent, type);
+ if (result != parent) OS.GCHandle_Free(parent);
+ return result;
+}
+
+/**
+ * Returns the column at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ * Columns are returned in the order that they were created.
+ * If no <code>TableColumn</code>s were created by the programmer,
+ * this method will throw <code>ERROR_INVALID_RANGE</code> despite
+ * the fact that a single column of data may be visible in the table.
+ * This occurs when the programmer uses the table like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ */
+public TableColumn getColumn (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < columnCount)) error (SWT.ERROR_INVALID_RANGE);
+ return columns [index];
+}
+
+TableColumn getColumn (int columns, int index) {
+ int gridColumn = OS.GridViewColumnCollection_default (columns, index);
+ int header = OS.GridViewColumn_Header (gridColumn);
+ TableColumn column = (TableColumn) display.getWidget (header);
+ OS.GCHandle_Free (header);
+ OS.GCHandle_Free (gridColumn);
+ return column;
+}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no <code>TableColumn</code>s were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the table like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @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 int getColumnCount () {
+ checkWidget ();
+ return columnCount;
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @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 Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public int[] getColumnOrder () {
+ checkWidget ();
+ int [] order = new int [columnCount];
+ for (int i=0; i<order.length; i++) order [i] = i;
+ int gvColumns = OS.GridView_Columns (gridViewHandle);
+ for (int i = 0; i < order.length; i++) {
+ TableColumn column = columns [i];
+ int index = OS.IList_IndexOf (gvColumns, column.handle);
+ order [index] = i;
+ }
+ OS.GCHandle_Free (gvColumns);
+ return order;
+}
+
+/**
+ * Returns an array of <code>TableColumn</code>s which are the
+ * columns in the receiver. Columns are returned in the order
+ * that they were created. If no <code>TableColumn</code>s were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the table like a list, adding items but
+ * never creating a column.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ */
+public TableColumn [] getColumns () {
+ checkWidget ();
+ TableColumn [] result = new TableColumn [columnCount];
+ for (int i = 0; i < result.length; i++) {
+ result [i] = columns [i];
+ }
+ return result;
+}
+
+/**
+ * Returns the width in pixels of a grid line.
+ *
+ * @return the width of a grid line in pixels
+ *
+ * @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 int getGridLineWidth () {
+ checkWidget ();
+ return 0; //FIXME: No grid lines yet
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public int getHeaderHeight () {
+ checkWidget ();
+ int columns = OS.GridView_Columns (gridViewHandle);
+ int column = OS.GridViewColumnCollection_default (columns, 0);
+ int height = 0;
+ int header = OS.GridViewColumn_Header (column);
+ if (header != 0) {
+ height = (int) OS.FrameworkElement_ActualHeight (header);
+ if (height == 0) {
+ updateLayout (header);
+ height = (int) OS.FrameworkElement_ActualHeight (header);
+ }
+ OS.GCHandle_Free (header);
+ }
+ OS.GCHandle_Free (column);
+ OS.GCHandle_Free (columns);
+ return height;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's header is visible,
+ * and <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's header's visibility 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>
+ */
+public boolean getHeaderVisible () {
+ checkWidget ();
+ int columns = OS.GridView_Columns (gridViewHandle);
+ int column = OS.GridViewColumnCollection_default (columns, 0);
+ int header = OS.GridViewColumn_Header (column);
+ boolean visible = OS.UIElement_Visibility (header) == OS.Visibility_Visible;
+ OS.GCHandle_Free (header);
+ OS.GCHandle_Free (column);
+ OS.GCHandle_Free (columns);
+ return visible;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 TableItem getItem (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ TableItem item = getItem (items, index, true);
+ OS.GCHandle_Free (items);
+ return item;
+}
+
+TableItem getItem (int items, int index, boolean create) {
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ TableItem result = getItem (item, create);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+TableItem getItem (int item, boolean create) {
+ int tag = OS.FrameworkElement_Tag (item);
+ if (tag != 0) {
+ int contentValue = OS.IntPtr_ToInt32 (tag);
+ OS.GCHandle_Free (tag);
+ return (TableItem) OS.JNIGetObject (contentValue);
+ }
+ if (create) {
+ int itemHandle = OS.GCHandle_Alloc (item);
+ return new TableItem (this, SWT.NONE, 0, itemHandle);
+ }
+ return null;
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ * <p>
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ * </p>
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 TableItem getItem (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int pt = OS.gcnew_Point (point.x, point.y);
+ int input = OS.UIElement_InputHitTest (handle, pt);
+ OS.GCHandle_Free (pt);
+ if (input == 0) return null;
+ Widget widget = display.getWidget (input);
+ OS.GCHandle_Free (input);
+ if (widget instanceof TableItem) {
+ return (TableItem) widget;
+ }
+ return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the receiver.
+ *
+ * @return the height of one item
+ *
+ * @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 int getItemHeight () {
+ checkWidget ();
+ //FIXME what is the default size?
+ if (itemCount == 0) return 16;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, 0);
+ double height = OS.FrameworkElement_ActualHeight (item);
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+ return height != 0 ? (int) height : 16;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>TableItem</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 TableItem [] getItems () {
+ checkWidget ();
+ TableItem [] result = new TableItem [itemCount];
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ result [i] = getItem (items, i, true);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's lines are visible,
+ * and <code>false</code> otherwise. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the visibility state of the lines
+ *
+ * @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 boolean getLinesVisible () {
+ checkWidget ();
+ //TODO
+ return linesVisible;
+}
+
+/**
+ * Returns an array of <code>TableItem</code>s that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @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 TableItem [] getSelection () {
+ checkWidget ();
+ int selected = OS.ListBox_SelectedItems (handle);
+ int enumerator = OS.IList_GetEnumerator (selected);
+ int count = OS.ICollection_Count (selected);
+ TableItem [] result = new TableItem [count];
+ int index = 0;
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int item = OS.IEnumerator_Current (enumerator);
+ result [index++] = getItem (item, true);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (selected);
+ return result;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @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 int getSelectionCount () {
+ checkWidget ();
+ int selected = OS.ListBox_SelectedItems (handle);
+ int count = OS.ICollection_Count (selected);
+ OS.GCHandle_Free (selected);
+ return count;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @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 int getSelectionIndex () {
+ checkWidget ();
+ return OS.Selector_SelectedIndex (handle);
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return the array of indices of the selected items
+ *
+ * @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 int [] getSelectionIndices () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int list = OS.ListBox_SelectedItems (handle);
+ int enumerator = OS.IList_GetEnumerator (list);
+ int count = OS.ICollection_Count (list);
+ int [] indices = new int [count];
+ int index = 0;
+ while (OS.IEnumerator_MoveNext (enumerator)) {
+ int item = OS.IEnumerator_Current (enumerator);
+ indices [index++] = OS.ItemCollection_IndexOf (items, item);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (list);
+ OS.GCHandle_Free (items);
+ sortAscending (indices);
+ return indices;
+}
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @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 #setSortColumn(TableColumn)
+ *
+ * @since 3.2
+ */
+public TableColumn getSortColumn () {
+ checkWidget ();
+ //TODO
+ return null;
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of <code>UP</code>, <code>DOWN</code>
+ * or <code>NONE</code>.
+ *
+ * @return the sort direction
+ *
+ * @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 #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+ checkWidget ();
+ //TODO
+ return -1;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @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 int getTopIndex () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, 0);
+ OS.GCHandle_Free (items);
+ int virtualizingStackPanel = OS.VisualTreeHelper_GetParent (item);
+ OS.GCHandle_Free (item);
+ int topIndex = 0;
+ if (virtualizingStackPanel != 0) {
+ topIndex = (int) OS.VirtualizingStackPanel_VerticalOffset (virtualizingStackPanel);
+ OS.GCHandle_Free (virtualizingStackPanel);
+ }
+ return topIndex;
+}
+
+boolean hasItems () {
+ return true;
+}
+
+void HandleChecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ TableItem item = (TableItem) display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (item.grayed) {
+ int checkbox = item.findPart (0, CHECKBOX_PART_NAME);
+ if (checkbox != 0) {
+ OS.ToggleButton_IsCheckedNullSetter (checkbox);
+ OS.GCHandle_Free (checkbox);
+ }
+ }
+ item.checked = true;
+ Event event = new Event ();
+ event.item = item;
+ event.detail = SWT.CHECK;
+ sendEvent (SWT.Selection, event);
+}
+
+void HandleIndeterminate (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ TableItem item = (TableItem) display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (!item.grayed) {
+ int checkbox = item.findPart (0, CHECKBOX_PART_NAME);
+ if (checkbox != 0) {
+ OS.ToggleButton_IsChecked (checkbox, false);
+ OS.GCHandle_Free (checkbox);
+ }
+ }
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_Return) {
+ int source = OS.RoutedEventArgs_OriginalSource (e);
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget instanceof TableItem) {
+ Event event = new Event ();
+ event.item = (TableItem)widget;
+ postEvent (SWT.DefaultSelection, event);
+ }
+ }
+}
+
+void HandleMouseDoubleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int source = OS.RoutedEventArgs_OriginalSource (e);
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget instanceof TableItem) {
+ Event event = new Event ();
+ event.item = (TableItem)widget;
+ postEvent (SWT.DefaultSelection, event);
+ }
+}
+
+void HandleSelectionChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int item = 0;
+ int list = OS.SelectionChangedEventArgs_AddedItems (e);
+ if (list != 0) {
+ int count = OS.ICollection_Count (list);
+ if (count > 0) item = OS.IList_default (list, count - 1);
+ }
+ OS.GCHandle_Free (list);
+ if (item == 0) {
+ list = OS.SelectionChangedEventArgs_RemovedItems (e);
+ int count = OS.ICollection_Count (list);
+ if (count > 0) item = OS.IList_default (list, count - 1);
+ OS.GCHandle_Free (list);
+ }
+ if (item != 0) {
+ TableItem result = getItem (item, true);
+ OS.GCHandle_Free (item);
+ if (result != null) {
+ Event event = new Event ();
+ event.item = result;
+ postEvent (SWT.Selection, event);
+ }
+ }
+}
+
+void HandleUnchecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ TableItem item = (TableItem) display.getWidget (source);
+ OS.GCHandle_Free (source);
+ item.checked = false;
+ Event event = new Event ();
+ event.item = item;
+ event.detail = SWT.CHECK;
+ sendEvent (SWT.Selection, event);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_SelectionChangedEventHandler (jniRef, "HandleSelectionChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Selector_SelectionChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandleMouseDoubleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Control_MouseDoubleClick (handle, handler);
+ OS.GCHandle_Free (handler);
+ if ((style & SWT.CHECK) != 0) {
+ /* Item events */
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleChecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ int event = OS.ToggleButton_CheckedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleUnchecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.ToggleButton_UncheckedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleIndeterminate");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.ToggleButton_IndeterminateEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the column 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 int indexOf (TableColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int columns = OS.GridView_Columns (gridViewHandle);
+ int index = OS.GridViewColumnCollection_IndexOf (columns, column.handle);
+ OS.GCHandle_Free (columns);
+ return index;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item 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 int indexOf (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int items = OS.ItemsControl_Items(handle);
+ int index = OS.ItemCollection_IndexOf(items, item.handle);
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+/**
+ * Returns <code>true</code> if the item is selected,
+ * and <code>false</code> otherwise. Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the selection state of the item at the index
+ *
+ * @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 boolean isSelected (int index) {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ boolean result = OS.ListBoxItem_IsSelected (item);
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+void OnRender (int source, int dc) {
+ if (isDisposed ()) return;
+ int type = OS.ListViewItem_typeid();
+ int itemHandle = findPartByType (source, type);
+ OS.GCHandle_Free (type);
+ TableItem item = getItem (itemHandle, true);
+ OS.GCHandle_Free (itemHandle);
+ if ((item.cached || (style & SWT.VIRTUAL) == 0) && item.rowHandle != 0) return;
+ checkData (item);
+ if (item.rowHandle == 0) {
+ int rowPresenterType = OS.GridViewRowPresenter_typeid ();
+ item.rowHandle = item.findRowPresenter (item.handle, rowPresenterType);
+ OS.GCHandle_Free (rowPresenterType);
+ }
+ int columns = columnCount == 0 ? 1 : columnCount;
+ item.updateCheck ();
+ for (int i=0; i<columns; i++) {
+ item.updateText (i);
+ item.updateImage (i);
+ item.updateBackground (i);
+ item.updateForeground (i);
+ item.updateFont (i);
+ }
+}
+
+int parentingHandle () {
+ return parentingHandle;
+}
+
+void register() {
+ super.register();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ int columns = OS.GridView_Columns (gridViewHandle);
+ for (int i=0; i<columnCount; i++) {
+ TableColumn column = getColumn(columns, i);
+ if (!column.isDisposed ()) column.release (false);
+ }
+ OS.GCHandle_Free (columns);
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ OS.GCHandle_Free (gridViewHandle);
+ gridViewHandle = 0;
+ OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ columns = null;
+}
+
+/**
+ * Removes the items from the receiver's list at the given
+ * zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the indices array 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 remove (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int [] newIndices = new int [indices.length];
+ System.arraycopy (indices, 0, newIndices, 0, indices.length);
+ sort (newIndices);
+ int start = newIndices [newIndices.length - 1], end = newIndices [0];
+ if (!(0 <= start && start <= end && end < itemCount)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ int lastIndex = -1;
+ for (int i = newIndices.length-1; i >= 0; i--) {
+ int index = newIndices [i];
+ if (index != lastIndex) {
+ TableItem item = getItem (items, index, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ OS.ItemCollection_RemoveAt (items, index);
+ lastIndex = index;
+ }
+ }
+ ignoreSelection = false;
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the item from the receiver at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ TableItem item = getItem (items, index, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ ignoreSelection = true;
+ OS.ItemCollection_RemoveAt (items, index);
+ ignoreSelection = false;
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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 remove (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ if (!(0 <= start && start <= end && end < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ if (start == 0 && end == itemCount - 1) {
+ removeAll ();
+ return;
+ }
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i = end; i >= start; i--) {
+ TableItem item = getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ OS.ItemCollection_RemoveAt (items, i);
+ }
+ ignoreSelection = false;
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @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 removeAll () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < itemCount; i++) {
+ TableItem item = getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+
+ ignoreSelection = true;
+ OS.ItemCollection_Clear (items);
+ ignoreSelection = false;
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ * </p>
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices 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>
+ *
+ * @see Table#setSelection(int[])
+ */
+public void select (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ ignoreSelection = true;
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < indices.length; i++) {
+ if (!(0 <= indices[i] && indices[i] < itemCount)) continue;
+ int item = OS.ItemCollection_GetItemAt (items, indices[i]);
+ OS.ListBoxItem_IsSelected (item, true);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (items);
+ ignoreSelection = false;
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 select (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) return;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ ignoreSelection = true;
+ OS.ListBoxItem_IsSelected (item, true);
+ ignoreSelection = false;
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @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 Table#setSelection(int,int)
+ */
+public void select (int start, int end) {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0 && start != end) return;
+ if (start <= 0 && end >= itemCount - 1) {
+ selectAll ();
+ } else {
+ start = Math.max (0, start);
+ end = Math.min (end, itemCount - 1);
+ int items = OS.ItemsControl_Items (handle);
+ ignoreSelection = true;
+ for (int i=start; i<=end; i++) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ OS.ListBoxItem_IsSelected (item, true);
+ OS.GCHandle_Free (item);
+ }
+ ignoreSelection = false;
+ OS.GCHandle_Free (items);
+ }
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ * </p>
+ *
+ * @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 selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ ignoreSelection = true;
+ OS.ListBox_SelectAll (handle);
+ ignoreSelection = false;
+}
+
+void setBackgroundBrush(int brush) {
+ if (brush != 0) {
+ OS.Control_Background (handle, brush);
+ } else {
+ int property = OS.Control_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0) {
+ if (columnCount == 0) {
+ int columns = OS.GridView_Columns (gridViewHandle);
+ int column = OS.GridViewColumnCollection_default (columns, 0);
+ OS.GridViewColumn_Width (column, width);
+ OS.GCHandle_Free (column);
+ OS.GCHandle_Free (columns);
+ }
+ OS.FrameworkElement_Width (handle, width);
+ OS.FrameworkElement_Height (handle, height);
+ }
+ return result;
+}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @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>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ *
+ * @see Table#getColumnOrder()
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setColumnOrder (int [] order) {
+ checkWidget ();
+ if (order == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ int [] oldOrder = getColumnOrder ();
+ boolean reorder = false;
+ boolean [] seen = new boolean [columnCount];
+ for (int i=0; i<order.length; i++) {
+ int index = order [i];
+ if (index < 0 || index >= columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+ seen [index] = true;
+ if (order [i] != oldOrder [i]) reorder = true;
+ }
+ if (!reorder) return;
+ int gvColumns = OS.GridView_Columns (gridViewHandle);
+ for (int i = 0; i < order.length; i++) {
+ TableColumn column = columns [order [i]];
+ int index = OS.IList_IndexOf (gvColumns, column.handle);
+ if (index != i) OS.ObservableCollectionGridViewColumn_Move (gvColumns, index, i);
+ }
+ OS.GCHandle_Free (gvColumns);
+}
+
+void setFont (int font, double size) {
+ if (font != 0) {
+ int fontFamily = OS.Typeface_FontFamily( font);
+ int style = OS.Typeface_Style (font);
+ int weight = OS.Typeface_Weight (font);
+ int stretch = OS.Typeface_Stretch (font);
+ OS.Control_FontFamily (handle, fontFamily);
+ OS.Control_FontStyle (handle, style);
+ OS.Control_FontWeight (handle, weight);
+ OS.Control_FontStretch (handle, stretch);
+ OS.Control_FontSize (handle, size);
+ OS.GCHandle_Free (fontFamily);
+ OS.GCHandle_Free (style);
+ OS.GCHandle_Free (weight);
+ OS.GCHandle_Free (stretch);
+ } else {
+ int property = OS.Control_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Marks the receiver's header as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param show the new visibility 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>
+ */
+public void setHeaderVisible (boolean show) {
+ checkWidget ();
+ int style = 0;
+ if (!show) {
+ style = OS.gcnew_Style ();
+ int dp = OS.UIElement_VisibilityProperty ();
+ int setter = OS.gcnew_SetterVisibility (dp, OS.Visibility_Collapsed);
+ int collection = OS.Style_Setters (style);
+ OS.SetterBaseCollection_Add (collection, setter);
+ OS.GCHandle_Free (collection);
+ OS.GCHandle_Free (setter);
+ OS.GCHandle_Free (dp);
+ }
+ OS.GridView_ColumnHeaderContainerStyle (gridViewHandle, style);
+ if (style != 0) OS.GCHandle_Free (style);
+ for (int i=0; i<columnCount; i++) {
+ TableColumn column = getColumn (i);
+ column.updateImage ();
+ column.updateText ();
+ }
+}
+
+/**
+ * Sets the number of items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void setItemCount (int count) {
+ checkWidget ();
+ count = Math.max (0, count);
+ if (count == itemCount) return;
+ int index = itemCount - 1;
+ int items = OS.ItemsControl_Items (handle);
+ while (index >= count) {
+ TableItem item = getItem (items, index, false);
+ if (item != null) {
+ if (!item.isDisposed()) item.release (true);
+ } else {
+ OS.ItemCollection_RemoveAt (items, index);
+ }
+ index--;
+ }
+ if (OS.ItemCollection_Count (items) > count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ if ((style & SWT.VIRTUAL) != 0) {
+ for (int i=itemCount; i<count; i++) {
+ int item = OS.gcnew_ListViewItem ();
+ if (item == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ItemCollection_Add (items, item);
+ OS.GCHandle_Free (item);
+ }
+ } else {
+ for (int i=itemCount; i<count; i++) {
+ new TableItem (this, SWT.NONE, i);
+ }
+ }
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount != count) error (SWT.ERROR_ITEM_NOT_ADDED);
+}
+
+/**
+ * Sets the height of the area which would be used to
+ * display <em>one</em> of the items in the table.
+ *
+ * @return the height of one item
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+ checkWidget ();
+}
+
+/**
+ * Marks the receiver's lines as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise. Note that some platforms draw grid lines
+ * while others may draw alternating row colors.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param show the new visibility 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>
+ */
+public void setLinesVisible (boolean show) {
+ checkWidget ();
+ linesVisible = show;
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ * </p>
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices 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>
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int[])
+ */
+public void setSelection (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ select (indices);
+ //TODO
+// int focusIndex = indices [0];
+// if (focusIndex != -1) setFocusIndex (focusIndex);
+ showSelection ();
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected.
+ * <p>
+ * If the item is not in the receiver, then it is ignored.
+ * </p>
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.2
+ */
+public void setSelection (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TableItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ * </p>
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</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>
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int[])
+ * @see Table#setSelection(int[])
+ */
+public void setSelection (TableItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = items.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ for (int i=0; i<length; i++) {
+ int index = indexOf (items [i]);
+ if (index != -1) {
+ select (index);
+ }
+ }
+ //TODO
+// if (focusIndex != -1) setFocusIndex (focusIndex);
+ showSelection ();
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * The current selection is first cleared, then the new item is selected.
+ *
+ * @param index the index of the item to select
+ *
+ * @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 Table#deselectAll()
+ * @see Table#select(int)
+ */
+public void setSelection (int index) {
+ checkWidget ();
+ deselectAll ();
+ select (index);
+ //TODO
+// if (index != -1) setFocusIndex (index);
+ showSelection ();
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ * </p>
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @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 Table#deselectAll()
+ * @see Table#select(int,int)
+ */
+public void setSelection (int start, int end) {
+ checkWidget ();
+ deselectAll ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ if (itemCount == 0 || start >= itemCount) return;
+ start = Math.max (0, start);
+ end = Math.min (end, itemCount - 1);
+ select (start, end);
+ //TODO
+// setFocusIndex (start);
+ showSelection ();
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator. The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the column is disposed</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>
+ *
+ * @since 3.2
+ */
+public void setSortColumn (TableColumn column) {
+ checkWidget ();
+ if (column != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ //TODO
+// if (sortColumn != null && !sortColumn.isDisposed ()) {
+// sortColumn.setSortDirection (SWT.NONE);
+// }
+// sortColumn = column;
+// if (sortColumn != null && sortDirection != SWT.NONE) {
+// sortColumn.setSortDirection (sortDirection);
+// }
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public void setSortDirection (int direction) {
+ checkWidget ();
+ if ((direction & (SWT.UP | SWT.DOWN)) == 0 && direction != SWT.NONE) return;
+ //TODO
+// sortDirection = direction;
+// if (sortColumn != null && !sortColumn.isDisposed ()) {
+// sortColumn.setSortDirection (direction);
+// }
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @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 setTopIndex (int index) {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Shows the column. If the column is already showing in the receiver,
+ * this method simply returns. Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the column has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void showColumn (TableColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (column.parent != this) return;
+ int index = indexOf (column);
+ if (!(0 <= index && index < columnCount)) return;
+ //TODO
+}
+
+/**
+ * Shows the item. If the item is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @see Table#showSelection()
+ */
+public void showItem (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ OS.ListBox_ScrollIntoView (handle, item.handle);
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @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 Table#showItem(TableItem)
+ */
+public void showSelection () {
+ checkWidget ();
+ int itemCollection = OS.ItemsControl_Items (handle);
+ int list = OS.ListBox_SelectedItems (handle);
+ int enumerator = OS.IList_GetEnumerator (list);
+ if (OS.IEnumerator_MoveNext (enumerator)) {
+ int item = OS.IEnumerator_Current (enumerator);
+ OS.ListBox_ScrollIntoView (handle, item);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (enumerator);
+ OS.GCHandle_Free (list);
+ OS.GCHandle_Free (itemCollection);
+}
+
+int topHandle () {
+ return parentingHandle;
+}
+
+void updateMoveable () {
+ int columns = OS.GridView_Columns (gridViewHandle);
+ boolean moveable = true;
+ for (int i = 0; moveable && i < columnCount; i++) {
+ TableColumn column = getColumn (columns, i);
+ if (!column.moveable) moveable = false;
+ }
+ OS.GCHandle_Free (columns);
+ OS.GridView_AllowsColumnReorder (gridViewHandle, moveable);
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableColumn.java
new file mode 100644
index 0000000000..dd5fdd3ba5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableColumn.java
@@ -0,0 +1,644 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a column in a table widget.
+ * <p><dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TableColumn extends Item {
+ static final int IMAGE_PART = 0;
+ static final int TEXT_PART = 1;
+ int headerHandle, stringHandle;
+ boolean moveable, resizable;
+ Table parent;
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TableColumn (Table parent, int style) {
+ super (parent, checkStyle (style));
+ resizable = true;
+ this.parent = parent;
+ parent.createItem (this, parent.getColumnCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TableColumn (Table parent, int style, int index) {
+ super (parent, checkStyle (style));
+ resizable = true;
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the column header is selected.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandle () {
+ handle = OS.gcnew_GridViewColumn ();
+ if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ headerHandle = OS.gcnew_GridViewColumnHeader ();
+ OS.GridViewColumn_Header (handle, headerHandle);
+}
+
+void deregister () {
+ display.removeWidget (headerHandle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+int findPart (String part) {
+ updateLayout (headerHandle);
+ int headerTemplate = OS.Control_Template (headerHandle);
+ int name = createDotNetString ("HeaderContent", false);
+ int contentPresenter = OS.FrameworkTemplate_FindName (headerTemplate, name, headerHandle);
+ OS.GCHandle_Free (name);
+ OS.GCHandle_Free (headerTemplate);
+ if (contentPresenter == 0) return 0;
+ int dataTemplate = OS.GridViewColumn_HeaderTemplate (handle);
+ name = createDotNetString (part, false);
+ int result = OS.FrameworkTemplate_FindName (dataTemplate, name, contentPresenter);
+ OS.GCHandle_Free (contentPresenter);
+ OS.GCHandle_Free (dataTemplate);
+ OS.GCHandle_Free (name);
+ return result;
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @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 int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Table</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Table getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @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 Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public boolean getMoveable () {
+ checkWidget ();
+ return moveable;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @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 boolean getResizable () {
+ checkWidget ();
+ return resizable;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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>
+ *
+ * @since 3.2
+ */
+public String getToolTipText () {
+ checkWidget ();
+ int strPtr = OS.FrameworkElement_ToolTip (headerHandle);
+ String string = createJavaString (strPtr);
+ OS.GCHandle_Free (strPtr);
+ return string;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @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 int getWidth () {
+ checkWidget ();
+ return (int) OS.GridViewColumn_ActualWidth (handle);
+}
+
+void HandleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ postEvent (SWT.Selection);
+}
+
+void HandleLoaded (int sender, int e) {
+ if (isDisposed ()) return;
+ updateImage ();
+ updateText ();
+}
+
+void HandleMouseDoubleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ postEvent (SWT.DefaultSelection);
+}
+
+void HandleSizeChanged (int sender, int e) {
+ if (!checkEvent(e)) return;
+ sendEvent (SWT.Resize);
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleLoaded");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Loaded (headerHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ int event = OS.ButtonBase_ClickEvent ();
+ OS.UIElement_AddHandler (headerHandle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleMouseDoubleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.Control_MouseDoubleClickEvent ();
+ OS.UIElement_AddHandler (headerHandle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleSizeChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.FrameworkElement_SizeChangedEvent ();
+ OS.UIElement_AddHandler (headerHandle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @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 pack () {
+ checkWidget ();
+ updateLayout (parent.handle);
+ double width = 0;
+ if (headerHandle != 0) {
+ int size = OS.UIElement_DesiredSize (headerHandle);
+ width = OS.Size_Width (size);
+ OS.GCHandle_Free (size);
+ }
+ int columnIndex = parent.indexOf (this);
+ int items = OS.ItemsControl_Items (parent.handle);
+ for (int i=0; i<parent.itemCount; i++) {
+ TableItem item = parent.getItem (items, i, false);
+ if (item != null) {
+ width = Math.max (width, item.computeWidth (columnIndex));
+ }
+ }
+ OS.GCHandle_Free (items);
+ OS.GridViewColumn_Width (handle, width);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ OS.GCHandle_Free (headerHandle);
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ if (stringHandle != 0) OS.GCHandle_Free (stringHandle);
+ stringHandle = 0;
+}
+
+void register() {
+ display.addWidget (headerHandle, this);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
+ * or <code>CENTER</code>.
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
+ * @param alignment the new alignment
+ *
+ * @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 setAlignment (int alignment) {
+ checkWidget ();
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ int index = parent.indexOf (this);
+ if (index == -1 || index == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ //TODO
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ super.setImage (image);
+ updateImage ();
+}
+
+/**
+ * Sets the moveable attribute. A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @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 Table#setColumnOrder(int[])
+ * @see Table#getColumnOrder()
+ * @see TableColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setMoveable (boolean moveable) {
+ checkWidget ();
+ this.moveable = moveable;
+ parent.updateMoveable ();
+}
+
+/**
+ * Sets the resizable attribute. A column that is
+ * resizable can be resized by the user dragging the
+ * edge of the header. A column that is not resizable
+ * cannot be dragged by the user but may be resized
+ * by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @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 setResizable (boolean resizable) {
+ checkWidget ();
+ this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+ //TODO
+}
+
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ text = string;
+ updateText ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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>
+ *
+ * @since 3.2
+ */
+public void setToolTipText (String string) {
+ checkWidget ();
+ if (string != null && string.length() == 0) string = null;
+ int strPtr = createDotNetString (string, false);
+ OS.FrameworkElement_ToolTip (headerHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @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 setWidth (int width) {
+ checkWidget ();
+ if (width < 0) return;
+ updateLayout (parent.handle);
+ OS.GridViewColumn_Width (handle, width);
+}
+
+void updateImage() {
+ int part = findPart (Table.IMAGE_PART_NAME);
+ if (part == 0) return;
+ OS.Image_Source (part, image == null ? 0 : image.handle);
+ OS.GCHandle_Free (part);
+}
+
+void updateText () {
+ int part = findPart (Table.TEXT_PART_NAME);
+ if (part == 0) return;
+ int str = createDotNetString (text, false);
+ OS.TextBlock_Text (part, str);
+ OS.GCHandle_Free (str);
+ OS.GCHandle_Free (part);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableItem.java
new file mode 100644
index 0000000000..6e4946d3bc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TableItem.java
@@ -0,0 +1,1208 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents an item in a table.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class TableItem extends Item {
+ Table parent;
+ Image [] images;
+ String [] strings;
+ Color [] cellBackground, cellForeground;
+ Font [] cellFont;
+ int rowHandle;
+ boolean checked, grayed, cached;
+ Color background, foreground;
+ Font font;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 TableItem (Table parent, int style) {
+ this (parent, style, -1);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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 TableItem (Table parent, int style, int index) {
+ this (parent, style, index, 0);
+}
+
+TableItem (Table parent, int style, int index, int handle) {
+ super (parent, style);
+ this.parent = parent;
+ this.handle = handle;
+ if (handle == 0) {
+ parent.createItem (this, index);
+ } else {
+ createWidget ();
+ }
+}
+
+double computeWidth (int columnIndex) {
+ int rowPresenterType = OS.GridViewRowPresenter_typeid ();
+ double width = 0;
+ if (rowHandle != 0) {
+ int contentPresenter = OS.VisualTreeHelper_GetChild (rowHandle, columnIndex);
+ int availSize = OS.gcnew_Size (0x7FFFFFFF,0x7FFFFFFF);
+ OS.UIElement_Measure (contentPresenter, availSize);
+ OS.GCHandle_Free (availSize);
+ int size = OS.UIElement_DesiredSize (contentPresenter);
+ width = OS.Size_Width (size);
+ OS.GCHandle_Free (size);
+ OS.GCHandle_Free (contentPresenter);
+ }
+ OS.GCHandle_Free (rowPresenterType);
+ return width;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void columnAdded (int index) {
+ int newLength = parent.columnCount + 1;
+ if (strings != null) {
+ String [] temp = new String [newLength];
+ System.arraycopy (strings, 0, temp, 0, index);
+ System.arraycopy (strings, index, temp, index + 1, parent.columnCount - index);
+ strings = temp;
+ }
+ if (images != null) {
+ Image [] temp = new Image [newLength];
+ System.arraycopy (images, 0, temp, 0, index);
+ System.arraycopy (images, index, temp, index + 1, parent.columnCount - index);
+ images = temp;
+ }
+ if (cellBackground != null) {
+ Color [] temp = new Color [newLength];
+ System.arraycopy (cellBackground, 0, temp, 0, index);
+ System.arraycopy (cellBackground, index, temp, index + 1, parent.columnCount - index);
+ cellBackground = temp;
+ }
+ if (cellForeground != null) {
+ Color [] temp = new Color [newLength];
+ System.arraycopy (cellForeground, 0, temp, 0, index);
+ System.arraycopy (cellForeground, index, temp, index + 1, parent.columnCount - index);
+ cellForeground = temp;
+ }
+ if (cellFont != null) {
+ Font [] temp = new Font [newLength];
+ System.arraycopy (cellFont, 0, temp, 0, index);
+ System.arraycopy (cellFont, index, temp, index + 1, parent.columnCount - index);
+ cellFont = temp;
+ }
+}
+
+void columnRemoved (int index) {
+ if (strings != null) {
+ String [] temp = new String [parent.columnCount];
+ System.arraycopy (strings, 0, temp, 0, index);
+ System.arraycopy (strings, index + 1, temp, index, parent.columnCount - index);
+ strings = temp;
+ }
+ if (images != null) {
+ Image [] temp = new Image [parent.columnCount];
+ System.arraycopy (images, 0, temp, 0, index);
+ System.arraycopy (images, index + 1, temp, index, parent.columnCount - index);
+ images = temp;
+ }
+ if (cellBackground != null) {
+ Color [] temp = new Color [parent.columnCount];
+ System.arraycopy (cellBackground, 0, temp, 0, index);
+ System.arraycopy (cellBackground, index + 1, temp, index, parent.columnCount - index);
+ cellBackground = temp;
+ }
+ if (cellForeground != null) {
+ Color [] temp = new Color [parent.columnCount];
+ System.arraycopy (cellForeground, 0, temp, 0, index);
+ System.arraycopy (cellForeground, index + 1, temp, index, parent.columnCount - index);
+ cellForeground = temp;
+ }
+ if (cellFont != null) {
+ Font [] temp = new Font [parent.columnCount];
+ System.arraycopy (cellFont, 0, temp, 0, index);
+ System.arraycopy (cellFont, index + 1, temp, index, parent.columnCount - index);
+ cellFont = temp;
+ }
+}
+
+void createHandle () {
+ if (handle == 0) {
+ handle = OS.gcnew_ListViewItem ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ }
+ OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Stretch);
+ OS.Control_VerticalContentAlignment (handle, OS.VerticalAlignment_Stretch);
+}
+
+void clear () {
+ strings = null;
+ images = null;
+ checked = grayed = false;
+ setFont (null);
+ setForeground (null);
+ setBackground (null);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
+ updateCheck ();
+ int columns = parent.columnCount == 0 ? 1 : parent.columnCount;
+ for (int i = 0; i < columns; i++) {
+ updateText (i);
+ updateImage (i);
+ updateBackground (i);
+ updateForeground (i);
+ updateFont (i);
+ }
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
+ int part = findPart (0, Table.RENDER_PANEL_NAME);
+ if (part != 0) OS.UIElement_InvalidateVisual (part);
+ OS.GCHandle_Free (part);
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+int findRowPresenter (int current, int rowPresenterType) {
+ int type = OS.Object_GetType (current);
+ boolean found = OS.Object_Equals (rowPresenterType, type);
+ OS.GCHandle_Free (type);
+ if (found) return current;
+ int childCount = OS.VisualTreeHelper_GetChildrenCount (current);
+ for (int i = 0; i < childCount; i++) {
+ int child = OS.VisualTreeHelper_GetChild (current, i);
+ int result = findRowPresenter (child, rowPresenterType);
+ if (child != result) OS.GCHandle_Free (child);
+ if (result != 0) return result;
+ }
+ return 0;
+}
+
+int findPart (int column, String partName) {
+ if (rowHandle == 0) return 0; //not Loaded yet.
+ updateLayout (rowHandle);
+ int contentPresenter = OS.VisualTreeHelper_GetChild (rowHandle, column);
+ if (contentPresenter == 0) return 0;
+ int columnHandle;
+ if (parent.columnCount == 0) {
+ int columns = OS.GridView_Columns (parent.gridViewHandle);
+ columnHandle = OS.GridViewColumnCollection_default (columns, column);
+ OS.GCHandle_Free (columns);
+ } else {
+ columnHandle = parent.columns [column].handle;
+ }
+ int cellTemplate = OS.GridViewColumn_CellTemplate (columnHandle);
+ int name = createDotNetString (partName, false);
+ int result = OS.FrameworkTemplate_FindName (cellTemplate, name, contentPresenter);
+ OS.GCHandle_Free (contentPresenter);
+ if (parent.columnCount == 0) OS.GCHandle_Free (columnHandle);
+ OS.GCHandle_Free (cellTemplate);
+ OS.GCHandle_Free (name);
+ return result;
+}
+
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public Color getBackground () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return background != null ? background : parent.getBackground ();
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public Color getBackground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getBackground ();
+ if (cellBackground == null || cellBackground [index] == null) return getBackground ();
+ return cellBackground [index];
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public Rectangle getBounds () {
+ checkWidget();
+ return getTextBounds (0);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the table.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @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 Rectangle getBounds (int index) {
+ checkWidget();
+ if (index != 0 && !parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (!(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ int rowPresenterType = OS.GridViewRowPresenter_typeid ();
+ int contentPresenter = OS.VisualTreeHelper_GetChild (rowHandle, index);
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int parentHandle = parent.topHandle ();
+ int location = OS.UIElement_TranslatePoint (contentPresenter, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (contentPresenter);
+ int height = (int) OS.FrameworkElement_ActualHeight (handle);
+ OS.GCHandle_Free (rowPresenterType);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ OS.GCHandle_Free (contentPresenter);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is checked,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the checked state of the checkbox
+ *
+ * @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 boolean getChecked () {
+ checkWidget();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return checked;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return font != null ? font : parent.getFont ();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public Font getFont (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getFont ();
+ if (cellFont == null || cellFont [index] == null) return getFont ();
+ return cellFont [index];
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @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>
+ *
+ * @since 2.0
+ */
+public Color getForeground () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return foreground != null ? foreground : parent.getForeground ();
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public Color getForeground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getForeground ();
+ if (cellForeground == null || cellForeground [index] == null) return getForeground ();
+ return cellForeground [index];
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @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 boolean getGrayed () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return grayed;
+}
+
+public Image getImage () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return getImage (0);
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @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 (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (images != null) {
+ if (0 <= index && index < images.length) return images [index];
+ }
+ return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * table. An empty rectangle is returned if index exceeds
+ * the index of the table's last column.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @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 Rectangle getImageBounds (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index != 0 && !(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ int parentHandle = parent.topHandle ();
+ int image = findPart (index, Table.IMAGE_PART_NAME);
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (image, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (image);
+ int height = (int) OS.FrameworkElement_ActualHeight (image);
+ OS.GCHandle_Free (image);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Gets the image indent.
+ *
+ * @return the indent
+ *
+ * @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 int getImageIndent () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ //TODO
+ return 0;
+// return imageIndent;
+}
+
+String getNameText () {
+ if ((parent.style & SWT.VIRTUAL) != 0) {
+ if (!cached) return "*virtual*"; //$NON-NLS-1$
+ }
+ return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Table</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Table getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of the text at a column in the
+ * table. An empty rectangle is returned if index exceeds
+ * the index of the table's last column.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding text rectangle
+ *
+ * @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>
+ *
+ * @since 3.3
+ */
+public Rectangle getTextBounds (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index != 0 && !(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ int parentHandle = parent.topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int textBlock = findPart (index, Table.TEXT_PART_NAME);
+ int renderPanel = findPart (index, Table.RENDER_PANEL_NAME);
+ Rectangle result = new Rectangle (0, 0, 0, 0);
+ if (textBlock != 0 && renderPanel != 0) {
+ int location = OS.UIElement_TranslatePoint (textBlock, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (location);
+ double textWidth = OS.FrameworkElement_ActualWidth (textBlock);
+ int panelLocation = OS.UIElement_TranslatePoint (textBlock, point, renderPanel);
+ double visibleWidth = Math.max (0, OS.FrameworkElement_ActualWidth (renderPanel) - OS.Point_X (panelLocation));
+ OS.GCHandle_Free (panelLocation);
+ int width = (int) Math.min (textWidth, visibleWidth);
+ int height = (int) OS.FrameworkElement_ActualHeight (textBlock);
+ result = new Rectangle (x, y, width, height);
+ }
+ OS.GCHandle_Free (point);
+ if (textBlock != 0) OS.GCHandle_Free (textBlock);
+ if (renderPanel != 0) OS.GCHandle_Free (renderPanel);
+ return result;
+}
+
+public String getText () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return getText (0);
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @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 (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (strings != null && 0 <= index && index < strings.length) {
+ return strings [index]!= null ? strings[index] : "";
+ }
+ return "";
+}
+
+Control getWidgetControl () {
+ return parent;
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ if (rowHandle != 0) OS.GCHandle_Free (rowHandle);
+ rowHandle = 0;
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ strings = null;
+ images = null;
+ cellBackground = cellForeground = null;
+ cellFont = null;
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 2.0
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (color != null) {
+ int brush = OS.gcnew_SolidColorBrush (color.handle);
+ OS.Control_Background (handle, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ background = color;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void setBackground (int index, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellBackground == null) cellBackground = new Color [count];
+ cellBackground [index] = color;
+ updateBackground (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the checked state of the checkbox for this item. This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param checked the new checked state of the checkbox
+ *
+ * @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 setChecked (boolean checked) {
+ checkWidget();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ if (this.checked == checked) return;
+ this.checked = checked;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ updateCheck ();
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (font != null) {
+ int family = OS.Typeface_FontFamily (font.handle);
+ OS.Control_FontFamily (handle, family);
+ OS.GCHandle_Free (family);
+ int stretch = OS.Typeface_Stretch (font.handle);
+ OS.Control_FontStretch (handle, stretch);
+ OS.GCHandle_Free (stretch);
+ int style = OS.Typeface_Style (font.handle);
+ OS.Control_FontStyle (handle, style);
+ OS.GCHandle_Free (style);
+ int weight = OS.Typeface_Weight (font.handle);
+ OS.Control_FontWeight (handle, weight);
+ OS.GCHandle_Free (weight);
+ OS.Control_FontSize (handle, font.size);
+ } else {
+ int property = OS.Control_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS. Control_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ this.font = font;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void setFont (int index, Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellFont == null) {
+ if (font == null) return;
+ cellFont = new Font [count];
+ }
+ Font oldFont = cellFont [index];
+ if (oldFont == font) return;
+ cellFont [index] = font;
+ if (oldFont != null && oldFont.equals (font)) return;
+ updateFont (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 2.0
+ */
+public void setForeground (Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (color != null) {
+ int brush = OS.gcnew_SolidColorBrush (color.handle);
+ OS.Control_Foreground (handle, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ foreground = color;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void setForeground (int index, Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellForeground == null) cellForeground = new Color [count];
+ cellForeground [index] = color;
+ updateForeground (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item. This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox;
+ *
+ * @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 setGrayed (boolean grayed) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ if (this.grayed == grayed) return;
+ this.grayed = grayed;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ updateCheck ();
+}
+
+/**
+ * Sets the image for multiple columns in the table.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</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 setImage (Image [] images) {
+ checkWidget ();
+ if (images == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<images.length; i++) {
+ setImage (i, images [i]);
+ }
+}
+
+/**
+ * Sets the receiver's image at a column.
+ *
+ * @param index the column index
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (int index, Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (images == null) images = new Image [count];
+ images [index] = image;
+ updateImage (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ setImage (0, image);
+}
+
+/**
+ * Sets the indent of the first column's image, expressed in terms of the image's width.
+ *
+ * @param indent the new indent
+ *
+ * </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>
+ *
+ * @deprecated this functionality is not supported on most platforms
+ */
+public void setImageIndent (int indent) {
+ checkWidget ();
+}
+
+/**
+ * Sets the text for multiple columns in the table.
+ *
+ * @param strings the array of new strings
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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 [] strings) {
+ checkWidget ();
+ if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<strings.length; i++) {
+ String string = strings [i];
+ if (string != null) setText (i, string);
+ }
+}
+
+/**
+ * Sets the receiver's text at a column
+ *
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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 (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (strings == null) strings = new String [count];
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ strings [index] = string;
+ updateText (index);
+}
+
+public void setText (String string) {
+ checkWidget ();
+ setText (0, string);
+}
+
+void updateBackground (int index) {
+ int panel = findPart (index, Table.CONTENTPANEL_PART_NAME);
+ if (panel != 0) {
+ if (cellBackground != null && cellBackground [index] != null) {
+ int brush = OS.gcnew_SolidColorBrush (cellBackground [index].handle);
+ int current = OS.Panel_Background (panel);
+ if (!OS.Object_Equals (brush, current))
+ OS.Panel_Background (panel, brush);
+ OS.GCHandle_Free (current);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Panel_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (panel, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (panel);
+ }
+}
+
+void updateCheck () {
+ if ((parent.style & SWT.CHECK) == 0) return;
+ int checkBox = findPart (0, Table.CHECKBOX_PART_NAME);
+ if (checkBox != 0) {
+ parent.ignoreSelection = true;
+ if (!grayed) {
+ OS.ToggleButton_IsChecked (checkBox, checked);
+ } else {
+ if (checked)
+ OS.ToggleButton_IsCheckedNullSetter (checkBox);
+ }
+ parent.ignoreSelection = false;
+ OS.GCHandle_Free (checkBox);
+ }
+}
+
+void updateFont (int index) {
+ int textBlock = findPart (index, Table.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ Font font = cellFont != null ? cellFont [index] : null;
+ if (font != null) {
+ int family = OS.Typeface_FontFamily (font.handle);
+ OS.TextBlock_FontFamily (textBlock, family);
+ OS.GCHandle_Free (family);
+ int stretch = OS.Typeface_Stretch (font.handle);
+ OS.TextBlock_FontStretch (textBlock, stretch);
+ OS.GCHandle_Free (stretch);
+ int style = OS.Typeface_Style (font.handle);
+ OS.TextBlock_FontStyle (textBlock, style);
+ OS.GCHandle_Free (style);
+ int weight = OS.Typeface_Weight (font.handle);
+ OS.TextBlock_FontWeight (textBlock, weight);
+ OS.GCHandle_Free (weight);
+ OS.TextBlock_FontSize (textBlock, font.size);
+ } else {
+ int property = OS.TextBlock_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+
+void updateForeground (int index) {
+ int textBlock = findPart (index, Table.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ if (cellForeground != null && cellForeground [index] != null) {
+ int brush = OS.gcnew_SolidColorBrush (cellForeground [index].handle);
+ OS.TextBlock_Foreground (textBlock, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+
+void updateImage (int index) {
+ int img = findPart (index, Table.IMAGE_PART_NAME);
+ if (img != 0) {
+ int src = 0;
+ if (images != null) src = images [index] != null ? images [index].handle : 0;
+ int current = OS.Image_Source (img);
+ OS.Image_Source (img, src);
+ OS.GCHandle_Free (current);
+ OS.GCHandle_Free (img);
+ }
+}
+
+void updateText (int index) {
+ int textBlock = findPart (index, Table.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ if (strings != null && strings [index] != null) {
+ int strPtr = createDotNetString (strings [index], false);
+ OS.TextBlock_Text (textBlock, strPtr);
+ OS.GCHandle_Free (strPtr);
+ } else {
+ int property = OS.TextBlock_TextProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Text.java
new file mode 100644
index 0000000000..b5295c1d40
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Text.java
@@ -0,0 +1,1510 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that allow the user to enter and modify text.
+ * Text controls can be either single or multi-line.
+ * When a text control is created with a border, the
+ * operating system includes a platform specific inset
+ * around the contents of the control. When created
+ * without a border, an effort is made to remove the
+ * inset such that the preferred size of the control
+ * is the same size as the contents.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>CENTER, ICON_CANCEL, ICON_SEARCH, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, Modify, Verify</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles MULTI and SINGLE may be specified,
+ * and only one of the styles LEFT, CENTER, and RIGHT may be specified.
+ * </p>
+ * <p>
+ * Note: The styles ICON_CANCEL and ICON_SEARCH are hints used in combination with SEARCH.
+ * When the platform supports the hint, the text control shows these icons. When an icon
+ * is selected, a default selection event is sent with the detail field set to one of
+ * ICON_CANCEL or ICON_SEARCH. Normally, application code does not need to check the
+ * detail. In the case of ICON_CANCEL, the text is cleared before the default selection
+ * event is sent causing the application to search for an empty string.
+ * </p>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#text">Text snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Text extends Scrollable {
+ boolean doubleClick;
+
+ /**
+ * The maximum number of characters that can be entered
+ * into a text widget.
+ * <p>
+ * Note that this value is platform dependent, based upon
+ * the native widget implementation.
+ * </p>
+ */
+ public static final int LIMIT;
+
+ /**
+ * The delimiter used by multi-line text widgets. When text
+ * is queried and from the widget, it will be delimited using
+ * this delimiter.
+ */
+ public static final String DELIMITER;
+
+ /*
+ * This code is intentionally commented.
+ */
+// static final char PASSWORD;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ static {
+ LIMIT = 0x7FFFFFFF;
+ DELIMITER = "\r\n";
+ }
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see SWT#PASSWORD
+ * @see SWT#SEARCH
+ * @see SWT#ICON_SEARCH
+ * @see SWT#ICON_CANCEL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Text (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is not called for texts.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text,
+ * or when ENTER is pressed in a search text. If the receiver has the <code>SWT.SEARCH | SWT.CANCEL</code> style
+ * and the user cancels the search, the event object detail field contains the value <code>SWT.CANCEL</code>.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #removeVerifyListener
+ */
+public void addVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+/**
+ * Appends a string.
+ * <p>
+ * The new text is appended to the text at
+ * the end of the widget.
+ * </p>
+ *
+ * @param string the string to be appended
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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 append (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBox_SelectionStart (handle, getCharCount ());
+ if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+ int start = OS.TextBox_SelectionStart (handle);
+ int end = start + OS.TextBox_SelectionLength (handle);
+ string = verifyText (string, start, end, false);
+ if (string == null) return;
+ }
+ int strPtr = createDotNetString (string, false);
+ OS.TextBoxBase_AppendText (handle, strPtr);
+ OS.TextBox_SelectionLength (handle, 0);
+ OS.GCHandle_Free (strPtr);
+}
+
+static int checkStyle (int style) {
+ if ((style & SWT.SEARCH) != 0) {
+ style |= SWT.SINGLE | SWT.BORDER;
+ style &= ~SWT.PASSWORD;
+ }
+ style &= ~SWT.SEARCH;
+ if ((style & SWT.SINGLE) != 0 && (style & SWT.MULTI) != 0) {
+ style &= ~SWT.MULTI;
+ }
+ style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+ if ((style & SWT.SINGLE) != 0) style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
+ if ((style & SWT.WRAP) != 0) {
+ style |= SWT.MULTI;
+ style &= ~SWT.H_SCROLL;
+ }
+ if ((style & SWT.MULTI) != 0) style &= ~SWT.PASSWORD;
+ if ((style & (SWT.SINGLE | SWT.MULTI)) != 0) return style;
+ if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) return style | SWT.MULTI;
+ return style | SWT.SINGLE;
+}
+
+/**
+ * Clears the selection.
+ *
+ * @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 clearSelection () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ int start = OS.TextBox_SelectionStart (handle);
+ int len = OS.TextBox_SelectionLength (handle);
+ OS.TextBox_SelectionStart (handle, start + len);
+ OS.TextBox_SelectionLength (handle, 0);
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @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 copy () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBoxBase_Copy (handle);
+}
+
+void createHandle () {
+ if ((style & SWT.PASSWORD) != 0) {
+ handle = OS.gcnew_PasswordBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ return;
+ }
+ handle = OS.gcnew_TextBox ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.MULTI) != 0) {
+ OS.TextBoxBase_AcceptsReturn (handle, true);
+ OS.TextBoxBase_AcceptsTab (handle, true);
+ if ((style & SWT.WRAP) != 0) OS.TextBox_TextWrapping (handle, OS.TextWrapping_Wrap);
+ }
+ if ((style & SWT.BORDER) == 0) {
+ int thickness = OS.gcnew_Thickness (0, 0, 0, 0);
+ OS.Control_BorderThickness (handle, thickness);
+ OS.Control_Padding(handle, thickness);
+ OS.GCHandle_Free (thickness);
+ }
+
+ if ((style & SWT.READ_ONLY) != 0) OS.TextBoxBase_IsReadOnly (handle, true);
+ if ((style & SWT.CENTER) != 0) OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Center);
+ if ((style & SWT.RIGHT) != 0) OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Right);
+ if ((style & SWT.V_SCROLL) != 0) OS.TextBoxBase_VerticalScrollBarVisibility (handle, OS.ScrollBarVisibility_Visible);
+ if ((style & SWT.H_SCROLL) != 0) OS.TextBoxBase_HorizontalScrollBarVisibility (handle, OS.ScrollBarVisibility_Visible);
+}
+
+void createWidget () {
+ super.createWidget ();
+ doubleClick = true;
+// setTabStops (8);
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @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 cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBoxBase_Cut (handle);
+}
+
+/**
+ * Returns the line number of the caret.
+ * <p>
+ * The line number of the caret is returned.
+ * </p>
+ *
+ * @return the line number
+ *
+ * @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 int getCaretLineNumber () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return 0;
+ if ((style & SWT.PASSWORD) != 0) return 0;
+ int caretIndex = OS.TextBox_CaretIndex (handle);
+ return OS.TextBox_GetLineIndexFromCharacterIndex (handle, caretIndex);
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ * <p>
+ * The location of the caret is returned.
+ * </p>
+ *
+ * @return a point, the location of the caret
+ *
+ * @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 Point getCaretLocation () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return new Point (0, 0);
+ int caretIndex = OS.TextBox_CaretIndex (handle);
+ int rect = OS.TextBox_GetRectFromCharacterIndex (handle, caretIndex);
+ Point result = new Point ((int)OS.Rect_X (rect), (int)OS.Rect_Y (rect));
+ OS.GCHandle_Free (rect);
+ return result;
+}
+
+/**
+ * Returns the character position of the caret.
+ * <p>
+ * Indexing is zero based.
+ * </p>
+ *
+ * @return the position of the caret
+ *
+ * @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 int getCaretPosition () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return 0;
+ return OS.TextBox_CaretIndex (handle);
+}
+
+/**
+ * Returns the number of characters.
+ *
+ * @return number of characters in the widget
+ *
+ * @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 int getCharCount () {
+ checkWidget ();
+ int text;
+ if ((style & SWT.PASSWORD) != 0) {
+ text = OS.PasswordBox_Password (handle);
+ } else {
+ text = OS.TextBox_Text (handle);
+ }
+ int length = OS.String_Length (text);
+ OS.GCHandle_Free (text);
+ return length;
+}
+
+/**
+ * Returns the double click enabled flag.
+ * <p>
+ * The double click flag enables or disables the
+ * default action of the text widget when the user
+ * double clicks.
+ * </p>
+ *
+ * @return whether or not double click is enabled
+ *
+ * @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 boolean getDoubleClickEnabled () {
+ checkWidget ();
+ return doubleClick;
+}
+
+/**
+ * Returns the echo character.
+ * <p>
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer.
+ * </p>
+ *
+ * @return the echo character
+ *
+ * @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 #setEchoChar
+ */
+public char getEchoChar () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) == 0) return 0;
+ return OS.PasswordBox_PasswordChar (handle);
+}
+
+/**
+ * Returns the editable state.
+ *
+ * @return whether or not the receiver is editable
+ *
+ * @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 boolean getEditable () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return true;
+ return !OS.TextBoxBase_IsReadOnly (handle);
+}
+
+/**
+ * Returns the number of lines.
+ *
+ * @return the number of lines in the widget
+ *
+ * @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 int getLineCount () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return 1;
+ if ((style & SWT.PASSWORD) != 0) return 1;
+ int lines = OS.TextBox_LineCount (handle);
+ if (lines == -1) {
+ updateLayout (handle);
+ lines = OS.TextBox_LineCount (handle);
+ }
+ return lines;
+}
+
+/**
+ * Returns the line delimiter.
+ *
+ * @return a string that is the line delimiter
+ *
+ * @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 #DELIMITER
+ */
+public String getLineDelimiter () {
+ checkWidget ();
+ return DELIMITER;
+}
+
+/**
+ * Returns the height of a line.
+ *
+ * @return the height of a row of 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 int getLineHeight () {
+ checkWidget ();
+ int family = OS.Control_FontFamily (handle);
+ double lineSpacing = OS.FontFamily_LineSpacing (family);
+ OS.GCHandle_Free (family);
+ double size = OS.Control_FontSize (handle);
+ return (int) (lineSpacing * size);
+}
+
+/**
+ * Returns the widget message. The message text is displayed
+ * as a hint for the user, indicating the purpose of the field.
+ * <p>
+ * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
+ * </p>
+ *
+ * @return the widget message
+ *
+ * @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>
+ *
+ * @since 3.3
+ */
+public String getMessage () {
+ checkWidget ();
+ return "";
+}
+
+/**
+ * Returns the orientation of the receiver, which will be one of the
+ * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @return the orientation style
+ *
+ * @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>
+ *
+ * @since 2.1.2
+ */
+public int getOrientation () {
+ checkWidget();
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns a <code>Point</code> whose x coordinate is the
+ * character position representing the start of the selected
+ * text, and whose y coordinate is the character position
+ * representing the end of the selection. An "empty" selection
+ * is indicated by the x and y coordinates having the same value.
+ * <p>
+ * Indexing is zero based. The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ * </p>
+ *
+ * @return a point representing the selection start and end
+ *
+ * @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 Point getSelection () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return new Point (0, 0);
+ int start = OS.TextBox_SelectionStart (handle);
+ int length = OS.TextBox_SelectionLength (handle);
+ return new Point (start, start+length);
+}
+
+/**
+ * Returns the number of selected characters.
+ *
+ * @return the number of selected characters.
+ *
+ * @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 int getSelectionCount () {
+ checkWidget ();
+ Point selection = getSelection ();
+ return selection.y - selection.x;
+}
+
+/**
+ * Gets the selected text, or an empty string if there is no current selection.
+ *
+ * @return the selected 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 getSelectionText () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return "";
+ int content = OS.TextBox_SelectedText (handle);
+ String string = createJavaString (content);
+ OS.GCHandle_Free (content);
+ return string;
+}
+
+/**
+ * Returns the number of tabs.
+ * <p>
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character. The width of a single
+ * tab stop is the pixel width of the spaces.
+ * </p>
+ *
+ * @return the number of tab characters
+ *
+ * @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 int getTabs () {
+ checkWidget ();
+ //FIXME
+ return 8;
+}
+
+/**
+ * Returns the widget text.
+ * <p>
+ * The text for a text widget is the characters in the widget, or
+ * an empty string if this has never been set.
+ * </p>
+ *
+ * @return the widget 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 text;
+ if ((style & SWT.PASSWORD) != 0) {
+ text = OS.PasswordBox_Password (handle);
+ } else {
+ text = OS.TextBox_Text (handle);
+ }
+ String string = createJavaString (text);
+ OS.GCHandle_Free (text);
+ return string;
+}
+
+/**
+ * Returns a range of text. Returns an empty string if the
+ * start of the range is greater than the end.
+ * <p>
+ * Indexing is zero based. The range of
+ * a selection is from 0..N-1 where N is
+ * the number of characters in the widget.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @return the range of 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 (int start, int end) {
+ checkWidget ();
+ if (!(start <= end && 0 <= end)) return "";
+ String text = getText ();
+ int length = text.length();
+ end = Math.min (end, length - 1);
+ if (start > end) return "";
+ start = Math.max (0, start);
+ /*
+ * NOTE: The current implementation uses substring ()
+ * which can reference a potentially large character
+ * array.
+ */
+ return text.substring (start, end + 1);
+}
+
+/**
+ * Returns the maximum number of characters that the receiver is capable of holding.
+ * <p>
+ * If this has not been changed by <code>setTextLimit()</code>,
+ * it will be the constant <code>Text.LIMIT</code>.
+ * </p>
+ *
+ * @return the text limit
+ *
+ * @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 #LIMIT
+ */
+public int getTextLimit () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return OS.PasswordBox_MaxLength (handle);
+ return OS.TextBox_MaxLength (handle);
+}
+
+/**
+ * Returns the zero-relative index of the line which is currently
+ * at the top of the receiver.
+ * <p>
+ * This index can change when lines are scrolled or new lines are added or removed.
+ * </p>
+ *
+ * @return the index of the top line
+ *
+ * @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 int getTopIndex () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return 0;
+ if ((style & SWT.PASSWORD) != 0) return 0;
+ return OS.TextBox_GetFirstVisibleLineIndex (handle);
+}
+
+/**
+ * Returns the top pixel.
+ * <p>
+ * The top pixel is the pixel position of the line
+ * that is currently at the top of the widget. On
+ * some platforms, a text widget can be scrolled by
+ * pixels instead of lines so that a partial line
+ * is displayed at the top of the widget.
+ * </p><p>
+ * The top pixel changes when the widget is scrolled.
+ * The top pixel does not include the widget trimming.
+ * </p>
+ *
+ * @return the pixel position of the top line
+ *
+ * @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 int getTopPixel () {
+ checkWidget ();
+ int name = createDotNetString ("PART_ContentHost", false);
+ int template = OS.Control_Template (handle);
+ int scroller = OS.FrameworkTemplate_FindName (template, name, handle);
+ if (scroller == 0) {
+ updateLayout (handle);
+ scroller = OS.FrameworkTemplate_FindName (template, name, handle);
+ }
+ OS.GCHandle_Free (name);
+ OS.GCHandle_Free (template);
+ if (scroller == 0) return 0;
+ double vertOffset = OS.ScrollViewer_VerticalOffset (scroller);
+ OS.GCHandle_Free (scroller);
+ return (int) vertOffset;
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ if ((style & SWT.SINGLE) != 0) {
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_Return) postEvent (SWT.DefaultSelection);
+ }
+}
+
+void HandlePreviewExecutedRoutedEvent (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int command = OS.ExecutedRoutedEventArgs_Command (e);
+ boolean doVerify = false;
+ String input = null;
+ int paste = OS.ApplicationCommands_Paste ();
+ int cut = OS.ApplicationCommands_Cut ();
+ int redo = OS.ApplicationCommands_Redo ();
+ int undo = OS.ApplicationCommands_Undo ();
+ int backspace = OS.EditingCommands_Backspace ();
+ int delete = OS.EditingCommands_Delete ();
+ int deleteNext = OS.EditingCommands_DeleteNextWord ();
+ int deletePrevious = OS.EditingCommands_DeletePreviousWord ();
+ if (OS.Object_Equals (command, paste)) {
+ doVerify = true;
+ int clipboardText = OS.Clipboard_GetText ();
+ input = createJavaString(clipboardText);
+ OS.GCHandle_Free(clipboardText);
+ } else if (OS.Object_Equals (command, cut)){
+ doVerify = true;
+ input = getSelectionText ();
+ } else if (OS.Object_Equals(command, redo)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals(command, undo)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals (command, backspace)) {
+ doVerify = true;
+ input = "";
+ } else if (OS.Object_Equals (command, delete)) {
+ doVerify = true;
+ input = "";
+ } else if (OS.Object_Equals(command, deleteNext)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ } else if (OS.Object_Equals(command, deletePrevious)) {
+ //FIXME
+ //doVerify = true;
+ OS.ExecutedRoutedEventArgs_Handled (e, true);
+ }
+ OS.GCHandle_Free (paste);
+ OS.GCHandle_Free (cut);
+ OS.GCHandle_Free (redo);
+ OS.GCHandle_Free (undo);
+ OS.GCHandle_Free (backspace);
+ OS.GCHandle_Free (delete);
+ OS.GCHandle_Free (deleteNext);
+ OS.GCHandle_Free (deletePrevious);
+ OS.GCHandle_Free (command);
+ /*
+ * FIXME - should do this first, but for now we want to swallow
+ * all Redo, Undo, DeleteNextWord and DeletePreviousWord to
+ * prevent those from changing the TextBox w/o Verify events
+ */
+ if (!hooks (SWT.Verify)) return;
+ if (!doVerify) return;
+ int start = OS.TextBox_SelectionStart (handle);
+ int end = start + OS.TextBox_SelectionLength (handle);
+ String text = verifyText (input, start, end, true);
+ if (text != null && !text.equals (input)) {
+ int strPtr = createDotNetString (text, false);
+ OS.TextBox_SelectedText (handle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ start = OS.TextBox_SelectionStart (handle);
+ int length = OS.TextBox_SelectionLength (handle);
+ OS.TextBox_Select (handle, start+length, 0);
+ OS.TextBox_SelectionLength (handle, 0);
+ text = null;
+ }
+ if (text == null) OS.ExecutedRoutedEventArgs_Handled (e, true);
+}
+
+void HandlePreviewTextInput (int sender, int e) {
+ super.HandlePreviewTextInput (sender, e);
+ if (!checkEvent (e)) return;
+ if ((style & SWT.PASSWORD) != 0) return;
+ int textPtr = OS.TextCompositionEventArgs_Text (e);
+ String input = createJavaString(textPtr);
+ OS.GCHandle_Free (textPtr);
+ int start = OS.TextBox_SelectionStart (handle);
+ int end = start + OS.TextBox_SelectionLength (handle);
+ String text = verifyText (input, start, end, true);
+ if (text != null && !text.equals (input)) {
+ textPtr = createDotNetString (text, false);
+ OS.TextBox_SelectedText (handle, textPtr);
+ OS.GCHandle_Free (textPtr);
+ start = OS.TextBox_SelectionStart (handle);
+ int length = OS.TextBox_SelectionLength (handle);
+ OS.TextBox_Select (handle, start+length, 0);
+ OS.TextBox_SelectionLength (handle, 0);
+ text = null;
+ }
+ if (text == null) OS.TextCompositionEventArgs_Handled (e, true);
+}
+
+void HandleTextChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ sendEvent (SWT.Modify);
+}
+
+void hookEvents () {
+ super.hookEvents();
+ if ((style & SWT.PASSWORD) != 0) {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleTextChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.PasswordBox_PasswordChanged (handle, handler);
+ OS.GCHandle_Free(handler);
+ return;
+ }
+
+ int handler = OS.gcnew_ExecutedRoutedEventHandler (jniRef, "HandlePreviewExecutedRoutedEvent");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.CommandManager_AddPreviewExecutedHandler (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_TextChangedEventHandler (jniRef, "HandleTextChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.TextBoxBase_TextChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Inserts a string.
+ * <p>
+ * The old selection is replaced with the new text.
+ * </p>
+ *
+ * @param string the string
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string is <code>null</code></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 insert (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.PASSWORD) != 0) return;
+ if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+ int start = OS.TextBox_SelectionStart (handle);
+ string = verifyText (string, start, start, false);
+ if (string == null) return;
+ }
+ int strPtr = createDotNetString (string, false);
+ OS.TextBox_SelectionLength (handle, 0);
+ OS.TextBox_SelectedText (handle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ int end = OS.TextBox_SelectionStart (handle) + OS.TextBox_SelectionLength (handle);
+ OS.TextBox_Select (handle, end, 0);
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @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 paste () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) {
+ OS.PasswordBox_Paste (handle);
+ return;
+ }
+ OS.TextBoxBase_Paste (handle);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ */
+public void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+/**
+ * Selects all the text in the receiver.
+ *
+ * @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 selectAll () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBoxBase_SelectAll (handle);
+}
+
+/**
+ * Sets the double click enabled flag.
+ * <p>
+ * The double click flag enables or disables the
+ * default action of the text widget when the user
+ * double clicks.
+ * </p><p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param doubleClick the new double click flag
+ *
+ * @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 setDoubleClickEnabled (boolean doubleClick) {
+ checkWidget ();
+ this.doubleClick = doubleClick;
+}
+
+/**
+ * Sets the echo character.
+ * <p>
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer. Setting
+ * the echo character to '\0' clears the echo
+ * character and redraws the original text.
+ * If for any reason the echo character is invalid,
+ * or if the platform does not allow modification
+ * of the echo character, the default echo character
+ * for the platform is used.
+ * </p>
+ *
+ * @param echo the new echo character
+ *
+ * @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 setEchoChar (char echo) {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) == 0) return;
+ OS.PasswordBox_PasswordChar (handle, echo);
+}
+
+/**
+ * Sets the editable state.
+ *
+ * @param editable the new editable 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>
+ */
+public void setEditable (boolean editable) {
+ checkWidget ();
+ style &= ~SWT.READ_ONLY;
+ if (!editable) style |= SWT.READ_ONLY;
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBoxBase_IsReadOnly (handle, !editable);
+}
+
+void setFont (int font, double size) {
+ super.setFont (font, size);
+ //FIXME
+// setTabStops (tabs);
+}
+
+/**
+ * Sets the widget message. The message text is displayed
+ * as a hint for the user, indicating the purpose of the field.
+ * <p>
+ * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
+ * </p>
+ *
+ * @param message the new message
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the message 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>
+ *
+ * @since 3.3
+ */
+public void setMessage (String message) {
+ checkWidget ();
+ if (message == null) error (SWT.ERROR_NULL_ARGUMENT);
+ //TODO
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param orientation new orientation style
+ *
+ * @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>
+ *
+ * @since 2.1.2
+ */
+public void setOrientation (int orientation) {
+ checkWidget();
+ int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+ if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
+ style &= ~flags;
+ style |= orientation & flags;
+ //FIXME FrameworkElement.FlowDirection ??
+}
+
+/**
+ * Sets the selection.
+ * <p>
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * regular array indexing rules.
+ * </p>
+ *
+ * @param start new caret position
+ *
+ * @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 setSelection (int start) {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ OS.TextBox_CaretIndex (handle, start);
+}
+
+/**
+ * Sets the selection to the range specified
+ * by the given start and end indices.
+ * <p>
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @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 setSelection (int start, int end) {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ int first = Math.max (Math.min (start, end), 0);
+ int last = Math.min (Math.max (start, end), getCharCount ());
+ OS.TextBox_Select (handle, first, last-first);
+}
+
+/**
+ * Sets the selection to the range specified
+ * by the given point, where the x coordinate
+ * represents the start index and the y coordinate
+ * represents the end index.
+ * <p>
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ * </p>
+ *
+ * @param selection the point
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 setSelection (Point selection) {
+ checkWidget ();
+ if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (selection.x, selection.y);
+}
+
+/**
+ * Sets the number of tabs.
+ * <p>
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character. The width of a single
+ * tab stop is the pixel width of the spaces.
+ * </p>
+ *
+ * @param tabs the number of tabs
+ *
+ * </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 setTabs (int tabs) {
+ checkWidget ();
+ if (tabs < 0) return;
+ //FIXME - no equivalent API in WPF TextBox
+// setTabStops (this.tabs = tabs);
+}
+
+/**
+ * Sets the contents of the receiver to the given string. If the receiver has style
+ * SINGLE and the argument contains multiple lines of text, the result of this
+ * operation is undefined and may vary from platform to platform.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the string 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);
+ if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+ string = verifyText (string, 0, getCharCount (), false);
+ if (string == null) return;
+ }
+ int ptr = createDotNetString (string, false);
+ if ((style & SWT.PASSWORD) != 0) {
+ OS.PasswordBox_Password (handle, ptr);
+ } else {
+ OS.TextBox_Text (handle, ptr);
+ }
+ OS.GCHandle_Free (ptr);
+}
+
+/**
+ * Sets the maximum number of characters that the receiver
+ * is capable of holding to be the argument.
+ * <p>
+ * Instead of trying to set the text limit to zero, consider
+ * creating a read-only text widget.
+ * </p><p>
+ * To reset this value to the default, use <code>setTextLimit(Text.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Text.LIMIT</code> sets the
+ * receiver's limit to <code>Text.LIMIT</code>.
+ * </p>
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</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>
+ *
+ * @see #LIMIT
+ */
+public void setTextLimit (int limit) {
+ checkWidget ();
+ if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+ if (limit < 0) limit = LIMIT;
+ limit = Math.min (limit, LIMIT);
+ if ((style & SWT.PASSWORD) != 0) {
+ OS.PasswordBox_MaxLength (handle, limit);
+ } else {
+ OS.TextBox_MaxLength (handle, limit);
+ }
+}
+
+/**
+ * Sets the zero-relative index of the line which is currently
+ * at the top of the receiver. This index can change when lines
+ * are scrolled or new lines are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @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 setTopIndex (int index) {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ if ((style & SWT.PASSWORD) != 0) return;
+ int count = OS.TextBox_LineCount (handle);
+ if (count == -1) {
+ updateLayout (handle);
+ count = OS.TextBox_LineCount (handle);
+ }
+ index = Math.max(0, Math.min (index, count-1));
+ int family = OS.Control_FontFamily (handle);
+ double lineSpacing = OS.FontFamily_LineSpacing (family);
+ OS.GCHandle_Free (family);
+ double size = OS.Control_FontSize (handle);
+ double lineHeight = lineSpacing * size;
+ int name = createDotNetString ("PART_ContentHost", false);
+ int template = OS.Control_Template (handle);
+ int scroller = OS.FrameworkTemplate_FindName (template, name, handle);
+ OS.GCHandle_Free (name);
+ OS.GCHandle_Free (template);
+ if (scroller == 0) return;
+ double vertOffset = index*lineHeight;
+ OS.ScrollViewer_ScrollToVerticalOffset (scroller, vertOffset);
+ OS.GCHandle_Free (scroller);
+ updateLayout(handle);
+}
+
+/**
+ * Shows the selection.
+ * <p>
+ * If the selection is already showing
+ * in the receiver, this method simply returns. Otherwise,
+ * lines are scrolled until the selection is visible.
+ * </p>
+ *
+ * @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 showSelection () {
+ checkWidget ();
+ if ((style & SWT.PASSWORD) != 0) return;
+ double offset = OS.TextBoxBase_VerticalOffset (handle);
+ OS.TextBoxBase_ScrollToVerticalOffset (handle, offset);
+}
+
+int traversalCode (int key, int event) {
+ int bits = super.traversalCode (key, event);
+ if ((style & SWT.READ_ONLY) != 0) return bits;
+ if ((style & SWT.MULTI) != 0) {
+ bits &= ~SWT.TRAVERSE_RETURN;
+ if (key == OS.Key_Tab && event != 0) {
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice(event);
+ int modifiers = OS.KeyboardDevice_Modifiers(keyboardDevice);
+ OS.GCHandle_Free(keyboardDevice);
+ boolean next = (modifiers & OS.ModifierKeys_Shift) == 0;
+ if (next && (modifiers & OS.ModifierKeys_Control) == 0) {
+ bits &= ~(SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS);
+ }
+ }
+ }
+ return bits;
+}
+
+String verifyText (String string, int start, int end, boolean keyEvent) {
+ Event event = new Event ();
+ event.text = string;
+ event.start = start;
+ event.end = end;
+ if (keyEvent && string.length () == 1) {
+ event.character = string.charAt (0);
+ setInputState (event, SWT.KeyDown, 0, 0);
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in the verify
+ * event. If this happens, answer null to cancel
+ * the operation.
+ */
+ sendEvent (SWT.Verify, event);
+ if (!event.doit || isDisposed ()) return null;
+ return event.text;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolBar.java
new file mode 100644
index 0000000000..ddc1d15a8e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolBar.java
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class support the layout of selectable
+ * tool bar items.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>ToolItem</code>.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add <code>Control</code> children to it,
+ * or set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>FLAT, WRAP, RIGHT, HORIZONTAL, VERTICAL, SHADOW_OUT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#toolbar">ToolBar, ToolItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ToolBar extends Composite {
+ int parentingHandle, trayHandle;
+ int itemCount;
+ Control [] children;
+ int childCount;
+
+ //TEMPORARY CODE
+ static boolean IsVertical;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#FLAT
+ * @see SWT#WRAP
+ * @see SWT#RIGHT
+ * @see SWT#HORIZONTAL
+ * @see SWT#SHADOW_OUT
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass()
+ * @see Widget#getStyle()
+ */
+public ToolBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+
+ /*
+ * Ensure that either of HORIZONTAL or VERTICAL is set.
+ * NOTE: HORIZONTAL and VERTICAL have the same values
+ * as H_SCROLL and V_SCROLL so it is necessary to first
+ * clear these bits to avoid scroll bars and then reset
+ * the bits using the original style supplied by the
+ * programmer.
+ */
+ if ((style & SWT.VERTICAL) != 0) {
+ this.style |= SWT.VERTICAL;
+ } else {
+ this.style |= SWT.HORIZONTAL;
+ }
+}
+
+static int checkStyle (int style) {
+ IsVertical = (style & SWT.V_SCROLL) != 0;
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+void addChild (Control widget) {
+ super.addChild (widget);
+ if (childCount == children.length) {
+ Control [] newChildren = new Control [childCount + 4];
+ System.arraycopy(children, 0, newChildren, 0, childCount);
+ children = newChildren;
+ }
+ children [childCount++] = widget;
+}
+
+int backgroundProperty () {
+ return OS.Control_BackgroundProperty ();
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ return super.computeSize (handle, wHint, hHint, changed);
+}
+
+void createHandle () {
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_ToolBar ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ trayHandle = OS.gcnew_ToolBarTray ();
+ if (trayHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ int brush = OS.Brushes_Transparent ();
+ OS.ToolBarTray_Background (trayHandle, brush);
+ OS.GCHandle_Free (brush);
+ int toolbars = OS.ToolBarTray_ToolBars (trayHandle);
+ OS.IList_Add (toolbars, handle);
+ OS.GCHandle_Free (toolbars);
+ if (IsVertical) OS.ToolBarTray_Orientation (trayHandle, OS.Orientation_Vertical);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, trayHandle);
+ OS.GCHandle_Free (children);
+ //FIXME: FLAT, WRAP, RIGHT, SHADOW_OUT
+}
+
+void createItem (ToolItem item, int index) {
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Insert (items, index, item.topHandle ());
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ itemCount++;
+}
+
+void createWidget () {
+ super.createWidget();
+ children = new Control [4];
+ updateLayout (parentingHandle);
+ setThumbVisibility (OS.Visibility_Collapsed);
+ setButtonVisibility (OS.Visibility_Collapsed);
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+int defaultBackground () {
+ if ((style & SWT.FLAT) != 0) {
+ return OS.Colors_Transparent;
+ }
+ return 0;
+}
+
+void destroyItem (ToolItem item) {
+ int items = OS.ItemsControl_Items (handle);
+ OS.ItemCollection_Remove (items, item.topHandle ());
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemCount--;
+}
+
+Control [] _getChildren () {
+ // return children in reverse order.
+ Control[] result = new Control [childCount];
+ for (int i =0; i < childCount; i++) {
+ result [childCount - i - 1] = children [i];
+ }
+ return result;
+}
+
+ToolItem getItem (int items, int index) {
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ ToolItem result = (ToolItem) display.getWidget (item);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 ToolItem getItem (int index) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ ToolItem result = getItem (items, index);
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 ToolItem getItem (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ ToolItem [] items = getItems ();
+ for (int i=0; i<items.length; i++) {
+ Rectangle rect = items [i].getBounds ();
+ if (rect.contains (point)) return items [i];
+ }
+ return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns an array of <code>ToolItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 ToolItem [] getItems () {
+ checkWidget ();
+ ToolItem [] result = new ToolItem [itemCount];
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < itemCount; i++) {
+ result[i] = getItem (items, i);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+/**
+ * Returns the number of rows in the receiver. When
+ * the receiver has the <code>WRAP</code> style, the
+ * number of rows can be greater than one. Otherwise,
+ * the number of rows is always one.
+ *
+ * @return the number of items
+ *
+ * @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 int getRowCount () {
+ checkWidget ();
+ //FIXME: when WRAP implemented
+ return 1;
+}
+
+boolean hasItems () {
+ return true;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the tool item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the tool item has been disposed</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 int indexOf (ToolItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ int index = OS.ItemCollection_IndexOf (items, item.topHandle ());
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+boolean mnemonicHit (char key) {
+ //TODO
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+// for (int i=0; i<itemCount; i++) {
+// if (mnemonicMatch (items [i].textHandle, key)) return true;
+// }
+ return false;
+}
+
+int parentingHandle () {
+ return parentingHandle;
+}
+
+void register () {
+ super.register ();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ ToolItem item = getItem (items, i);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ super.releaseChildren (destroy);
+}
+
+void removeChild (Control control) {
+ super.removeChild (control);
+ int index = 0;
+ while (index < childCount) {
+ if (children [index] == control) break;
+ index++;
+ }
+ if (index == childCount) return;
+ System.arraycopy (children, index+1, children, index, --childCount - index);
+ children [childCount] = null;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (parentingHandle != 0) OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+ if (trayHandle != 0) OS.GCHandle_Free (trayHandle);
+ trayHandle = 0;
+}
+
+void removeControl (Control control) {
+ super.removeControl (control);
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ ToolItem item = getItem (items, i);
+ if (item.control == control) {
+ item.setControl (null);
+ break;
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+void setButtonVisibility (byte visibility) {
+ int template = OS.Control_Template (handle);
+ int overFlowName = createDotNetString ("OverflowGrid", false);
+ int overFlowGrid = OS.FrameworkTemplate_FindName (template, overFlowName, handle);
+ if (overFlowGrid != 0) {
+ OS.UIElement_Visibility (overFlowGrid, visibility);
+ OS.GCHandle_Free (overFlowGrid);
+ }
+ OS.GCHandle_Free (overFlowName);
+ int borderName = createDotNetString ("MainPanelBorder", false);
+ int border = OS.FrameworkTemplate_FindName (template, borderName, handle);
+ if (border != 0) {
+ int left = visibility == OS.Visibility_Visible ? 11 : 0;
+ int margin = OS.gcnew_Thickness (0, 0, left, 0);
+ OS.FrameworkElement_Margin (border, margin);
+ OS.GCHandle_Free (border);
+ OS.GCHandle_Free (margin);
+ }
+ OS.GCHandle_Free (borderName);
+ OS.GCHandle_Free (template);
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+void setThumbVisibility (byte visibility) {
+ int template = OS.Control_Template (handle);
+ int thumbName = createDotNetString ("ToolBarThumb", false);
+ int thumb = OS.FrameworkTemplate_FindName (template, thumbName, handle);
+ if (thumb != 0) {
+ OS.UIElement_Visibility (thumb, visibility);
+ OS.GCHandle_Free (thumb);
+ }
+ OS.GCHandle_Free (thumbName);
+ OS.GCHandle_Free (template);
+}
+
+int topHandle() {
+ return parentingHandle;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolItem.java
new file mode 100644
index 0000000000..5dda1d3821
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/ToolItem.java
@@ -0,0 +1,849 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a button in a tool bar.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN
+ * may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#toolbar">ToolBar, ToolItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ToolItem extends Item {
+ int imageHandle, textHandle, arrowHandle;
+ ToolBar parent;
+ Control control;
+ String toolTipText;
+ Image disabledImage, hotImage;
+ boolean ignoreSelection;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>ToolBar</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolItem (ToolBar parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>ToolBar</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolItem (ToolBar parent, int style, int index) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool,
+ * the event object detail field contains the value <code>SWT.ARROW</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user,
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+int createArrow () {
+ int geometry = OS.gcnew_StreamGeometry ();
+ int context = OS.StreamGeometry_Open (geometry);
+ int start = OS.gcnew_Point (0, 1);
+ int point = OS.gcnew_Point (3, 4);
+ int end = OS.gcnew_Point (6, 1);
+ OS.StreamGeometryContext_BeginFigure (context, start, true, true);
+ OS.StreamGeometryContext_LineTo (context, point, true, true);
+ OS.StreamGeometryContext_LineTo (context, end, true, true);
+ OS.StreamGeometryContext_Close (context);
+ int path = OS.gcnew_Path ();
+ OS.Path_Data (path, geometry);
+ int padding = OS.gcnew_Thickness (3, 0, 0, 0);
+ OS.FrameworkElement_Margin (path, padding);
+ int brush = OS.Brushes_Black ();
+ OS.Path_Fill (path, brush);
+ OS.FrameworkElement_Width (path, 6);
+ OS.FrameworkElement_Height (path, 6);
+ OS.FrameworkElement_HorizontalAlignment (path, OS.HorizontalAlignment_Center);
+ OS.FrameworkElement_VerticalAlignment (path, OS.VerticalAlignment_Center);
+ OS.GCHandle_Free (padding);
+ OS.GCHandle_Free (start);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (end);
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (context);
+ OS.GCHandle_Free (geometry);
+ return path;
+}
+
+void createHandle () {
+ if ((style & SWT.SEPARATOR) != 0) {
+ handle = OS.gcnew_Separator ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ return;
+ }
+ int bits = SWT.RADIO | SWT.CHECK | SWT.PUSH | SWT.DROP_DOWN;
+ switch (style & bits) {
+ case SWT.RADIO:
+ handle = OS.gcnew_RadioButton();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.CHECK:
+ handle = OS.gcnew_CheckBox();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.DROP_DOWN:
+ handle = OS.gcnew_Button();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ case SWT.PUSH:
+ default:
+ handle = OS.gcnew_Button();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ break;
+ }
+ OS.ToolBar_SetOverflowMode (handle, OS.OverflowMode_Never);
+ imageHandle = OS.gcnew_Image ();
+ if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Image_Stretch (imageHandle, OS.Stretch_None);
+ OS.UIElement_Visibility (imageHandle, OS.Visibility_Collapsed);
+ textHandle = OS.gcnew_AccessText ();
+ if (textHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_VerticalAlignment (textHandle, OS.VerticalAlignment_Center);
+ OS.FrameworkElement_HorizontalAlignment (textHandle, OS.HorizontalAlignment_Center);
+ int panel = OS.gcnew_StackPanel ();
+ if (panel == 0) error (SWT.ERROR_NO_HANDLES);
+ int orientation = (parent.style & SWT.RIGHT) != 0 ? OS.Orientation_Horizontal : OS.Orientation_Vertical;
+ OS.StackPanel_Orientation (panel, orientation);
+ int thickness = OS.gcnew_Thickness (1, 1, 1, 1);
+ if (thickness == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (panel, thickness);
+ OS.GCHandle_Free (thickness);
+ int children = OS.Panel_Children (panel);
+ OS.UIElementCollection_Add (children, imageHandle);
+ OS.UIElementCollection_Add (children, textHandle);
+ if ((style & SWT.DROP_DOWN) != 0) {
+ arrowHandle = createArrow ();
+ if ((parent.style & SWT.RIGHT) != 0) {
+ OS.UIElementCollection_Add (children, arrowHandle);
+ } else {
+ int newPanel = OS.gcnew_StackPanel ();
+ OS.StackPanel_Orientation (newPanel, OS.Orientation_Horizontal);
+ int horizontalChildren = OS.Panel_Children (newPanel);
+ OS.UIElementCollection_Add (horizontalChildren, panel);
+ OS.UIElementCollection_Add (horizontalChildren, arrowHandle);
+ OS.GCHandle_Free (horizontalChildren);
+ OS.GCHandle_Free (panel);
+ panel = newPanel;
+ }
+ }
+ OS.ContentControl_Content (handle, panel);
+ OS.GCHandle_Free (children);
+ OS.GCHandle_Free (panel);
+ int margin = OS.gcnew_Thickness (0, 0, 0, 0);
+ OS.Control_Padding (handle, margin);
+ OS.GCHandle_Free (margin);
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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 Rectangle getBounds () {
+ checkWidget ();
+ int parentHandle = parent.handle;
+ int topHandle = control == null ? topHandle () : control.topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (topHandle, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (topHandle);
+ int height = (int) OS.FrameworkElement_ActualHeight (topHandle);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the control that is used to fill the bounds of
+ * the item when the item is a <code>SEPARATOR</code>.
+ *
+ * @return the control
+ *
+ * @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 Control getControl () {
+ checkWidget ();
+ return control;
+}
+
+/**
+ * Returns the receiver's disabled image if it has one, or null
+ * if it does not.
+ * <p>
+ * The disabled image is displayed when the receiver is disabled.
+ * </p>
+ *
+ * @return the receiver's disabled 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 getDisabledImage () {
+ checkWidget ();
+ return disabledImage;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return OS.UIElement_IsEnabled (handle);
+}
+
+/**
+ * Returns the receiver's hot image if it has one, or null
+ * if it does not.
+ * <p>
+ * The hot image is displayed when the mouse enters the receiver.
+ * </p>
+ *
+ * @return the receiver's hot 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 getHotImage () {
+ checkWidget ();
+ return hotImage;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>ToolBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 ToolBar getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button). If the receiver is of any other type, this method
+ * returns false.
+ * </p>
+ *
+ * @return the selection 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>
+ */
+public boolean getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+ return OS.ToggleButton_IsChecked(handle);
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has not been set.
+ *
+ * @return the receiver's tool tip 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 getToolTipText () {
+ checkWidget ();
+ return toolTipText;
+}
+
+Control getWidgetControl () {
+ return parent;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @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 int getWidth () {
+ checkWidget ();
+ return (int) OS.FrameworkElement_ActualWidth (topHandle ());
+}
+
+void HandleChecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ postEvent (SWT.Selection);
+}
+
+void HandleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ Event event = new Event ();
+ if ((style & SWT.DROP_DOWN) != 0) {
+ int mousePos = OS.Mouse_GetPosition (handle);
+ int zero = OS.gcnew_Point (0, OS.FrameworkElement_ActualHeight (topHandle ()));
+ int arrowPos = OS.UIElement_TranslatePoint (arrowHandle, zero, handle);
+ if (OS.Point_X (mousePos) > OS.Point_X (arrowPos)) {
+ event.detail = SWT.ARROW;
+ int location = OS.UIElement_TranslatePoint (handle, zero, parent.handle);
+ event.x = (int) OS.Point_X (location);
+ event.y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (location);
+ }
+ OS.GCHandle_Free (arrowPos);
+ OS.GCHandle_Free (zero);
+ OS.GCHandle_Free (mousePos);
+ }
+ postEvent (SWT.Selection, event);
+}
+
+void HandleUnchecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ postEvent (SWT.Selection);
+}
+
+void HandleMouseEnter (int sender, int e) {
+ if (!checkEvent (e)) return;
+ updateImages (getEnabled () && parent.getEnabled ());
+}
+
+void HandleMouseLeave (int sender, int e) {
+ if (!checkEvent (e)) return;
+ updateImages (getEnabled () && parent.getEnabled ());
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if ((style & (SWT.RADIO | SWT.CHECK)) != 0) {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleChecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ToggleButton_Checked (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleUnchecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ToggleButton_Unchecked (handle, handler);
+ OS.GCHandle_Free (handler);
+ } else {
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.ButtonBase_Click (handle, handler);
+ OS.GCHandle_Free (handler);
+ }
+ int handler = OS.gcnew_MouseEventHandler (jniRef, "HandleMouseEnter");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.UIElement_MouseEnter (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseEventHandler (jniRef, "HandleMouseLeave");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.UIElement_MouseLeave (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled control is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled 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 #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget ();
+ return getEnabled () && parent.isEnabled ();
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ control = null;
+ toolTipText = null;
+ image = disabledImage = hotImage = null;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ if (imageHandle != 0) {
+ OS.GCHandle_Free (imageHandle);
+ imageHandle = 0;
+ }
+ if (textHandle != 0) {
+ OS.GCHandle_Free (textHandle);
+ textHandle = 0;
+ }
+ if (arrowHandle != 0) {
+ OS.GCHandle_Free (arrowHandle);
+ arrowHandle = 0;
+ }
+ parent = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the control that is used to fill the bounds of
+ * the item when the item is a <code>SEPARATOR</code>.
+ *
+ * @param control the new control
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</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 setControl (Control control) {
+ checkWidget ();
+ if (control != null) {
+ if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if ((style & SWT.SEPARATOR) == 0) return;
+ if (control == null) {
+ int property = OS.Control_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ Control oldControl = this.control;
+ if (oldControl != null && !oldControl.isDisposed ()) OS.Panel_SetZIndex (oldControl.handle, 0);
+ } else {
+ int brush = OS.Brushes_Transparent ();
+ OS.Control_Background (handle, brush);
+ OS.GCHandle_Free (brush);
+ int pt = OS.gcnew_Point (0, 0);
+ if (pt == 0) error (SWT.ERROR_NO_HANDLES);
+ int loc = OS.UIElement_TranslatePoint (handle, pt, parent.parentingHandle);
+ OS.GCHandle_Free (pt);
+ OS.Canvas_SetLeft (control.handle, OS.Point_X (loc));
+ OS.Canvas_SetTop (control.handle, OS.Point_Y (loc));
+ OS.Panel_SetZIndex (control.handle, parent.childCount);
+ OS.GCHandle_Free (loc);
+ }
+ this.control = control;
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise.
+ * <p>
+ * A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ * </p>
+ *
+ * @param enabled the new enabled 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>
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ OS.UIElement_IsEnabled (handle, enabled);
+ updateImages (enabled && parent.getEnabled ());
+ if (arrowHandle != 0) {
+ OS.UIElement_Opacity (arrowHandle, enabled ? 1 : 0.4);
+ }
+}
+
+/**
+ * Sets the receiver's disabled image to the argument, which may be
+ * null indicating that no disabled image should be displayed.
+ * <p>
+ * The disabled image is displayed when the receiver is disabled.
+ * </p>
+ *
+ * @param image the disabled image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setDisabledImage (Image image) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ disabledImage = image;
+ updateImages (getEnabled () && parent.getEnabled ());
+}
+
+/**
+ * Sets the receiver's hot image to the argument, which may be
+ * null indicating that no hot image should be displayed.
+ * <p>
+ * The hot image is displayed when the mouse enters the receiver.
+ * </p>
+ *
+ * @param image the hot image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setHotImage (Image image) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ hotImage = image;
+ updateImages (getEnabled () && parent.getEnabled ());
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ super.setImage (image);
+ updateImages (getEnabled () && parent.getEnabled ());
+}
+
+/**
+ * Sets the selection state of the receiver.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button).
+ * </p>
+ *
+ * @param selected the new selection 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>
+ */
+public void setSelection (boolean selected) {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+ ignoreSelection = true;
+ OS.ToggleButton_IsChecked (handle, selected);
+ ignoreSelection = false;
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (string.equals (text)) return;
+ super.setText (string);
+ int strPtr = createDotNetString (string, true);
+ if (strPtr == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.AccessText_Text (textHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+ OS.UIElement_Visibility (textHandle, string.length() == 0 && image != null ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = image != null && text.length () != 0 ? 3 : 0;
+ int margin = (parent.style & SWT.RIGHT) != 0 ? OS.gcnew_Thickness (0, 0, spacing, 0) : OS.gcnew_Thickness (0, 0, 0, spacing);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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 setToolTipText (String string) {
+ checkWidget ();
+ toolTipText = string;
+ if (string != null && string.length() == 0) string = null;
+ int strPtr = createDotNetString (string, false);
+ OS.FrameworkElement_ToolTip (handle, strPtr);
+ if (strPtr != 0) OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * Sets the width of the receiver, for <code>SEPARATOR</code> ToolItems.
+ *
+ * @param width the new width
+ *
+ * @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 setWidth (int width) {
+ checkWidget ();
+ int controlHandle = control != null ? control.handle : handle;
+ OS.FrameworkElement_Width (controlHandle, width);
+}
+
+void updateImages (boolean enabled) {
+ if ((style & SWT.SEPARATOR) != 0) return;
+ Image next = image;
+ if (image != null && !enabled && disabledImage != null) next = disabledImage;
+ if (image != null && enabled && hotImage != null && OS.UIElement_IsMouseOver (handle)) next = hotImage;
+ OS.Image_Source (imageHandle, next != null ? next.handle : 0);
+ OS.UIElement_Visibility (imageHandle, next != null ? OS.Visibility_Visible : OS.Visibility_Collapsed);
+ OS.UIElement_Visibility (textHandle, next != null && text.length () == 0 ? OS.Visibility_Collapsed : OS.Visibility_Visible);
+ int spacing = next != null && text.length () != 0 ? 3 : 0;
+ int margin = (parent.style & SWT.RIGHT) != 0 ? OS.gcnew_Thickness (0, 0, spacing, 0) : OS.gcnew_Thickness (0, 0, 0, spacing);
+ if (margin == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Margin (imageHandle, margin);
+ OS.GCHandle_Free (margin);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tracker.java
new file mode 100644
index 0000000000..884c71b1cf
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tracker.java
@@ -0,0 +1,892 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class implement rubber banding rectangles that are
+ * drawn onto a parent <code>Composite</code> or <code>Display</code>.
+ * These rectangles can be specified to respond to mouse and key events
+ * by either moving or resizing themselves accordingly. Trackers are
+ * typically used to represent window geometries in a lightweight manner.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, UP, DOWN, RESIZE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Move, Resize</dd>
+ * </dl>
+ * <p>
+ * Note: Rectangle move behavior is assumed unless RESIZE is specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tracker">Tracker snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Tracker extends Widget {
+ Composite parent;
+ boolean cancelled, stippled;
+ Rectangle [] rectangles, proportions;
+ Rectangle bounds;
+ Cursor clientCursor;
+ int resizeCursor, cursorOrientation = SWT.NONE;
+ int oldX, oldY;
+ int canvasHandle;
+ int frame;
+
+ /*
+ * The following values mirror step sizes on Windows
+ */
+ final static int STEPSIZE_SMALL = 1;
+ final static int STEPSIZE_LARGE = 9;
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget 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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ * @see SWT#RESIZE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Tracker (Composite parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p><p>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the tracker on the currently active
+ * display if there is one. If there is no current display, the
+ * tracker is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the tracker on
+ * @param style the style of control to construct
+ *
+ * @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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ * @see SWT#RESIZE
+ */
+public Tracker (Display display, int style) {
+ if (display == null) display = Display.getCurrent ();
+ if (display == null) display = Display.getDefault ();
+ if (!display.isValidThread ()) {
+ error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.style = checkStyle (style);
+ this.display = display;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Resize, typedListener);
+ addListener (SWT.Move, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard, by sending
+ * it one of the messages defined in the <code>KeyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see KeyListener
+ * @see #removeKeyListener
+ */
+public void addKeyListener (KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.KeyUp,typedListener);
+ addListener (SWT.KeyDown,typedListener);
+}
+
+Point adjustMoveCursor () {
+ if (bounds == null) return null;
+ int newX = bounds.x + bounds.width / 2;
+ int newY = bounds.y;
+ Point point = display.map (parent, null, newX, newY);
+ display.setCursorLocation (point);
+ return point;
+}
+
+Point adjustResizeCursor () {
+ if (bounds == null) return null;
+ int newX, newY;
+ if ((cursorOrientation & SWT.LEFT) != 0) {
+ newX = bounds.x;
+ } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+ newX = bounds.x + bounds.width;
+ } else {
+ newX = bounds.x + bounds.width / 2;
+ }
+ if ((cursorOrientation & SWT.UP) != 0) {
+ newY = bounds.y;
+ } else if ((cursorOrientation & SWT.DOWN) != 0) {
+ newY = bounds.y + bounds.height;
+ } else {
+ newY = bounds.y + bounds.height / 2;
+ }
+
+ Point point = display.map (parent, null, newX, newY);
+ display.setCursorLocation (point);
+
+ /*
+ * If the client has not provided a custom cursor then determine
+ * the appropriate resize cursor.
+ */
+ if (clientCursor == null) {
+ int newCursor = 0;
+ switch (cursorOrientation) {
+ case SWT.UP:
+ newCursor = OS.Cursors_SizeNS ();
+ break;
+ case SWT.DOWN:
+ newCursor = OS.Cursors_SizeNS ();
+ break;
+ case SWT.LEFT:
+ newCursor = OS.Cursors_SizeWE ();
+ break;
+ case SWT.RIGHT:
+ newCursor = OS.Cursors_SizeWE ();
+ break;
+ case SWT.LEFT | SWT.UP:
+ newCursor = OS.Cursors_SizeNWSE ();
+ break;
+ case SWT.RIGHT | SWT.DOWN:
+ newCursor = OS.Cursors_SizeNWSE ();
+ break;
+ case SWT.LEFT | SWT.DOWN:
+ newCursor = OS.Cursors_SizeNESW ();
+ break;
+ case SWT.RIGHT | SWT.UP:
+ newCursor = OS.Cursors_SizeNESW ();
+ break;
+ default:
+ newCursor = OS.Cursors_SizeAll ();
+ break;
+ }
+ OS.FrameworkElement_Cursor (canvasHandle, newCursor);
+ if (resizeCursor != 0) {
+ OS.GCHandle_Free (resizeCursor);
+ }
+ resizeCursor = newCursor;
+ }
+ return point;
+}
+
+static int checkStyle (int style) {
+ if ((style & (SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN)) == 0) {
+ style |= SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN;
+ }
+ return style;
+}
+
+/**
+ * Stops displaying the tracker rectangles. Note that this is not considered
+ * to be a cancelation by the user.
+ *
+ * @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 close () {
+ checkWidget ();
+ if (frame != 0) OS.DispatcherFrame_Continue(frame, false);
+}
+
+Rectangle computeBounds () {
+ if (rectangles.length == 0) return null;
+ int xMin = rectangles [0].x;
+ int yMin = rectangles [0].y;
+ int xMax = rectangles [0].x + rectangles [0].width;
+ int yMax = rectangles [0].y + rectangles [0].height;
+
+ for (int i = 1; i < rectangles.length; i++) {
+ if (rectangles [i].x < xMin) xMin = rectangles [i].x;
+ if (rectangles [i].y < yMin) yMin = rectangles [i].y;
+ int rectRight = rectangles [i].x + rectangles [i].width;
+ if (rectRight > xMax) xMax = rectRight;
+ int rectBottom = rectangles [i].y + rectangles [i].height;
+ if (rectBottom > yMax) yMax = rectBottom;
+ }
+
+ return new Rectangle (xMin, yMin, xMax - xMin, yMax - yMin);
+}
+
+Rectangle [] computeProportions (Rectangle [] rects) {
+ Rectangle [] result = new Rectangle [rects.length];
+ bounds = computeBounds ();
+ if (bounds != null) {
+ for (int i = 0; i < rects.length; i++) {
+ int x = 0, y = 0, width = 0, height = 0;
+ if (bounds.width != 0) {
+ x = (rects [i].x - bounds.x) * 100 / bounds.width;
+ width = rects [i].width * 100 / bounds.width;
+ } else {
+ width = 100;
+ }
+ if (bounds.height != 0) {
+ y = (rects [i].y - bounds.y) * 100 / bounds.height;
+ height = rects [i].height * 100 / bounds.height;
+ } else {
+ height = 100;
+ }
+ result [i] = new Rectangle (x, y, width, height);
+ }
+ }
+ return result;
+}
+
+/**
+ * Draw the rectangles displayed by the tracker.
+ */
+void drawRectangles () {
+ Rectangle bounds = this.bounds;
+ if (bounds == null) return;
+ int children = OS.Panel_Children (canvasHandle);
+ OS.UIElementCollection_Clear (children);
+ if (parent != null) {
+ Rectangle rect = parent.getClientArea ();
+ rect.intersect (bounds);
+ bounds = rect;
+ Point pt = display.map (parent, null, bounds.x, bounds.y);
+ OS.Popup_HorizontalOffset (handle, pt.x);
+ OS.Popup_VerticalOffset (handle, pt.y);
+ } else {
+ OS.Popup_HorizontalOffset (handle, bounds.x);
+ OS.Popup_VerticalOffset (handle, bounds.y);
+ }
+ OS.FrameworkElement_Width (handle, bounds.width);
+ OS.FrameworkElement_Height (handle, bounds.height);
+ int stroke, brush;
+ if (stippled) {
+ stroke = 3;
+ int pixelFormat = OS.PixelFormats_BlackWhite ();
+ byte [] buffer = {-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0};
+ int image = OS.BitmapSource_Create (8, 8, 96, 96, pixelFormat, 0, buffer, buffer.length, 2);
+ OS.GCHandle_Free (pixelFormat);
+ brush = OS.gcnew_ImageBrush (image);
+ OS.TileBrush_TileMode (brush, OS.TileMode_Tile);
+ OS.TileBrush_Stretch (brush, OS.Stretch_Fill);
+ OS.TileBrush_ViewportUnits (brush, OS.BrushMappingMode_Absolute);
+ int rect = OS.gcnew_Rect (0, 0, OS.BitmapSource_PixelWidth(image), OS.BitmapSource_PixelHeight(image));
+ OS.TileBrush_Viewport (brush, rect);
+ OS.GCHandle_Free (rect);
+ OS.GCHandle_Free (image);
+ } else {
+ stroke = 1;
+ brush = OS.Brushes_Black ();
+ }
+ for (int i = 0; i < rectangles.length; i++) {
+ int child = OS.gcnew_Rectangle ();
+ OS.UIElementCollection_Add (children, child);
+ OS.Shape_StrokeThickness (child, stroke);
+ OS.Shape_Stroke (child, brush);
+ Rectangle rect = rectangles [i];
+ OS.Canvas_SetLeft (child, rect.x - bounds.x);
+ OS.Canvas_SetTop (child, rect.y - bounds.y);
+ OS.FrameworkElement_Width (child, rect.width);
+ OS.FrameworkElement_Height (child, rect.height);
+ OS.GCHandle_Free (child);
+ }
+ OS.GCHandle_Free (brush);
+ OS.GCHandle_Free (children);
+}
+
+/**
+ * Returns the bounds that are being drawn, expressed relative to the parent
+ * widget. If the parent is a <code>Display</code> then these are screen
+ * coordinates.
+ *
+ * @return the bounds of the Rectangles being drawn
+ *
+ * @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 Rectangle [] getRectangles () {
+ checkWidget();
+ int length = 0;
+ if (rectangles != null) length = rectangles.length;
+ Rectangle [] result = new Rectangle [length];
+ for (int i = 0; i < length; i++) {
+ Rectangle current = rectangles [i];
+ result [i] = new Rectangle (current.x, current.y, current.width, current.height);
+ }
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the rectangles are drawn with a stippled line, <code>false</code> otherwise.
+ *
+ * @return the stippled effect of the rectangles
+ *
+ * @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 boolean getStippled () {
+ checkWidget ();
+ return stippled;
+}
+
+void HandleKeyUp (int sender, int e) {
+ if (handle == 0) return;
+ if (!sendKeyEvent (SWT.KeyUp, e, false)) return;
+}
+
+void HandleKeyDown (int sender, int e) {
+ if (handle == 0) return;
+ if (!sendKeyEvent (SWT.KeyDown, e, false)) return;
+
+ boolean ctrlDown = (OS.Keyboard_Modifiers() & OS.ModifierKeys_Control) != 0;
+ int stepSize = ctrlDown ? STEPSIZE_SMALL : STEPSIZE_LARGE;
+ int key = OS.KeyEventArgs_Key(e);
+ int xChange = 0, yChange = 0;
+ switch (key) {
+ case OS.Key_System:
+ case OS.Key_Escape:
+ cancelled = true;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ break;
+ case OS.Key_Return:
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ break;
+ case OS.Key_Left:
+ xChange = -stepSize;
+ break;
+ case OS.Key_Right:
+ xChange = stepSize;
+ break;
+ case OS.Key_Up:
+ yChange = -stepSize;
+ break;
+ case OS.Key_Down:
+ yChange = stepSize;
+ break;
+ }
+ if (xChange != 0 || yChange != 0) {
+ Event event = new Event ();
+ event.x = oldX + xChange;
+ event.y = oldY + yChange;
+ Point cursorPos;
+ if ((style & SWT.RESIZE) != 0) {
+ resizeRectangles (xChange, yChange);
+ sendEvent (SWT.Resize, event);
+ if (isDisposed ()) {
+ cancelled = true;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ return;
+ }
+ drawRectangles ();
+ cursorPos = adjustResizeCursor ();
+ } else {
+ moveRectangles (xChange, yChange);
+ sendEvent (SWT.Move, event);
+ if (isDisposed ()) {
+ cancelled = true;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ return;
+ }
+ drawRectangles ();
+ cursorPos = adjustMoveCursor ();
+ }
+ oldX = cursorPos.x;
+ oldY = cursorPos.y;
+ }
+}
+
+void HandleMouseUp (int sender, int e) {
+ if (handle == 0) return;
+ if (!sendMouseEvent (SWT.MouseUp, e, false)) return;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+}
+
+void HandleMouseDown (int sender, int e) {
+ if (handle == 0) return;
+ if (!sendMouseEvent (SWT.MouseDown, e, false)) return;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+}
+
+void HandleMouseMove (int sender, int e) {
+ if (handle == 0) return;
+ if (!sendMouseEvent (SWT.MouseMove, e, false)) return;
+ int pointCanvas = OS.MouseEventArgs_GetPosition (e, canvasHandle);
+ int point = OS.Visual_PointToScreen (canvasHandle, pointCanvas);
+ int newX = (int) OS.Point_X (point);
+ int newY = (int) OS.Point_Y (point);
+ OS.GCHandle_Free (pointCanvas);
+ OS.GCHandle_Free (point);
+ if (newX != oldX || newY != oldY) {
+ Event event = new Event ();
+ event.x = newX;
+ event.y = newY;
+ if ((style & SWT.RESIZE) != 0) {
+ resizeRectangles (newX - oldX, newY - oldY);
+ sendEvent (SWT.Resize, event);
+ if (isDisposed ()) {
+ cancelled = true;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ }
+ drawRectangles ();
+ Point cursorPos = adjustResizeCursor ();
+ if (cursorPos != null) {
+ newX = cursorPos.x;
+ newY = cursorPos.y;
+ }
+ } else {
+ moveRectangles (newX - oldX, newY - oldY);
+ sendEvent (SWT.Move, event);
+ if (isDisposed ()) {
+ cancelled = true;
+ if (frame != 0) OS.DispatcherFrame_Continue (frame, false);
+ }
+ drawRectangles ();
+ }
+ oldX = newX;
+ oldY = newY;
+ }
+}
+
+void moveRectangles (int xChange, int yChange) {
+ if (bounds == null) return;
+ if (xChange < 0 && ((style & SWT.LEFT) == 0)) xChange = 0;
+ if (xChange > 0 && ((style & SWT.RIGHT) == 0)) xChange = 0;
+ if (yChange < 0 && ((style & SWT.UP) == 0)) yChange = 0;
+ if (yChange > 0 && ((style & SWT.DOWN) == 0)) yChange = 0;
+ if (xChange == 0 && yChange == 0) return;
+ bounds.x += xChange; bounds.y += yChange;
+ for (int i = 0; i < rectangles.length; i++) {
+ rectangles [i].x += xChange;
+ rectangles [i].y += yChange;
+ }
+}
+
+/**
+ * Displays the Tracker rectangles for manipulation by the user. Returns when
+ * the user has either finished manipulating the rectangles or has cancelled the
+ * Tracker.
+ *
+ * @return <code>true</code> if the user did not cancel the Tracker, <code>false</code> otherwise
+ *
+ * @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 boolean open () {
+ checkWidget ();
+ if (rectangles == null) return false;
+ if (rectangles.length == 0) return false;
+ cancelled = false;
+
+ /*
+ * If exactly one of UP/DOWN is specified as a style then set the cursor
+ * orientation accordingly (the same is done for LEFT/RIGHT styles below).
+ */
+ int vStyle = style & (SWT.UP | SWT.DOWN);
+ if (vStyle == SWT.UP || vStyle == SWT.DOWN) {
+ cursorOrientation |= vStyle;
+ }
+ int hStyle = style & (SWT.LEFT | SWT.RIGHT);
+ if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) {
+ cursorOrientation |= hStyle;
+ }
+
+ jniRef = OS.NewGlobalRef (this);
+ if (jniRef == 0) error (SWT.ERROR_NO_HANDLES);
+ handle = OS.gcnew_Popup ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Popup_AllowsTransparency (handle, true);
+
+ canvasHandle = OS.gcnew_Canvas ();
+ if (canvasHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Popup_Child (handle, canvasHandle);
+ OS.UIElement_IsHitTestVisible (canvasHandle, false);
+ OS.FrameworkElement_FocusVisualStyle (canvasHandle, 0);
+ if (clientCursor != null) {
+ OS.FrameworkElement_Cursor (canvasHandle, clientCursor.handle);
+ }
+
+ drawRectangles ();
+
+ OS.Popup_IsOpen (handle, true);
+ OS.UIElement_Focusable (canvasHandle, true);
+ OS.UIElement_Focus (canvasHandle);
+ OS.UIElement_CaptureMouse (canvasHandle);
+
+ boolean mouseDown = OS.Mouse_LeftButton() == OS.MouseButtonState_Pressed;
+ Point cursorPos;
+ if (mouseDown) {
+ int pointCanvas = OS.Mouse_GetPosition (canvasHandle);
+ int point = OS.Visual_PointToScreen (canvasHandle, pointCanvas);
+ cursorPos = new Point ((int) OS.Point_X (point), (int) OS.Point_Y (point));
+ OS.GCHandle_Free (pointCanvas);
+ OS.GCHandle_Free (point);
+ } else {
+ if ((style & SWT.RESIZE) != 0) {
+ cursorPos = adjustResizeCursor ();
+ } else {
+ cursorPos = adjustMoveCursor ();
+ }
+ }
+ oldX = cursorPos.x;
+ oldY = cursorPos.y;
+
+ int handler = OS.gcnew_KeyEventHandler (jniRef, "HandleKeyDown");
+ OS.UIElement_KeyDown (canvasHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_KeyEventHandler (jniRef, "HandleKeyUp");
+ OS.UIElement_KeyUp (canvasHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseEventHandler (jniRef, "HandleMouseMove");
+ OS.UIElement_MouseMove (canvasHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandleMouseUp");
+ OS.UIElement_MouseUp (canvasHandle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandleMouseDown");
+ OS.UIElement_MouseDown (canvasHandle, handler);
+ OS.GCHandle_Free (handler);
+
+ /* Tracker behaves like a Dialog with its own OS event loop. */
+ frame = OS.gcnew_DispatcherFrame ();
+ OS.Dispatcher_PushFrame (frame);
+
+ if (resizeCursor != 0) {
+ OS.GCHandle_Free (resizeCursor);
+ resizeCursor = 0;
+ }
+ OS.UIElement_ReleaseMouseCapture (canvasHandle);
+ OS.Popup_IsOpen (handle, false);
+ OS.GCHandle_Free (canvasHandle);
+ OS.GCHandle_Free (handle);
+ if (frame != 0) OS.GCHandle_Free (frame);
+ OS.DeleteGlobalRef (jniRef);
+ jniRef = handle = canvasHandle = frame = 0;
+
+ return !cancelled;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Resize, listener);
+ eventTable.unhook (SWT.Move, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.KeyUp, listener);
+ eventTable.unhook (SWT.KeyDown, listener);
+}
+
+void resizeRectangles (int xChange, int yChange) {
+ if (bounds == null) return;
+ /*
+ * If the cursor orientation has not been set in the orientation of
+ * this change then try to set it here.
+ */
+ if (xChange < 0 && ((style & SWT.LEFT) != 0) && ((cursorOrientation & SWT.RIGHT) == 0)) {
+ cursorOrientation |= SWT.LEFT;
+ }
+ if (xChange > 0 && ((style & SWT.RIGHT) != 0) && ((cursorOrientation & SWT.LEFT) == 0)) {
+ cursorOrientation |= SWT.RIGHT;
+ }
+ if (yChange < 0 && ((style & SWT.UP) != 0) && ((cursorOrientation & SWT.DOWN) == 0)) {
+ cursorOrientation |= SWT.UP;
+ }
+ if (yChange > 0 && ((style & SWT.DOWN) != 0) && ((cursorOrientation & SWT.UP) == 0)) {
+ cursorOrientation |= SWT.DOWN;
+ }
+
+ /*
+ * If the bounds will flip about the x or y axis then apply the adjustment
+ * up to the axis (ie.- where bounds width/height becomes 0), change the
+ * cursor's orientation accordingly, and flip each Rectangle's origin (only
+ * necessary for > 1 Rectangles)
+ */
+ if ((cursorOrientation & SWT.LEFT) != 0) {
+ if (xChange > bounds.width) {
+ if ((style & SWT.RIGHT) == 0) return;
+ cursorOrientation |= SWT.RIGHT;
+ cursorOrientation &= ~SWT.LEFT;
+ bounds.x += bounds.width;
+ xChange -= bounds.width;
+ bounds.width = 0;
+ if (proportions.length > 1) {
+ for (int i = 0; i < proportions.length; i++) {
+ Rectangle proportion = proportions [i];
+ proportion.x = 100 - proportion.x - proportion.width;
+ }
+ }
+ }
+ } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+ if (bounds.width < -xChange) {
+ if ((style & SWT.LEFT) == 0) return;
+ cursorOrientation |= SWT.LEFT;
+ cursorOrientation &= ~SWT.RIGHT;
+ xChange += bounds.width;
+ bounds.width = 0;
+ if (proportions.length > 1) {
+ for (int i = 0; i < proportions.length; i++) {
+ Rectangle proportion = proportions [i];
+ proportion.x = 100 - proportion.x - proportion.width;
+ }
+ }
+ }
+ }
+ if ((cursorOrientation & SWT.UP) != 0) {
+ if (yChange > bounds.height) {
+ if ((style & SWT.DOWN) == 0) return;
+ cursorOrientation |= SWT.DOWN;
+ cursorOrientation &= ~SWT.UP;
+ bounds.y += bounds.height;
+ yChange -= bounds.height;
+ bounds.height = 0;
+ if (proportions.length > 1) {
+ for (int i = 0; i < proportions.length; i++) {
+ Rectangle proportion = proportions [i];
+ proportion.y = 100 - proportion.y - proportion.height;
+ }
+ }
+ }
+ } else if ((cursorOrientation & SWT.DOWN) != 0) {
+ if (bounds.height < -yChange) {
+ if ((style & SWT.UP) == 0) return;
+ cursorOrientation |= SWT.UP;
+ cursorOrientation &= ~SWT.DOWN;
+ yChange += bounds.height;
+ bounds.height = 0;
+ if (proportions.length > 1) {
+ for (int i = 0; i < proportions.length; i++) {
+ Rectangle proportion = proportions [i];
+ proportion.y = 100 - proportion.y - proportion.height;
+ }
+ }
+ }
+ }
+
+ // apply the bounds adjustment
+ if ((cursorOrientation & SWT.LEFT) != 0) {
+ bounds.x += xChange;
+ bounds.width -= xChange;
+ } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+ bounds.width += xChange;
+ }
+ if ((cursorOrientation & SWT.UP) != 0) {
+ bounds.y += yChange;
+ bounds.height -= yChange;
+ } else if ((cursorOrientation & SWT.DOWN) != 0) {
+ bounds.height += yChange;
+ }
+
+ Rectangle [] newRects = new Rectangle [rectangles.length];
+ for (int i = 0; i < rectangles.length; i++) {
+ Rectangle proportion = proportions[i];
+ newRects[i] = new Rectangle (
+ proportion.x * bounds.width / 100 + bounds.x,
+ proportion.y * bounds.height / 100 + bounds.y,
+ proportion.width * bounds.width / 100,
+ proportion.height * bounds.height / 100);
+ }
+ rectangles = newRects;
+}
+
+/**
+ * Sets the <code>Cursor</code> of the Tracker. If this cursor is <code>null</code>
+ * then the cursor reverts to the default.
+ *
+ * @param newCursor the new <code>Cursor</code> to display
+ *
+ * @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 setCursor(Cursor newCursor) {
+ checkWidget();
+ clientCursor = newCursor;
+ if (canvasHandle != 0) {
+ OS.FrameworkElement_Cursor (canvasHandle, clientCursor != null ? clientCursor.handle : 0);
+ }
+}
+
+/**
+ * Specifies the rectangles that should be drawn, expressed relative to the parent
+ * widget. If the parent is a Display then these are screen coordinates.
+ *
+ * @param rectangles the bounds of the rectangles to be drawn
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of rectangles is null or contains a null rectangle</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 setRectangles (Rectangle [] rectangles) {
+ checkWidget ();
+ if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int length = rectangles.length;
+ this.rectangles = new Rectangle [length];
+ for (int i = 0; i < length; i++) {
+ Rectangle current = rectangles [i];
+ if (current == null) error (SWT.ERROR_NULL_ARGUMENT);
+ this.rectangles [i] = new Rectangle (current.x, current.y, current.width, current.height);
+ }
+ proportions = computeProportions (rectangles);
+}
+
+/**
+ * Changes the appearance of the line used to draw the rectangles.
+ *
+ * @param stippled <code>true</code> if rectangle should appear stippled
+ *
+ * @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 setStippled (boolean stippled) {
+ checkWidget ();
+ this.stippled = stippled;
+ if (handle != 0) {
+ //TODO CHANGE RECT BRUSH
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TrayItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TrayItem.java
new file mode 100644
index 0000000000..15db30ef73
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TrayItem.java
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent icons that can be placed on the
+ * system tray or task bar status area.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, MenuDetect, Selection</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tray">Tray, TrayItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TrayItem extends Item {
+ Tray parent;
+ int id;
+ ToolTip toolTip;
+ String toolTipText;
+ boolean visible = true;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tray</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 TrayItem (Tray parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, parent.getItemCount ());
+ createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the receiver is selected
+ * <code>widgetDefaultSelected</code> is called when the receiver is double-clicked
+ * </p>
+ *
+ * @param listener the listener which should be notified when the receiver is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the platform-specific context menu trigger
+ * has occurred, by sending it one of the messages defined in
+ * the <code>MenuDetectListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see MenuDetectListener
+ * @see #removeMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void addMenuDetectListener (MenuDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MenuDetect, typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandle () {
+ handle = OS.gcnew_NotifyIcon ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.NotifyIcon_Visible (handle, true);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+Point getLocation () {
+ return display.getCursorLocation ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tray</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public Tray getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's tool tip, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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>
+ *
+ * @since 3.2
+ */
+public ToolTip getToolTip () {
+ checkWidget ();
+ return toolTip;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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 getToolTipText () {
+ checkWidget ();
+ return toolTipText;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and
+ * <code>false</code> otherwise.
+ *
+ * @return the receiver's visibility
+ *
+ * @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 boolean getVisible () {
+ checkWidget ();
+ return visible;
+}
+
+void HandleDoubleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (hooks (SWT.DefaultSelection)) {
+ postEvent (SWT.DefaultSelection);
+ }
+ display.wakeThread ();
+}
+
+void HandleMouseDown (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (hooks (SWT.Selection)) {
+ postEvent (SWT.Selection);
+ }
+ display.wakeThread ();
+}
+
+void HandleMouseUp (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (hooks (SWT.MenuDetect)) {
+ int button = OS.FormsMouseEventArgs_Button (e);
+ if (button == OS.MouseButtons_Right) sendEvent (SWT.MenuDetect);
+ }
+ display.wakeThread ();
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ int handler = OS.gcnew_FormsMouseEventHandler (jniRef, "HandleMouseDown");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.NotifyIcon_MouseDown (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_FormsMouseEventHandler (jniRef, "HandleMouseUp");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.NotifyIcon_MouseUp (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_EventHandler (jniRef, "HandleDoubleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.NotifyIcon_DoubleClick (handle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+void releaseHandle () {
+ setImage (null);
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ parent = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the platform-specific context menu trigger has
+ * occurred.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see MenuDetectListener
+ * @see #addMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void removeMenuDetectListener (MenuDetectListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MenuDetect, listener);
+}
+
+/**
+ * Sets the receiver's image.
+ *
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ super.setImage (image);
+ if (image != null) {
+ int format = OS.PixelFormats_Bgra32 ();
+ int newImage = OS.gcnew_FormatConvertedBitmap (image.handle, format, OS.BitmapSource_Palette(image.handle), 0);
+ int depth = OS.PixelFormat_BitsPerPixel (format);
+ OS.GCHandle_Free (format);
+ int width = OS.BitmapSource_PixelWidth (newImage);
+ int height = OS.BitmapSource_PixelHeight (newImage);
+ int scanlinePad = 4;
+ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad;
+ byte[] buffer = new byte [bytesPerLine * height];
+ int rect = OS.Int32Rect_Empty ();
+ OS.BitmapSource_CopyPixels (newImage, rect, buffer, buffer.length, bytesPerLine);
+ OS.GCHandle_Free (rect);
+ OS.GCHandle_Free (newImage);
+ int bitmap = OS.gcnew_Bitmap (width, height, bytesPerLine, Win32.PixelFormat_Format32bppArgb, buffer);//TODO
+ int hIcon = OS.Bitmap_GetHicon (bitmap);
+ OS.GCHandle_Free (bitmap);
+ int icon = OS.Icon_FromHandle (hIcon);
+ OS.NotifyIcon_Icon (handle, icon);
+ OS.GCHandle_Free (icon);
+ } else {
+ OS.NotifyIcon_Icon (handle, 0);
+ }
+}
+
+/**
+ * Sets the receiver's tool tip to the argument, which
+ * may be null indicating that no tool tip should be shown.
+ *
+ * @param toolTip the new tool tip (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>
+ *
+ * @since 3.2
+ */
+public void setToolTip (ToolTip toolTip) {
+ checkWidget ();
+ this.toolTip = toolTip;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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 setToolTipText (String value) {
+ checkWidget ();
+ toolTipText = value;
+ int strPtr = createDotNetString (value, false);
+ OS.NotifyIcon_Text (handle, strPtr);
+ OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * Makes the receiver visible if the argument is <code>true</code>,
+ * and makes it invisible otherwise.
+ *
+ * @param visible the new visibility 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>
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if (this.visible == visible) 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;
+ }
+ this.visible = visible;
+ OS.NotifyIcon_Visible (handle, visible);
+ if (!visible) sendEvent (SWT.Hide);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tree.java
new file mode 100644
index 0000000000..72d06c0c46
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Tree.java
@@ -0,0 +1,2406 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class provide a selectable user interface object
+ * that displays a hierarchy of items and issues notification when an
+ * item in the hierarchy is selected.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TreeItem</code>.
+ * </p><p>
+ * Style <code>VIRTUAL</code> is used to create a <code>Tree</code> whose
+ * <code>TreeItem</code>s are to be populated by the client on an on-demand basis
+ * instead of up-front. This can provide significant performance improvements for
+ * trees that are very large or for which <code>TreeItem</code> population is
+ * expensive (for example, retrieving values from an external source).
+ * </p><p>
+ * Here is an example of using a <code>Tree</code> with style <code>VIRTUAL</code>:
+ * <code><pre>
+ * final Tree tree = new Tree(parent, SWT.VIRTUAL | SWT.BORDER);
+ * tree.setItemCount(20);
+ * tree.addListener(SWT.SetData, new Listener() {
+ * public void handleEvent(Event event) {
+ * TreeItem item = (TreeItem)event.item;
+ * TreeItem parentItem = item.getParentItem();
+ * String text = null;
+ * if (parentItem == null) {
+ * text = "node " + tree.indexOf(item);
+ * } else {
+ * text = parentItem.getText() + " - " + parentItem.indexOf(item);
+ * }
+ * item.setText(text);
+ * System.out.println(text);
+ * item.setItemCount(10);
+ * }
+ * });
+ * </pre></code>
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL, NO_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles SINGLE and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Tree extends Composite {
+ int gvColumns, parentingHandle, headerTemplate;
+ int columnCount, itemCount;
+ TreeItem anchor, lastSelection, unselect, reselect;
+ TreeColumn [] columns;
+ byte headerVisibility = OS.Visibility_Collapsed;
+ boolean ignoreSelection, shiftDown, ctrlDown;
+
+ static final String HEADER_PART_NAME = "SWT_PART_HEADER";
+ static final String SCROLLVIEWER_PART_NAME = "SWT_PART_SCROLLVIEWER";
+ static final String CHECKBOX_PART_NAME = "SWT_PART_CHECKBOX";
+ static final String IMAGE_PART_NAME = "SWT_PART_IMAGE";
+ static final String TEXT_PART_NAME = "SWT_PART_TEXT";
+ static final String CONTENTPANEL_PART_NAME = "SWT_PART_CONTENTPANEL";
+ static final String RENDER_PANEL_NAME = "SWT_PART_RENDERPANEL";
+
+ static String scrollViewerStyle = "<Style TargetType=\"ScrollViewer\" " +
+ "xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
+ "xmlns:s=\"clr-namespace:System;assembly=mscorlib\" " +
+ "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">" +
+ "<Setter Property=\"UIElement.Focusable\" Value=\"False\"/>" +
+ "<Setter Property=\"Control.Template\">" +
+ "<Setter.Value>" +
+ "<ControlTemplate TargetType=\"ScrollViewer\">" +
+ "<Grid Background=\"{TemplateBinding Control.Background}\" SnapsToDevicePixels=\"True\">" +
+ "<Grid.ColumnDefinitions>" +
+ "<ColumnDefinition Width=\"*\" />" +
+ "<ColumnDefinition Width=\"Auto\" />" +
+ "</Grid.ColumnDefinitions>" +
+ "<Grid.RowDefinitions>" +
+ "<RowDefinition Height=\"*\" />" +
+ "<RowDefinition Height=\"Auto\" />" +
+ "</Grid.RowDefinitions>" +
+ "<DockPanel Margin=\"{TemplateBinding Control.Padding}\">" +
+ "<ScrollViewer HorizontalScrollBarVisibility=\"Hidden\" VerticalScrollBarVisibility=\"Hidden\" Focusable=\"False\" DockPanel.Dock=\"Top\">" +
+ "<GridViewHeaderRowPresenter Name=\"SWT_PART_HEADER\" Margin=\"2,0,2,0\" Visibility=\"Collapsed\" ColumnHeaderToolTip=\"{x:Null}\" " +
+ "ColumnHeaderContainerStyle=\"{x:Null}\" SnapsToDevicePixels=\"{TemplateBinding UIElement.SnapsToDevicePixels}\" " +
+ "AllowsColumnReorder=\"True\" ColumnHeaderTemplate=\"{x:Null}\" ColumnHeaderContextMenu=\"{x:Null}\">" +
+ "<GridViewHeaderRowPresenter.Columns>" +
+ "<TemplateBinding Property=\"GridViewHeaderRowPresenter.Columns\"/>" +
+ "</GridViewHeaderRowPresenter.Columns>" +
+ "</GridViewHeaderRowPresenter>" +
+ "</ScrollViewer>" +
+ "<ScrollContentPresenter VirtualizingStackPanel.IsVirtualizing=\"True\" CanVerticallyScroll=\"False\" " +
+ "CanHorizontallyScroll=\"False\" Name=\"PART_ScrollContentPresenter\" " +
+ "SnapsToDevicePixels=\"{TemplateBinding UIElement.SnapsToDevicePixels}\" " +
+ "ContentTemplate=\"{TemplateBinding ContentControl.ContentTemplate}\" " +
+ "CanContentScroll=\"{TemplateBinding ScrollViewer.CanContentScroll}\" " +
+ "Content=\"{TemplateBinding ContentControl.Content}\" KeyboardNavigation.DirectionalNavigation=\"Local\" />" +
+ "</DockPanel>" +
+ "<ScrollBar Value=\"{TemplateBinding HorizontalOffset}\" Maximum=\"{TemplateBinding ScrollViewer.ScrollableWidth}\" " +
+ "Visibility=\"{TemplateBinding ScrollViewer.ComputedHorizontalScrollBarVisibility}\" Name=\"PART_HorizontalScrollBar\" " +
+ "Cursor=\"Arrow\" Minimum=\"0\" Orientation=\"Horizontal\" Grid.Row=\"1\" " +
+ "ViewportSize=\"{TemplateBinding ViewportWidth}\"/>" +
+ "<ScrollBar Value=\"{TemplateBinding VerticalOffset}\" Maximum=\"{TemplateBinding ScrollViewer.ScrollableHeight}\" " +
+ "Visibility=\"{TemplateBinding ScrollViewer.ComputedVerticalScrollBarVisibility}\" Name=\"PART_VerticalScrollBar\" " +
+ "Cursor=\"Arrow\" Minimum=\"0\" Orientation=\"Vertical\" Grid.Column=\"1\" " +
+ "ViewportSize=\"{TemplateBinding ViewportHeight}\" />" +
+ "<DockPanel Background=\"{x:Null}\" LastChildFill=\"False\" Grid.Column=\"1\" Grid.Row=\"1\">" +
+ "<Rectangle Width=\"1\" Visibility=\"{TemplateBinding ScrollViewer.ComputedVerticalScrollBarVisibility}\" " +
+ "Fill=\"#FFFFFFFF\" DockPanel.Dock=\"Left\" />" +
+ "<Rectangle Height=\"1\" Visibility=\"{TemplateBinding ScrollViewer.ComputedHorizontalScrollBarVisibility}\" " +
+ "Fill=\"#FFFFFFFF\" DockPanel.Dock=\"Top\" />" +
+ "</DockPanel>" +
+ "</Grid>" +
+ "</ControlTemplate>" +
+ "</Setter.Value>" +
+ "</Setter>" +
+ "</Style>";
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see SWT#VIRTUAL
+ * @see SWT#NO_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Tree (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ /*
+ * Feature in Windows. Even when WS_HSCROLL or
+ * WS_VSCROLL is not specified, Windows creates
+ * trees and tables with scroll bars. The fix
+ * is to set H_SCROLL and V_SCROLL.
+ *
+ * NOTE: This code appears on all platforms so that
+ * applications have consistent scroll bar behavior.
+ */
+ if ((style & SWT.NO_SCROLL) == 0) {
+ style |= SWT.H_SCROLL | SWT.V_SCROLL;
+ }
+ /* WPF is always FULL_SELECTION */
+ style |= SWT.FULL_SELECTION;
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has the <code>SWT.CHECK</code> style and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the <code>TreeListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see TreeListener
+ * @see #removeTreeListener
+ */
+public void addTreeListener (TreeListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Expand, typedListener);
+ addListener (SWT.Collapse, typedListener);
+}
+
+int backgroundHandle () {
+ return parentingHandle;
+}
+
+boolean checkData (TreeItem item) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ if (!item.cached) {
+ item.cached = true;
+ int parentItem = OS.FrameworkElement_Parent (item.handle);
+ int items = OS.ItemsControl_Items (parentItem);
+ int index = OS.ItemCollection_IndexOf (items, item.handle);
+ OS.GCHandle_Free (items);
+ OS.GCHandle_Free (parentItem);
+ Event event = new Event ();
+ event.item = item;
+ event.index = index;
+ sendEvent (SWT.SetData, event);
+ if (isDisposed () || item.isDisposed ()) return false;
+ }
+ return true;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the tree was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all <code>true</code> if all child items of the indexed item should be
+ * cleared recursively, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, boolean all) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) SWT.error (SWT.ERROR_INVALID_RANGE);
+ clear (handle, index, all);
+}
+
+void clear (int parentHandle, int index, boolean all) {
+ int items = OS.ItemsControl_Items (parentHandle);
+ TreeItem item = getItem (items, index, false);
+ if (item != null) {
+ item.clear ();
+ if (all) clearAll (item, true);
+ }
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * tree was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @param all <code>true</code> if all child items should be cleared
+ * recursively, and <code>false</code> otherwise
+ *
+ * @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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clearAll (boolean all) {
+ checkWidget ();
+ clearAll (null, all);
+}
+
+void clearAll (TreeItem parentItem, boolean all) {
+ int count = parentItem != null ? parentItem.itemCount : itemCount;
+ int parentHandle = parentItem != null ? parentItem.handle : handle;
+ int items = OS.ItemsControl_Items (parentHandle);
+ for (int i=0; i<count; i++) {
+ TreeItem item = getItem (items, i, false);
+ if (item != null) {
+ item.clear ();
+ if (all) clearAll (item, true);
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+int createCellTemplate (int index) {
+ int template = OS.gcnew_DataTemplate ();
+ int renderPanelType = OS.SWTDockPanel_typeid ();
+ int renderPanelName = createDotNetString(RENDER_PANEL_NAME, false);
+ int onRenderNode = OS.gcnew_FrameworkElementFactory (renderPanelType, renderPanelName);
+ OS.GCHandle_Free(renderPanelName);
+ OS.GCHandle_Free (renderPanelType);
+ int jniRefProperty = OS.SWTDockPanel_JNIRefProperty ();
+ OS.FrameworkElementFactory_SetValueInt (onRenderNode, jniRefProperty, jniRef);
+ OS.GCHandle_Free (jniRefProperty);
+ int contentPanelName = createDotNetString (CONTENTPANEL_PART_NAME, false);
+ int contentPanelType = OS.StackPanel_typeid ();
+ int cellContentNode = OS.gcnew_FrameworkElementFactory (contentPanelType, contentPanelName);
+ OS.GCHandle_Free (contentPanelType);
+ OS.GCHandle_Free (contentPanelName);
+ int clipProperty = OS.UIElement_ClipToBoundsProperty ();
+ OS.FrameworkElementFactory_SetValue (cellContentNode, clipProperty, true);
+ OS.GCHandle_Free (clipProperty);
+ int orientationProperty = OS.StackPanel_OrientationProperty ();
+ OS.FrameworkElementFactory_SetValueOrientation (cellContentNode, orientationProperty, OS.Orientation_Horizontal);
+ OS.GCHandle_Free (orientationProperty);
+
+
+// int vert = OS.FrameworkElement_VerticalAlignmentProperty();
+// OS.FrameworkElementFactory_SetValueVerticalAlignment(onRenderNode, vert, OS.VerticalAlignment_Stretch);
+// OS.GCHandle_Free (vert);
+//
+// int dp = OS.Panel_BackgroundProperty();
+// int red = OS.Brushes_Red();
+// int navy = OS.Brushes_Navy();
+// OS.FrameworkElementFactory_SetValue(cellContentNode, dp, red);
+// OS.FrameworkElementFactory_SetValue(onRenderNode, dp, navy);
+// OS.GCHandle_Free (dp);
+// OS.GCHandle_Free (red);
+// OS.GCHandle_Free (navy);
+
+
+ if (index == 0 && (style & SWT.CHECK) != 0) {
+ int checkBoxType = OS.CheckBox_typeid ();
+ int checkBoxName = createDotNetString (CHECKBOX_PART_NAME, false);
+ int checkBoxNode = OS.gcnew_FrameworkElementFactory (checkBoxType, checkBoxName);
+ int verticalAlignmentProperty = OS.FrameworkElement_VerticalAlignmentProperty ();
+ OS.FrameworkElementFactory_SetValueVerticalAlignment (checkBoxNode, verticalAlignmentProperty, OS.VerticalAlignment_Center);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (checkBoxNode, marginProperty, thickness);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, checkBoxNode);
+ OS.GCHandle_Free (thickness);
+ OS.GCHandle_Free (marginProperty);
+ OS.GCHandle_Free (verticalAlignmentProperty);
+ OS.GCHandle_Free (checkBoxName);
+ OS.GCHandle_Free (checkBoxNode);
+ OS.GCHandle_Free (checkBoxType);
+ }
+ int textType = OS.TextBlock_typeid ();
+ int textName = createDotNetString (TEXT_PART_NAME, false);
+ int textNode = OS.gcnew_FrameworkElementFactory (textType, textName);
+ OS.GCHandle_Free (textName);
+ OS.GCHandle_Free (textType);
+ int verticalAlignmentProperty = OS.FrameworkElement_VerticalAlignmentProperty ();
+ OS.FrameworkElementFactory_SetValueVerticalAlignment (textNode, verticalAlignmentProperty, OS.VerticalAlignment_Center);
+ OS.GCHandle_Free (verticalAlignmentProperty);
+ int imageType = OS.Image_typeid ();
+ int imageName = createDotNetString (IMAGE_PART_NAME, false);
+ int imageNode = OS.gcnew_FrameworkElementFactory (imageType, imageName);
+ OS.GCHandle_Free (imageName);
+ OS.GCHandle_Free (imageType);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (imageNode, marginProperty, thickness);
+ OS.GCHandle_Free (marginProperty);
+ OS.GCHandle_Free (thickness);
+ int stretchProperty = OS.Image_StretchProperty ();
+ OS.FrameworkElementFactory_SetValueStretch(imageNode, stretchProperty, OS.Stretch_None);
+ OS.GCHandle_Free(stretchProperty);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, imageNode);
+ OS.GCHandle_Free (imageNode);
+ OS.FrameworkElementFactory_AppendChild (cellContentNode, textNode);
+ OS.GCHandle_Free (textNode);
+ OS.FrameworkElementFactory_AppendChild (onRenderNode, cellContentNode);
+ OS.GCHandle_Free (cellContentNode);
+ OS.FrameworkTemplate_VisualTree (template, onRenderNode);
+ OS.GCHandle_Free (onRenderNode);
+ return template;
+}
+
+int createControlTemplate () {
+ int template = OS.gcnew_ControlTemplate ();
+ int borderType = OS.Border_typeid ();
+ int borderNode = OS.gcnew_FrameworkElementFactory (borderType);
+ int brushProperty = OS.Control_BorderBrushProperty ();
+ int brushBinding = OS.gcnew_TemplateBindingExtension (brushProperty);
+ OS.FrameworkElementFactory_SetValue (borderNode, brushProperty, brushBinding);
+ int thicknessProperty = OS.Control_BorderThicknessProperty ();
+ int thicknessBinding = OS.gcnew_TemplateBindingExtension (thicknessProperty);
+ OS.FrameworkElementFactory_SetValue (borderNode, thicknessProperty, thicknessBinding);
+ int scrollViewerType = OS.ScrollViewer_typeid ();
+ int scrollViewerName = createDotNetString (SCROLLVIEWER_PART_NAME, false);
+ int scrollViewerNode = OS.gcnew_FrameworkElementFactory (scrollViewerType, scrollViewerName);
+ int itemsPresenterType = OS.ItemsPresenter_typeid ();
+ int itemsPresenterNode = OS.gcnew_FrameworkElementFactory (itemsPresenterType);
+ OS.FrameworkElementFactory_AppendChild (borderNode, scrollViewerNode);
+ OS.FrameworkElementFactory_AppendChild (scrollViewerNode, itemsPresenterNode);
+ int scrollStyle = createDotNetString(scrollViewerStyle, false);
+ int stringReader = OS.gcnew_StringReader (scrollStyle);
+ int xmlReader = OS.XmlReader_Create (stringReader);
+ int xamlStyle = OS.XamlReader_Load (xmlReader);
+ int styleProperty = OS.FrameworkElement_StyleProperty();
+ OS.FrameworkElementFactory_SetValue (scrollViewerNode, styleProperty, xamlStyle);
+ int columnsProperty = OS.GridViewRowPresenterBase_ColumnsProperty ();
+ OS.FrameworkElementFactory_SetValue (scrollViewerNode, columnsProperty, gvColumns);
+ OS.FrameworkTemplate_VisualTree (template, borderNode);
+ OS.GCHandle_Free (brushProperty);
+ OS.GCHandle_Free (thicknessProperty);
+ OS.GCHandle_Free (brushBinding);
+ OS.GCHandle_Free (thicknessBinding);
+ OS.GCHandle_Free (scrollStyle);
+ OS.GCHandle_Free (stringReader);
+ OS.GCHandle_Free (xmlReader);
+ OS.GCHandle_Free (styleProperty);
+ OS.GCHandle_Free (columnsProperty);
+ OS.GCHandle_Free (xamlStyle);
+ OS.GCHandle_Free (scrollViewerType);
+ OS.GCHandle_Free (scrollViewerName);
+ OS.GCHandle_Free (scrollViewerNode);
+ OS.GCHandle_Free (borderType);
+ OS.GCHandle_Free (borderNode);
+ OS.GCHandle_Free (itemsPresenterType);
+ OS.GCHandle_Free (itemsPresenterNode);
+ return template;
+}
+
+void createHandle () {
+ parentingHandle = OS.gcnew_Canvas ();
+ if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ if ((style & SWT.SINGLE) != 0) {
+ handle = OS.gcnew_TreeView ();
+ } else {
+ handle = OS.gcnew_SWTTreeView (jniRef);
+ }
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Canvas_SetLeft (handle, 0);
+ OS.Canvas_SetTop (handle, 0);
+ int children = OS.Panel_Children (parentingHandle);
+ OS.UIElementCollection_Add (children, handle);
+ OS.GCHandle_Free (children);
+}
+
+int createHeaderTemplate (int columnJniRef) {
+ int template = OS.gcnew_DataTemplate ();
+ int stackPanelType = OS.StackPanel_typeid ();
+ int stackPanelName = createDotNetString (CONTENTPANEL_PART_NAME, false);
+ int stackPanelNode = OS.gcnew_FrameworkElementFactory (stackPanelType, stackPanelName);
+ OS.GCHandle_Free (stackPanelName);
+ OS.GCHandle_Free (stackPanelType);
+ int textType = OS.TextBlock_typeid ();
+ int textName = createDotNetString (TEXT_PART_NAME, false);
+ int textNode = OS.gcnew_FrameworkElementFactory (textType, textName);
+ OS.GCHandle_Free (textName);
+ OS.GCHandle_Free (textType);
+ int imageType = OS.Image_typeid ();
+ int imageName = createDotNetString (IMAGE_PART_NAME, false);
+ int imageNode = OS.gcnew_FrameworkElementFactory (imageType, imageName);
+ OS.GCHandle_Free (imageName);
+ OS.GCHandle_Free (imageType);
+ int marginProperty = OS.FrameworkElement_MarginProperty ();
+ int thickness = OS.gcnew_Thickness (0,0,4,0);
+ OS.FrameworkElementFactory_SetValue (imageNode, marginProperty, thickness);
+ OS.GCHandle_Free (thickness);
+ OS.GCHandle_Free (marginProperty);
+ int orientationProperty = OS.StackPanel_OrientationProperty ();
+ OS.FrameworkElementFactory_SetValueOrientation (stackPanelNode, orientationProperty, OS.Orientation_Horizontal);
+ OS.GCHandle_Free (orientationProperty);
+ int stretchProperty = OS.Image_StretchProperty ();
+ OS.FrameworkElementFactory_SetValueStretch (imageNode, stretchProperty, OS.Stretch_None);
+ OS.GCHandle_Free (stretchProperty);
+ OS.FrameworkElementFactory_AppendChild (stackPanelNode, imageNode);
+ OS.GCHandle_Free (imageNode);
+ OS.FrameworkElementFactory_AppendChild (stackPanelNode, textNode);
+ OS.GCHandle_Free (textNode);
+ OS.FrameworkTemplate_VisualTree (template, stackPanelNode);
+ OS.GCHandle_Free (stackPanelNode);
+ return template;
+}
+
+void createItem (TreeColumn column, int index) {
+ if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE);
+ if (columnCount == 0) {
+ gvColumns = OS.gcnew_GridViewColumnCollection ();
+ if (gvColumns == 0) error (SWT.ERROR_NO_HANDLES);
+ int template = createControlTemplate ();
+ OS.Control_Template (handle, template);
+ OS.GCHandle_Free (template);
+ updateHeaderVisibility ();
+ }
+ column.createWidget ();
+ int template = createHeaderTemplate (column.jniRef);
+ OS.GridViewColumn_HeaderTemplate (column.handle, template);
+ OS.GCHandle_Free (template);
+ template = createCellTemplate (index);
+ OS.GridViewColumn_CellTemplate (column.handle, template);
+ OS.GCHandle_Free (template);
+ if (columnCount == 0) {
+ OS.GridViewColumnCollection_Clear (gvColumns);
+ }
+ OS.GridViewColumnCollection_Insert (gvColumns, index, column.handle);
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = getItem (items, i, false);
+ if (item != null) {
+ item.columnAdded (index);
+ }
+ }
+ OS.GCHandle_Free (items);
+ if (columns == null) columns = new TreeColumn [4];
+ if (columns.length == columnCount) {
+ TreeColumn [] newColumns = new TreeColumn [columnCount + 4];
+ System.arraycopy(columns, 0, newColumns, 0, columnCount);
+ columns = newColumns;
+ }
+ columns [columnCount] = column;
+ columnCount++;
+}
+
+void createItem (TreeItem item, TreeItem parentItem, int index) {
+ int itemCount = parentItem != null ? parentItem.itemCount : this.itemCount;
+ if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+ item.createWidget ();
+ int parentHandle = parentItem != null ? parentItem.handle : handle;
+ int items = OS.ItemsControl_Items (parentHandle);
+ OS.ItemCollection_Insert (items, index, item.handle);
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ if (parentItem != null) {
+ parentItem.itemCount++;
+ } else {
+ this.itemCount++;
+ }
+}
+
+void createWidget() {
+ super.createWidget ();
+ headerTemplate = createCellTemplate (0);
+ int brush = OS.Brushes_Transparent ();
+ OS.Control_Background (handle, brush);
+ OS.GCHandle_Free (brush);
+}
+
+int defaultBackground () {
+ return display.getSystemColor (SWT.COLOR_LIST_BACKGROUND).handle;
+}
+
+int defaultForeground () {
+ return display.getSystemColor (SWT.COLOR_LIST_FOREGROUND).handle;
+}
+
+void deregister () {
+ super.deregister ();
+ display.removeWidget (parentingHandle);
+}
+
+/**
+ * Deselects an item in the receiver. If the item was already
+ * deselected, it remains deselected.
+ *
+ * @param item the item to be deselected
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.4
+ */
+public void deselect (TreeItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ if ((style & SWT.SINGLE) != 0) {
+ ignoreSelection = true;
+ OS.TreeViewItem_IsSelected (item.handle, false);
+ ignoreSelection = false;
+ return;
+ }
+ ignoreSelection = true;
+ setIsSelectionActiveProperty(true);
+ OS.TreeViewItem_IsSelected (item.handle, false);
+ setIsSelectionActiveProperty(false);
+ ignoreSelection = false;
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @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 deselectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) {
+ int tvItem = OS.TreeView_SelectedItem (handle);
+ if (tvItem != 0) {
+ ignoreSelection = true;
+ OS.TreeViewItem_IsSelected (tvItem, false);
+ ignoreSelection = false;
+ OS.GCHandle_Free (tvItem);
+ }
+ } else {
+ int items = OS.ItemsControl_Items (handle);
+ int itemCount = OS.ItemCollection_Count (items);
+ boolean[] selecting = new boolean[] {false};
+ for (int i = 0; i < itemCount; i++) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ fixSelection (item, null, null, selecting);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (items);
+ }
+}
+
+void destroyItem (TreeColumn column) {
+ int index = OS.GridViewColumnCollection_IndexOf (gvColumns, column.handle);
+ boolean removed = OS.GridViewColumnCollection_Remove (gvColumns, column.handle);
+ if (!removed) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ int arrayIndex = -1;
+ for (int i = 0; i < columnCount; i++) {
+ TreeColumn tc = columns [i];
+ if (tc.equals(column)) {
+ arrayIndex = i;
+ break;
+ }
+ }
+ columnCount--;
+ columns [arrayIndex] = null;
+ if (arrayIndex < columnCount) System.arraycopy (columns, arrayIndex+1, columns, arrayIndex, columnCount - arrayIndex);
+ if (columnCount == 0) {
+ OS.GCHandle_Free (gvColumns);
+ gvColumns = 0;
+ int templateProperty = OS.Control_TemplateProperty ();
+ OS.DependencyObject_ClearValue(handle, templateProperty);
+ OS.GCHandle_Free(templateProperty);
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = getItem (items, i, false);
+ if (item != null) {
+ item.columnRemoved (index);
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+void destroyItem (TreeItem item) {
+ TreeItem parentItem = item.getParentItem ();
+ int itemCount = parentItem != null ? parentItem.itemCount : this.itemCount;
+ int parentHandle = parentItem != null ? parentItem.handle : handle;
+ int items = OS.ItemsControl_Items (parentHandle);
+ OS.ItemCollection_Remove (items, item.handle);
+ int count = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (count == itemCount) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ if (parentItem != null) {
+ parentItem.itemCount--;
+ } else {
+ this.itemCount--;
+ }
+}
+
+int findScrollViewer(int current, int scrollViewerType) {
+ if (columnCount != 0) {
+ int template = OS.Control_Template (handle);
+ int scrollViewerName = createDotNetString (SCROLLVIEWER_PART_NAME, false);
+ int scrollViewer = OS.FrameworkTemplate_FindName (template, scrollViewerName, handle);
+ OS.GCHandle_Free (scrollViewerName);
+ OS.GCHandle_Free (template);
+ return scrollViewer;
+ }
+ return super.findScrollViewer (current, scrollViewerType);
+}
+
+int findPartOfType (int source, int type) {
+ if (OS.Type_IsInstanceOfType (type, source)) return source;
+ int parent = OS.VisualTreeHelper_GetParent(source);
+ if (parent == 0) return 0;
+ int result = findPartOfType(parent, type);
+ if (result != parent) OS.GCHandle_Free(parent);
+ return result;
+}
+
+void fixScrollbarVisibility () {
+ int typeid = OS.ScrollViewer_typeid();
+ int scrolledHandle = findScrollViewer(handle, typeid);
+ OS.ScrollViewer_SetHorizontalScrollBarVisibility (scrolledHandle, OS.ScrollBarVisibility_Visible);
+ OS.ScrollViewer_SetVerticalScrollBarVisibility (scrolledHandle, OS.ScrollBarVisibility_Visible);
+ OS.GCHandle_Free(scrolledHandle);
+ OS.GCHandle_Free(typeid);
+}
+
+/**
+ * Returns the width in pixels of a grid line.
+ *
+ * @return the width of a grid line in pixels
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public int getGridLineWidth () {
+ checkWidget ();
+ //TODO
+ return 0;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public int getHeaderHeight () {
+ checkWidget ();
+ if (gvColumns == 0) return 0;
+ int column = OS.GridViewColumnCollection_default (gvColumns, 0);
+ int height = 0;
+ int header = OS.GridViewColumn_Header (column);
+ if (header != 0) {
+ height = (int) OS.FrameworkElement_ActualHeight (header);
+ if (height == 0) {
+ updateLayout (header);
+ height = (int) OS.FrameworkElement_ActualHeight (header);
+ }
+ OS.GCHandle_Free (header);
+ }
+ OS.GCHandle_Free (column);
+ OS.GCHandle_Free (gvColumns);
+ return height;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's header is visible,
+ * and <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's header's visibility 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>
+ *
+ * @since 3.1
+ */
+public boolean getHeaderVisible () {
+ checkWidget ();
+ if (gvColumns == 0) return false;
+ int column = OS.GridViewColumnCollection_default (gvColumns, 0);
+ int header = OS.GridViewColumn_Header (column);
+ boolean visible = OS.UIElement_Visibility (header) == OS.Visibility_Visible;
+ OS.GCHandle_Free (header);
+ OS.GCHandle_Free (column);
+ return visible;
+}
+
+/**
+ * Returns the column at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ * Columns are returned in the order that they were created.
+ * If no <code>TreeColumn</code>s were created by the programmer,
+ * this method will throw <code>ERROR_INVALID_RANGE</code> despite
+ * the fact that a single column of data may be visible in the tree.
+ * This occurs when the programmer uses the tree like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn getColumn (int index) {
+ checkWidget ();
+ if (!(0 <= index && index < columnCount)) error (SWT.ERROR_INVALID_RANGE);
+ return columns [index];
+}
+
+//TreeColumn _getColumn (int index) {
+// if (columnCount == 0) return null;
+// int gridColumn = OS.GridViewColumnCollection_default (gvColumns, index);
+// int header = OS.GridViewColumn_Header (gridColumn);
+// TreeColumn column = (TreeColumn) display.getWidget (header);
+// OS.GCHandle_Free (gridColumn);
+// OS.GCHandle_Free (header);
+// return column;
+//}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no <code>TreeColumn</code>s were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the tree like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public int getColumnCount () {
+ checkWidget ();
+ return columnCount;
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @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 Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public int[] getColumnOrder () {
+ checkWidget ();
+ int [] order = new int [columnCount];
+ for (int i=0; i<order.length; i++) order [i] = i;
+ for (int i = 0; i < order.length; i++) {
+ TreeColumn column = columns [i];
+ int index = OS.IList_IndexOf (gvColumns, column.handle);
+ order [index] = i;
+ }
+ return order;
+}
+
+/**
+ * Returns an array of <code>TreeColumn</code>s which are the
+ * columns in the receiver. Columns are returned in the order
+ * that they were created. If no <code>TreeColumn</code>s were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the tree like a list, adding items but
+ * never creating a column.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @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 Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn [] getColumns () {
+ checkWidget ();
+ TreeColumn [] result = new TreeColumn [columnCount];
+ for (int i = 0; i < result.length; i++) {
+ result [i] = columns [i];
+ }
+ return result;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @since 3.1
+ */
+public TreeItem getItem (int index) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+ int items = OS.ItemsControl_Items (handle);
+ TreeItem treeItem = getItem (items, index, true);
+ OS.GCHandle_Free (items);
+ return treeItem;
+}
+
+TreeItem getItem (int items, int index, boolean create) {
+ int item = OS.ItemCollection_GetItemAt (items, index);
+ TreeItem result = getItem (item, create);
+ OS.GCHandle_Free (item);
+ return result;
+}
+
+TreeItem getItem (int item, boolean create) {
+ int tag = OS.FrameworkElement_Tag (item);
+ if (tag != 0) {
+ int contentValue = OS.IntPtr_ToInt32 (tag);
+ OS.GCHandle_Free (tag);
+ return (TreeItem) OS.JNIGetObject (contentValue);
+ }
+ if (create) {
+ int itemHandle = OS.GCHandle_Alloc (item);
+ int parentHandle = OS.FrameworkElement_Parent (item);
+ TreeItem parentItem = null;
+ if (!OS.Object_Equals (parentHandle, handle)) parentItem = (TreeItem) display.getWidget (parentHandle);
+ OS.GCHandle_Free (parentHandle);
+ return new TreeItem (this, parentItem, SWT.NONE, 0, itemHandle);
+ }
+ return null;
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ * <p>
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ * </p>
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point 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 TreeItem getItem (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int pt = OS.gcnew_Point (point.x, point.y);
+ int input = OS.UIElement_InputHitTest (handle, pt);
+ OS.GCHandle_Free (pt);
+ if (input == 0) return null;
+ Widget widget = display.getWidget (input);
+ OS.GCHandle_Free (input);
+ if (widget instanceof TreeItem) {
+ return (TreeItem) widget;
+ }
+ return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver. The
+ * number that is returned is the number of roots in the
+ * tree.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ return itemCount;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the tree.
+ *
+ * @return the height of one item
+ *
+ * @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 int getItemHeight () {
+ checkWidget ();
+ //FIXME
+ if (itemCount == 0) return 16;
+ int items = OS.ItemsControl_Items (handle);
+ int item = OS.ItemCollection_GetItemAt (items, 0);
+ double height = OS.FrameworkElement_ActualHeight (item);
+ OS.GCHandle_Free (item);
+ OS.GCHandle_Free (items);
+ return height != 0 ? (int) height : 16;
+}
+
+/**
+ * Returns a (possibly empty) array of items contained in the
+ * receiver that are direct item children of the receiver. These
+ * are the roots of the tree.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items
+ *
+ * @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 TreeItem [] getItems () {
+ checkWidget ();
+ TreeItem [] result = new TreeItem [itemCount];
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < itemCount; i++) {
+ result [i] = getItem (items, i, true);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's lines are visible,
+ * and <code>false</code> otherwise. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the visibility state of the lines
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public boolean getLinesVisible () {
+ checkWidget ();
+ //TODO
+ return false;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>TreeItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @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 TreeItem getParentItem () {
+ checkWidget ();
+ return null;
+}
+
+/**
+ * Returns an array of <code>TreeItem</code>s that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @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 TreeItem [] getSelection () {
+ checkWidget ();
+ TreeItem [] result;
+ if ((style & SWT.SINGLE) != 0) {
+ int item = OS.TreeView_SelectedItem (handle);
+ if (item == 0) return new TreeItem [0];
+ result = new TreeItem [] { (TreeItem) display.getWidget (item) };
+ OS.GCHandle_Free (item);
+ } else {
+ result = getSelectedItems (handle, new TreeItem [4], new int [1]);
+ }
+ return result;
+}
+
+TreeItem[] getSelectedItems(int itemsControl, TreeItem [] selectedItems, int [] nextIndex) {
+ int items = OS.ItemsControl_Items (itemsControl);
+ int count = OS.ItemCollection_Count (items);
+ for (int i = 0; i < count; i++) {
+ int item = OS.ItemCollection_GetItemAt (items, i);
+ boolean selected = OS.TreeViewItem_IsSelected (item);
+ if (selected) {
+ if (nextIndex [0] == selectedItems.length) {
+ TreeItem [] newArray = new TreeItem [selectedItems.length + 4];
+ System.arraycopy (selectedItems, 0, newArray, 0, selectedItems.length);
+ selectedItems = newArray;
+ }
+ selectedItems [nextIndex[0]++] = getItem (item, true);
+ }
+ if (OS.TreeViewItem_IsExpanded (item)) {
+ selectedItems = getSelectedItems (item, selectedItems, nextIndex);
+ }
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (items);
+ if (selectedItems.length != nextIndex [0]) {
+ TreeItem[] newArray = new TreeItem [nextIndex[0]];
+ System.arraycopy (selectedItems, 0, newArray, 0, nextIndex [0]);
+ selectedItems = newArray;
+ }
+ return selectedItems;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @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 int getSelectionCount () {
+ checkWidget ();
+ int result;
+ if ((style & SWT.SINGLE) != 0) {
+ int item = OS.TreeView_SelectedItem (handle);
+ result = item == 0 ? 0 : 1;
+ OS.GCHandle_Free (item);
+ } else {
+ TreeItem[] selectedItems = getSelectedItems(handle, new TreeItem[4], new int[] {0});
+ result = selectedItems.length;
+ }
+ return result;
+}
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @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 #setSortColumn(TreeColumn)
+ *
+ * @since 3.2
+ */
+public TreeColumn getSortColumn () {
+ checkWidget ();
+ //TODO
+ return null;
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of <code>UP</code>, <code>DOWN</code>
+ * or <code>NONE</code>.
+ *
+ * @return the sort direction
+ *
+ * @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 #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+ checkWidget ();
+ //TODO
+ return SWT.NONE;
+}
+
+/**
+ * Returns the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @return the item at the top of the receiver
+ *
+ * @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>
+ *
+ * @since 2.1
+ */
+public TreeItem getTopItem () {
+ checkWidget ();
+ //TODO
+ return null;
+}
+
+boolean hasItems () {
+ return true;
+}
+
+void HandleChecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int origsource = OS.RoutedEventArgs_OriginalSource (e);
+ int typeid = OS.CheckBox_typeid ();
+ boolean isCheckBox = OS.Type_IsInstanceOfType (typeid, origsource);
+ OS.GCHandle_Free (typeid);
+ OS.GCHandle_Free (origsource);
+ if (!isCheckBox) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ TreeItem item = (TreeItem) display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (item.grayed) {
+ int checkbox = item.findPart (0, CHECKBOX_PART_NAME);
+ if (checkbox != 0) {
+ OS.ToggleButton_IsCheckedNullSetter (checkbox);
+ OS.GCHandle_Free (checkbox);
+ }
+ }
+ item.checked = true;
+ item.updateCheck ();
+ Event event = new Event ();
+ event.item = item;
+ event.detail = SWT.CHECK;
+ sendEvent (SWT.Selection, event);
+
+}
+
+void HandleCollapsed (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ if (OS.ItemsControl_HasItems (source)) {
+ TreeItem item = (TreeItem) display.getWidget (source);
+ int items = OS.ItemsControl_Items (item.handle);
+ int count = OS.ItemCollection_Count (items);
+ boolean[] selecting = new boolean [] {false};
+ for (int i = 0; i < count; i++) {
+ int child = OS.ItemCollection_GetItemAt (items, i);
+ fixSelection (child, null, null, selecting);
+ OS.GCHandle_Free (child);
+ }
+ OS.GCHandle_Free (items);
+ Event event = new Event ();
+ event.item = item;
+ sendEvent (SWT.Collapse, event);
+ }
+ OS.GCHandle_Free (source);
+}
+
+void HandleExpanded (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ if (OS.ItemsControl_HasItems (source)) {
+ Event event = new Event ();
+ event.item = (TreeItem) display.getWidget (source);
+ sendEvent (SWT.Expand, event);
+ }
+ OS.GCHandle_Free (source);
+}
+
+void HandlePreviewKeyDown (int sender, int e) {
+ super.HandlePreviewKeyDown (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_Return) {
+ int source = OS.RoutedEventArgs_OriginalSource (e);
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget instanceof TreeItem) {
+ Event event = new Event ();
+ event.item = (TreeItem) widget;
+ postEvent (SWT.DefaultSelection, event);
+ }
+ }
+ if (key == OS.Key_RightShift || key == OS.Key_LeftShift) shiftDown = true;
+ if (key == OS.Key_RightCtrl || key == OS.Key_LeftCtrl) ctrlDown = true;
+}
+
+void HandlePreviewKeyUp (int sender, int e) {
+ super.HandlePreviewKeyUp (sender, e);
+ if (!checkEvent (e)) return;
+ int key = OS.KeyEventArgs_Key (e);
+ if (key == OS.Key_RightShift || key == OS.Key_LeftShift) shiftDown = false;
+ if (key == OS.Key_RightCtrl || key == OS.Key_LeftCtrl) ctrlDown = false;
+}
+
+void HandleLoaded (int sender, int e) {
+ if (!checkEvent (e)) return;
+ updateHeaderVisibility();
+}
+
+void HandlePreviewMouseDoubleClick (int sender, int e) {
+ if (!checkEvent (e)) return;
+ int source = OS.RoutedEventArgs_OriginalSource (e);
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget instanceof TreeItem) {
+ Event event = new Event ();
+ event.item = (TreeItem) widget;
+ postEvent (SWT.DefaultSelection, event);
+ }
+ if (hooks (SWT.DefaultSelection)) OS.RoutedEventArgs_Handled(e, true);
+}
+
+void HandlePreviewMouseDown (int sender, int e) {
+ super.HandlePreviewMouseDown (sender, e);
+ if (!checkEvent (e)) return;
+ if ((style & SWT.SINGLE) != 0) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget instanceof TreeItem) {
+ TreeItem item = (TreeItem) widget;
+ /* Check that content of item was clicked, not the expander */
+ int point = OS.MouseEventArgs_GetPosition (e, item.contentHandle);
+ int input = OS.UIElement_InputHitTest (item.contentHandle, point);
+ OS.GCHandle_Free (point);
+ if (input != 0) {
+ OS.GCHandle_Free (input);
+ boolean rightClick = OS.MouseEventArgs_RightButton (e) == OS.MouseButtonState_Pressed;
+ if (rightClick && (ctrlDown || shiftDown)) return;
+ if (ctrlDown) {
+ boolean selected = OS.TreeViewItem_IsSelected (item.handle);
+ if (widget.equals (lastSelection)) {
+ OS.TreeViewItem_IsSelected (item.handle, !selected);
+ } else {
+ if (selected) unselect = item;
+ if (lastSelection != null && OS.TreeViewItem_IsSelected (lastSelection.handle)) reselect = lastSelection;
+ }
+ }
+ if (!shiftDown && !ctrlDown) {
+ boolean selected = OS.TreeViewItem_IsSelected (item.handle);
+ if (selected && rightClick) return;
+ deselectAll ();
+ OS.TreeViewItem_IsSelected (item.handle, true);
+ }
+ }
+ lastSelection = item;
+ }
+}
+
+void HandleSelectedItemChanged (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int selectedItem = OS.TreeView_SelectedItem (handle);
+ if (selectedItem == 0) return;
+ TreeItem item = (TreeItem) display.getWidget (selectedItem);
+ OS.GCHandle_Free (selectedItem);
+ Event event = new Event ();
+ event.item = item;
+ postEvent (SWT.Selection, event);
+}
+
+void HandleUnchecked (int sender, int e) {
+ if (!checkEvent (e)) return;
+ if (ignoreSelection) return;
+ int origsource = OS.RoutedEventArgs_OriginalSource (e);
+ int typeid = OS.CheckBox_typeid ();
+ boolean isCheckBox = OS.Type_IsInstanceOfType (typeid, origsource);
+ OS.GCHandle_Free (typeid);
+ OS.GCHandle_Free (origsource);
+ if (!isCheckBox) return;
+ int source = OS.RoutedEventArgs_Source (e);
+ TreeItem item = (TreeItem) display.getWidget (source);
+ OS.GCHandle_Free (source);
+ item.checked = false;
+ item.updateCheck ();
+ Event event = new Event ();
+ event.item = item;
+ event.detail = SWT.CHECK;
+ sendEvent (SWT.Selection, event);
+}
+
+void hookEvents () {
+ super.hookEvents ();
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleLoaded");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Loaded (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedPropertyChangedEventHandlerObject (jniRef, "HandleSelectedItemChanged");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.TreeView_SelectedItemChanged (handle, handler);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_MouseButtonEventHandler (jniRef, "HandlePreviewMouseDoubleClick");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.Control_PreviewMouseDoubleClick (handle, handler);
+ OS.GCHandle_Free (handler);
+
+ /* Item events */
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleExpanded");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ int event = OS.TreeViewItem_ExpandedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleCollapsed");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.TreeViewItem_CollapsedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ if ((style & SWT.CHECK) != 0) {
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleChecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.ToggleButton_CheckedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleUnchecked");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ event = OS.ToggleButton_UncheckedEvent ();
+ OS.UIElement_AddHandler (handle, event, handler, false);
+ OS.GCHandle_Free (event);
+ OS.GCHandle_Free (handler);
+ }
+}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the column 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>
+ *
+ * @since 3.1
+ */
+public int indexOf (TreeColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gvColumns == 0) return -1;
+ int index = OS.GridViewColumnCollection_IndexOf (gvColumns, column.handle);
+ return index;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.1
+ */
+public int indexOf (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ int index = OS.ItemCollection_IndexOf (items, item.handle);
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+void OnRender (int source, int dc) {
+ int type = OS.TreeViewItem_typeid ();
+ int itemHandle = findPartOfType (source, type);
+ OS.GCHandle_Free (type);
+ TreeItem item = getItem (itemHandle, true);
+ OS.GCHandle_Free (itemHandle);
+ if ((item.cached || (style & SWT.VIRTUAL) == 0) && item.contentHandle != 0) return;
+ checkData (item);
+ if (item.contentHandle == 0) {
+ item.contentHandle = item.findContentPresenter();
+ }
+ int columns = columnCount == 0 ? 1 : columnCount;
+ item.updateCheck ();
+ for (int i=0; i<columns; i++) {
+ item.updateText (i);
+ item.updateImage (i);
+ item.updateBackground (i);
+ item.updateForeground (i);
+ item.updateFont (i);
+ }
+}
+
+void OnSelectedItemChanged (int args) {
+ int newItemRef = OS.RoutedPropertyChangedEventArgs_NewValue (args);
+ TreeItem newItem = null;
+ if (newItemRef != 0) {
+ int unsetValue = OS.DependencyProperty_UnsetValue ();
+ if (!OS.Object_Equals (newItemRef, unsetValue)) newItem = getItem (newItemRef, false);
+ OS.GCHandle_Free (newItemRef);
+ OS.GCHandle_Free (unsetValue);
+ newItemRef = 0;
+ }
+ setIsSelectionActiveProperty (true);
+ if (!shiftDown && !ctrlDown) {
+ deselectAll ();
+ if (newItem != null) OS.TreeViewItem_IsSelected (newItem.handle, true);
+ anchor = newItem;
+ } else {
+ if (shiftDown) {
+ deselectAll ();
+ if (anchor == null || anchor == newItem) {
+ if (newItem != null) OS.TreeViewItem_IsSelected (newItem.handle, true);
+ anchor = newItem;
+ } else {
+ int zero = OS.gcnew_Point (0, 0);
+ int point = OS.UIElement_TranslatePoint (anchor.handle, zero, newItem.handle);
+ OS.GCHandle_Free (zero);
+ boolean down = OS.Point_Y (point) < 0;
+ OS.GCHandle_Free (point);
+ TreeItem from = down ? anchor : newItem;
+ TreeItem to = down ? newItem : anchor;
+ int items = OS.ItemsControl_Items (handle);
+ int itemCount = OS.ItemCollection_Count (items);
+ boolean[] selecting = new boolean[] {false};
+ for (int i = 0; i < itemCount; i++) {
+ int item = OS.ItemCollection_GetItemAt(items, i);
+ fixSelection (item, from, to, selecting);
+ OS.GCHandle_Free (item);
+ }
+ OS.GCHandle_Free (items);
+ }
+ } else {
+ if (unselect != null) {
+ OS.TreeViewItem_IsSelected (unselect.handle, false);
+ unselect = null;
+ }
+ if (reselect != null) {
+ OS.TreeViewItem_IsSelected (reselect.handle, true);
+ reselect = null;
+ }
+ anchor = newItem;
+ }
+ }
+ setIsSelectionActiveProperty (false);
+}
+
+private void fixSelection (int tvItem, TreeItem from, TreeItem to, boolean [] selecting) {
+ if (selecting [0]) {
+ OS.TreeViewItem_IsSelected (tvItem, true);
+ if (to != null && OS.Object_Equals (tvItem, to.handle)) selecting [0] = false;
+ } else {
+ if (from != null && OS.Object_Equals (tvItem, from.handle)) selecting [0] = true;
+ OS.TreeViewItem_IsSelected(tvItem, selecting [0]);
+ }
+ if (OS.TreeViewItem_IsExpanded (tvItem)) {
+ int items = OS.ItemsControl_Items (tvItem);
+ int itemCount = OS.ItemCollection_Count (items);
+ for (int i = 0; i < itemCount; i++) {
+ int tvChild = OS.ItemCollection_GetItemAt (items, i);
+ fixSelection (tvChild, from, to, selecting);
+ OS.GCHandle_Free (tvChild);
+ }
+ OS.GCHandle_Free (items);
+ }
+}
+
+int parentingHandle () {
+ return parentingHandle;
+}
+
+void register() {
+ super.register();
+ display.addWidget (parentingHandle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ for (int i=0; i<columnCount; i++) {
+ TreeColumn column = columns [i];
+ if (column != null && !column.isDisposed ()) {
+ column.release (false);
+ }
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (gvColumns != 0) OS.GCHandle_Free (gvColumns);
+ gvColumns = 0;
+ if (headerTemplate != 0) OS.GCHandle_Free (headerTemplate);
+ headerTemplate = 0;
+ OS.GCHandle_Free (parentingHandle);
+ parentingHandle = 0;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ columns = null;
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @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 removeAll () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < itemCount; i++) {
+ TreeItem item = getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ ignoreSelection = true;
+ OS.ItemCollection_Clear (items);
+ ignoreSelection = false;
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see TreeListener
+ * @see #addTreeListener
+ */
+public void removeTreeListener(TreeListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Expand, listener);
+ eventTable.unhook (SWT.Collapse, listener);
+}
+
+int setBounds (int x, int y, int width, int height, int flags) {
+ int result = super.setBounds (x, y, width, height, flags);
+ if ((result & RESIZED) != 0) {
+ OS.FrameworkElement_Width (handle, width);
+ OS.FrameworkElement_Height (handle, height);
+ }
+ return result;
+}
+
+/**
+ * Display a mark indicating the point at which an item will be inserted.
+ * The drop insert item has a visual hint to show where a dragged item
+ * will be inserted when dropped on the tree.
+ *
+ * @param item the insert item. Null will clear the insertion mark.
+ * @param before true places the insert mark above 'item'. false places
+ * the insert mark below 'item'.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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 setInsertMark (TreeItem item, boolean before) {
+ checkWidget ();
+ if (item != null && item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ //TODO
+}
+
+/**
+ * Sets the number of root-level items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public void setItemCount (int count) {
+ checkWidget ();
+ setItemCount (null, count);
+}
+
+void setItemCount (TreeItem parentItem, int count) {
+ int itemCount = parentItem != null ? parentItem.itemCount : this.itemCount;
+ count = Math.max (0, count);
+ if (count == itemCount) return;
+ int parentHandle = parentItem != null ? parentItem.handle : handle;
+ int index = itemCount - 1;
+ int items = OS.ItemsControl_Items (parentHandle);
+ while (index >= count) {
+ TreeItem item = getItem (items, index, false);
+ if (item != null) {
+ if (!item.isDisposed()) item.release (true);
+ } else {
+ OS.ItemCollection_RemoveAt (items, index);
+ }
+ index--;
+ }
+ if (OS.ItemCollection_Count (items) > count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ if ((style & SWT.VIRTUAL) != 0) {
+ for (int i=itemCount; i<count; i++) {
+ int item = OS.gcnew_TreeViewItem ();
+ if (item == 0) error (SWT.ERROR_NO_HANDLES);
+ if (columnCount != 0) {
+ int headerHandle = OS.gcnew_SWTTreeViewRowPresenter (handle);
+ if (headerHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GridViewRowPresenterBase_Columns (headerHandle, gvColumns);
+ OS.HeaderedItemsControl_Header (item, headerHandle);
+ OS.GCHandle_Free (headerHandle);
+ } else {
+ OS.TreeViewItem_HeaderTemplate (item, headerTemplate);
+ }
+ OS.ItemCollection_Add (items, item);
+ OS.GCHandle_Free (item);
+ }
+ } else {
+ for (int i=itemCount; i<count; i++) {
+ new TreeItem (this, parentItem, SWT.NONE, i, 0);
+ }
+ }
+ itemCount = OS.ItemCollection_Count (items);
+ OS.GCHandle_Free (items);
+ if (itemCount != count) error (SWT.ERROR_ITEM_NOT_ADDED);
+ if (parentItem != null) {
+ parentItem.itemCount = itemCount;
+ } else {
+ this.itemCount = itemCount;
+ }
+}
+
+/**
+ * Sets the height of the area which would be used to
+ * display <em>one</em> of the items in the tree.
+ *
+ * @return the height of one item
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+ checkWidget ();
+ if (itemHeight < -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ //TODO
+}
+
+/**
+ * Marks the receiver's lines as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param show the new visibility 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>
+ *
+ * @since 3.1
+ */
+public void setLinesVisible (boolean show) {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Selects an item in the receiver. If the item was already
+ * selected, it remains selected.
+ *
+ * @param item the item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.4
+ */
+public void select (TreeItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ if ((style & SWT.SINGLE) != 0) {
+ ignoreSelection = true;
+ OS.TreeViewItem_IsSelected (item.handle, true);
+ ignoreSelection = false;
+ return;
+ }
+
+ ignoreSelection = true;
+ setIsSelectionActiveProperty(true);
+ OS.TreeViewItem_IsSelected (item.handle, true);
+ setIsSelectionActiveProperty(false);
+ ignoreSelection = false;
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ * </p>
+ *
+ * @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 selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ int items = OS.ItemsControl_Items (handle);
+ int itemCount = OS.ItemCollection_Count (items);
+ boolean[] selecting = new boolean[] {true};
+ setIsSelectionActiveProperty(true);
+ for (int i = 0; i < itemCount; i++) {
+ int item = OS.ItemCollection_GetItemAt(items, i);
+ fixSelection(item, null, null, selecting);
+ OS.GCHandle_Free(item);
+ }
+ setIsSelectionActiveProperty(false);
+ OS.GCHandle_Free(items);
+}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @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>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ *
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setColumnOrder (int [] order) {
+ checkWidget ();
+ if (order == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ int [] oldOrder = getColumnOrder ();
+ boolean reorder = false;
+ boolean [] seen = new boolean [columnCount];
+ for (int i=0; i<order.length; i++) {
+ int index = order [i];
+ if (index < 0 || index >= columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+ seen [index] = true;
+ if (order [i] != oldOrder [i]) reorder = true;
+ }
+ if (!reorder) return;
+ for (int i = 0; i < order.length; i++) {
+ TreeColumn column = columns [order [i]];
+ int index = OS.IList_IndexOf (gvColumns, column.handle);
+ if (index != i) OS.ObservableCollectionGridViewColumn_Move (gvColumns, index, i);
+ }
+}
+
+void setFont (int font, double size) {
+ if (font != 0) {
+ int fontFamily = OS.Typeface_FontFamily( font);
+ int style = OS.Typeface_Style (font);
+ int weight = OS.Typeface_Weight (font);
+ int stretch = OS.Typeface_Stretch (font);
+ OS.Control_FontFamily (handle, fontFamily);
+ OS.Control_FontStyle (handle, style);
+ OS.Control_FontWeight (handle, weight);
+ OS.Control_FontStretch (handle, stretch);
+ OS.Control_FontSize (handle, size);
+ OS.GCHandle_Free (fontFamily);
+ OS.GCHandle_Free (style);
+ OS.GCHandle_Free (weight);
+ OS.GCHandle_Free (stretch);
+ } else {
+ int property = OS.Control_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+void setForegroundBrush (int brush) {
+ if (brush != 0) {
+ OS.Control_Foreground (handle, brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+}
+
+/**
+ * Marks the receiver's header as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param show the new visibility 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>
+ *
+ * @since 3.1
+ */
+public void setHeaderVisible (boolean show) {
+ checkWidget ();
+ headerVisibility = show ? OS.Visibility_Visible : OS.Visibility_Collapsed;
+ updateHeaderVisibility ();
+ for (int i=0; i<columnCount; i++) {
+ TreeColumn column = getColumn(i);
+ column.updateImage ();
+ column.updateText ();
+ }
+}
+
+void setIsSelectionActiveProperty(boolean active) {
+ int treeType = OS.Object_GetType (handle);
+ int propertyName = createDotNetString ("IsSelectionChangeActive", false);
+ int property = OS.Type_GetProperty (treeType, propertyName, OS.BindingFlags_Instance | OS.BindingFlags_NonPublic);
+ OS.GCHandle_Free (treeType);
+ OS.GCHandle_Free (propertyName);
+ OS.PropertyInfo_SetValueBoolean (property, handle, active, 0);
+ OS.GCHandle_Free (property);
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected.
+ * <p>
+ * If the item is not in the receiver, then it is ignored.
+ * </p>
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.2
+ */
+public void setSelection (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TreeItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ * </p>
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</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>
+ *
+ * @see Tree#deselectAll()
+ */
+public void setSelection (TreeItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int length = items.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) {
+ deselectAll ();
+ return;
+ }
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = items [i];
+ if (item != null && item.isDisposed ()) error (SWT.ERROR_WIDGET_DISPOSED);
+ }
+ deselectAll ();
+ ignoreSelection = true;
+ if ((style & SWT.SINGLE) != 0) {
+ TreeItem select = items [0];
+ if (select != null) {
+ OS.TreeViewItem_IsSelected (items [0].handle, true);
+ }
+ } else {
+ setIsSelectionActiveProperty (true);
+ for (int i = 0; i < length; i++) {
+ TreeItem item = items [i];
+ if (item != null) OS.TreeViewItem_IsSelected (item.handle, true);
+ }
+ setIsSelectionActiveProperty (false);
+ }
+ ignoreSelection = false;
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator. The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the column is disposed</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>
+ *
+ * @since 3.2
+ */
+public void setSortColumn (TreeColumn column) {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public void setSortDirection (int direction) {
+ checkWidget ();
+ //TODO
+}
+
+/**
+ * Sets the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @see Tree#getTopItem()
+ *
+ * @since 2.1
+ */
+public void setTopItem (TreeItem item) {
+ checkWidget ();
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ //TODO
+}
+
+/**
+ * Shows the column. If the column is already showing in the receiver,
+ * this method simply returns. Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.1
+ */
+public void showColumn (TreeColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (column.parent != this) return;
+ int index = indexOf (column);
+ if (index == -1) return;
+ //TODO
+}
+
+/**
+ * Shows the item. If the item is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled
+ * and expanded until the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @see Tree#showSelection()
+ */
+public void showItem (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (item.parent != this) return;
+ int parent = OS.FrameworkElement_Parent (item.handle);
+ while (!OS.Object_Equals (parent, handle)) {
+ OS.TreeViewItem_IsExpanded (parent, true);
+ int newParent = OS.FrameworkElement_Parent (parent);
+ OS.GCHandle_Free (parent);
+ parent = newParent;
+ }
+ OS.GCHandle_Free (parent);
+ OS.FrameworkElement_BringIntoView (item.handle);
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @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 Tree#showItem(TreeItem)
+ */
+public void showSelection () {
+ checkWidget ();
+ int item = OS.TreeView_SelectedItem (handle);
+ if (item != 0) {
+ OS.FrameworkElement_BringIntoView (item);
+ OS.GCHandle_Free (item);
+ }
+}
+
+int topHandle () {
+ return parentingHandle;
+}
+
+void updateHeaderVisibility() {
+ int template = OS.Control_Template (handle);
+ int scrollViewerName = createDotNetString (SCROLLVIEWER_PART_NAME, false);
+ int scrollViewer = OS.FrameworkTemplate_FindName (template, scrollViewerName, handle);
+ if (scrollViewer != 0) {
+ int scrollViewerTemplate = OS.Control_Template(scrollViewer);
+ int headerName = createDotNetString(HEADER_PART_NAME, false);
+ int header = OS.FrameworkTemplate_FindName (scrollViewerTemplate, headerName, scrollViewer);
+ if (header != 0) {
+ OS.UIElement_Visibility (header, headerVisibility);
+ OS.GCHandle_Free (header);
+ }
+ OS.GCHandle_Free (scrollViewerTemplate);
+ OS.GCHandle_Free (headerName);
+ OS.GCHandle_Free (scrollViewer);
+ }
+ OS.GCHandle_Free (scrollViewerName);
+ OS.GCHandle_Free (template);
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeColumn.java
new file mode 100644
index 0000000000..3671770dc0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeColumn.java
@@ -0,0 +1,613 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent a column in a tree widget.
+ * <p><dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TreeColumn extends Item {
+ Tree parent;
+ int headerHandle;
+ int stringPtr;
+ boolean moveable, resizable;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeColumn (Tree parent, int style) {
+ this (checkNull(parent), checkStyle (style), parent.columnCount);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeColumn (Tree parent, int style, int index) {
+ super (parent, checkStyle (style));
+ resizable = true;
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the column header is selected.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static Tree checkNull (Tree tree) {
+ if (tree == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return tree;
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandle () {
+ handle = OS.gcnew_GridViewColumn ();
+ if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+ headerHandle = OS.gcnew_GridViewColumnHeader ();
+ OS.GridViewColumn_Header (handle, headerHandle);
+ OS.GridViewColumn_Width (handle, 0);
+}
+
+void deregister () {
+ display.removeWidget (headerHandle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+int findContentPresenter (int element, int contentPresenterType) {
+ int type = OS.Object_GetType (element);
+ boolean found = OS.Object_Equals (contentPresenterType, type);
+ OS.GCHandle_Free (type);
+ if (found) return element;
+ int count = OS.VisualTreeHelper_GetChildrenCount (element);
+ for (int i = 0; i < count; i++) {
+ int child = OS.VisualTreeHelper_GetChild (element, i);
+ int result = findContentPresenter (child, contentPresenterType);
+ if (child != result) OS.GCHandle_Free (child);
+ if (result != 0) return result;
+ }
+ return 0;
+}
+
+int findPart (String part) {
+ int contentPresenterType = OS.ContentPresenter_typeid ();
+ int contentPresenter = findContentPresenter (headerHandle, contentPresenterType);
+ int result = 0;
+ if (contentPresenter != 0) {
+ int template = OS.GridViewColumn_HeaderTemplate (handle);
+ int strPtr = createDotNetString (part, false);
+ result = OS.FrameworkTemplate_FindName (template, strPtr, contentPresenter);
+ OS.GCHandle_Free (strPtr);
+ OS.GCHandle_Free (template);
+ OS.GCHandle_Free (contentPresenter);
+ }
+ OS.GCHandle_Free (contentPresenterType);
+ return result;
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @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 int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @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 Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public boolean getMoveable () {
+ checkWidget ();
+ return moveable;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tree</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Tree getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @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 boolean getResizable () {
+ checkWidget ();
+ return resizable;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip 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>
+ *
+ * @since 3.2
+ */
+public String getToolTipText () {
+ checkWidget ();
+ int strPtr = OS.FrameworkElement_ToolTip (headerHandle);
+ String string = createJavaString (strPtr);
+ OS.GCHandle_Free (strPtr);
+ return string;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @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 int getWidth () {
+ checkWidget ();
+ return (int) OS.GridViewColumn_ActualWidth(handle);
+}
+
+
+void HandleLoaded (int source, int e) {
+ updateImage ();
+ updateText ();
+}
+
+void hookEvents() {
+ super.hookEvents ();
+ int handler = OS.gcnew_RoutedEventHandler (jniRef, "HandleLoaded");
+ if (handler == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.FrameworkElement_Loaded (headerHandle, handler);
+ OS.GCHandle_Free (handler);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @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 pack () {
+ checkWidget ();
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ int widthProperty = OS.GridViewColumn_WidthProperty ();
+ OS.DependencyObject_ClearValue (handle, widthProperty);
+ OS.GCHandle_Free (widthProperty);
+}
+
+void register() {
+ display.addWidget (headerHandle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ OS.GCHandle_Free (headerHandle);
+ headerHandle = 0;
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ if (stringPtr != 0) OS.GCHandle_Free (stringPtr);
+ stringPtr = 0;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
+ * or <code>CENTER</code>.
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
+ * @param alignment the new alignment
+ *
+ * @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 setAlignment (int alignment) {
+ checkWidget ();
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ int index = parent.indexOf (this);
+ if (index == -1 || index == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ //TODO
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ super.setImage (image);
+ updateImage ();
+}
+
+/**
+ * Sets the moveable attribute. A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @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 Tree#setColumnOrder(int[])
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setMoveable (boolean moveable) {
+ checkWidget ();
+ this.moveable = moveable;
+}
+
+/**
+ * Sets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @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 setResizable (boolean resizable) {
+ checkWidget ();
+ this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+ //TODO
+}
+
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ text = string;
+ updateText ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @param string the new tool tip text (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>
+ *
+ * @since 3.2
+ */
+public void setToolTipText (String string) {
+ checkWidget();
+ if (string != null && string.length() == 0) string = null;
+ int strPtr = createDotNetString (string, false);
+ OS.FrameworkElement_ToolTip (headerHandle, strPtr);
+ OS.GCHandle_Free (strPtr);
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @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 setWidth (int width) {
+ checkWidget ();
+ if (width < 0) return;
+ OS.GridViewColumn_Width (handle, width);
+}
+
+void updateImage() {
+ int part = findPart (Tree.IMAGE_PART_NAME);
+ if (part == 0) return;
+ OS.Image_Source (part, image == null ? 0 : image.handle);
+ OS.GCHandle_Free (part);
+}
+
+void updateText () {
+ int part = findPart (Tree.TEXT_PART_NAME);
+ if (part == 0) return;
+ int str = createDotNetString (text, false);
+ OS.TextBlock_Text (part, str);
+ OS.GCHandle_Free (str);
+ OS.GCHandle_Free (part);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeItem.java
new file mode 100644
index 0000000000..24e2c25c4e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/TreeItem.java
@@ -0,0 +1,1638 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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.internal.wpf.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a hierarchy of tree items in a tree widget.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class TreeItem extends Item {
+ Tree parent;
+ int contentHandle;
+ int itemCount;
+ Image [] images;
+ String [] strings;
+ Color [] cellBackground, cellForeground;
+ Font [] cellFont;
+ boolean checked, grayed, cached, ignoreNotify;
+ Color background, foreground;
+ Font font;
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a tree 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 TreeItem (Tree parent, int style) {
+ this (checkNull (parent), null, style, parent.itemCount, 0);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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 TreeItem (Tree parent, int style, int index) {
+ this (checkNull (parent), null, style, index, 0);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parentItem a tree 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 TreeItem (TreeItem parentItem, int style) {
+ this (checkNull (parentItem).parent, parentItem, style, parentItem.itemCount, 0);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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 TreeItem (TreeItem parentItem, int style, int index) {
+ this (checkNull (parentItem).parent, parentItem, style, index, 0);
+}
+
+TreeItem (Tree parent, TreeItem parentItem, int style, int index, int handle) {
+ super (parent, style);
+ this.parent = parent;
+ this.handle = handle;
+ if (handle == 0) {
+ parent.createItem (this, parentItem, index);
+ } else {
+ createWidget ();
+ }
+}
+
+static Tree checkNull (Tree tree) {
+ if (tree == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return tree;
+}
+
+static TreeItem checkNull (TreeItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return item;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void clear () {
+ strings = null;
+ images = null;
+ checked = grayed = false;
+ updateCheck ();
+ setForeground (null);
+ setBackground (null);
+ setFont (null);
+ int columns = parent.columnCount == 0 ? 1 : parent.columnCount;
+ for (int i = 0; i < columns; i++) {
+ updateText (i);
+ updateImage (i);
+ updateBackground (i);
+ updateForeground (i);
+ updateFont (i);
+ }
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
+ int part = findPart (0, Tree.RENDER_PANEL_NAME);
+ if (part != 0) OS.UIElement_InvalidateVisual (part);
+ OS.GCHandle_Free (part);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the tree was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all <code>true</code> if all child items of the indexed item should be
+ * cleared recursively, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, boolean all) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) SWT.error (SWT.ERROR_INVALID_RANGE);
+ parent.clear (handle, index, all);
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * tree was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @param all <code>true</code> if all child items should be cleared
+ * recursively, and <code>false</code> otherwise
+ *
+ * @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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clearAll (boolean all) {
+ checkWidget ();
+ parent.clearAll (this, all);
+}
+
+void columnAdded (int index) {
+ if (parent.columnCount == 0) {
+ int headerTemplate = OS.HeaderedItemsControl_HeaderTemplateProperty ();
+ OS.DependencyObject_ClearValue (handle, headerTemplate);
+ OS.GCHandle_Free (headerTemplate);
+ int header = OS.gcnew_SWTTreeViewRowPresenter (parent.handle);
+ if (header == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GridViewRowPresenterBase_Columns (header, parent.gvColumns);
+ OS.HeaderedItemsControl_Header (handle, header);
+ OS.GCHandle_Free (header);
+ } else {
+ int newLength = parent.columnCount + 1;
+ if (strings != null) {
+ String [] temp = new String [newLength];
+ System.arraycopy (strings, 0, temp, 0, index);
+ System.arraycopy (strings, index, temp, index + 1, parent.columnCount - index);
+ strings = temp;
+ }
+ if (images != null) {
+ Image [] temp = new Image [newLength];
+ System.arraycopy (images, 0, temp, 0, index);
+ System.arraycopy (images, index, temp, index + 1, parent.columnCount - index);
+ images = temp;
+ }
+ if (cellBackground != null) {
+ Color [] temp = new Color [newLength];
+ System.arraycopy (cellBackground, 0, temp, 0, index);
+ System.arraycopy (cellBackground, index, temp, index + 1, parent.columnCount - index);
+ cellBackground = temp;
+ }
+ if (cellForeground != null) {
+ Color [] temp = new Color [newLength];
+ System.arraycopy (cellForeground, 0, temp, 0, index);
+ System.arraycopy (cellForeground, index, temp, index + 1, parent.columnCount - index);
+ cellForeground = temp;
+ }
+ if (cellFont != null) {
+ Font [] temp = new Font [newLength];
+ System.arraycopy (cellFont, 0, temp, 0, index);
+ System.arraycopy (cellFont, index, temp, index + 1, parent.columnCount - index);
+ cellFont = temp;
+ }
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = parent.getItem (items, i, false);
+ if (item != null) {
+ item.columnAdded (index);
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+void columnRemoved(int index) {
+ if (parent.columnCount == 0) {
+ OS.TreeViewItem_HeaderTemplate (handle, parent.headerTemplate);
+ } else {
+ if (strings == null) {
+ String [] temp = new String [parent.columnCount];
+ System.arraycopy (strings, 0, temp, 0, index);
+ System.arraycopy (strings, index + 1, temp, index, parent.columnCount - index);
+ strings = temp;
+ }
+ if (images != null) {
+ Image [] temp = new Image [parent.columnCount];
+ System.arraycopy (images, 0, temp, 0, index);
+ System.arraycopy (images, index + 1, temp, index, parent.columnCount - index);
+ images = temp;
+ }
+ if (cellBackground != null) {
+ Color [] temp = new Color [parent.columnCount];
+ System.arraycopy (cellBackground, 0, temp, 0, index);
+ System.arraycopy (cellBackground, index + 1, temp, index, parent.columnCount - index);
+ cellBackground = temp;
+ }
+ if (cellForeground != null) {
+ Color [] temp = new Color [parent.columnCount];
+ System.arraycopy (cellForeground, 0, temp, 0, index);
+ System.arraycopy (cellForeground, index + 1, temp, index, parent.columnCount - index);
+ cellForeground = temp;
+ }
+ if (cellFont != null) {
+ Font [] temp = new Font [parent.columnCount];
+ System.arraycopy (cellFont, 0, temp, 0, index);
+ System.arraycopy (cellFont, index + 1, temp, index, parent.columnCount - index);
+ cellFont = temp;
+ }
+ }
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = parent.getItem (items, i, false);
+ if (item != null) {
+ item.columnRemoved (index);
+ }
+ }
+ OS.GCHandle_Free (items);
+}
+
+void createHandle () {
+ if (handle == 0) {
+ handle = OS.gcnew_TreeViewItem ();
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+ if (parent.columnCount != 0) {
+ int headerHandle = OS.gcnew_SWTTreeViewRowPresenter (parent.handle);
+ if (headerHandle == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GridViewRowPresenterBase_Columns (headerHandle, parent.gvColumns);
+ OS.HeaderedItemsControl_Header (handle, headerHandle);
+ OS.GCHandle_Free (headerHandle);
+ } else {
+ OS.TreeViewItem_HeaderTemplate (handle, parent.headerTemplate);
+ }
+ }
+ OS.Control_HorizontalContentAlignment (handle, OS.HorizontalAlignment_Stretch);
+ OS.Control_VerticalContentAlignment (handle, OS.VerticalAlignment_Stretch);
+ updateCheck ();
+ fixStyle ();
+}
+
+void deregister () {
+ display.removeWidget (handle);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+int findContentPresenter () {
+ updateLayout (handle);
+ int controlTemplate = OS.Control_Template (handle);
+ int headerName = createDotNetString ("PART_Header", false);
+ int contentPresenter = OS.FrameworkTemplate_FindName (controlTemplate, headerName, handle);
+ OS.GCHandle_Free (headerName);
+ OS.GCHandle_Free (controlTemplate);
+ return contentPresenter;
+}
+
+int findPart (int column, String partName) {
+ if (contentHandle == 0) updateLayout (handle);
+ if (contentHandle == 0) return 0;
+ int name = createDotNetString (partName, false);
+ int result = 0;
+ if (parent.columnCount == 0) {
+ int template = OS.TreeViewItem_HeaderTemplate (handle);
+ result = OS.FrameworkTemplate_FindName (template, name, contentHandle);
+ OS.GCHandle_Free (template);
+ } else {
+ int rowPresenter = OS.HeaderedItemsControl_Header (handle);
+ int contentPresenter = OS.VisualTreeHelper_GetChild (rowPresenter, column);
+ OS.GCHandle_Free (rowPresenter);
+ int columnHandle = OS.GridViewColumnCollection_default (parent.gvColumns, column);
+ int template = OS.GridViewColumn_CellTemplate (columnHandle);
+ OS.GCHandle_Free (columnHandle);
+ result = OS.FrameworkTemplate_FindName (template, name, contentPresenter);
+ OS.GCHandle_Free (contentPresenter);
+ OS.GCHandle_Free (template);
+ }
+ OS.GCHandle_Free (name);
+ return result;
+}
+
+void fixStyle () {
+ int itemStyle = OS.gcnew_Style ();
+ if (itemStyle == 0) error (SWT.ERROR_NO_HANDLES);
+ int setters = OS.Style_Setters (itemStyle);
+ int source = OS.gcnew_RelativeSource (OS.RelativeSourceMode_FindAncestor);
+ int treeViewType = OS.TreeView_typeid ();
+
+ /* clear the templated foreground color */
+ int property = OS.Control_ForegroundProperty ();
+ int propertyPath = createDotNetString ("Foreground", false);
+ int binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.RelativeSource_AncestorType (source, treeViewType);
+ OS.Binding_RelativeSource (binding, source);
+ int setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ /* bind font properties to tree instead of parent item */
+ property = OS.Control_FontSizeProperty ();
+ propertyPath = createDotNetString ("FontSize", false);
+ binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.Binding_RelativeSource (binding, source);
+ setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ property = OS.TextBlock_FontFamilyProperty ();
+ propertyPath = createDotNetString ("FontFamily", false);
+ binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.Binding_RelativeSource (binding, source);
+ setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ property = OS.TextBlock_FontStretchProperty ();
+ propertyPath = createDotNetString ("FontStretch", false);
+ binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.Binding_RelativeSource (binding, source);
+ setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ property = OS.TextBlock_FontWeightProperty ();
+ propertyPath = createDotNetString ("FontWeight", false);
+ binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.Binding_RelativeSource (binding, source);
+ setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ property = OS.TextBlock_FontStyleProperty ();
+ propertyPath = createDotNetString ("FontStyle", false);
+ binding = OS.gcnew_Binding (propertyPath);
+ if (binding == 0) error (SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free (propertyPath);
+ OS.Binding_RelativeSource (binding, source);
+ setter = OS.gcnew_Setter (property, binding);
+ OS.GCHandle_Free (property);
+ OS.GCHandle_Free (binding);
+ OS.SetterBaseCollection_Add (setters, setter);
+ OS.GCHandle_Free (setter);
+
+ OS.FrameworkElement_Style (handle, itemStyle);
+ OS.GCHandle_Free (treeViewType);
+ OS.GCHandle_Free (source);
+ OS.GCHandle_Free (setters);
+ OS.GCHandle_Free (itemStyle);
+}
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @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>
+ *
+ * @since 2.0
+ *
+ */
+public Color getBackground () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return background != null ? background : parent.getBackground ();
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Color getBackground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getBackground ();
+ if (cellBackground == null || cellBackground [index] == null) return getBackground ();
+ return cellBackground [index];
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @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 Rectangle getBounds () {
+ checkWidget ();
+ return getTextBounds (0);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Rectangle getBounds (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index != 0 && !(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ if (!OS.UIElement_IsVisible (handle)) return new Rectangle (0, 0, 0, 0);
+ updateLayout (handle);
+ int point = OS.gcnew_Point (0, 0);
+ int stackPanel = findPart (index, Tree.CONTENTPANEL_PART_NAME);
+ int location = OS.UIElement_TranslatePoint (stackPanel, point, parent.handle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (stackPanel);
+ int height = (int) OS.FrameworkElement_ActualHeight (stackPanel);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ OS.GCHandle_Free (stackPanel);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is checked,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK style, return false.
+ * <p>
+ *
+ * @return the checked 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>
+ */
+public boolean getChecked () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return checked;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is expanded,
+ * and false otherwise.
+ * <p>
+ *
+ * @return the expanded 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>
+ */
+public boolean getExpanded () {
+ checkWidget ();
+ return OS.TreeViewItem_IsExpanded (handle);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return font != null ? font : parent.getFont ();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Font getFont (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getFont ();
+ if (cellFont == null || cellFont [index] == null) return getFont ();
+ return cellFont [index];
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @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>
+ *
+ * @since 2.0
+ *
+ */
+public Color getForeground () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return foreground != null ? foreground : parent.getForeground ();
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Color getForeground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.columnCount);
+ if (0 > index || index > count -1) return getForeground ();
+ if (cellForeground == null || cellForeground [index] == null) return getForeground ();
+ return cellForeground [index];
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK style, return false.
+ * <p>
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @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 boolean getGrayed () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return false;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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>
+ *
+ * @since 3.1
+ */
+public TreeItem getItem (int index) {
+ checkWidget ();
+ if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int items = OS.ItemsControl_Items (handle);
+ TreeItem item = parent.getItem (items, index, true);
+ OS.GCHandle_Free (items);
+ return item;
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.
+ *
+ * @return the number of items
+ *
+ * @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 int getItemCount () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return itemCount;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>TreeItem</code>s which
+ * are the direct item children of the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the receiver's items
+ *
+ * @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 TreeItem [] getItems () {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int items = OS.ItemsControl_Items (handle);
+ TreeItem [] result = new TreeItem [itemCount];
+ for (int i = 0; i < result.length; i++) {
+ result [i] = parent.getItem (items, i, true);
+ }
+ OS.GCHandle_Free (items);
+ return result;
+}
+
+public Image getImage () {
+ checkWidget ();
+ return getImage (0);
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Image getImage (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (images != null) {
+ if (0 <= index && index < images.length) return images [index];
+ }
+ return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public Rectangle getImageBounds (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index != 0 && !(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ int parentHandle = parent.topHandle ();
+ int part = findPart (index, Tree.IMAGE_PART_NAME);
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int location = OS.UIElement_TranslatePoint (part, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (point);
+ OS.GCHandle_Free (location);
+ int width = (int) OS.FrameworkElement_ActualWidth (part);
+ int height = (int) OS.FrameworkElement_ActualHeight (part);
+ OS.GCHandle_Free (part);
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tree</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @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 Tree getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>TreeItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @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 TreeItem getParentItem () {
+ checkWidget ();
+ int parentItem = OS.FrameworkElement_Parent (handle);
+ TreeItem result = null;
+ if (!OS.Object_Equals (parentItem, parent.handle)) {
+ result = (TreeItem) display.getWidget (parentItem);
+ }
+ OS.GCHandle_Free (parentItem);
+ return result;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of the text at a column in the
+ * tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding text rectangle
+ *
+ * @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>
+ *
+ * @since 3.3
+ */
+public Rectangle getTextBounds (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index != 0 && !(0 <= index && index < parent.columnCount)) return new Rectangle (0, 0, 0, 0);
+ int parentHandle = parent.topHandle ();
+ int point = OS.gcnew_Point (0, 0);
+ if (point == 0) error (SWT.ERROR_NO_HANDLES);
+ int textBlock = findPart (index, Tree.TEXT_PART_NAME);
+ int renderPanel = findPart (index, Table.RENDER_PANEL_NAME);
+ Rectangle result = new Rectangle (0, 0, 0, 0);
+ if (textBlock != 0 && renderPanel != 0) {
+ int location = OS.UIElement_TranslatePoint (textBlock, point, parentHandle);
+ int x = (int) OS.Point_X (location);
+ int y = (int) OS.Point_Y (location);
+ OS.GCHandle_Free (location);
+ double textWidth = OS.FrameworkElement_ActualWidth (textBlock);
+ int panelLocation = OS.UIElement_TranslatePoint (textBlock, point, renderPanel);
+ double visibleWidth = Math.max (0, OS.FrameworkElement_ActualWidth (renderPanel) - OS.Point_X (panelLocation));
+ OS.GCHandle_Free (panelLocation);
+ int width = (int) Math.min (textWidth, visibleWidth);
+ int height = (int) OS.FrameworkElement_ActualHeight (textBlock);
+ result = new Rectangle (x, y, width, height);
+ }
+ OS.GCHandle_Free (point);
+ if (textBlock != 0) OS.GCHandle_Free (textBlock);
+ if (renderPanel != 0) OS.GCHandle_Free (renderPanel);
+ return result;
+}
+
+public String getText () {
+ checkWidget ();
+ return getText (0);
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @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>
+ *
+ * @since 3.1
+ */
+public String getText (int index) {
+ checkWidget ();
+ if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (strings != null && 0 <= index && index < strings.length) {
+ return strings [index]!= null ? strings [index] : "";
+ }
+ return "";
+}
+
+Control getWidgetControl () {
+ return parent;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</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>
+ *
+ * @since 3.1
+ */
+public int indexOf (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ int items = OS.ItemsControl_Items (handle);
+ int index = OS.ItemCollection_IndexOf (items, item.handle);
+ OS.GCHandle_Free (items);
+ return index;
+}
+
+void register () {
+ display.addWidget (handle, this);
+}
+
+void releaseChildren (boolean destroy) {
+ int items = OS.ItemsControl_Items (handle);
+ for (int i=0; i<itemCount; i++) {
+ TreeItem item = parent.getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ OS.GCHandle_Free (items);
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ if (handle != 0) OS.GCHandle_Free (handle);
+ handle = 0;
+ if (contentHandle != 0) OS.GCHandle_Free (contentHandle);
+ contentHandle = 0;
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ strings = null;
+ images = null;
+ cellBackground = cellForeground = null;
+ cellFont = null;
+}
+
+/**
+ * Removes all of the items from the receiver.
+ * <p>
+ * @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>
+ *
+ * @since 3.1
+ */
+public void removeAll () {
+ checkWidget ();
+ int items = OS.ItemsControl_Items (handle);
+ for (int i = 0; i < itemCount; i++) {
+ TreeItem item = parent.getItem (items, i, false);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ parent.ignoreSelection = true;
+ OS.ItemCollection_Clear (items);
+ parent.ignoreSelection = false;
+ OS.GCHandle_Free (items);
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 2.0
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (color != null) {
+ int brush = OS.gcnew_SolidColorBrush (color.handle);
+ OS.Control_Background (handle, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ background = color;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.1
+ *
+ */
+public void setBackground (int index, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellBackground == null) cellBackground = new Color [count];
+ cellBackground [index] = color;
+ updateBackground (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the checked state of the receiver.
+ * <p>
+ *
+ * @param checked the new checked 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>
+ */
+public void setChecked (boolean checked) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ if (this.checked == checked) return;
+ this.checked = checked;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ parent.ignoreSelection = true;
+ updateCheck ();
+ parent.ignoreSelection = false;
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ * <p>
+ *
+ * @param expanded the new expanded 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>
+ */
+public void setExpanded (boolean expanded) {
+ checkWidget ();
+ OS.TreeViewItem_IsExpanded (handle, expanded);
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (font != null) {
+ int family = OS.Typeface_FontFamily (font.handle);
+ OS.Control_FontFamily (handle, family);
+ OS.GCHandle_Free (family);
+ int stretch = OS.Typeface_Stretch (font.handle);
+ OS.Control_FontStretch (handle, stretch);
+ OS.GCHandle_Free (stretch);
+ int style = OS.Typeface_Style (font.handle);
+ OS.Control_FontStyle (handle, style);
+ OS.GCHandle_Free (style);
+ int weight = OS.Typeface_Weight (font.handle);
+ OS.Control_FontWeight (handle, weight);
+ OS.GCHandle_Free (weight);
+ OS.Control_FontSize (handle, font.size);
+ } else {
+ int property = OS.Control_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS. Control_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ property = OS.Control_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ this.font = font;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.1
+ */
+public void setFont (int index, Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellFont == null) {
+ if (font == null) return;
+ cellFont = new Font [count];
+ }
+ Font oldFont = cellFont [index];
+ if (oldFont == font) return;
+ cellFont [index] = font;
+ if (oldFont != null && oldFont.equals (font)) return;
+ updateFont (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @since 2.0
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 2.0
+ *
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (color != null) {
+ int brush = OS.gcnew_SolidColorBrush (color.handle);
+ OS.Control_Foreground (handle, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (handle, property);
+ OS.GCHandle_Free (property);
+ }
+ foreground = color;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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>
+ *
+ * @since 3.1
+ *
+ */
+public void setForeground (int index, Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (cellForeground == null) cellForeground = new Color [count];
+ cellForeground [index] = color;
+ updateForeground (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item. This state change
+ * only applies if the Tree was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox
+ *
+ * @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 setGrayed (boolean grayed) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ if (this.grayed == grayed) return;
+ this.grayed = grayed;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ parent.ignoreSelection = true;
+ updateCheck ();
+ parent.ignoreSelection = false;
+}
+
+/**
+ * Sets the image for multiple columns in the tree.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</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>
+ *
+ * @since 3.1
+ */
+public void setImage (Image [] images) {
+ checkWidget ();
+ if (images == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<images.length; i++) {
+ setImage (i, images [i]);
+ }
+}
+
+/**
+ * Sets the receiver's image at a column.
+ *
+ * @param index the column index
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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>
+ *
+ * @since 3.1
+ */
+public void setImage (int index, Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) {
+ error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (images == null) images = new Image [count];
+ images [index] = image;
+ updateImage (index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ setImage (0, image);
+}
+
+/**
+ * Sets the number of child items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @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>
+ *
+ * @since 3.2
+ */
+public void setItemCount (int count) {
+ checkWidget ();
+ parent.setItemCount (this, count);
+}
+
+/**
+ * Sets the text for multiple columns in the tree.
+ *
+ * @param strings the array of new strings
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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>
+ *
+ * @since 3.1
+ */
+public void setText (String [] strings) {
+ checkWidget ();
+ if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i<strings.length; i++) {
+ String string = strings [i];
+ if (string != null) setText (i, string);
+ }
+}
+
+/**
+ * Sets the receiver's text at a column
+ *
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text 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>
+ *
+ * @since 3.1
+ */
+public void setText (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (strings == null) strings = new String [count];
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ strings [index] = string;
+ updateText (index);
+}
+
+public void setText (String string) {
+ checkWidget ();
+ setText (0, string);
+}
+
+void updateBackground (int index) {
+ int panel = findPart (index, Tree.CONTENTPANEL_PART_NAME);
+ if (panel != 0) {
+ if (cellBackground != null && cellBackground [index] != null) {
+ int brush = OS.gcnew_SolidColorBrush (cellBackground [index].handle);
+ OS.Panel_Background (panel, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Panel_BackgroundProperty ();
+ OS.DependencyObject_ClearValue (panel, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (panel);
+ }
+}
+
+void updateCheck () {
+ if ((parent.style & SWT.CHECK) == 0) return;
+ int checkBox = findPart (0, Tree.CHECKBOX_PART_NAME);
+ if (checkBox != 0) {
+ parent.ignoreSelection = true;
+ if (!grayed) {
+ OS.ToggleButton_IsChecked (checkBox, checked);
+ } else {
+ if (checked)
+ OS.ToggleButton_IsCheckedNullSetter (checkBox);
+ }
+ parent.ignoreSelection = false;
+ OS.GCHandle_Free (checkBox);
+ }
+}
+
+void updateFont (int index) {
+ if (cellFont == null) return;
+ int textBlock = findPart (index, Tree.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ Font font = cellFont != null ? cellFont [index] : null;
+ if (font != null) {
+ int family = OS.Typeface_FontFamily (font.handle);
+ OS.TextBlock_FontFamily (textBlock, family);
+ OS.GCHandle_Free (family);
+ int stretch = OS.Typeface_Stretch (font.handle);
+ OS.TextBlock_FontStretch (textBlock, stretch);
+ OS.GCHandle_Free (stretch);
+ int style = OS.Typeface_Style (font.handle);
+ OS.TextBlock_FontStyle (textBlock, style);
+ OS.GCHandle_Free (style);
+ int weight = OS.Typeface_Weight (font.handle);
+ OS.TextBlock_FontWeight (textBlock, weight);
+ OS.GCHandle_Free (weight);
+ OS.TextBlock_FontSize (textBlock, font.size);
+ } else {
+ int property = OS.TextBlock_FontFamilyProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontSizeProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStretchProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontWeightProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ property = OS.TextBlock_FontStyleProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+
+void updateForeground (int index) {
+ int textBlock = findPart (index, Tree.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ if (cellForeground != null && cellForeground [index] != null) {
+ int brush = OS.gcnew_SolidColorBrush (cellForeground [index].handle);
+ OS.TextBlock_Foreground (textBlock, brush);
+ OS.GCHandle_Free (brush);
+ } else {
+ int property = OS.Control_ForegroundProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+
+void updateImage (int index) {
+ if (images == null) return;
+ int img = findPart (index, Tree.IMAGE_PART_NAME);
+ if (img != 0) {
+ int src = 0;
+ if (images != null) src = images [index] != null ? images [index].handle : 0;
+ OS.Image_Source (img, src);
+ OS.GCHandle_Free (img);
+ }
+}
+
+void updateText (int index) {
+ int textBlock = findPart (index, Tree.TEXT_PART_NAME);
+ if (textBlock != 0) {
+ if (strings != null && strings [index] != null) {
+ int strPtr = createDotNetString (strings [index], false);
+ OS.TextBlock_Text (textBlock, strPtr);
+ OS.GCHandle_Free (strPtr);
+ } else {
+ int property = OS.TextBlock_TextProperty ();
+ OS.DependencyObject_ClearValue (textBlock, property);
+ OS.GCHandle_Free (property);
+ }
+ OS.GCHandle_Free (textBlock);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Widget.java
new file mode 100644
index 0000000000..1ef18e0873
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/widgets/Widget.java
@@ -0,0 +1,1478 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.internal.*;
+import org.eclipse.swt.internal.wpf.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * This class is the abstract superclass of all user interface objects.
+ * Widgets are created, disposed and issue notification to listeners
+ * when events occur which affect them.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Dispose</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation. However, it has not been marked
+ * final to allow those outside of the SWT development team to implement
+ * patched versions of the class in order to get around specific
+ * limitations in advance of when those limitations can be addressed
+ * by the team. Any class built using subclassing to access the internals
+ * of this class will likely fail to compile or run between releases and
+ * may be strongly platform specific. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the workings of the
+ * hierarchy. No support is provided for user-written classes which are
+ * implemented as subclasses of this class.
+ * </p>
+ *
+ * @see #checkSubclass
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Widget {
+ /**
+ * the handle to the OS resource
+ * (Warning: This field is platform dependent)
+ * <p>
+ * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ * </p>
+ */
+ public int handle;
+ int jniRef;
+ int style, state;
+ Display display;
+ EventTable eventTable;
+ Object data;
+
+ /* Global state flags */
+ static final int DISPOSED = 1<<0;
+ static final int CANVAS = 1<<1;
+ static final int KEYED_DATA = 1<<2;
+ static final int DISABLED = 1<<3;
+ static final int HIDDEN = 1<<4;
+
+ /* A layout was requested on this widget */
+ static final int LAYOUT_NEEDED = 1<<5;
+
+ /* The preferred size of a child has changed */
+ static final int LAYOUT_CHANGED = 1<<6;
+
+ /* A layout was requested in this widget hierachy */
+ static final int LAYOUT_CHILD = 1<<7;
+
+ /* Background flags */
+ static final int THEME_BACKGROUND = 1<<8;
+ static final int DRAW_BACKGROUND = 1<<9;
+ static final int PARENT_BACKGROUND = 1<<10;
+
+ /* Dispose and release flags */
+ static final int RELEASED = 1<<11;
+ static final int DISPOSE_SENT = 1<<12;
+
+ static final int MOVED = 1<<13;
+ static final int RESIZED = 1<<14;
+
+ /* DragDetect */
+ static final int DRAG_DETECT = 1<<15;
+
+ /* Default size for widgets */
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+
+
+ static final int CLICK = 1;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Widget () {
+}
+
+/**
+ * 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
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</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 #checkSubclass
+ * @see #getStyle
+ */
+public Widget (Widget parent, int style) {
+ checkSubclass ();
+ checkParent (parent);
+ this.style = style;
+ display = parent.display;
+}
+
+void _addListener (int eventType, Listener listener) {
+ if (eventTable == null) eventTable = new EventTable ();
+ eventTable.hook (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an event of the given type occurs. When the
+ * event does occur in the widget, the listener is notified by
+ * sending it the <code>handleEvent()</code> message. The event
+ * type is one of the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @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>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #getListeners(int)
+ * @see #removeListener(int, Listener)
+ * @see #notifyListeners
+ */
+public void addListener (int eventType, Listener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ _addListener (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the widget is disposed. When the widget is
+ * disposed, the listener is notified by sending it the
+ * <code>widgetDisposed()</code> message.
+ *
+ * @param listener the listener which should be notified when the receiver is disposed
+ *
+ * @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>
+ *
+ * @see DisposeListener
+ * @see #removeDisposeListener
+ */
+public void addDisposeListener (DisposeListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Dispose, typedListener);
+}
+
+void addWidget () {
+}
+
+/**
+ * Returns a style with exactly one style bit set out of
+ * the specified set of exclusive style bits. All other
+ * possible bits are cleared when the first matching bit
+ * is found. Bits that are not part of the possible set
+ * are untouched.
+ *
+ * @param style the original style bits
+ * @param int0 the 0th possible style bit
+ * @param int1 the 1st possible style bit
+ * @param int2 the 2nd possible style bit
+ * @param int3 the 3rd possible style bit
+ * @param int4 the 4th possible style bit
+ * @param int5 the 5th possible style bit
+ *
+ * @return the new style bits
+ */
+static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) {
+ int mask = int0 | int1 | int2 | int3 | int4 | int5;
+ if ((style & mask) == 0) style |= int0;
+ if ((style & int0) != 0) style = (style & ~mask) | int0;
+ if ((style & int1) != 0) style = (style & ~mask) | int1;
+ if ((style & int2) != 0) style = (style & ~mask) | int2;
+ if ((style & int3) != 0) style = (style & ~mask) | int3;
+ if ((style & int4) != 0) style = (style & ~mask) | int4;
+ if ((style & int5) != 0) style = (style & ~mask) | int5;
+ return style;
+}
+
+boolean checkEvent (int e) {
+ if (isDisposed ()) return false;
+ int routedEventType = OS.RoutedEventArgs_typeid ();
+ int source = 0;
+ if (OS.Type_IsInstanceOfType (routedEventType, e)) {
+ source = OS.RoutedEventArgs_OriginalSource (e);
+ }
+ OS.GCHandle_Free (routedEventType);
+ if (source == 0) return true;
+ if (OS.Object_Equals (source, handle)) {
+ OS.GCHandle_Free (source);
+ return true;
+ }
+ Widget widget = display.getWidget (source);
+ OS.GCHandle_Free (source);
+ if (widget == this) return true;
+ if (hasItems ()) {
+ if (this == widget.getWidgetControl ()) return true;
+ }
+ return false;
+}
+
+void checkOrientation (Widget parent) {
+ style &= ~SWT.MIRRORED;
+ if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+ if (parent != null) {
+ if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
+ if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) style |= SWT.RIGHT_TO_LEFT;
+ }
+ }
+ style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
+void checkOpened () {
+ /* Do nothing */
+}
+
+/**
+ * Throws an exception if the specified widget can not be
+ * used as a parent for the receiver.
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ */
+void checkParent (Widget parent) {
+ if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ parent.checkWidget ();
+ parent.checkOpened ();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * The SWT class library is intended to be subclassed
+ * only at specific, controlled points (most notably,
+ * <code>Composite</code> and <code>Canvas</code> when
+ * implementing new widgets). This method enforces this
+ * rule unless it is overridden.
+ * </p><p>
+ * <em>IMPORTANT:</em> By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between SWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ * </p><p>
+ * The ability to subclass outside of the allowed SWT classes
+ * is intended purely to enable those not on the SWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * widget implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code>) on a widget that has had its
+ * <code>dispose()</code> method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * </p>
+ *
+ * @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>
+ */
+protected void checkWidget () {
+ Display display = this.display;
+ if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED);
+}
+
+void createHandle () {
+}
+
+int createDotNetString (String string, boolean fixMnemonic) {
+ if (string == null) return 0;
+ char [] buffer;
+ if (fixMnemonic) {
+ buffer = fixMnemonic (string);
+ } else {
+ int length = string.length ();
+ buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ }
+ int ptr = OS.gcnew_String (buffer);
+ if (ptr == 0) error (SWT.ERROR_NO_HANDLES);
+ return ptr;
+}
+
+static String createJavaString (int ptr) {
+ int charArray = OS.String_ToCharArray (ptr);
+ char[] chars = new char[OS.String_Length (ptr)];
+ OS.memcpy (chars, charArray, chars.length * 2);
+ OS.GCHandle_Free (charArray);
+ return new String (chars);
+}
+
+void createWidget () {
+ jniRef = OS.NewGlobalRef (this);
+ if (jniRef == 0) error (SWT.ERROR_NO_HANDLES);
+ createHandle ();
+ addWidget ();
+ register ();
+ hookEvents ();
+ setNameScope ();
+}
+
+void deregister () {
+}
+
+/**
+ * Destroys the widget in the operating system and releases
+ * the widget's handle. If the widget does not have a handle,
+ * this method may hide the widget, mark the widget as destroyed
+ * or do nothing, depending on the widget.
+ * <p>
+ * When a widget is destroyed in the operating system, its
+ * descendents are also destroyed by the operating system.
+ * This means that it is only necessary to call <code>destroyWidget</code>
+ * on the root of the widget tree.
+ * </p><p>
+ * This method is called after <code>releaseWidget()</code>.
+ * </p><p>
+ * See also <code>releaseChild()</code>, <code>releaseWidget()</code>
+ * and <code>releaseHandle()</code>.
+ * </p>
+ *
+ * @see #dispose
+ */
+void destroyWidget () {
+ releaseHandle ();
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver and all its descendants. After this method has
+ * been invoked, the receiver and all descendants will answer
+ * <code>true</code> when sent the message <code>isDisposed()</code>.
+ * Any internal connections between the widgets in the tree will
+ * have been removed to facilitate garbage collection.
+ * <p>
+ * NOTE: This method is not called recursively on the descendants
+ * of the receiver. This means that, widget implementers can not
+ * detect when a widget is being disposed of by re-implementing
+ * this method, but should instead listen for the <code>Dispose</code>
+ * event.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #addDisposeListener
+ * @see #removeDisposeListener
+ * @see #checkWidget
+ */
+public void dispose () {
+ /*
+ * Note: It is valid to attempt to dispose a widget
+ * more than once. If this happens, fail silently.
+ */
+ if (isDisposed ()) return;
+ if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ release (true);
+}
+
+boolean dragOverride () {
+ return false;
+}
+
+static void dumpObjectType (int object) {
+ int objectType = OS.Object_GetType(object);
+ int type = OS.Type_FullName(objectType);
+ String typeName = createJavaString(type);
+ OS.GCHandle_Free(objectType);
+ OS.GCHandle_Free(type);
+ System.out.println(typeName);
+}
+
+void dumpVisualTree (int visual, int depth) {
+ for (int i = 0; i < depth; i++) System.out.print ("\t");
+ int type = OS.Object_GetType (visual);
+ int typeNamePtr = OS.Type_FullName (type);
+ OS.GCHandle_Free (type);
+ String typeName = createJavaString (typeNamePtr);
+ OS.GCHandle_Free(typeNamePtr);
+ int name = OS.FrameworkElement_Name (visual);
+ double width = OS.FrameworkElement_Width (visual);
+ double actualWidth = OS.FrameworkElement_ActualWidth (visual);
+ double height = OS.FrameworkElement_Height (visual);
+ double actualHeight = OS.FrameworkElement_ActualHeight (visual);
+ String widgetName = createJavaString (name);
+ OS.GCHandle_Free (name);
+ System.out.println(typeName + " ["+widgetName+ " width=" + width + " actualWidth=" + actualWidth + " height=" + height + " actualHeight=" + actualHeight+"]");
+ int count = OS.VisualTreeHelper_GetChildrenCount(visual);
+ for (int i = 0; i < count; i++) {
+ int child = OS.VisualTreeHelper_GetChild (visual, i);
+ dumpVisualTree(child, depth+1);
+ OS.GCHandle_Free(child);
+ }
+}
+/**
+ * Does whatever widget specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+ SWT.error(code);
+}
+
+boolean filters (int eventType) {
+ return display.filters (eventType);
+}
+
+char [] fixMnemonic (String string) {
+ int length = string.length ();
+ char [] text = new char [length];
+ string.getChars (0, length, text, 0);
+ int i = 0, j = 0;
+ char [] result = new char [length * 2 + 1];
+ while (i < length) {
+ switch (text [i]) {
+ case '&':
+ if (i + 1 < length && text [i + 1] == '&') {
+ i++;
+ } else {
+ text [i] = '_';
+ }
+ break;
+ case '_':
+ result [j++] = '_';
+ break;
+ }
+ result [j++] = text [i++];
+ }
+ return result;
+}
+
+/**
+ * Returns the application defined widget data associated
+ * with the receiver, or null if it has not been set. The
+ * <em>widget data</em> is a single, unnamed field that is
+ * stored with every widget.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ * </p>
+ *
+ * @return the widget data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
+ * </ul>
+ *
+ * @see #setData(Object)
+ */
+public Object getData () {
+ checkWidget();
+ return (state & KEYED_DATA) != 0 ? ((Object []) data) [0] : data;
+}
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the key 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>
+ *
+ * @see #setData(String, Object)
+ */
+public Object getData (String key) {
+ checkWidget();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((state & KEYED_DATA) != 0) {
+ Object [] table = (Object []) data;
+ for (int i=1; i<table.length; i+=2) {
+ if (key.equals (table [i])) return table [i+1];
+ }
+ }
+ return null;
+}
+
+/**
+ * Returns the <code>Display</code> that is associated with
+ * the receiver.
+ * <p>
+ * A widget's display is either provided when it is created
+ * (for example, top level <code>Shell</code>s) or is the
+ * same as its parent's display.
+ * </p>
+ *
+ * @return the receiver's display
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Display getDisplay () {
+ Display display = this.display;
+ if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
+ return display;
+}
+
+/**
+ * Returns an array of listeners who will be notified when an event
+ * of the given type occurs. The event type is one of the event constants
+ * defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @return an array of listeners that will be notified when the event occurs
+ *
+ * @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 Listener
+ * @see SWT
+ * @see #addListener(int, Listener)
+ * @see #removeListener(int, Listener)
+ * @see #notifyListeners
+ *
+ * @since 3.4
+ */
+public Listener[] getListeners (int eventType) {
+ checkWidget();
+ if (eventTable == null) return new Listener[0];
+ return eventTable.getListeners(eventType);
+}
+
+Menu getMenu () {
+ return null;
+}
+
+/**
+ * Returns the name of the widget. This is the name of
+ * the class without the package name.
+ *
+ * @return the name of the widget
+ */
+String getName () {
+ String string = getClass ().getName ();
+ int index = string.lastIndexOf ('.');
+ if (index == -1) return string;
+ return string.substring (index + 1, string.length ());
+}
+
+/*
+ * Returns a short printable representation for the contents
+ * of a widget. For example, a button may answer the label
+ * text. This is used by <code>toString</code> to provide a
+ * more meaningful description of the widget.
+ *
+ * @return the contents string for the widget
+ *
+ * @see #toString
+ */
+String getNameText () {
+ return ""; //$NON-NLS-1$
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles. For example, if the platform widget used to
+ * implement a particular SWT widget always has scroll bars, the
+ * result of calling this method would always have the
+ * <code>SWT.H_SCROLL</code> and <code>SWT.V_SCROLL</code> bits set.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @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 int getStyle () {
+ checkWidget();
+ return style;
+}
+
+Control getWidgetControl () {
+ return null;
+}
+
+boolean hasItems () {
+ return false;
+}
+
+void hookEvents () {
+}
+
+/*
+ * Returns <code>true</code> if the specified eventType is
+ * hooked, and <code>false</code> otherwise. Implementations
+ * of SWT can avoid creating objects and sending events
+ * when an event happens in the operating system but
+ * there are no listeners hooked for the event.
+ *
+ * @param eventType the event to be checked
+ *
+ * @return <code>true</code> when the eventType is hooked and <code>false</code> otherwise
+ *
+ * @see #isListening
+ */
+boolean hooks (int eventType) {
+ if (eventTable == null) return false;
+ return eventTable.hooks (eventType);
+}
+
+/**
+ * Returns <code>true</code> if the widget has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the widget.
+ * When a widget has been disposed, it is an error to
+ * invoke any other method using the widget.
+ * </p>
+ *
+ * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+ return (state & DISPOSED) != 0;
+}
+
+/**
+ * Returns <code>true</code> if there are any listeners
+ * for the specified event type associated with the receiver,
+ * and <code>false</code> otherwise. The event type is one of
+ * the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event
+ * @return true if the event is hooked
+ *
+ * @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 SWT
+ */
+public boolean isListening (int eventType) {
+ checkWidget();
+ return hooks (eventType);
+}
+
+/*
+ * Returns <code>true</code> when subclassing is
+ * allowed and <code>false</code> otherwise
+ *
+ * @return <code>true</code> when subclassing is allowed and <code>false</code> otherwise
+ */
+boolean isValidSubclass () {
+ return Display.isValidClass (getClass ());
+}
+
+/*
+ * Returns <code>true</code> when the current thread is
+ * the thread that created the widget and <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> when the current thread is the thread that created the widget and <code>false</code> otherwise
+ */
+boolean isValidThread () {
+ return getDisplay ().isValidThread ();
+}
+
+void mapEvent (int hwnd, Event event) {
+}
+
+boolean mnemonicMatch (int accessText, char key) {
+ if (accessText == 0) return false;
+ char mnemonic = OS.AccessText_AccessKey (accessText);
+ return Character.toLowerCase (key) == Character.toLowerCase (mnemonic);
+}
+
+/**
+ * Notifies all of the receiver's listeners for events
+ * of the given type that one such event has occurred by
+ * invoking their <code>handleEvent()</code> method. The
+ * event type is one of the event constants defined in class
+ * <code>SWT</code>.
+ *
+ * @param eventType the type of event which has occurred
+ * @param event the event data
+ *
+ * @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 SWT
+ * @see #addListener
+ * @see #getListeners(int)
+ * @see #removeListener(int, Listener)
+ */
+public void notifyListeners (int eventType, Event event) {
+ checkWidget();
+ if (event == null) event = new Event ();
+ sendEvent (eventType, event);
+}
+
+void postEvent (int eventType) {
+ sendEvent (eventType, null, false);
+}
+
+void postEvent (int eventType, Event event) {
+ sendEvent (eventType, event, false);
+}
+
+void register () {
+}
+
+/*
+ * Releases the widget hiearchy and optionally destroys
+ * the receiver.
+ * <p>
+ * Typically, a widget with children will broadcast this
+ * message to all children so that they too can release their
+ * resources. The <code>releaseHandle</code> method is used
+ * as part of this broadcast to zero the handle fields of the
+ * children without calling <code>destroyWidget</code>. In
+ * this scenario, the children are actually destroyed later,
+ * when the operating system destroys the widget tree.
+ * </p>
+ *
+ * @param destroy indicates that the receiver should be destroyed
+ *
+ * @see #dispose
+ * @see #releaseHandle
+ * @see #releaseParent
+ * @see #releaseWidget
+*/
+void release (boolean destroy) {
+ if ((state & DISPOSE_SENT) == 0) {
+ state |= DISPOSE_SENT;
+ sendEvent (SWT.Dispose);
+ }
+ if ((state & DISPOSED) == 0) {
+ releaseChildren (destroy);
+ }
+ if ((state & RELEASED) == 0) {
+ state |= RELEASED;
+ if (destroy) {
+ releaseParent ();
+ releaseWidget ();
+ destroyWidget ();
+ } else {
+ releaseWidget ();
+ releaseHandle ();
+ }
+ }
+}
+
+void releaseChildren (boolean destroy) {
+}
+
+/*
+ * Releases the widget's handle by zero'ing it out.
+ * Does not destroy or release any operating system
+ * resources.
+ * <p>
+ * This method is called after <code>releaseWidget</code>
+ * or from <code>destroyWidget</code> when a widget is being
+ * destroyed to ensure that the widget is marked as destroyed
+ * in case the act of destroying the widget in the operating
+ * system causes application code to run in callback that
+ * could access the widget.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseParent
+ * @see #releaseWidget
+ */
+void releaseHandle () {
+ state |= DISPOSED;
+ display = null;
+ if (jniRef != 0) OS.DeleteGlobalRef (jniRef);
+ jniRef = 0;
+}
+
+/*
+ * Releases the receiver, a child in a widget hierarchy,
+ * from its parent.
+ * <p>
+ * When a widget is destroyed, it may be necessary to remove
+ * it from an internal data structure of the parent. When
+ * a widget has no handle, it may also be necessary for the
+ * parent to hide the widget or otherwise indicate that the
+ * widget has been disposed. For example, disposing a menu
+ * bar requires that the menu bar first be released from the
+ * shell when the menu bar is active.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseWidget
+ * @see #releaseHandle
+ */
+void releaseParent () {
+}
+
+/*
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the widget handle.
+ * <p>
+ * When a widget is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the widget made a
+ * copy of an icon, supplied by the programmer, this copy
+ * would be freed in <code>releaseWidget</code>. Also,
+ * to assist the garbage collector and minimize the amount
+ * of memory that is not reclaimed when the programmer keeps
+ * a reference to a disposed widget, all fields except the
+ * handle are zero'd. The handle is needed by <code>destroyWidget</code>.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseHandle
+ * @see #releaseParent
+ */
+void releaseWidget () {
+ deregister ();
+ eventTable = null;
+ data = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs. The event
+ * type is one of the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addListener
+ * @see #getListeners(int)
+ * @see #notifyListeners
+ */
+public void removeListener (int eventType, Listener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see Listener
+ * @see #addListener
+ */
+protected void removeListener (int eventType, SWTEventListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the widget is disposed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @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>
+ *
+ * @see DisposeListener
+ * @see #addDisposeListener
+ */
+public void removeDisposeListener (DisposeListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Dispose, listener);
+}
+
+boolean sendDragEvent (int e) {
+ return sendMouseEvent (SWT.DragDetect, e, false);
+}
+
+boolean sendDragEvent (int button, int stateMask, int x, int y) {
+ Event event = new Event ();
+ event.button = button;
+ event.x = x;
+ event.y = y;
+ event.stateMask = stateMask;
+ postEvent (SWT.DragDetect, event);
+ return event.doit;
+}
+
+void sendEvent (Event event) {
+ Display display = event.display;
+ if (!display.filterEvent (event)) {
+ if (eventTable != null) eventTable.sendEvent (event);
+ }
+}
+
+void sendEvent (int eventType) {
+ sendEvent (eventType, null, true);
+}
+
+void sendEvent (int eventType, Event event) {
+ sendEvent (eventType, event, true);
+}
+
+void sendEvent (int eventType, Event event, boolean send) {
+ if (eventTable == null && !display.filters (eventType)) {
+ return;
+ }
+ if (event == null) event = new Event ();
+ event.type = eventType;
+ event.display = display;
+ event.widget = this;
+ if (event.time == 0) {
+ event.time = display.getLastEventTime ();
+ }
+ if (send) {
+ sendEvent (event);
+ } else {
+ display.postEvent (event);
+ }
+}
+
+boolean sendKeyEvent (int type, int e, boolean textInput) {
+ if (textInput) {
+ int text = OS.TextCompositionEventArgs_Text(e);
+ if (OS.String_Length(text) == 0) {
+ OS.GCHandle_Free(text);
+ text = OS.TextCompositionEventArgs_SystemText(e);
+ if (OS.String_Length(text) == 0) {
+ OS.GCHandle_Free(text);
+ text = OS.TextCompositionEventArgs_ControlText(e);
+ if (OS.String_Length(text) == 0) {
+ return false;
+ }
+ }
+ }
+ int chars = OS.String_ToCharArray(text);
+ char[] buffer = new char[OS.String_Length(text)];
+ OS.memcpy(buffer, chars, buffer.length * 2);
+ OS.GCHandle_Free(chars);
+ OS.GCHandle_Free(text);
+ for (int i = 0; i < buffer.length; i++) {
+ Event event = new Event ();
+ if (buffer.length == 1) {
+ event.keyCode = Display.translateKey(display.lastKey);
+ }
+ event.character = buffer[i];
+ //hack for dead key
+ if (display.deadChar) {
+ event.character = display.lastChar;
+ display.deadChar = false;
+ }
+ setInputState(event, type, 0, 0);
+ sendEvent (type, event);
+ if (isDisposed ()) return false;
+ }
+ return true;
+ } else {
+ Event event = new Event ();
+ if (!setKeyState (event, type, e)) return true;
+ sendEvent (type, event);
+ if (isDisposed ()) return false;
+ return event.doit;
+ }
+}
+
+boolean sendMouseEvent (int type, int e, boolean send) {
+ boolean hooksType = hooks (type) || filters (type);
+ boolean hooksDoubleClick = type == SWT.MouseDown && (hooks (SWT.MouseDoubleClick) || filters (SWT.MouseDoubleClick));
+ if (!hooksType && !hooksDoubleClick) return true;
+ Event event = new Event ();
+ if (type == SWT.MouseDown || type == SWT.MouseUp || type == SWT.DragDetect) {
+ event.button = OS.MouseButtonEventArgs_ChangedButton (e) + 1;
+ event.count = OS.MouseButtonEventArgs_ClickCount (e);
+ }
+ if (type == SWT.MouseWheel) {
+ int lines = OS.SystemParameters_WheelScrollLines ();
+ int delta = OS.MouseWheelEventArgs_Delta (e);
+ if (lines == -1) {
+ event.detail = SWT.SCROLL_PAGE;
+ event.count = delta / 120;
+ } else {
+ event.detail = SWT.SCROLL_LINE;
+ event.count = delta * lines / 120;
+ }
+ }
+ int point = OS.MouseEventArgs_GetPosition (e, handle);
+ event.x = (int) OS.Point_X (point);
+ event.y = (int) OS.Point_Y (point);
+ OS.GCHandle_Free (point);
+ setInputState (event, type, e, 0);
+ Event doubleClick = null;
+ if (hooksDoubleClick && (event.count & 1) == 0) {
+ doubleClick = new Event();
+ doubleClick.button = event.button;
+ doubleClick.x = event.x;
+ doubleClick.y = event.y;
+ doubleClick.count = event.count;
+ doubleClick.stateMask = event.stateMask;
+ }
+ if (send) {
+ sendEvent (type, event);
+ if (isDisposed ()) return false;
+ } else {
+ postEvent (type, event);
+ }
+ if (doubleClick != null) {
+ if (send) {
+ sendEvent (SWT.MouseDoubleClick, doubleClick);
+ if (isDisposed ()) return false;
+ } else {
+ postEvent (SWT.MouseDoubleClick, doubleClick);
+ }
+ }
+ return event.doit;
+}
+
+//TEMPORARY CODE
+void setClipping (int widget, boolean clip) {
+ //TODO - should be is-kind-of UIElement rather than not DrawingVisual
+ int type = OS.Object_GetType(widget);
+ int drawingVisualType = OS.DrawingVisual_typeid();
+ if (!OS.Object_Equals(type, drawingVisualType)) {
+ OS.UIElement_ClipToBounds (widget, clip);
+ }
+ OS.GCHandle_Free(drawingVisualType);
+ OS.GCHandle_Free(type);
+ int count = OS.VisualTreeHelper_GetChildrenCount(widget);
+ for (int i = 0; i < count; i++) {
+ int child = OS.VisualTreeHelper_GetChild (widget, i);
+ setClipping(child, clip);
+ OS.GCHandle_Free(child);
+ }
+}
+
+/**
+ * Sets the application defined widget data associated
+ * with the receiver to be the argument. The <em>widget
+ * data</em> is a single, unnamed field that is stored
+ * with every widget.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ * </p>
+ *
+ * @param data the widget data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
+ * </ul>
+ *
+ * @see #getData()
+ */
+public void setData (Object data) {
+ checkWidget();
+ if ((state & KEYED_DATA) != 0) {
+ ((Object []) this.data) [0] = data;
+ } else {
+ this.data = data;
+ }
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given value.
+ * <p>
+ * Applications may associate arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the key 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>
+ *
+ * @see #getData(String)
+ */
+public void setData (String key, Object value) {
+ checkWidget();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = 1;
+ Object [] table = null;
+ if ((state & KEYED_DATA) != 0) {
+ table = (Object []) data;
+ while (index < table.length) {
+ if (key.equals (table [index])) break;
+ index += 2;
+ }
+ }
+ if (value != null) {
+ if ((state & KEYED_DATA) != 0) {
+ if (index == table.length) {
+ Object [] newTable = new Object [table.length + 2];
+ System.arraycopy (table, 0, newTable, 0, table.length);
+ data = table = newTable;
+ }
+ } else {
+ table = new Object [3];
+ table [0] = data;
+ data = table;
+ state |= KEYED_DATA;
+ }
+ table [index] = key;
+ table [index + 1] = value;
+ } else {
+ if ((state & KEYED_DATA) != 0) {
+ if (index != table.length) {
+ int length = table.length - 2;
+ if (length == 1) {
+ data = table [0];
+ state &= ~KEYED_DATA;
+ } else {
+ Object [] newTable = new Object [length];
+ System.arraycopy (table, 0, newTable, 0, index);
+ System.arraycopy (table, index + 2, newTable, index, length - index);
+ data = newTable;
+ }
+ }
+ }
+ }
+
+ // Demo
+ if ("XAML".equals(key) && value instanceof String) {
+ setClipping (topHandle (), false);
+ String string = (String) value;
+ int ptr = createDotNetString(string, false);
+ int stringReader = OS.gcnew_StringReader (ptr);
+ int xmlReader = OS.XmlReader_Create (stringReader);
+ int resource = OS.XamlReader_Load (xmlReader);
+ if (resource != 0) {
+ OS.FrameworkElement_Resources (handle, resource);
+ OS.GCHandle_Free(resource);
+ }
+ OS.GCHandle_Free(xmlReader);
+ OS.GCHandle_Free(stringReader);
+ OS.GCHandle_Free(ptr);
+ }
+ if ("ResourceDictionary".equals(key) && value instanceof String) {
+ String string = (String) value;
+ int ptr = createDotNetString(string, false);
+ int uri = OS.gcnew_Uri(ptr, OS.UriKind_RelativeOrAbsolute);
+ int resources = OS.gcnew_ResourceDictionary();
+ OS.ResourceDictionary_Source(resources, uri);
+ OS.FrameworkElement_Resources(handle, resources);
+ OS.GCHandle_Free(resources);
+ OS.GCHandle_Free(uri);
+ OS.GCHandle_Free(ptr);
+ }
+}
+
+boolean sendFocusEvent (int type) {
+ sendEvent (type);
+ // widget could be disposed at this point
+ return true;
+}
+
+boolean setInputState (Event event, int type, int mouseEvent, int keyEvent) {
+ int modifiers;
+ if (keyEvent != 0) {
+ int keyboardDevice = OS.KeyboardEventArgs_KeyboardDevice(keyEvent);
+ modifiers = OS.KeyboardDevice_Modifiers(keyboardDevice);
+ OS.GCHandle_Free(keyboardDevice);
+ } else {
+ modifiers = OS.Keyboard_Modifiers();
+ }
+ if ((modifiers & OS.ModifierKeys_Alt) != 0) event.stateMask |= SWT.ALT;
+ if ((modifiers & OS.ModifierKeys_Shift) != 0) event.stateMask |= SWT.SHIFT;
+ if ((modifiers & OS.ModifierKeys_Control) != 0) event.stateMask |= SWT.CONTROL;
+ if (mouseEvent != 0) {
+ if (OS.MouseEventArgs_LeftButton(mouseEvent) == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON1;
+ if (OS.MouseEventArgs_MiddleButton(mouseEvent) == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON2;
+ if (OS.MouseEventArgs_RightButton(mouseEvent) == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON3;
+ if (OS.MouseEventArgs_XButton1(mouseEvent) == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON4;
+ if (OS.MouseEventArgs_XButton2(mouseEvent) == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON5;
+ } else {
+ if (OS.Mouse_LeftButton() == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON1;
+ if (OS.Mouse_MiddleButton() == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON2;
+ if (OS.Mouse_RightButton() == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON3;
+ if (OS.Mouse_XButton1() == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON4;
+ if (OS.Mouse_XButton2() == OS.MouseButtonState_Pressed) event.stateMask |= SWT.BUTTON5;
+ }
+ switch (type) {
+ case SWT.MouseDown:
+ case SWT.MouseDoubleClick:
+ if (event.button == 1) event.stateMask &= ~SWT.BUTTON1;
+ if (event.button == 2) event.stateMask &= ~SWT.BUTTON2;
+ if (event.button == 3) event.stateMask &= ~SWT.BUTTON3;
+ if (event.button == 4) event.stateMask &= ~SWT.BUTTON4;
+ if (event.button == 5) event.stateMask &= ~SWT.BUTTON5;
+ break;
+ case SWT.MouseUp:
+ if (event.button == 1) event.stateMask |= SWT.BUTTON1;
+ if (event.button == 2) event.stateMask |= SWT.BUTTON2;
+ if (event.button == 3) event.stateMask |= SWT.BUTTON3;
+ if (event.button == 4) event.stateMask |= SWT.BUTTON4;
+ if (event.button == 5) event.stateMask |= SWT.BUTTON5;
+ break;
+ case SWT.KeyDown:
+ case SWT.Traverse:
+ if (event.keyCode == SWT.ALT) event.stateMask &= ~SWT.ALT;
+ if (event.keyCode == SWT.SHIFT) event.stateMask &= ~SWT.SHIFT;
+ if (event.keyCode == SWT.CONTROL) event.stateMask &= ~SWT.CONTROL;
+ break;
+ case SWT.KeyUp:
+ if (event.keyCode == SWT.ALT) event.stateMask |= SWT.ALT;
+ if (event.keyCode == SWT.SHIFT) event.stateMask |= SWT.SHIFT;
+ if (event.keyCode == SWT.CONTROL) event.stateMask |= SWT.CONTROL;
+ break;
+ }
+ return true;
+}
+
+boolean setKeyState (Event event, int type, int e) {
+ int key = display.lastKey = OS.KeyEventArgs_Key(e);
+ boolean repeat = OS.KeyEventArgs_IsRepeat(e);
+ switch (key) {
+ case OS.Key_ImeProcessed:
+ return false;
+ case OS.Key_LeftAlt:
+ case OS.Key_RightAlt:
+ case OS.Key_LeftCtrl:
+ case OS.Key_LeftShift:
+ case OS.Key_RightCtrl:
+ case OS.Key_RightShift:
+ if (repeat) return false;
+ break;
+ case OS.Key_System:
+ key = OS.KeyEventArgs_SystemKey(e);
+ switch (key) {
+ case OS.Key_LeftAlt:
+ case OS.Key_RightAlt:
+ if (repeat) return false;
+ }
+ }
+ boolean textual = false;
+ int vKey = OS.KeyInterop_VirtualKeyFromKey (key);
+ int mapKey = Win32.MapVirtualKeyW (vKey, 2);
+ if ((mapKey & 0x80000000) != 0) {
+ display.deadChar = true;
+ return false;
+ }
+ char [] result = new char [1];
+ byte [] keyboard = new byte [256];
+ Win32.GetKeyboardState (keyboard);
+ textual = Win32.ToUnicode (vKey, 0, keyboard, result, 1, 0) == 1;
+ if (textual && type == SWT.KeyDown) {
+ if (display.deadChar) display.lastChar = result [0];
+ //TODO problem: in german, dead key + non-combing key
+ // example: '^' + 'p' fails.
+ return false;
+ }
+ event.keyCode = Display.translateKey (key);
+ switch (key) {
+ case OS.Key_Back: event.character = SWT.BS; break;
+ case OS.Key_LineFeed: event.character = SWT.LF; break;
+ case OS.Key_Return: event.character = SWT.CR; break;
+ case OS.Key_Delete: event.character = SWT.DEL; break;
+ case OS.Key_Escape: event.character = SWT.ESC; break;
+ case OS.Key_Tab: event.character = SWT.TAB; break;
+ }
+ if (type == SWT.KeyUp) event.character = result [0];
+ return setInputState (event, type, 0, e);
+}
+
+void setNameScope() {
+// Name Scope should most likely be on topHandle, but animation
+// is using handle right now because topHandle isn't visible
+// OS.NameScope_SetNameScope(topHandle(), display.nameScope);
+ OS.NameScope_SetNameScope(handle, display.nameScope);
+}
+
+boolean showMenu (int x, int y) {
+ Event event = new Event ();
+ event.x = x;
+ event.y = y;
+ sendEvent (SWT.MenuDetect, event);
+ if (!event.doit) return true;
+ Menu menu = getMenu ();
+ if (menu != null && !menu.isDisposed ()) {
+ if (x != event.x || y != event.y) {
+ menu.setLocation (event.x, event.y);
+ }
+ menu.setVisible (true);
+ return true;
+ }
+ return false;
+}
+
+int topHandle () {
+ return handle;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ String string = "*Disposed*"; //$NON-NLS-1$
+ if (!isDisposed ()) {
+ string = "*Wrong Thread*"; //$NON-NLS-1$
+ if (isValidThread ()) string = getNameText ();
+ }
+ return getName () + " {" + string + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+void updateLayout (int updateHandle) {
+ boolean ignore = display.ignoreRender;
+ display.ignoreRender = true;
+ OS.UIElement_UpdateLayout (updateHandle);
+ display.ignoreRender = ignore;
+}
+
+}

Back to the top