diff options
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt')
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 '&' 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 '&' can be + * escaped by doubling it in the string, causing a single + * '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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 '&' 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 + * '&' can be escaped by doubling it in the string, causing + * a single '&' 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 '&' 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 + * '&' can be escaped by doubling it in the string, causing + * a single '&' 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, <A> and </A>. 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 '&' 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 '&' can be + * escaped by doubling it in the string, causing a single + * '&' 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 '&' 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 '&' can be + * escaped by doubling it in the string, causing a single + * '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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 '&' 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 '&' can be + * escaped by doubling it in the string, causing a single + * '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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 '&') is not displayed in a tool tip. + * To display a single '&' in the tool tip, the character '&' 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; +} + +} |