Mercurial > projects > dwt-mac
diff dwt/widgets/Control.d @ 45:d8635bb48c7c
Merge with SWT 3.5
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Mon, 01 Dec 2008 17:07:00 +0100 |
parents | 642f460a0908 |
children | cfa563df4fdd |
line wrap: on
line diff
--- a/dwt/widgets/Control.d Tue Oct 21 15:20:04 2008 +0200 +++ b/dwt/widgets/Control.d Mon Dec 01 17:07:00 2008 +0100 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,13 +9,14 @@ * IBM Corporation - initial API and implementation * * Port to the D programming language: - * Jacob Carlborg <jacob.carlborg@gmail.com> + * Jacob Carlborg <doob@me.com> *******************************************************************************/ module dwt.widgets.Control; import dwt.DWT; import dwt.DWTException; +import dwt.accessibility.ACC; import dwt.accessibility.Accessible; import dwt.events.ControlListener; import dwt.events.DragDetectListener; @@ -40,18 +41,25 @@ import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.graphics.Region; +import dwt.internal.cocoa.NSApplication; +import dwt.internal.cocoa.NSArray; +import dwt.internal.cocoa.NSAttributedString; +import dwt.internal.cocoa.NSBezierPath; +import dwt.internal.cocoa.NSColor; import dwt.internal.cocoa.NSControl; +import dwt.internal.cocoa.NSDate; import dwt.internal.cocoa.NSEvent; import dwt.internal.cocoa.NSFont; import dwt.internal.cocoa.NSGraphicsContext; +import dwt.internal.cocoa.NSInputManager; +import dwt.internal.cocoa.NSMutableArray; 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; +import dwt.internal.cocoa.id; import tango.core.Thread; @@ -89,6 +97,10 @@ * IMPORTANT: This class is intended to be subclassed <em>only</em> * within the DWT implementation. * </p> + * + * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a> + * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a> + * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> */ public abstract class Control : Widget , Drawable { @@ -159,29 +171,156 @@ createWidget (); } -bool acceptsFirstResponder () { - objc_super super_struct = objc_super(); - super_struct.receiver = view.id_; - super_struct.cls = cast(objc.Class) OS.objc_msgSend(view.id_, OS.sel_superclass); - return OS.objc_msgSendSuper(&super_struct, OS.sel_acceptsFirstResponder) !is null; +int accessibilityActionNames(int /*long*/ id, int /*long*/ sel) { + if (accessible !is null) { + NSArray returnValue = accessible.internal_accessibilityActionNames(ACC.CHILDID_SELF); + if (returnValue !is null) return returnValue.id_; + } + + return super.accessibilityActionNames(id, sel); +} + +int accessibilityAttributeNames(objc.id id, objc.SEL sel) { + + if (id is view.id_ || (cast(NSControl)view && (cast(NSControl)view).cell() !is null && (cast(NSControl)view).cell().id_ is id)) { + if (accessible !is null) { + + // First, see if the accessible is going to define a set of attributes for the control. + // If it does, return that. + NSArray returnValue = accessible.internal_accessibilityAttributeNames(ACC.CHILDID_SELF); + if (returnValue !is null) return returnValue.id; + + // If not, see if it will override or augment the standard list. + // Help, title, and description can be overridden. + NSMutableArray extraAttributes = NSMutableArray.arrayWithCapacity(3); + extraAttributes.addObject(OS.NSAccessibilityHelpAttribute); + extraAttributes.addObject(OS.NSAccessibilityDescriptionAttribute); + extraAttributes.addObject(OS.NSAccessibilityTitleAttribute); + + for (int i = extraAttributes.count() - 1; i >= 0; i--) { + NSString attribute = new NSString(extraAttributes.objectAtIndex(i).id); + if (accessible.internal_accessibilityAttributeValue(attribute, ACC.CHILDID_SELF) is null) { + extraAttributes.removeObjectAtIndex(i); + } + } + + if (extraAttributes.count() > 0) { + int superResult = super.accessibilityAttributeNames(id, sel); + NSArray baseAttributes = new NSArray(superResult); + NSMutableArray mutableAttributes = NSMutableArray.arrayWithCapacity(baseAttributes.count() + 1); + mutableAttributes.addObjectsFromArray(baseAttributes); + + for (int i = 0; i < extraAttributes.count(); i++) { + id currAttribute = extraAttributes.objectAtIndex(i); + if (!mutableAttributes.containsObject(currAttribute)) { + mutableAttributes.addObject(currAttribute); + } + } + + return mutableAttributes.id; + } + } + } + + return super.accessibilityAttributeNames(id, sel); +} + +int accessibilityParameterizedAttributeNames(int /*long*/ id, int /*long*/ sel) { + + if (id is view.id || (view instanceof NSControl && ((NSControl)view).cell() !is null && ((NSControl)view).cell().id is id)) { + if (accessible !is null) { + NSArray returnValue = accessible.internal_accessibilityParameterizedAttributeNames(ACC.CHILDID_SELF); + if (returnValue !is null) return returnValue.id; + } + } + + return super.accessibilityParameterizedAttributeNames(id, sel); } -bool becomeFirstResponder () { -//TODO - query focusControl() in DWT.FocusIn/Out is the control - sendEvent (DWT.FocusIn); - objc_super super_struct = objc_super(); - super_struct.receiver = view.id_; - super_struct.cls = cast(objc.Class) OS.objc_msgSend(view.id_, OS.sel_superclass); - return OS.objc_msgSendSuper(&super_struct, OS.sel_becomeFirstResponder) !is null; + +bool accessibilityIsAttributeSettable(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) { + + // TODO: Carbon didn't support setting attributes, so for now Cocoa doesn't as well. + // NSString attribute = new NSString(arg0); + // + // if (accessible !is null) { + // return accessible.accessibilityIsAttributeSettable(attribute, ACC.CHILDID_SELF); + // } + // + // return super.accessibilityIsAttributeSettable(id, sel, arg0); + return false; +} + +int accessibilityFocusedUIElement(int /*long*/ id, int /*long*/ sel) { + id returnValue = null; + + if (id is view.id || (view instanceof NSControl && ((NSControl)view).cell() !is null && ((NSControl)view).cell().id is id)) { + if (accessible !is null) { + returnValue = accessible.internal_accessibilityFocusedUIElement(ACC.CHILDID_SELF); + } + } + + // If we had an accessible and it didn't handle the attribute request, let the + // superclass handle it. + if (returnValue is null) + return super.accessibilityFocusedUIElement(id, sel); + else + return returnValue.id; } -bool resignFirstResponder () { -//TODO - query focusControl() in DWT.FocusIn/Out is the control - sendEvent (DWT.FocusOut); - objc_super super_struct = objc_super(); - super_struct.receiver = view.id_; - super_struct.cls = cast(objc.Class) OS.objc_msgSend(view.id_, OS.sel_superclass); - return OS.objc_msgSendSuper(&super_struct, OS.sel_resignFirstResponder) !is null; +int accessibilityHitTest(int /*long*/ id, int /*long*/ sel, NSPoint point) { + id returnValue = null; + + if (id is view.id || (view instanceof NSControl && ((NSControl)view).cell() !is null && ((NSControl)view).cell().id is id)) { + if (accessible !is null) { + returnValue = accessible.internal_accessibilityHitTest(point, ACC.CHILDID_SELF); + } + } + + // If we had an accessible and it didn't handle the attribute request, let the + // superclass handle it. + if (returnValue is null) + return super.accessibilityHitTest(id, sel, point); + else + return returnValue.id; +} + +int accessibilityAttributeValue(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) { + NSString attribute = new NSString(arg0); + int returnValue = 0; + id returnObject = null; + + if (accessible !is null) { + returnObject = accessible.internal_accessibilityAttributeValue(attribute, ACC.CHILDID_SELF); + } + + // If we had an accessible and it didn't handle the attribute request, let the + // superclass handle it. + if (returnObject is null) { + returnValue = super.accessibilityAttributeValue(id, sel, arg0); + } else { + returnValue = returnObject.id; + } + + return returnValue; +} + +int accessibilityAttributeValue_forParameter(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1) { + NSString attribute = new NSString(arg0); + + id returnValue = null; + + if (accessible !is null) { + id parameter = new id(arg1); + returnValue = accessible.internal_accessibilityAttributeValue_forParameter(attribute, parameter, ACC.CHILDID_SELF); + } + + // If we had an accessible and it didn't handle the attribute request, let the + // superclass handle it. + if (returnValue is null) + return super.accessibilityAttributeValue_forParameter(id, sel, arg0, arg1); + else + return returnValue.id; } /** @@ -618,18 +757,22 @@ 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 (cast(NSControl) topView()) { NSRect oldRect = topView().frame(); (cast(NSControl)topView()).sizeToFit(); NSRect newRect = topView().frame(); topView().setFrame (oldRect); - return new Point (cast(int)newRect.width, cast(int)newRect.height); + width = cast(int) newRect.width; + height = cast(int)newRect.height; + } + int border = getBorderWidth (); + if (wHint !is DWT.DEFAULT) { + width = wHint; + width += border * 2; + } + if (hHint !is DWT.DEFAULT) { + height = hHint; + height += border * 2; } return new Point (width, height); } @@ -663,6 +806,10 @@ return parent.computeTabRoot (); } +NSView contentView () { + return view; +} + void createWidget () { state |= DRAG_DETECT; checkOrientation (parent); @@ -692,12 +839,42 @@ return display.getSystemColor (DWT.COLOR_WIDGET_FOREGROUND); } +void deregister () { + super.deregister (); + display.removeWidget (view); +} + void destroyWidget () { NSView view = topView (); view.removeFromSuperview (); releaseHandle (); } +void doCommandBySelector (int /*long*/ id, int /*long*/ sel, int /*long*/ selector) { + if (view.window ().firstResponder ().id is id) { + NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent (); + if (nsEvent !is null && nsEvent.type () is OS.NSKeyDown) { + // TODO is this workaround ok? + /* + * Feature in Cocoa. Pressing Alt+UpArrow invokes doCommandBySelector + * twice, with selectors moveBackward and moveToBeginningOfParagraph + * (Alt+DownArrow behaves similarly). In order to avoid sending + * multiple events for these keys, do not send a KeyDown if the + * selector is moveToBeginningOfParagraph or moveToEndOfParagraph. + */ + if (selector is OS.sel_moveToBeginningOfParagraph_|| selector is OS.sel_moveToEndOfParagraph_) return; + + bool [] consume = new bool [1]; + if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return; + if (isDisposed ()) return; + if (!sendKeyEvent (nsEvent, DWT.KeyDown)) return; + if (consume [0]) return; + } + if ((state & CANVAS) !is 0) return; + } + super.doCommandBySelector (id, sel, selector); +} + /** * Detects a drag and drop gesture. This method is used * to detect a drag gesture when called from within a mouse @@ -737,7 +914,7 @@ 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); + return dragDetect (); } /** @@ -779,38 +956,25 @@ 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); + return dragDetect(); } -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 () { + NSApplication application = NSApplication.sharedApplication(); + NSEvent event = application.nextEventMatchingMask(OS.NSLeftMouseDraggedMask, NSDate.dateWithTimeIntervalSinceNow(0.2), OS.NSDefaultRunLoopMode, false); + return (event !is null); } 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 += cast(int) pt.x; -// y += cast(int) pt.y; -// OS.GetWindowBounds (window, cast(short) OS.kWindowStructureRgn, rect); -// x += rect.left; -// y += rect.top; -// dwt.internal.carbon.Point pt1 = new dwt.internal.carbon.Point (); -// pt1.h = cast(short) x; -// pt1.v = cast(short) y; -// return OS.WaitMouseMoved (pt1); - return false; + return dragDetect(); } bool drawGripper (int x, int y, int width, int height, bool vertical) { return false; } -void drawRect(objc.id id, NSRect rect) { - super.drawRect(id, rect); +void drawWidget (objc.id id, NSRect rect) { + if (id !is view.id) return; if (!hooks (DWT.Paint) && !filters (DWT.Paint)) return; /* Send paint event */ @@ -830,12 +994,39 @@ } void enableWidget (bool enabled) { - //TODO - other views if (cast(NSControl) view) { (cast(NSControl)view).setEnabled(enabled); } } +void fillBackground (NSView view, NSGraphicsContext context, NSRect rect) { + Control control = findBackgroundControl(); + if (control is null) control = this; + Image image = control.backgroundImage; + if (image !is null && !image.isDisposed()) { + context.saveGraphicsState(); + NSColor.colorWithPatternImage(image.handle).setFill(); + NSPoint phase = new NSPoint(); + NSView controlView = control.view; + NSView contentView = controlView.window().contentView(); + phase = controlView.convertPoint_toView_(phase, contentView); + phase.y = contentView.bounds().height - phase.y; + context.setPatternPhase(phase); + NSBezierPath.fillRect(rect); + context.restoreGraphicsState(); + return; + } + Color background = control.getBackgroundColor (); + if (background !is null && !background.isDisposed ()) { + float [] color = background.handle; + context.saveGraphicsState(); + NSColor.colorWithDeviceRed(color [0], color [1], color [2], getThemeAlpha()).setFill(); + NSBezierPath.fillRect(rect); + context.restoreGraphicsState(); + return; + } +} + Cursor findCursor () { if (cursor !is null) return cursor; return parent.findCursor (); @@ -867,6 +1058,43 @@ // OS.ClearKeyboardFocus (window); } +void flagsChanged (int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) { + if (view.window ().firstResponder ().id is id) { + if ((state & SAFARI_EVENTS_FIX) is 0) { + int mask = 0; + NSEvent nsEvent = new NSEvent (theEvent); + int /*long*/ modifiers = nsEvent.modifierFlags (); + int keyCode = Display.translateKey (nsEvent.keyCode ()); + switch (keyCode) { + case DWT.ALT: mask = OS.NSAlternateKeyMask; break; + case DWT.CONTROL: mask = OS.NSControlKeyMask; break; + case DWT.COMMAND: mask = OS.NSCommandKeyMask; break; + case DWT.SHIFT: mask = OS.NSShiftKeyMask; break; + case DWT.CAPS_LOCK: + Event event = new Event(); + event.keyCode = keyCode; + setInputState (event, nsEvent, DWT.KeyDown); + sendKeyEvent (DWT.KeyDown, event); + setInputState (event, nsEvent, DWT.KeyUp); + sendKeyEvent (DWT.KeyUp, event); + break; + } + if (mask !is 0) { + int type = (mask & modifiers) !is 0 ? DWT.KeyDown : DWT.KeyUp; + Event event = new Event(); + event.keyCode = keyCode; + setInputState (event, nsEvent, type); + if (!sendKeyEvent (type, event)) return; + } + } + } + super.flagsChanged (id, sel, theEvent); +} + +NSView focusView () { + return view; +} + /** * Forces the receiver to have the <em>keyboard focus</em>, causing * all keyboard events to be delivered to it. @@ -882,7 +1110,6 @@ */ public bool forceFocus () { checkWidget(); -// if (display.focusEvent is DWT.FocusOut) return false; Decorations shell = menuShell (); shell.setSavedFocus (this); if (!isEnabled () || !isVisible ()/* || !isActive ()*/) return false; @@ -890,10 +1117,10 @@ shell.setSavedFocus (null); shell.bringToTop (false); if (isDisposed ()) return false; - view.window ().makeFirstResponder (view); + bool result = view.window ().makeFirstResponder (focusView ()); if (isDisposed ()) return false; shell.setSavedFocus (this); - return hasFocus (); + return result; } /** @@ -918,7 +1145,7 @@ if (accessible is null) accessible = new_Accessible (this); return accessible; } - + /** * Returns the receiver's background color. * @@ -1011,13 +1238,19 @@ return (state & DRAG_DETECT) !is 0; } +NSBezierPath getClipping() { + return parent.getClipping (); +} + /** * 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> + * + * @return the receiver's cursor or <code>null</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> @@ -1215,6 +1448,19 @@ return result; } +/** + * Returns the region that defines the shape of the control, + * or null if the control has the default shape. + * + * @return the region that defines the shape of the shell (or null) + * + * @exception 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.4 + */ public Region getRegion () { checkWidget (); return region; @@ -1259,6 +1505,10 @@ return new Point(cast(int)rect.width, cast(int)rect.height); } +float getThemeAlpha () { + return 1 * parent.getThemeAlpha (); +} + /** * Returns the receiver's tool tip text, or null if it has * not been set. @@ -1302,7 +1552,35 @@ } bool hasFocus () { - return this is display.getFocusControl (); + return (view.window().firstResponder().id is view.id); +} + +int /*long*/ hitTest (int /*long*/ id, int /*long*/ sel, NSPoint point) { + if ((state & DISABLED) !is 0) return 0; + return super.hitTest(id, sel, point); +} + +bool insertText (int /*long*/ id, int /*long*/ sel, int /*long*/ string) { + if (view.window ().firstResponder ().id is id) { + NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent (); + if (nsEvent !is null && nsEvent.type () is OS.NSKeyDown) { + NSString str = new NSString (string); + if (str.isKindOfClass (OS.objc_getClass ("NSAttributedString"))) { + str = new NSAttributedString (string).string (); + } + int length = (int)/*64*/str.length (); + char[] buffer = new char [length]; + str.getCharacters(buffer); + for (int i = 0; i < buffer.length; i++) { + Event event = new Event (); + if (length is 1) setKeyState (event, DWT.KeyDown, nsEvent); + event.character = buffer [i]; + if (!sendKeyEvent (nsEvent, DWT.KeyDown)) return false; + } + } + if ((state & CANVAS) !is 0) return true; + } + return super.insertText (id, sel, string); } /** @@ -1324,7 +1602,9 @@ if (data !is null && data.paintRect !is null) { context = NSGraphicsContext.currentContext().id_; } else { - context = NSGraphicsContext.graphicsContextWithWindow(view.window()).id_; + NSGraphicsContext graphicsContext = NSGraphicsContext.graphicsContextWithWindow (view.window ()); + display.addContext (graphicsContext); + context = graphicsContext.id_; } if (data !is null) { int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; @@ -1332,12 +1612,13 @@ data.style |= style & (mask | DWT.MIRRORED); } data.device = display; + data.thread = display.thread; 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 (); + data.font = font !is null ? font : defaultFont (); } return context; } @@ -1356,7 +1637,16 @@ * @param data the platform specific GC data */ public void internal_dispose_GC (objc.id context, GCData data) { - checkWidget (); + checkWidget (); + NSGraphicsContext graphicsContext = new NSGraphicsContext (context); + display.removeContext (graphicsContext); + if (data !is null) { + if (data.paintRect !is null) { + NSGraphicsContext.setCurrentContext (graphicsContext); + } else { + graphicsContext.flushGraphics (); + } + } } /** @@ -1404,10 +1694,6 @@ */ public bool isFocusControl () { checkWidget(); -// Control focusControl = display.focusControl; -// if (focusControl !is null && !focusControl.isDisposed ()) { -// return this is focusControl; -// } return hasFocus (); } @@ -1467,6 +1753,10 @@ return (code & (DWT.TRAVERSE_ARROW_PREVIOUS | DWT.TRAVERSE_ARROW_NEXT)) !is 0; } +bool isTrim (NSView view) { + return false; +} + /** * Returns <code>true</code> if the receiver is visible and all * ancestors up to and including the receiver's nearest ancestor @@ -1486,10 +1776,36 @@ return getVisible () && parent.isVisible (); } -objc.id menuForEvent (objc.id nsEvent) { - NSPoint pt = NSEvent.mouseLocation(); - NSWindow window = view.window(); - pt.y = cast(int) (window.screen().frame().height - pt.y); +void keyDown (objc.id id, objc.SEL sel, objc.id theEvent) { + if (view.window ().firstResponder ().id_ is id) { + bool textInput = OS.objc_msgSend (id, OS.sel_conformsToProtocol_, OS.objc_getProtocol ("NSTextInput")) !is null; + if (!textInput) { + NSEvent nsEvent = new NSEvent (theEvent); + bool [] consume = new bool [1]; + if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return; + if (isDisposed ()) return; + if (!sendKeyEvent (nsEvent, DWT.KeyDown)) return; + if (consume [0]) return; + } + } + super.keyDown (id, sel, theEvent); +} + +void keyUp (int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) { + if (view.window ().firstResponder ().id is id) { + NSEvent nsEvent = new NSEvent (theEvent); + if (!sendKeyEvent (nsEvent, DWT.KeyUp)) return; + } + super.keyUp (id, sel, theEvent); +} + +void markLayout (bool changed, bool all) { + /* Do nothing */ +} + +int /*long*/ menuForEvent (int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) { + NSPoint pt = NSEvent.mouseLocation(); + pt.y = (int) (display.getPrimaryFrame().height - pt.y); int x = cast(int) pt.x; int y = cast(int) pt.y; Event event = new Event (); @@ -1504,133 +1820,36 @@ } return menu.nsMenu.id_; } - objc_super super_struct = objc_super(); - super_struct.receiver = view.id_; - super_struct.cls = cast(objc.Class) OS.objc_msgSend(view.id_, OS.sel_superclass); - return OS.objc_msgSendSuper(&super_struct, OS.sel_menuForEvent_1, nsEvent); + return super.menuForEvent (id, sel, theEvent); } 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 scrollWheel (int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) { + if (id is view.id) { + if (hooks (DWT.MouseWheel) || filters (DWT.MouseWheel)) { + NSEvent nsEvent = new NSEvent(theEvent); + if (nsEvent.deltaY() !is 0) { + if (!sendMouseEvent(nsEvent, DWT.MouseWheel, true)) { + return; + } + } + } + } + super.scrollWheel(id, sel, theEvent); } -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 = cast(int) point.x; - event.y = cast(int) point.y; - setInputState (event, nsEvent, type); - sendEvent (type, event); -} - -void mouseDown(objc.id theEvent) { - NSEvent nsEvent = new NSEvent (theEvent); - sendMouseEvent (nsEvent, DWT.MouseDown, 1); -} - -void mouseDragged(objc.id theEvent) { - NSEvent nsEvent = new NSEvent (theEvent); - sendMouseEvent (nsEvent, DWT.MouseMove, 1); -} - -void mouseUp(objc.id theEvent) { - NSEvent nsEvent = new NSEvent (theEvent); - sendMouseEvent (nsEvent, DWT.MouseUp, 1); -} - -bool sendKeyEvent (Event event) { - sendEvent (event); - return event.doit; +void mouseDown(int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) { + Display display = this.display; + display.trackingControl = this; + super.mouseDown(id, sel, theEvent); + display.trackingControl = null; } -//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 = cast(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 ((cast(Widget)this).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 */ +void moved () { + sendEvent (DWT.Move); } /** @@ -1738,6 +1957,23 @@ setSize (computeSize (DWT.DEFAULT, DWT.DEFAULT, changed)); } +/** + * Prints the receiver and all children. + * + * @param gc the gc where the drawing occurs + * @return <code>true</code> if the operation was successful and <code>false</code> otherwise + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the gc is null</li> + * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li> + * </ul> + * @exception 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.4 + */ public bool print (GC gc) { checkWidget (); if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); @@ -1827,23 +2063,31 @@ view.setNeedsDisplayInRect(rect); } +void register () { + super.register (); + display.addWidget (view, this); +} + void releaseHandle () { super.releaseHandle (); - if (view !is null) { - OS.objc_msgSend(view.id_, OS.sel_setTag_1, -1); - view.release(); - } + if (view !is null) view.release(); view = null; parent = null; } void releaseParent () { -// setVisible (topHandle (), false); parent.removeControl (this); } void releaseWidget () { super.releaseWidget (); + if (display.currentControl is this) { + display.currentControl = null; + display.timerExec(-1, display.hoverTimer); + } + if (display.grabControl is this) { + display.grabControl = null; + } if (menu !is null && !menu.isDisposed ()) { menu.dispose (); } @@ -2158,6 +2402,10 @@ eventTable.unhook (DWT.Traverse, listener); } +void resized () { + sendEvent (DWT.Resize); +} + bool sendDragEvent (int button, int stateMask, int x, int y) { Event event = new Event (); event.button = button; @@ -2168,38 +2416,18 @@ 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; +bool sendDragEvent (NSEvent nsEvent) { + return sendMouseEvent(nsEvent, DWT.DragDetect, true); } 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 @@ -2218,58 +2446,59 @@ 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 = cast(int) pt.x; -// int y = cast(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], cast(short) x, cast(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; +bool sendMouseEvent (NSEvent nsEvent, int type, bool send) { + NSInputManager manager = NSInputManager.currentInputManager (); + if (manager !is null && manager.wantsToHandleMouseEvents ()) { + if (manager.handleMouseEvent (nsEvent)) { + return true; + } + } + Shell shell = null; 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; + switch (type) { + case DWT.MouseDown: + shell = getShell (); + //FALL THROUGH + case DWT.MouseUp: + case DWT.MouseDoubleClick: + int button = (int)/*64*/nsEvent.buttonNumber(); + switch (button) { + case 0: event.button = 1; break; + case 1: event.button = 3; break; + case 2: event.button = 2; break; + case 3: event.button = 4; break; + case 4: event.button = 5; break; + } + break; + case DWT.MouseWheel: + event.detail = DWT.SCROLL_LINE; + float /*double*/ delta = nsEvent.deltaY(); + event.count = delta > 0 ? Math.max (1, (int)delta) : Math.min (-1, (int)delta); + break; } - event.x = x; - event.y = y; - event.count = count; - event.detail = detail; - setInputState (event, type, chord, modifiers); + if (event.button !is 0) event.count = (int)/*64*/nsEvent.clickCount(); + NSPoint windowPoint; + if (nsEvent is null || nsEvent.type() is OS.NSMouseMoved) { + windowPoint = view.window().convertScreenToBase(NSEvent.mouseLocation()); + } else { + windowPoint = nsEvent.locationInWindow(); + } + NSPoint point = view.convertPoint_fromView_(windowPoint, null); + event.x = (int) point.x; + event.y = (int) point.y; + setInputState (event, nsEvent, type); if (send) { sendEvent (type, event); if (isDisposed ()) return false; } else { postEvent (type, event); } + if (shell !is null) shell.setActiveControl(this); return event.doit; } -bool sendMouseWheel (short wheelAxis, int wheelDelta) { - return false; -} - void setBackground () { // redrawWidget (handle, false); } @@ -2378,44 +2607,26 @@ 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; +void setBounds (int x, int y, int width, int height, bool move, bool resize) { 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); - } + NSRect rect = new NSRect(); + 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 = NSPoint(); - point.x = x; - point.y = y; - topView.setFrameOrigin(point); - } + 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 = NSSize(); - size.width = width; - size.height = height; - topView.setFrameSize(size); - } + 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; } /** @@ -2445,7 +2656,8 @@ /** * 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. + * <code>false</code> as the argument. Note that on some platforms, + * a mouse button must currently be down for capture to be assigned. * * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it * @@ -2481,8 +2693,8 @@ checkWidget(); if (cursor !is null && cursor.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); this.cursor = cursor; - //TODO null -// view.addCursorRect(view.frame(), cursor.handle); + if (!isEnabled()) return; + display.setCursor (display.currentControl); } void setDefaultFont () { @@ -2531,10 +2743,8 @@ Control control = null; bool fixFocus_ = false; if (!enabled) { -// if (display.focusEvent !is DWT.FocusOut) { - control = display.getFocusControl (); - fixFocus_ = isFocusAncestor (control); -// } + control = display.getFocusControl (); + fixFocus = isFocusAncestor (control); } if (enabled) { state &= ~DISABLED; @@ -2641,6 +2851,32 @@ // OS.SetControlFontStyle (control, fontStyle); } +void setFrameOrigin (int /*long*/ id, int /*long*/ sel, NSPoint point) { + NSView topView = topView (); + if (topView.id !is id) { + super.setFrameOrigin(id, sel, point); + return; + } + NSRect frame = topView.frame(); + super.setFrameOrigin(id, sel, point); + if (frame.x !is point.x || frame.y !is point.y) { + moved (); + } +} + +void setFrameSize (int /*long*/ id, int /*long*/ sel, NSSize size) { + NSView topView = topView (); + if (topView.id !is id) { + super.setFrameSize(id, sel, size); + return; + } + NSRect frame = topView.frame(); + super.setFrameSize(id, sel, size); + if (frame.width !is size.width || frame.height !is size.height) { + resized (); + } +} + /** * Sets the layout data associated with the receiver to the argument. * @@ -2765,10 +3001,11 @@ 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); + NSView topView = topView (); + topView.retain(); + topView.removeFromSuperview(); + parent.contentView().addSubview(topView, OS.NSWindowBelow, null); + topView.release(); this.parent = parent; return true; } @@ -2813,6 +3050,23 @@ } } +/** + * Sets the shape of the control to the region specified + * by the argument. When the argument is null, the + * default shape of the control is restored. + * + * @param region the region that defines the shape of the control (or null) + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li> + * </ul> + * @exception 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.4 + */ public void setRegion (Region region) { checkWidget (); if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); @@ -2941,10 +3195,8 @@ Control control = null; bool fixFocus_ = false; if (!visible) { -// if (display.focusEvent !is DWT.FocusOut) { - control = display.getFocusControl (); - fixFocus_ = isFocusAncestor (control); -// } + control = display.getFocusControl (); + fixFocus = isFocusAncestor (control); } topView().setHidden(!visible); if (!visible) { @@ -2960,21 +3212,15 @@ } 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); + NSView topView = topView (); + parent.contentView().addSubview(topView, OS.NSWindowBelow, null); } 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 ? NSWindowAbove : NSWindowBelow, otherView); + parent.contentView().addSubview(view, above ? NSWindowAbove : NSWindowBelow, otherView); view.release(); } @@ -3101,7 +3347,7 @@ break; } case 48: /* Tab */ { - int modifiers = display.lastModifiers; + int /*long*/ modifiers = theEvent.modifierFlags (); bool next = (modifiers & OS.NSShiftKeyMask) is 0; detail = next ? DWT.TRAVERSE_TAB_NEXT : DWT.TRAVERSE_TAB_PREVIOUS; break; @@ -3117,10 +3363,9 @@ 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; + int /*long*/ modifiers = theEvent.modifierFlags (); + if ((modifiers & OS.NSControlKeyMask) is 0) return false; + detail = key is 121 /* Page down */ ? DWT.TRAVERSE_PAGE_NEXT : DWT.TRAVERSE_PAGE_PREVIOUS; break; } default: @@ -3144,7 +3389,7 @@ } int traversalCode (short key, NSEvent theEvent) { - int code = DWT.TRAVERSE_RETURN | DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS; + int code = DWT.TRAVERSE_RETURN | DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS | DWT.TRAVERSE_PAGE_NEXT | DWT.TRAVERSE_PAGE_PREVIOUS; Shell shell = getShell (); if (shell.parent !is null) code |= DWT.TRAVERSE_ESCAPE; return code; @@ -3292,7 +3537,7 @@ void update (bool all) { // checkWidget(); //TODO - not all -// OS.HIViewRender (handle); + view.displayIfNeeded (); } void updateBackgroundMode () {