diff dwt/widgets/Button.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/Button.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/widgets/Button.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,27 +9,36 @@
  *     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.Button;
 
 
 import dwt.DWT;
 import dwt.DWTException;
+import dwt.accessibility.ACC;
 import dwt.events.SelectionEvent;
 import dwt.events.SelectionListener;
 import dwt.graphics.Image;
+import dwt.graphics.Point;
+import dwt.internal.cocoa.NSAffineTransform;
 import dwt.internal.cocoa.NSAttributedString;
+import dwt.internal.cocoa.NSBezierPath;
 import dwt.internal.cocoa.NSButton;
 import dwt.internal.cocoa.NSButtonCell;
 import dwt.internal.cocoa.NSColor;
+import dwt.internal.cocoa.NSControl;
 import dwt.internal.cocoa.NSEvent;
+import dwt.internal.cocoa.NSFont;
+import dwt.internal.cocoa.NSGraphicsContext;
 import dwt.internal.cocoa.NSMutableDictionary;
 import dwt.internal.cocoa.NSMutableParagraphStyle;
+import dwt.internal.cocoa.NSPoint;
 import dwt.internal.cocoa.NSRect;
 import dwt.internal.cocoa.NSString;
 import dwt.internal.cocoa.OS;
 import dwt.internal.cocoa.SWTButton;
+import dwt.internal.cocoa.id;
 
 import dwt.dwthelper.utils;
 import dwt.internal.cocoa.CGFloat;
@@ -63,6 +72,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/#button">Button 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 class Button : Control {
     String text = "";
@@ -109,6 +122,37 @@
     super (parent, checkStyle (style));
 }
 
+int accessibilityAttributeValue (int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) {
+    NSString nsAttributeName = new NSString(arg0);
+    
+    if (accessible !is null) {
+        id returnObject = accessible.internal_accessibilityAttributeValue(nsAttributeName, ACC.CHILDID_SELF);
+        if (returnObject !is null) return returnObject.id;
+    }
+    
+    if (nsAttributeName.isEqualToString (OS.NSAccessibilityRoleAttribute) || nsAttributeName.isEqualToString (OS.NSAccessibilityRoleDescriptionAttribute)) {
+        NSString role = null;
+        
+        if ((style & DWT.RADIO) !is 0) {
+            role = OS.NSAccessibilityRadioButtonRole;
+        } else if ((style & DWT.ARROW) !is 0) {
+            role = OS.NSAccessibilityButtonRole;
+        }
+        
+        if (role !is null) {
+            if (nsAttributeName.isEqualToString (OS.NSAccessibilityRoleAttribute))
+                return role.id;
+            else {
+                int roleDescription = OS.NSAccessibilityRoleDescription(role.id, 0);
+                return roleDescription;
+            }
+        }
+    }
+    
+    return super.accessibilityAttributeValue(id, sel, arg0);
+}
+
+
 /**
  * Adds the listener to the collection of listeners who will
  * be notified when the control is selected by the user, by sending
@@ -160,15 +204,26 @@
     postEvent (DWT.Selection);
 }
 
+public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget();
+    if ((style & DWT.ARROW) !is 0) {
+        // TODO use some OS metric instead of hardcoded values
+        int width = wHint !is DWT.DEFAULT ? wHint : 23;
+        int height = hHint !is DWT.DEFAULT ? hHint : 23;
+        return new Point (width, height);
+    }
+    return super.computeSize(wHint, hHint, changed);
+}
+
 NSAttributedString createString() {
     NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity(4);
     if (foreground !is null) {
         NSColor color = NSColor.colorWithDeviceRed(cast(CGFloat) foreground.handle[0], cast(CGFloat) foreground.handle[1], cast(CGFloat) foreground.handle[2], 1);
-        dict.setObject(color, OS.NSForegroundColorAttributeName());
+        dict.setObject(color, OS.NSForegroundColorAttributeName);
     }
-    if (font !is null) {
-        dict.setObject(font.handle, OS.NSFontAttributeName());
-    }
+
+    dict.setObject(getFont().handle, OS.NSFontAttributeName);
+
     NSTextAlignment alignment;
     if ((style & DWT.CENTER) !is 0) {
         alignment = NSCenterTextAlignment;
@@ -180,12 +235,12 @@
     NSMutableParagraphStyle pStyle = cast(NSMutableParagraphStyle)(new NSMutableParagraphStyle()).alloc().init();
     pStyle.autorelease();
     pStyle.setAlignment(alignment);
-    dict.setObject(pStyle, OS.NSParagraphStyleAttributeName());
+    dict.setObject(pStyle, OS.NSParagraphStyleAttributeName);
     char [] chars = new char [text.length ()];
     text.getChars (0, chars.length, chars, 0);
     NSUInteger length = fixMnemonic (chars);
     NSString str = NSString.stringWithCharacters(chars.toString16().ptr, length);
-    NSAttributedString attribStr = (cast(NSAttributedString)(new NSAttributedString()).alloc()).initWithString_attributes_(str, dict);
+    NSAttributedString attribStr = (cast(NSAttributedString)(new NSAttributedString()).alloc()).initWithString(str, dict);
     attribStr.autorelease();
     return attribStr;
 }
@@ -193,9 +248,14 @@
 void createHandle () {
     NSButton widget = cast(NSButton)(new SWTButton()).alloc();
     widget.initWithFrame(NSRect());
-    NSButtonType type = NSMomentaryPushButton;
+    NSButtonType type = NSMomentaryLightButton;
     if ((style & DWT.PUSH) !is 0) {
-        widget.setBezelStyle(NSRoundedBezelStyle);
+        if ((style & DWT.FLAT) !is 0) {
+            widget.setBezelStyle(OS.NSShadowlessSquareBezelStyle);
+//          if ((style & DWT.BORDER) is 0) widget.setShowsBorderOnlyWhileMouseInside(true);
+        } else {
+            widget.setBezelStyle(OS.NSRoundedBezelStyle);
+        }
     } else if ((style & DWT.CHECK) !is 0) {
         type = NSSwitchButton;
         widget.setAllowsMixedState (true);
@@ -204,20 +264,70 @@
     } else if ((style & DWT.TOGGLE) !is 0) {
         type = NSPushOnPushOffButton;
         widget.setBezelStyle(NSRegularSquareBezelStyle);
+            widget.setBezelStyle(OS.NSShadowlessSquareBezelStyle);
+//          if ((style & DWT.BORDER) is 0) widget.setShowsBorderOnlyWhileMouseInside(true);
+        } else {
+            widget.setBezelStyle(OS.NSRoundedBezelStyle);
+        }
     } else if ((style & DWT.ARROW) !is 0) {
-        widget.setBezelStyle(NSRoundedDisclosureBezelStyle);
+        widget.setBezelStyle(NSRegularSquareBezelStyle);
     }
     widget.setButtonType(type);
     widget.setTitle(NSString.stringWith(""));
     widget.setImagePosition(NSImageLeft);
     widget.setTarget(widget);
     widget.setAction(OS.sel_sendSelection);
-    widget.setTag(jniRef);
-    view = widget;  
-    parent.contentView().addSubview_(widget);
+    view = widget;
     _setAlignment(style);
 }
 
+void deregister () {
+    super.deregister ();
+    display.removeWidget(((NSControl)view).cell());
+}
+
+void drawWidget (int /*long*/ id, NSRect rect) {
+    if ((style & DWT.ARROW) !is 0) {    
+        NSRect frame = view.frame();
+        int arrowSize = Math.min((int)frame.height, (int)frame.width) / 2;
+        NSGraphicsContext context = NSGraphicsContext.currentContext();
+        context.saveGraphicsState();
+        NSPoint p1 = new NSPoint();
+        p1.x = (float)Math.floor(-arrowSize / 2);
+        p1.y = (float)Math.floor(-arrowSize / 2);
+        NSPoint p2 = new NSPoint();
+        p2.x = (float)Math.ceil(arrowSize / 2);
+        p2.y = p1.y;
+        NSPoint p3 = new NSPoint();
+        p3.y = (float)Math.ceil(arrowSize / 2);
+    
+        NSBezierPath path = NSBezierPath.bezierPath();
+        path.moveToPoint(p1);
+        path.lineToPoint(p2);
+        path.lineToPoint(p3);
+        path.closePath();
+    
+        NSAffineTransform transform = NSAffineTransform.transform();
+        if ((style & DWT.LEFT) !is 0) {
+            transform.rotateByDegrees(90);
+        } else if ((style & DWT.UP) !is 0) {
+            transform.rotateByDegrees(180);
+        } else if ((style & DWT.RIGHT) !is 0) {
+            transform.rotateByDegrees(-90);
+        }
+        path.transformUsingAffineTransform(transform);
+        transform = NSAffineTransform.transform();
+        transform.translateXBy(frame.width / 2, frame.height / 2);
+        path.transformUsingAffineTransform(transform);
+    
+        NSColor color = isEnabled() ? NSColor.blackColor() : NSColor.disabledControlTextColor();
+        color.set();
+        path.fill();
+        context.restoreGraphicsState();
+    }
+    super.drawWidget (id, rect);
+}
+
 /**
  * Returns a value which describes the position of the
  * text or image in the receiver. The value will be one of
@@ -249,6 +359,20 @@
     return DWT.LEFT;
 }
 
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the widget does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception 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 getGrayed() {
     checkWidget ();
     if ((style &DWT.CHECK) !is 0) return false;
@@ -315,6 +439,11 @@
     return text;
 }
 
+void register() {
+    super.register();
+    display.addWidget(((NSControl)view).cell(), this);
+}
+
 void releaseWidget () {
     super.releaseWidget ();
     image = null;
@@ -470,14 +599,38 @@
 
 void setDefault (bool value) {
     if ((style & DWT.PUSH) is 0) return;
-//  int window = OS.GetControlOwner (handle);
-//  OS.SetWindowDefaultButton (window, value ? handle : 0);
+//  NSWindow window = view.window();
+//  NSButtonCell cell = null;
+//  if (value) {
+//      cell = new NSButtonCell(((NSButton)view).cell());
+//  }
+//  window.setDefaultButtonCell(cell);
+}
+
+void setFont (NSFont font) {
+    if (text !is null) {
+        ((NSButton)view).setAttributedTitle(createString());
+    }
 }
 
 void setForeground (float [] color) {
     (cast(NSButton)view).setAttributedTitle(createString());
 }
 
+/**
+ * Sets the grayed state of the receiver.  This state change 
+ * only applies if the control was created with the DWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed 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.4
+ */
 public void setGrayed(bool grayed) {
     checkWidget ();
     if ((style & DWT.CHECK) is 0) return;
@@ -513,12 +666,12 @@
  */
 public void setImage (Image image) {
     checkWidget();
-    if ((style & DWT.ARROW) !is 0) return;
     if (image !is null && image.isDisposed ()) {
         error (DWT.ERROR_INVALID_ARGUMENT);
     }
+    if ((style & DWT.ARROW) !is 0) return;
     this.image = image;
-    (cast(NSButton)view).setImage(image.handle);
+    (cast(NSButton)view).setImage(image !is null ? image.handle : null);
 }
 
 bool setRadioSelection (bool value){
@@ -597,6 +750,7 @@
 
 int traversalCode (int key, NSEvent theEvent) {
     int code = super.traversalCode (key, theEvent);
+    if ((style & DWT.ARROW) !is 0) code &= ~(DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS);
     if ((style & DWT.RADIO) !is 0) code |= DWT.TRAVERSE_ARROW_NEXT | DWT.TRAVERSE_ARROW_PREVIOUS;
     return code;
 }