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