diff dwt/widgets/Control.d @ 0:380af2bdd8e5

Upload of whole dwt tree
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sat, 09 Aug 2008 17:00:02 +0200
parents
children 649b8e223d5a 2952d5604c0a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/widgets/Control.d	Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,3285 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.widgets.Control;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTException;
+import dwt.accessibility.Accessible;
+import dwt.events.ControlListener;
+import dwt.events.DragDetectListener;
+import dwt.events.FocusListener;
+import dwt.events.HelpListener;
+import dwt.events.KeyListener;
+import dwt.events.MenuDetectListener;
+import dwt.events.MouseEvent;
+import dwt.events.MouseListener;
+import dwt.events.MouseMoveListener;
+import dwt.events.MouseTrackListener;
+import dwt.events.MouseWheelListener;
+import dwt.events.PaintListener;
+import dwt.events.TraverseListener;
+import dwt.graphics.Color;
+import dwt.graphics.Cursor;
+import dwt.graphics.Drawable;
+import dwt.graphics.Font;
+import dwt.graphics.GC;
+import dwt.graphics.GCData;
+import dwt.graphics.Image;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.graphics.Region;
+import dwt.internal.cocoa.NSControl;
+import dwt.internal.cocoa.NSEvent;
+import dwt.internal.cocoa.NSFont;
+import dwt.internal.cocoa.NSGraphicsContext;
+import dwt.internal.cocoa.NSPoint;
+import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.NSView;
+import dwt.internal.cocoa.NSWindow;
+import dwt.internal.cocoa.OS;
+import dwt.internal.cocoa.objc_super;
+
+/**
+ * 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 DWT implementation.
+ * </p>
+ */
+public abstract class Control extends Widget implements Drawable {
+    /**
+     * 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 DWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by DWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public NSView view;
+    Composite parent;
+    String toolTipText;
+    Object layoutData;
+    int drawCount;
+//  int visibleRgn;
+    Menu menu;
+    Color foreground, background;
+    Image backgroundImage;
+    Font font;
+    Cursor cursor;
+    Region region;
+//  GCData gcs[];
+    Accessible accessible;
+
+//  static final String RESET_VISIBLE_REGION = "dwt.internal.resetVisibleRegion";
+
+Control () {
+    /* Do nothing */
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>DWT</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>DWT</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 DWTException <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 DWT#BORDER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Control (Composite parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    createWidget ();
+}
+
+bool acceptsFirstResponder () {
+    objc_super super_struct = new objc_super();
+    super_struct.receiver = view.id;
+    super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
+    return OS.objc_msgSendSuper(super_struct, OS.sel_acceptsFirstResponder) !is 0;
+}
+
+bool becomeFirstResponder () {
+//TODO - query focusControl() in DWT.FocusIn/Out is the control
+    sendEvent (DWT.FocusIn);
+    objc_super super_struct = new objc_super();
+    super_struct.receiver = view.id;
+    super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
+    return OS.objc_msgSendSuper(super_struct, OS.sel_becomeFirstResponder) !is 0;
+}
+
+bool resignFirstResponder () {
+//TODO - query focusControl() in DWT.FocusIn/Out is the control
+    sendEvent (DWT.FocusOut);
+    objc_super super_struct = new objc_super();
+    super_struct.receiver = view.id;
+    super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
+    return OS.objc_msgSendSuper(super_struct, OS.sel_resignFirstResponder) !is 0;
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.Resize,typedListener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener(DWT.FocusIn,typedListener);
+    addListener(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener(DWT.KeyUp,typedListener);
+    addListener(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener(DWT.MouseDown,typedListener);
+    addListener(DWT.MouseUp,typedListener);
+    addListener(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.MouseEnter,typedListener);
+    addListener (DWT.MouseExit,typedListener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (DWT.Traverse,typedListener);
+}
+
+void checkBackground () {
+    Shell shell = getShell ();
+    if (this is shell) return;
+    state &= ~PARENT_BACKGROUND;    
+    Composite composite = parent;
+    do {
+        int mode = composite.backgroundMode;
+        if (mode !is 0) {
+            if (mode is DWT.INHERIT_DEFAULT) {
+                Control control = this;
+                do {
+                    if ((control.state & THEME_BACKGROUND) is 0) {
+                        return;
+                    }
+                    control = control.parent;
+                } while (control !is composite);
+            }
+            state |= PARENT_BACKGROUND;                 
+            return;
+        }
+        if (composite is shell) break;
+        composite = composite.parent;
+    } while (true);
+}
+
+void checkBuffered () {
+    style |= DWT.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>DWT.DEFAULT</code> is passed for the hint. 
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>DWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>DWT.DEFAULT</code>)
+ * @return the preferred size of the control
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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(bool)
+ * @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>DWT.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>DWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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(bool)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget();
+    int width = DEFAULT_WIDTH;
+    int height = DEFAULT_HEIGHT;
+//  if (wHint !is DWT.DEFAULT) width = wHint;
+//  if (hHint !is DWT.DEFAULT) height = hHint;
+//  int border = getBorderWidth ();
+//  width += border * 2;
+//  height += border * 2;
+//  return new Point (width, height);
+    if (topView() instanceof NSControl) {
+        NSRect oldRect = topView().frame();
+        ((NSControl)topView()).sizeToFit();
+        NSRect newRect = topView().frame();
+        topView().setFrame (oldRect);
+        return new Point ((int)newRect.width, (int)newRect.height);
+    }
+    return new Point (width, height);
+}
+
+Control computeTabGroup () {
+    if (isTabGroup()) return this;
+    return parent.computeTabGroup ();
+}
+
+Control[] computeTabList() {
+    if (isTabGroup()) {
+        if (getVisible() && getEnabled()) {
+            return new Control[] {this};
+        }
+    }
+    return new Control[0];
+}
+
+Control computeTabRoot () {
+    Control[] tabList = parent._getTabList();
+    if (tabList !is null) {
+        int index = 0;
+        while (index < tabList.length) {
+            if (tabList [index] is this) break;
+            index++;
+        }
+        if (index is tabList.length) {
+            if (isTabGroup ()) return this;
+        }
+    }
+    return parent.computeTabRoot ();
+}
+
+void createWidget () {
+    state |= DRAG_DETECT;
+    checkOrientation (parent);
+    super.createWidget ();
+    checkBackground ();
+    checkBuffered ();
+    setDefaultFont ();
+    setZOrder ();
+}
+
+Color defaultBackground () {
+    return display.getSystemColor (DWT.COLOR_WIDGET_BACKGROUND);
+}
+
+Font defaultFont () {
+    //TODO - Controls only, does this leak?
+    if (view instanceof NSControl) {
+        NSFont nsFont = ((NSControl)view).font ();
+        if (nsFont !is null) {
+            return Font.cocoa_new (display, nsFont);
+        }
+    }
+    return display.getSystemFont ();
+}
+
+Color defaultForeground () {
+    return display.getSystemColor (DWT.COLOR_WIDGET_FOREGROUND);
+}
+
+void destroyWidget () {
+    NSView view = topView ();
+    view.removeFromSuperview ();
+    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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool dragDetect (Event event) {
+    checkWidget ();
+    if (event is null) error (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool dragDetect (MouseEvent event) {
+    checkWidget ();
+    if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
+    return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
+}
+
+bool dragDetect (int button, int count, int stateMask, int x, int y) {
+    if (button !is 1 || count !is 1) return false;
+    if (!dragDetect (x, y, false, null)) return false;
+    return sendDragEvent (button, stateMask, x, y);
+}
+
+bool dragDetect (int x, int y, bool filter, bool [] consume) {
+//  Rect rect = new Rect ();
+//  int window = OS.GetControlOwner (handle);
+//  CGPoint pt = new CGPoint ();
+//  OS.HIViewConvertPoint (pt, handle, 0);
+//  x += (int) pt.x;
+//  y += (int) pt.y;
+//  OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
+//  x += rect.left;
+//  y += rect.top;
+//  dwt.internal.carbon.Point pt1 = new dwt.internal.carbon.Point ();
+//  pt1.h = (short) x;
+//  pt1.v = (short) y;
+//  return OS.WaitMouseMoved (pt1);
+    return false;
+}
+
+bool drawGripper (int x, int y, int width, int height, bool vertical) {
+    return false;
+}
+
+void drawRect(int id, NSRect rect) {
+    super.drawRect(id, rect);
+    if (!hooks (DWT.Paint) && !filters (DWT.Paint)) return;
+
+    /* Send paint event */
+    GCData data = new GCData ();
+    data.paintRect = rect;
+    GC gc = GC.cocoa_new (this, data);
+    Event event = new Event ();
+    event.gc = gc;
+    event.x = (int)rect.x;
+    event.y = (int)rect.y;
+    event.width = (int)rect.width;
+    event.height = (int)rect.height;
+    sendEvent (DWT.Paint, event);
+    event.gc = null;
+    gc.dispose ();
+}
+
+void enableWidget (bool enabled) {
+    //TODO - other views
+    if (view instanceof NSControl) {
+        ((NSControl)view).setEnabled(enabled);
+    }
+}
+
+Cursor findCursor () {
+    if (cursor !is null) return cursor;
+    return parent.findCursor ();
+}
+
+Control findBackgroundControl () {
+    if (backgroundImage !is null || background !is null) return this;
+    return (state & PARENT_BACKGROUND) !is 0 ? parent.findBackgroundControl () : null;
+}
+
+Menu [] findMenus (Control control) {
+    if (menu !is null && this !is control) return new Menu [] {menu};
+    return new Menu [0];
+}
+
+void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+    oldShell.fixShell (newShell, this);
+    oldDecorations.fixDecorations (newDecorations, this, menus);
+}
+
+void fixFocus (Control focusControl) {
+    Shell shell = getShell ();
+    Control control = this;
+    while (control !is shell && (control = control.parent) !is null) {
+        if (control.setFocus ()) return;
+    }
+    shell.setSavedFocus (focusControl);
+//  int window = OS.GetControlOwner (handle);
+//  OS.ClearKeyboardFocus (window);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool forceFocus () {
+    checkWidget();
+//  if (display.focusEvent is DWT.FocusOut) return false;
+    Decorations shell = menuShell ();
+    shell.setSavedFocus (this);
+    if (!isEnabled () || !isVisible ()/* || !isActive ()*/) return false;
+    if (isFocusControl ()) return true;
+    shell.setSavedFocus (null);
+    shell.bringToTop (false);
+    if (isDisposed ()) return false;
+    view.window ().makeFirstResponder (view);
+    if (isDisposed ()) return false;
+    shell.setSavedFocus (this);
+    return hasFocus ();
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) accessible = new_Accessible (this);
+    return accessible;
+}
+    
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) control = this;
+    return control.getBackgroundColor ();
+}
+
+Color getBackgroundColor () {
+    return background !is null ? background : defaultBackground ();
+}
+
+/**
+ * Returns the receiver's background image.
+ *
+ * @return the background image
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) control = this;
+    return control.backgroundImage;
+}
+
+/**
+ * Returns the receiver's border width.
+ *
+ * @return the border width
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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();
+    return 0;
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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();
+    NSRect rect = topView().frame();
+    return new Rectangle((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is detecting
+ * drag gestures, and  <code>false</code> otherwise. 
+ *
+ * @return the receiver's drag detect state
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool getDragDetect () {
+    checkWidget ();
+    return (state & DRAG_DETECT) !is 0;
+}
+
+/**
+ * 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>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool getEnabled () {
+    checkWidget();
+    return (state & DISABLED) is 0;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 !is null ? font : defaultFont ();
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 getForegroundColor ();
+}
+
+Color getForegroundColor () {
+    return foreground !is null ? foreground: defaultForeground ();
+}
+
+/**
+ * Returns layout data which is associated with the receiver.
+ *
+ * @return the receiver's layout data
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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();
+    NSRect rect = topView().frame();
+    return new Point((int)rect.x, (int)rect.y);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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;
+}
+
+int getMininumHeight () {
+    return 0;
+}
+
+/**
+ * Returns the receiver's monitor.
+ * 
+ * @return the receiver's monitor
+ * 
+ * @since 3.0
+ */
+public Monitor getMonitor () {
+    checkWidget();
+    Monitor [] monitors = display.getMonitors ();
+    if (monitors.length is 1) return monitors [0];
+    int index = -1, value = -1;
+    Rectangle bounds = getBounds ();
+    if (this !is getShell ()) {
+        bounds = display.map (this.parent, null, bounds);
+    }
+    for (int i=0; i<monitors.length; i++) {
+        Rectangle rect = bounds.intersection (monitors [i].getBounds ());
+        int area = rect.width * rect.height;
+        if (area > 0 && area > value) {
+            index = i;
+            value = area;
+        }
+    }
+    if (index >= 0) return monitors [index];
+    int centerX = bounds.x + bounds.width / 2, centerY = bounds.y + bounds.height / 2;
+    for (int i=0; i<monitors.length; i++) {
+        Rectangle rect = monitors [i].getBounds ();
+        int x = centerX < rect.x ? rect.x - centerX : centerX > rect.x + rect.width ? centerX - rect.x - rect.width : 0;
+        int y = centerY < rect.y ? rect.y - centerY : centerY > rect.y + rect.height ? centerY - rect.y - rect.height : 0;
+        int distance = x * x + y * y;
+        if (index is -1 || distance < value) {
+            index = i;
+            value = distance;
+        } 
+    }
+    return monitors [index];
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 !is shell) {
+        count++;
+        control = control.parent;
+    }
+    control = this;
+    Control [] result = new Control [count];
+    while (control !is shell) {
+        result [--count] = control;
+        control = control.parent;
+    }
+    return result;
+}
+
+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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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();
+    NSRect rect = topView().frame();
+    return new Point((int)rect.width, (int)rect.height);
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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.
+ * <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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public bool getVisible () {
+    checkWidget();
+    return (state & HIDDEN) is 0;
+}
+
+bool hasBorder () {
+    return (style & DWT.BORDER) !is 0;
+}
+
+bool hasFocus () {
+    return this is display.getFocusControl ();
+}
+
+/**  
+ * 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 DWT. 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 context = 0;
+    if (data !is null && data.paintRect !is null) {
+        context = NSGraphicsContext.currentContext().id;
+    } else {
+        context = NSGraphicsContext.graphicsContextWithWindow(view.window()).id;
+    }
+    if (data !is null) {
+        int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
+        if ((data.style & mask) is 0) {
+            data.style |= style & (mask | DWT.MIRRORED);
+        }
+        data.device = display;
+        data.view = view;
+        data.foreground = getForegroundColor ().handle;
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        data.background = control.getBackgroundColor ().handle;
+        data.font = font !is null ? font : defaultFont ();       
+    }
+    return context;
+}
+
+/**  
+ * 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 DWT. 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 context, GCData data) {
+    checkWidget (); 
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool isEnabled () {
+    checkWidget();
+    return getEnabled () && parent.isEnabled ();
+}
+
+bool isEnabledCursor () {
+    return isEnabled ();
+}
+
+bool isFocusAncestor (Control control) {
+    while (control !is null && control !is this && !(control instanceof Shell)) {
+        control = control.parent;
+    }
+    return control is this;
+}
+
+/**
+ * Returns <code>true</code> if the receiver has the user-interface
+ * focus, and <code>false</code> otherwise.
+ *
+ * @return the receiver's focus state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public bool isFocusControl () {
+    checkWidget();
+//  Control focusControl = display.focusControl;
+//  if (focusControl !is null && !focusControl.isDisposed ()) {
+//      return this is focusControl;
+//  }
+    return hasFocus ();
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public bool isReparentable () {
+    checkWidget();
+    return true;
+}
+
+bool 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 !is null) {
+        Point size = control.getSize ();
+        if (size.x is 0 || size.y is 0) {
+            return false;
+        }
+        control = control.parent;
+    }
+    return true;
+}
+
+bool isTabGroup () {
+    Control [] tabList = parent._getTabList ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] is this) return true;
+        }
+    }
+    int code = traversalCode (0, null);
+    if ((code & (DWT.TRAVERSE_ARROW_PREVIOUS | DWT.TRAVERSE_ARROW_NEXT)) !is 0) return false;
+    return (code & (DWT.TRAVERSE_TAB_PREVIOUS | DWT.TRAVERSE_TAB_NEXT)) !is 0;
+}
+
+bool isTabItem () {
+    Control [] tabList = parent._getTabList ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] is this) return false;
+        }
+    }
+    int code = traversalCode (0, null);
+    return (code & (DWT.TRAVERSE_ARROW_PREVIOUS | DWT.TRAVERSE_ARROW_NEXT)) !is 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool isVisible () {
+    checkWidget();
+    return getVisible () && parent.isVisible ();
+}
+
+int menuForEvent (int nsEvent) {
+    NSPoint pt = NSEvent.mouseLocation();   
+    NSWindow window = view.window();
+    pt.y = (int) (window.screen().frame().height - pt.y);
+    int x = (int) pt.x;
+    int y = (int) pt.y;
+    Event event = new Event ();
+    event.x = x;
+    event.y = y;
+    sendEvent (DWT.MenuDetect, event);
+    if (!event.doit) return 0;
+    Menu menu = getMenu ();
+    if (menu !is null && !menu.isDisposed ()) {
+        if (x !is event.x || y !is event.y) {
+            menu.setLocation (event.x, event.y);
+        }
+        return menu.nsMenu.id;
+    }
+    objc_super super_struct = new objc_super();
+    super_struct.receiver = view.id;
+    super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
+    return OS.objc_msgSendSuper(super_struct, OS.sel_menuForEvent_1, nsEvent);
+}
+
+Decorations menuShell () {
+    return parent.menuShell ();
+}
+
+bool setInputState (Event event, NSEvent nsEvent, int type) {
+    int modifierFlags = nsEvent.modifierFlags();
+    if ((modifierFlags & OS.NSAlternateKeyMask) !is 0) event.stateMask |= DWT.ALT;
+    if ((modifierFlags & OS.NSShiftKeyMask) !is 0) event.stateMask |= DWT.SHIFT;
+    if ((modifierFlags & OS.NSControlKeyMask) !is 0) event.stateMask |= DWT.CONTROL;
+    if ((modifierFlags & OS.NSCommandKeyMask) !is 0) event.stateMask |= DWT.COMMAND;
+    
+    //WRONG
+    if ((modifierFlags & OS.NSLeftMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON1;
+    if ((modifierFlags & OS.NSLeftMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON1;
+    if ((modifierFlags & OS.NSLeftMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON1;
+    if ((modifierFlags & OS.NSOtherMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON2;
+    if ((modifierFlags & OS.NSOtherMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON2;
+    if ((modifierFlags & OS.NSOtherMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON1;
+    if ((modifierFlags & OS.NSRightMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON3;
+    if ((modifierFlags & OS.NSRightMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON3;
+    if ((modifierFlags & OS.NSRightMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON3;
+    
+//  if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4;
+//  if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5;
+//  switch (type) {
+//      case DWT.MouseDown:
+//      case DWT.MouseDoubleClick:
+//          if (event.button is 1) event.stateMask &= ~DWT.BUTTON1;
+//          if (event.button is 2) event.stateMask &= ~DWT.BUTTON2;
+//          if (event.button is 3) event.stateMask &= ~DWT.BUTTON3;
+//          if (event.button is 4) event.stateMask &= ~DWT.BUTTON4;
+//          if (event.button is 5) event.stateMask &= ~DWT.BUTTON5;
+//          break;
+//      case DWT.MouseUp:
+//          if (event.button is 1) event.stateMask |= DWT.BUTTON1;
+//          if (event.button is 2) event.stateMask |= DWT.BUTTON2;
+//          if (event.button is 3) event.stateMask |= DWT.BUTTON3;
+//          if (event.button is 4) event.stateMask |= DWT.BUTTON4;
+//          if (event.button is 5) event.stateMask |= DWT.BUTTON5;
+//          break;
+//      case DWT.KeyDown:
+//      case DWT.Traverse:
+//          if (event.keyCode is DWT.ALT) event.stateMask &= ~DWT.ALT;
+//          if (event.keyCode is DWT.SHIFT) event.stateMask &= ~DWT.SHIFT;
+//          if (event.keyCode is DWT.CONTROL) event.stateMask &= ~DWT.CONTROL;
+//          break;
+//      case DWT.KeyUp:
+//          if (event.keyCode is DWT.ALT) event.stateMask |= DWT.ALT;
+//          if (event.keyCode is DWT.SHIFT) event.stateMask |= DWT.SHIFT;
+//          if (event.keyCode is DWT.CONTROL) event.stateMask |= DWT.CONTROL;
+//          break;
+//  }       
+    return true;
+}
+
+void sendMouseEvent (NSEvent nsEvent, int type, int button) {
+    Event event = new Event ();
+    event.button = button;
+//  event.detail = detail;
+    event.count = nsEvent.clickCount();
+    NSPoint location = nsEvent.locationInWindow();
+    NSPoint point = view.convertPoint_fromView_(location, null);
+    event.x = (int) point.x;
+    event.y = (int) point.y;
+    setInputState (event, nsEvent, type);
+    sendEvent (type, event);
+}
+
+void mouseDown(int theEvent) {
+    NSEvent nsEvent = new NSEvent (theEvent);
+    sendMouseEvent (nsEvent, DWT.MouseDown, 1);
+}
+
+void mouseDragged(int theEvent) {
+    NSEvent nsEvent = new NSEvent (theEvent);
+    sendMouseEvent (nsEvent, DWT.MouseMove, 1);
+}
+
+void mouseUp(int theEvent) {
+    NSEvent nsEvent = new NSEvent (theEvent);
+    sendMouseEvent (nsEvent, DWT.MouseUp, 1);
+}
+
+bool sendKeyEvent (Event event) {
+    sendEvent (event);
+    return event.doit;
+}
+
+//TODO - missing modifier keys (see flagsChanged:)
+bool sendKeyEvent (NSEvent nsEvent, int type) {
+    if ((state & SAFARI_EVENTS_FIX) !is 0) return false;
+    int count = 0;
+    NSString keys = nsEvent.characters();
+    //TODO - check lowercase doesn't mangle char codes
+    NSString keyCodes = nsEvent.charactersIgnoringModifiers().lowercaseString();
+    char [] chars = new char [keys.length()];
+    for (int i=0; i<keys.length(); i++) {
+        Event event = new Event ();
+        int keyCode = Display.translateKey (keys.characterAtIndex (i) & 0xFFFF);
+        if (keyCode !is 0) {
+            event.keyCode = keyCode;
+        } else {
+            event.character = (char) keys.characterAtIndex (i);
+            //TODO - get unshifted values for Shift+1
+            event.keyCode = keyCodes.characterAtIndex (i);
+        }
+        setInputState (event, nsEvent, type);
+        if (!setKeyState(event, type, nsEvent)) return false;
+        if (sendKeyEvent (type, event)) {
+            chars [count++] = chars [i];
+        }
+    }
+//  if (count is 0) return false;
+    if (count !is keys.length () - 1) {
+//      OS.SetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, count * 2, chars);
+    }
+    return count is keys.length ();
+}
+
+void markLayout (bool changed, bool all) {
+    /* Do nothing */
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 (control !is null) {
+        if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+        if (parent !is control.parent) return;
+    }
+    setZOrder (control, true);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 (control !is null) {
+        if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+        if (parent !is control.parent) return;
+    }
+    setZOrder (control, false);
+}
+
+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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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, bool)
+ */
+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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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, bool)
+ */
+public void pack (bool changed) {
+    checkWidget();
+    setSize (computeSize (DWT.DEFAULT, DWT.DEFAULT, changed));
+}
+
+public bool print (GC gc) {
+    checkWidget ();
+    if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+//  int [] outImage = new int [1];
+//  CGRect outFrame = new CGRect ();
+//  if (OS.HIViewCreateOffscreenImage (handle, 0, outFrame, outImage) is OS.noErr) {
+//      int width = OS.CGImageGetWidth (outImage [0]);
+//      int height = OS.CGImageGetHeight (outImage [0]);
+//      CGRect rect = new CGRect();
+//      rect.width = width;
+//      rect.height = height;
+//      //TODO - does not draw the browser (cocoa widgets?)
+//      OS.HIViewDrawCGImage (gc.handle, rect, outImage [0]);
+//      OS.CGImageRelease (outImage [0]);
+//  }
+//  return true;
+    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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWT#Paint
+ * @see DWT#NO_BACKGROUND
+ * @see DWT#NO_REDRAW_RESIZE
+ * @see DWT#NO_MERGE_PAINTS
+ * @see DWT#DOUBLE_BUFFERED
+ */
+public void redraw () {
+    checkWidget();
+    view.setNeedsDisplay(true);
+}
+
+void redraw (bool children) {
+//  checkWidget();
+    
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWT#Paint
+ * @see DWT#NO_BACKGROUND
+ * @see DWT#NO_REDRAW_RESIZE
+ * @see DWT#NO_MERGE_PAINTS
+ * @see DWT#DOUBLE_BUFFERED
+ */
+public void redraw (int x, int y, int width, int height, bool all) {
+    checkWidget ();
+    NSRect rect = new NSRect();
+    rect.x = x;
+    rect.y = y;
+    rect.width = width;
+    rect.height = height;
+    view.setNeedsDisplayInRect(rect);
+}
+
+void releaseHandle () {
+    super.releaseHandle ();
+    if (view !is null) {
+        OS.objc_msgSend(view.id, OS.sel_setTag_1, -1);
+        view.release();
+    }
+    view = null;
+    parent = null;
+}
+
+void releaseParent () {
+//  setVisible (topHandle (), false);
+    parent.removeControl (this);
+}
+
+void releaseWidget () {
+    super.releaseWidget ();
+    if (menu !is null && !menu.isDisposed ()) {
+        menu.dispose ();
+    }
+    menu = null;
+    layoutData = null;
+    if (accessible !is 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.Move, listener);
+    eventTable.unhook (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(DWT.FocusIn, listener);
+    eventTable.unhook(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(DWT.KeyUp, listener);
+    eventTable.unhook(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.MenuDetect, 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(DWT.MouseDown, listener);
+    eventTable.unhook(DWT.MouseUp, listener);
+    eventTable.unhook(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(DWT.MouseMove, 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.MouseEnter, listener);
+    eventTable.unhook (DWT.MouseExit, listener);
+    eventTable.unhook (DWT.MouseHover, 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (DWT.Traverse, listener);
+}
+
+bool 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 (DWT.DragDetect, event);
+    return event.doit;
+}
+
+bool sendDragEvent (int button, int chord, int modifiers, int x, int y) {
+    Event event = new Event ();
+    switch (button) {
+        case 1: event.button = 1; break;
+        case 2: event.button = 3; break;
+        case 3: event.button = 2; break;
+        case 4: event.button = 4; break;
+        case 5: event.button = 5; break;
+    }
+    event.x = x;
+    event.y = y;
+    setInputState (event, DWT.DragDetect, chord, modifiers);
+    postEvent (DWT.DragDetect, event);
+    return event.doit;
+}
+
+void sendFocusEvent (int type, bool post) {
+    Display display = this.display;
+    Shell shell = getShell ();
+    /*
+    * Feature in the Macintosh.  GetKeyboardFocus() returns NULL during
+    * kEventControlSetFocusPart if the focus part is not kControlFocusNoPart.
+    * The fix is to remember the focus control and return it during
+    * kEventControlSetFocusPart.
+    */
+//  display.focusControl = this;
+//  display.focusEvent = type;
+    if (post) {
+        postEvent (type);
+    } else {
+        sendEvent (type);
+    }   
+    /*
+    * 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 DWT.FocusIn:
+                shell.setActiveControl (this);
+                break;
+            case DWT.FocusOut:
+                if (shell !is display.getActiveShell ()) {
+                    shell.setActiveControl (null);
+                }
+                break;
+        }
+    }
+//  display.focusEvent = DWT.None;
+//  display.focusControl = null;
+}
+
+bool sendMouseEvent (int type, short button, int count, int detail, bool send, int theEvent) {
+//  CGPoint pt = new CGPoint ();
+//  OS.GetEventParameter (theEvent, OS.kEventParamWindowMouseLocation, OS.typeHIPoint, null, CGPoint.sizeof, null, pt);
+//  OS.HIViewConvertPoint (pt, 0, handle);
+//  int x = (int) pt.x;
+//  int y = (int) pt.y;
+//  display.lastX = x;
+//  display.lastY = y;
+//  int [] chord = new int [1];
+//  OS.GetEventParameter (theEvent, OS.kEventParamMouseChord, OS.typeUInt32, null, 4, null, chord);
+//  int [] modifiers = new int [1];
+//  OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
+//  return sendMouseEvent (type, button, count, detail, send, chord [0], (short) x, (short) y, modifiers [0]);
+    return false;
+}
+
+bool sendMouseEvent (int type, short button, int count, bool send, int chord, short x, short y, int modifiers) {
+    return sendMouseEvent (type, button, count, 0, send, chord, x, y, modifiers);
+}
+
+bool sendMouseEvent (int type, short button, int count, int detail, bool send, int chord, short x, short y, int modifiers) {
+    if (!hooks (type) && !filters (type)) return true;
+    Event event = new Event ();
+    switch (button) {
+        case 1: event.button = 1; break;
+        case 2: event.button = 3; break;
+        case 3: event.button = 2; break;
+        case 4: event.button = 4; break;
+        case 5: event.button = 5; break;
+    }
+    event.x = x;
+    event.y = y;
+    event.count = count;
+    event.detail = detail;
+    setInputState (event, type, chord, modifiers);
+    if (send) {
+        sendEvent (type, event);
+        if (isDisposed ()) return false;
+    } else {
+        postEvent (type, event);
+    }
+    return event.doit;
+}
+
+bool sendMouseWheel (short wheelAxis, int wheelDelta) {
+    return false;
+}
+
+void setBackground () {
+//  redrawWidget (handle, false);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 !is null) {
+        if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    }
+//  if (equals (background, this.background)) return;
+    this.background = color;
+    setBackground (color !is null ? color.handle : null);
+    view.setNeedsDisplay(true);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 !is null && image.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    if (image is backgroundImage) return;
+    backgroundImage = image;
+//  redrawWidget (handle, false);
+}
+
+void setBackground (float [] color) {
+}
+
+void setBackground (int control, float [] color) {
+//  ControlFontStyleRec fontStyle = new ControlFontStyleRec ();
+//  OS.GetControlData (control, (short) OS.kControlEntireControl, OS.kControlFontStyleTag, ControlFontStyleRec.sizeof, fontStyle, null);
+//  if (color !is null) {
+//      fontStyle.backColor_red = (short) (color [0] * 0xffff);
+//      fontStyle.backColor_green = (short) (color [1] * 0xffff);
+//      fontStyle.backColor_blue = (short) (color [2] * 0xffff);
+//      fontStyle.flags |= OS.kControlUseBackColorMask;
+//  } else {
+//      fontStyle.flags &= ~OS.kControlUseBackColorMask;
+//  }
+//  OS.SetControlFontStyle (control, fontStyle);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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();
+    setBounds (x, y, Math.max (0, width), Math.max (0, height), true, true);
+}
+
+int setBounds (int x, int y, int width, int height, bool move, bool resize) {
+    int result = 0;
+    NSView topView = topView();
+    NSRect rect = topView.frame();
+    if (move && resize) {
+        if (rect.x !is x || rect.y !is y) result |= MOVED;
+        if (rect.width !is width || rect.height !is height) result |= RESIZED;
+        if (result !is 0) {
+            rect.x = x;
+            rect.y = y;
+            rect.width = width;
+            rect.height = height;
+            topView.setFrame (rect);
+        }
+    } else if (move) {
+        if (rect.x !is x || rect.y !is y) {
+            result |= MOVED;
+            NSPoint point = new NSPoint();
+            point.x = x;
+            point.y = y;
+            topView.setFrameOrigin(point);
+        }
+    } else if (resize) {
+        if (rect.width !is width || rect.height !is height) {
+            result |= RESIZED;
+            NSSize size = new NSSize();
+            size.width = width;
+            size.height = height;
+            topView.setFrameSize(size);
+        }
+    }
+    if ((result & MOVED) !is 0) {
+        sendEvent(DWT.Move);
+    }
+    if ((result & RESIZED) !is 0) {
+        sendEvent(DWT.Resize);
+    }
+    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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    setBounds (rect.x, rect.y, Math.max (0, rect.width), Math.max (0, rect.height), true, true);
+}
+
+/**
+ * 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.
+ *
+ * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 (bool capture) {
+    checkWidget();
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 !is null && cursor.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    this.cursor = cursor;
+    //TODO null
+//  view.addCursorRect(view.frame(), cursor.handle);
+}
+
+void setDefaultFont () {
+//  if (display.smallFonts) setFontStyle (defaultFont ());
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 (bool dragDetect) {
+    checkWidget ();
+    if (dragDetect) {
+        state |= DRAG_DETECT;   
+    } else {
+        state &= ~DRAG_DETECT;
+    }
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 (bool enabled) {
+    checkWidget();
+    if (((state & DISABLED) is 0) is enabled) return;
+    Control control = null;
+    bool fixFocus = false;
+    if (!enabled) {
+//      if (display.focusEvent !is DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 bool setFocus () {
+    checkWidget();
+    if ((style & DWT.NO_FOCUS) !is 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 !is null) { 
+        if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.font = font;
+    setFont (font !is null ? font.handle : defaultFont().handle);
+}
+
+void setFont (NSFont font) {
+    //TODO - bad cast
+    if (view instanceof NSControl) {
+        ((NSControl)view).setFont(font);
+    }
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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();
+    if (color !is null) {
+        if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    }
+//  if (equals (foreground, this.foreground)) return;
+    this.foreground = color;
+    setForeground (color !is null ? color.handle : null);
+    view.setNeedsDisplay(true);
+}
+
+void setForeground (float [] color) {
+}
+
+void setForeground (int control, float [] color) {
+//  ControlFontStyleRec fontStyle = new ControlFontStyleRec ();
+//  OS.GetControlData (control, (short) OS.kControlEntireControl, OS.kControlFontStyleTag, ControlFontStyleRec.sizeof, fontStyle, null);
+//  if (color !is null) {
+//      fontStyle.foreColor_red = (short) (color [0] * 0xffff);
+//      fontStyle.foreColor_green = (short) (color [1] * 0xffff);
+//      fontStyle.foreColor_blue = (short) (color [2] * 0xffff);
+//      fontStyle.flags |= OS.kControlUseForeColorMask;
+//  } else {
+//      fontStyle.flags &= ~OS.kControlUseForeColorMask;
+//  }
+//  OS.SetControlFontStyle (control, fontStyle);
+}
+
+/**
+ * Sets the layout data associated with the receiver to the argument.
+ * 
+ * @param layoutData the new layout data for the receiver.
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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();
+    setBounds (x, y, 0, 0, true, false);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    setBounds (location.x, location.y, 0, 0, true, false);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 !is null) {
+        if (menu.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+        if ((menu.style & DWT.POP_UP) is 0) {
+            error (DWT.ERROR_MENU_NOT_POP_UP);
+        }
+        if (menu.parent !is menuShell ()) {
+            error (DWT.ERROR_INVALID_PARENT);
+        }
+    }
+    this.menu = menu;
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ *  </ul>
+ */
+public bool setParent (Composite parent) {
+    checkWidget();
+    if (parent is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (parent.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    if (this.parent is parent) return true;
+    if (!isReparentable ()) return false;
+    releaseParent ();
+    Shell newShell = parent.getShell (), oldShell = getShell ();
+    Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
+    if (oldShell !is newShell || oldDecorations !is newDecorations) {
+        Menu [] menus = oldShell.findMenus (this);
+        fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    }
+//  int topHandle = topHandle ();
+//  OS.HIViewAddSubview (parent.handle, topHandle);
+//  OS.HIViewSetVisible (topHandle, (state & HIDDEN) is 0);
+//  OS.HIViewSetZOrder (topHandle, OS.kHIViewZOrderBelow, 0);
+    this.parent = parent;
+    return true;
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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, bool)
+ * @see #update()
+ */
+public void setRedraw (bool redraw) {
+    checkWidget();
+    if (redraw) {
+        if (--drawCount is 0) {
+//          OS.HIViewSetDrawingEnabled (handle, true);
+//          invalidateVisibleRegion (handle);
+//          redrawWidget (handle, true);
+        }
+    } else {
+        if (drawCount is 0) {
+//          OS.HIViewSetDrawingEnabled (handle, false);
+//          invalidateVisibleRegion (handle);
+        }
+        drawCount++;
+    }
+}
+
+public void setRegion (Region region) {
+    checkWidget ();
+    if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
+    this.region = region;
+//  redrawWidget (handle, true);
+}
+
+bool setRadioSelection (bool value){
+    return false;
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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();
+    setBounds (0, 0, Math.max (0, width), Math.max (0, height), false, true);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true);
+}
+
+bool setTabGroupFocus () {
+    return setTabItemFocus ();
+}
+
+bool setTabItemFocus () {
+    if (!isShowing ()) return false;
+    return forceFocus ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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;
+    view.setToolTip(string !is null ? NSString.stringWith(string) : null);
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 (bool visible) {
+    checkWidget();
+    if (visible) {
+        if ((state & HIDDEN) is 0) return;
+        state &= ~HIDDEN;
+    } else {
+        if ((state & HIDDEN) !is 0) return;
+        state |= HIDDEN;
+    }
+    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 (DWT.Show);
+        if (isDisposed ()) return;
+    }
+    
+    /*
+    * Feature in the Macintosh.  If the receiver has focus, hiding
+    * the receiver causes no control to have focus.  Also, the focus
+    * needs to be cleared from any TXNObject so that it stops blinking
+    * the caret.  The fix is to assign focus to the first ancestor
+    * control that takes focus.  If no control will take focus, clear
+    * the focus control.
+    */
+    Control control = null;
+    bool fixFocus = false;
+    if (!visible) {
+//      if (display.focusEvent !is DWT.FocusOut) {
+            control = display.getFocusControl ();
+            fixFocus = isFocusAncestor (control);
+//      }
+    }
+    topView().setHidden(!visible);
+    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 (DWT.Hide);
+        if (isDisposed ()) return;
+    }
+    if (fixFocus) fixFocus (control);
+}
+
+void setZOrder () {
+//  int topHandle = topHandle ();
+//  int parentHandle = parent.handle;
+//  OS.HIViewAddSubview (parentHandle, topHandle);
+//  OS.HIViewSetZOrder (topHandle, OS.kHIViewZOrderBelow, 0);
+//  Rect rect = getInset ();
+//  rect.right = rect.left;
+//  rect.bottom = rect.top;
+//  OS.SetControlBounds (topHandle, rect);
+}
+
+void setZOrder (Control control, bool above) {
+    NSView otherView = control is null ? null : control.topView ();
+    view.retain();
+    view.removeFromSuperview();
+    parent.contentView().addSubview_positioned_relativeTo_(view, above ? OS.NSWindowAbove : OS.NSWindowBelow, otherView);
+    view.release();
+}
+
+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;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 is null) error (DWT.ERROR_NULL_ARGUMENT);
+    return toDisplay (point.x, point.y);
+}
+
+NSView topView () {
+    return view;
+}
+
+bool translateTraversal (int key, NSEvent theEvent, bool [] consume) {
+    int detail = DWT.TRAVERSE_NONE;
+    int code = traversalCode (key, theEvent);
+    bool all = false;
+    switch (key) {
+        case 53: /* Esc */ {
+            all = true;
+            detail = DWT.TRAVERSE_ESCAPE;
+            break;
+        }
+        case 76: /* KP Enter */
+        case 36: /* Return */ {
+            all = true;
+            detail = DWT.TRAVERSE_RETURN;
+            break;
+        }
+        case 48: /* Tab */ {
+            int modifiers = display.lastModifiers;
+            bool next = (modifiers & OS.NSShiftKeyMask) is 0;
+            detail = next ? DWT.TRAVERSE_TAB_NEXT : DWT.TRAVERSE_TAB_PREVIOUS;
+            break;
+        }
+        case 126: /* Up arrow */
+        case 123: /* Left arrow */
+        case 125: /* Down arrow */
+        case 124: /* Right arrow */ {
+            bool next = key is 125 /* Down arrow */ || key is 124 /* Right arrow */;
+            detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS;
+            break;
+        }
+        case 116: /* Page up */
+        case 121: /* Page down */ {
+            all = true;
+//          int [] modifiers = new int [1];
+//          OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
+//          if ((modifiers [0] & OS.controlKey) is 0) return false;
+//          detail = key is 121 /* Page down */ ? DWT.TRAVERSE_PAGE_NEXT : DWT.TRAVERSE_PAGE_PREVIOUS;
+            break;
+        }
+        default:
+            return false;
+    }
+    Event event = new Event ();
+    event.doit = consume [0] = (code & detail) !is 0;
+    event.detail = detail;
+    if (!setKeyState (event, DWT.Traverse, theEvent)) return false;
+    Shell shell = getShell ();
+    Control control = this;
+    do {
+        if (control.traverse (event)) return true;
+        if (!event.doit && control.hooks (DWT.Traverse)) {
+            return false;
+        }
+        if (control is shell) return false;
+        control = control.parent;
+    } while (all && control !is null);
+    return false;
+}
+
+int traversalCode (int key, NSEvent theEvent) {
+    int code = DWT.TRAVERSE_RETURN | DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS;
+    Shell shell = getShell ();
+    if (shell.parent !is null) code |= DWT.TRAVERSE_ESCAPE;
+    return code;
+}
+
+bool traverseMnemonic (char key) {
+    return false;
+}
+
+/**
+ * Based on the argument, perform one of the expected platform
+ * traversal action. The argument should be one of the constants:
+ * <code>DWT.TRAVERSE_ESCAPE</code>, <code>DWT.TRAVERSE_RETURN</code>, 
+ * <code>DWT.TRAVERSE_TAB_NEXT</code>, <code>DWT.TRAVERSE_TAB_PREVIOUS</code>, 
+ * <code>DWT.TRAVERSE_ARROW_NEXT</code> and <code>DWT.TRAVERSE_ARROW_PREVIOUS</code>.
+ *
+ * @param traversal the type of traversal
+ * @return true if the traversal succeeded
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public bool traverse (int traversal) {
+    checkWidget();
+    Event event = new Event ();
+    event.doit = true;
+    event.detail = traversal;
+    return traverse (event);
+}
+
+bool traverse (Event event) {
+    sendEvent (DWT.Traverse, event);
+    if (isDisposed ()) return true;
+    if (!event.doit) return false;
+    switch (event.detail) {
+        case DWT.TRAVERSE_NONE:             return true;
+        case DWT.TRAVERSE_ESCAPE:           return traverseEscape ();
+        case DWT.TRAVERSE_RETURN:           return traverseReturn ();
+        case DWT.TRAVERSE_TAB_NEXT:         return traverseGroup (true);
+        case DWT.TRAVERSE_TAB_PREVIOUS:     return traverseGroup (false);
+        case DWT.TRAVERSE_ARROW_NEXT:       return traverseItem (true);
+        case DWT.TRAVERSE_ARROW_PREVIOUS:   return traverseItem (false);
+        case DWT.TRAVERSE_MNEMONIC:         return traverseMnemonic (event);    
+        case DWT.TRAVERSE_PAGE_NEXT:        return traversePage (true);
+        case DWT.TRAVERSE_PAGE_PREVIOUS:    return traversePage (false);
+    }
+    return false;
+}
+
+bool traverseEscape () {
+    return false;
+}
+
+bool traverseGroup (bool next) {
+    Control root = computeTabRoot ();
+    Control group = computeTabGroup ();
+    Control [] list = root.computeTabList ();
+    int length = list.length;
+    int index = 0;
+    while (index < length) {
+        if (list [index] is 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 is length) return false;
+    int start = index, offset = (next) ? 1 : -1;
+    while ((index = ((index + offset + length) % length)) !is start) {
+        Control control = list [index];
+        if (!control.isDisposed () && control.setTabGroupFocus ()) {
+            return true;
+        }
+    }
+    if (group.isDisposed ()) return false;
+    return group.setTabGroupFocus ();
+}
+
+bool traverseItem (bool next) {
+    Control [] children = parent._getChildren ();
+    int length = children.length;
+    int index = 0;
+    while (index < length) {
+        if (children [index] is 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 is length) return false;
+    int start = index, offset = (next) ? 1 : -1;
+    while ((index = (index + offset + length) % length) !is start) {
+        Control child = children [index];
+        if (!child.isDisposed () && child.isTabItem ()) {
+            if (child.setTabItemFocus ()) return true;
+        }
+    }
+    return false;
+}
+
+bool traverseReturn () {
+    return false;
+}
+
+bool traversePage (bool next) {
+    return false;
+}
+
+bool traverseMnemonic (Event event) {
+    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 DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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, bool)
+ * @see PaintListener
+ * @see DWT#Paint
+ */
+public void update () {
+    checkWidget();
+    update (false);
+}
+
+void update (bool all) {
+//  checkWidget();
+    //TODO - not all
+//  OS.HIViewRender (handle);
+}
+
+void updateBackgroundMode () {
+    int oldState = state & PARENT_BACKGROUND;
+    checkBackground ();
+    if (oldState !is (state & PARENT_BACKGROUND)) {
+        setBackground ();
+    }
+}
+
+void updateLayout (bool all) {
+    /* Do nothing */
+}
+
+}