Mercurial > projects > dwt-mac
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 */ +} + +}