diff dwt/widgets/Spinner.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents e831403a80a9
children cfa563df4fdd
line wrap: on
line diff
--- a/dwt/widgets/Spinner.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/widgets/Spinner.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
@@ -22,12 +22,18 @@
 import dwt.graphics.Rectangle;
 import dwt.internal.cocoa.NSAttributedString;
 import dwt.internal.cocoa.NSCell;
+import dwt.internal.cocoa.NSCharacterSet;
+import dwt.internal.cocoa.NSEvent;
+import dwt.internal.cocoa.NSFont;
 import dwt.internal.cocoa.NSMutableDictionary;
+import dwt.internal.cocoa.NSNumber;
+import dwt.internal.cocoa.NSNumberFormatter;
 import dwt.internal.cocoa.NSRect;
 import dwt.internal.cocoa.NSSize;
 import dwt.internal.cocoa.NSStepper;
 import dwt.internal.cocoa.NSString;
 import dwt.internal.cocoa.NSTextField;
+import dwt.internal.cocoa.NSView;
 import dwt.internal.cocoa.OS;
 import dwt.internal.cocoa.SWTStepper;
 import dwt.internal.cocoa.SWTTextField;
@@ -50,11 +56,16 @@
  * </p><p>
  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
  * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#spinner">Spinner 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>
  * 
  * @since 3.1
  */
 public class Spinner : Composite {
     NSTextField textView;
+    NSNumberFormatter textFormatter;
     NSStepper buttonView;
     int pageIncrement = 10;
     int digits = 0;
@@ -94,6 +105,11 @@
     super (parent, checkStyle (style));
 }
 
+bool acceptsFirstResponder(int /*long*/ id, int /*long*/ sel) {
+    if (id is view.id) return false;
+    return super.acceptsFirstResponder (id, sel);
+}
+
 /**
  * Adds the listener to the collection of listeners who will
  * be notified when the receiver's text is modified, by sending
@@ -198,16 +214,16 @@
     float width = 0, height = 0;
     String string = Double.toString (buttonView.maxValue ());
     NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity (1);
-    dict.setObject(textView.font (), OS.NSFontAttributeName ());
+    dict.setObject(textView.font (), OS.NSFontAttributeName);
     int length = string.length ();
     char [] chars = new char [length];
     string.getChars (0, length, chars, 0);
     NSString nsString = NSString.stringWithCharacters (chars, length);
-    NSAttributedString str = (cast(NSAttributedString) new NSAttributedString ().alloc ()).initWithString_attributes_ (nsString, dict);
+    NSAttributedString str = (cast(NSAttributedString) new NSAttributedString ().alloc ()).initWithString (nsString, dict);
     NSSize size = str.size ();
     str.release ();
-    width = size.width;
-    height = size.height;
+    width = (int)/*64*/size.width;
+    height = (int)/*64*/size.height;
     NSRect frameRect = textView.frame();
     NSCell cell = new NSCell (textView.cell ());
     NSRect cellRect = cell.drawingRectForBounds(frameRect);
@@ -219,7 +235,7 @@
     NSRect newRect = buttonView.frame ();
     buttonView.setFrame (oldRect);
     width += newRect.width;
-    height = Math.max (height, newRect.height);
+    height = Math.max (height, (int)/*64*/newRect.height);
     if (wHint !is DWT.DEFAULT) width = wHint;
     if (hHint !is DWT.DEFAULT) height = hHint;
     Rectangle trim = computeTrim (0, 0, cast(int) width, cast(int) height);
@@ -255,27 +271,27 @@
 }
 
 void createHandle () {
-    SWTView widget = cast(SWTView)new SWTView().alloc();
+    NSView widget = cast(NSView)new SWTView().alloc();
     widget.initWithFrame(new NSRect());
 //  widget.setDrawsBackground(false);
-    widget.setTag(jniRef);
     NSStepper buttonWidget = cast(NSStepper)new SWTStepper().alloc();
     buttonWidget.initWithFrame(new NSRect());
     buttonWidget.setValueWraps((style & DWT.WRAP) !is 0);
     buttonWidget.setTarget(buttonWidget);
     buttonWidget.setAction(OS.sel_sendSelection);
-    buttonWidget.setTag(jniRef);
     NSTextField textWidget = cast(NSTextField)new SWTTextField().alloc();
     textWidget.initWithFrame(new NSRect());
 //  textWidget.setTarget(widget);
-    textWidget.setTag(jniRef);
     textWidget.setEditable((style & DWT.READ_ONLY) is 0);
-    widget.addSubview_(textWidget);
-    widget.addSubview_(buttonWidget);
+    textFormatter = new NSNumberFormatter();
+    textFormatter.alloc().init(); //.autorelease();
+    textFormatter.setNumberStyle(OS.NSNumberFormatterDecimalStyle);
+    //textWidget.cell().setFormatter(textFormatter);
+    widget.addSubview(textWidget);
+    widget.addSubview(buttonWidget);
     buttonView = buttonWidget;
     textView = textWidget;
-    view = widget;  
-    parent.contentView().addSubview_(widget);
+    view = widget;
     setSelection (0, false, true, false);
 }
 
@@ -303,11 +319,28 @@
 //  }
 }
 
+void deregister () {
+    super.deregister ();
+    if (textView !is null) {
+        display.removeWidget (textView);
+        display.removeWidget (textView.cell());
+    }
+    
+    if (buttonView !is null) {
+        display.removeWidget (buttonView);
+        display.removeWidget (buttonView.cell());
+    }
+}
+
 void enableWidget (bool enabled) {
     buttonView.setEnabled(enabled);
     textView.setEnabled(enabled);
 }
 
+NSView focusView () {
+    return textView;
+}
+
 /**
  * Returns the number of decimal places used by the receiver.
  *
@@ -400,10 +433,102 @@
     return cast(int)(cast(NSStepper)buttonView).doubleValue();
 }
 
-int getSelectionText () {
+int getSelectionText (bool[] parseFail) {
+    String string = textView.stringValue().getString();
+    try {
+        int value;
+        if (digits > 0) {
+            String decimalSeparator = textFormatter.decimalSeparator().getString();
+            int index = string.indexOf (decimalSeparator);
+            if (index !is -1)  {
+                int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0;
+                String wholePart = startIndex !is index ? string.substring (startIndex, index) : "0";
+                String decimalPart = string.substring (index + 1);
+                if (decimalPart.length () > digits) {
+                    decimalPart = decimalPart.substring (0, digits);
+                } else {
+                    int i = digits - decimalPart.length ();
+                    for (int j = 0; j < i; j++) {
+                        decimalPart = decimalPart + "0";
+                    }
+                }
+                int wholeValue = Integer.parseInt (wholePart);
+                int decimalValue = Integer.parseInt (decimalPart);
+                for (int i = 0; i < digits; i++) wholeValue *= 10;
+                value = wholeValue + decimalValue;
+                if (string.startsWith ("-")) value = -value;
+            } else {
+                value = Integer.parseInt (string);
+                for (int i = 0; i < digits; i++) value *= 10;
+            }
+        } else {
+            value = Integer.parseInt (string);
+        }
+        int max = getMaximum();
+        int min = getMinimum();
+        if (min <= value && value <= max) return value;
+    } catch (NumberFormatException e) {
+    }
+    parseFail [0] = true;
     return -1;
 }
 
+void keyDown (int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) {
+    NSEvent event = new NSEvent(theEvent);
+    NSString chars = event.charactersIgnoringModifiers();
+    
+    int delta = 0;
+    int keyChar = 0;
+
+    if (chars.length() !is 1) return;
+    
+    keyChar = chars.characterAtIndex(0);
+
+    switch (keyChar) {
+        case OS.NSEnterCharacter: /* KP Enter */
+        case OS.NSNewlineCharacter: /* Return */
+            postEvent (DWT.DefaultSelection);
+            return;
+        case OS.NSPageUpFunctionKey: delta = pageIncrement; break;
+        case OS.NSPageDownFunctionKey: delta = -pageIncrement; break;
+        case OS.NSDownArrowFunctionKey: delta = -getIncrement(); break;
+        case OS.NSUpArrowFunctionKey: delta = getIncrement(); break;
+        
+        default: {
+            NSCharacterSet numbers = new NSCharacterSet(NSCharacterSet.decimalDigitCharacterSet().id);
+            bool isANumber = numbers.characterIsMember((short) keyChar);
+            bool isSeparator = (keyChar is textFormatter.decimalSeparator().characterAtIndex(0));
+            bool isMathSymbol = (keyChar is 0x2d || keyChar is 0x2b); // Minus sign, plus sign
+            if (isANumber || (isSeparator && digits > 0) || isMathSymbol) super.keyDown(id, sel, theEvent);
+        }
+    }
+
+    if (delta !is 0) {
+        bool [] parseFail = new bool [1];
+        int value = getSelectionText (parseFail);
+        if (parseFail [0]) {
+            value = (int)buttonView.doubleValue();
+        }
+        int newValue = value + delta;
+        int max = (int)buttonView.maxValue();
+        int min = (int)buttonView.minValue();
+        if ((style & DWT.WRAP) !is 0) {
+            if (newValue > max) newValue = min;
+            if (newValue < min) newValue = max;
+        }
+        newValue = Math.min (Math.max (min, newValue), max);
+        if (value !is newValue) setSelection (newValue, true, true, true);
+        return;
+    } else {
+        bool [] parseFail = new bool [1];
+        int value = getSelectionText (parseFail);
+        if (!parseFail [0]) {
+            int pos = (int)buttonView.doubleValue();
+            if (pos !is value) setSelection (value, true, false, true);
+        }
+    }
+}
+
 /**
  * Pastes text from clipboard.
  * <p>
@@ -425,16 +550,25 @@
 //  setText (text, selection [0], selection [1], true);
 }
 
+void register () {
+    super.register ();
+    if (textView !is null) {
+        display.addWidget (textView, this);
+        display.addWidget (textView.cell(), this);
+    }
+    
+    if (buttonView !is null) {
+        display.addWidget (buttonView, this);
+        display.addWidget (buttonView.cell(), this);
+    }
+}
+
 void releaseHandle () {
     super.releaseHandle();
-    if (buttonView !is null) {
-        buttonView.setTag(-1);
-        buttonView.release();
-    }
-    if (textView !is null) {
-        textView.setTag(-1);
-        textView.release();
-    }
+    if (textFormatter !is null) textFormatter.release();
+    if (buttonView !is null) buttonView.release();
+    if (textView !is null) textView.release();
+    textFormatter = null;
     buttonView = null;
     textView = null;
 }
@@ -512,25 +646,22 @@
     eventTable.unhook (DWT.Verify, listener);   
 }
 
-void sendSelection () { 
-    setSelection (getSelection(), false, true, true);
+void resized () {
+    super.resized ();
+    buttonView.sizeToFit();
+    NSRect buttonFrame = buttonView.bounds();
+    NSRect frame = view.frame();
+    buttonFrame.x = frame.width - buttonFrame.width;
+    buttonFrame.y = 0;
+    frame.x = 0;
+    frame.y = 0;
+    frame.width -= buttonFrame.width + GAP;
+    textView.setFrame(frame);
+    buttonView.setFrame(buttonFrame);
 }
 
-int setBounds (int x, int y, int width, int height, bool move, bool resize) {
-    int result = super.setBounds(x, y, width, height, move, resize);
-    if ((result & RESIZED) !is 0) {
-        buttonView.sizeToFit();
-        NSRect buttonFrame = buttonView.bounds();
-        NSRect frame = view.frame();
-        buttonFrame.x = frame.width - buttonFrame.width;
-        buttonFrame.y = 0;
-        frame.x = 0;
-        frame.y = 0;
-        frame.width -= buttonFrame.width + GAP;
-        textView.setFrame(frame);
-        buttonView.setFrame(buttonFrame);
-    }
-    return result;
+void sendSelection () { 
+    setSelection (getSelection(), false, true, true);
 }
 
 /**
@@ -556,10 +687,15 @@
 public void setDigits (int value) {
     checkWidget ();
     if (value < 0) error (DWT.ERROR_INVALID_ARGUMENT);
-//  if (value is digits) return;
-//  digits = value;
-//  int pos = OS.GetControl32BitValue (buttonHandle);   
-//  setSelection (pos, false, true, false);
+    if (value is digits) return;
+    digits = value;
+    int pos = (int)buttonView.doubleValue();    
+    textFormatter.setMaximumFractionDigits(digits);
+    setSelection (pos, false, true, false);
+}
+
+void setFont(NSFont font) {
+    textView.setFont(font);
 }
 
 /**
@@ -600,16 +736,17 @@
     if (value <= min) return;
     int pos = getSelection();
     buttonView.setMaxValue(value);
+    textFormatter.setMaximum(NSNumber.numberWithInt(value));
     if (pos > value) setSelection (value, true, true, false);   
 }
 
 /**
  * Sets the minimum value that the receiver will allow.  This new
- * value will be ignored if it is negative or is not less than the receiver's
+ * value will be ignored if it is not less than the receiver's
  * current maximum value.  If the new minimum is applied then the receiver's
  * selection value will be adjusted if necessary to fall within its new range.
  *
- * @param value the new minimum, which must be nonnegative and less than the current maximum
+ * @param value the new minimum, which must be less than the current maximum
  *
  * @exception DWTException <ul>
  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
@@ -623,6 +760,7 @@
     if (value >= max) return;
     int pos = getSelection();
     buttonView.setMinValue(value);
+    textFormatter.setMinimum(NSNumber.numberWithInt(value));
     if (pos < value) setSelection (value, true, true, false);
 }
 
@@ -672,7 +810,7 @@
     if (setText) {
         String string = String.valueOf (value);
         if (digits > 0) {
-            String decimalSeparator = ".";//getDecimalSeparator ();
+            String decimalSeparator = textFormatter.decimalSeparator().getString();
             int index = string.length () - digits;
             StringBuffer buffer = new StringBuffer ();
             if (index > 0) {
@@ -689,13 +827,11 @@
         }
         NSCell cell = new NSCell(textView.cell());
         if (hooks (DWT.Verify) || filters (DWT.Verify)) {
-            int length = cell.title().length();
+            int length = (int)/*64*/cell.title().length();
             string = verifyText (string, 0, length, null);
             if (string is null) return;
         }
-        cell.setTitle(NSString.stringWith(string));
-//      short [] selection = new short [] {0, cast(short)string.length ()};
-//      OS.SetControlData (textHandle, cast(short)OS.kControlEntireControl, OS.kControlEditTextSelectionTag, 4, selection);
+        textView.setStringValue(NSString.stringWith(string));
         sendEvent (DWT.Modify);
     }
     if (notify) postEvent (DWT.Selection);
@@ -740,6 +876,19 @@
     setSelection (selection, true, true, false);
 }
 
+void textDidChange (int /*long*/ id, int /*long*/ sel, int /*long*/ aNotification) {
+    postEvent (DWT.Modify);
+}
+
+void textDidEndEditing(int /*long*/ id, int /*long*/ sel, int /*long*/ aNotification) {
+    bool [] parseFail = new bool [1];
+    int value = getSelectionText (parseFail);
+    if (parseFail [0]) {
+        value = (int)buttonView.doubleValue();
+        setSelection (value, false, true, false);
+    }
+}
+
 String verifyText (String string, int start, int end, Event keyEvent) {
     Event event = new Event ();
     event.text = string;