diff dwt/widgets/Menu.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 a470e49a1890
line wrap: on
line diff
--- a/dwt/widgets/Menu.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/widgets/Menu.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,7 +9,7 @@
  *     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.Menu;
 
@@ -57,6 +57,10 @@
  * </p><p>
  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
  * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#menu">Menu 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 Menu : Widget {
     /**
@@ -70,18 +74,21 @@
      * </p>
      */
     NSMenu nsMenu;
-    short id;
     int x, y, itemCount;
-//  int width, height;
-    bool hasLocation, modified, closed;
+    bool hasLocation, visible;
     MenuItem [] items;
-    MenuItem cascade, defaultItem, lastTarget;
+    MenuItem cascade, defaultItem;
     Decorations parent;
 
 /**
  * Constructs a new instance of this class given its parent,
  * and sets the style for the instance so that the instance
  * will be a popup menu on the given parent's shell.
+ * <p>
+ * After constructing a menu, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code>.  In this case, the parent may
+ * be any control in the same widget tree as the parent.
+ * </p>
  *
  * @param parent a control which will be the parent of the new instance (cannot be null)
  *
@@ -113,6 +120,9 @@
  * 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><p>
+ * After constructing a menu or menuBar, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code> or <code>parent.setMenuBar(menuBar)</code>.
  * </p>
  *
  * @param parent a decorations control which will be the parent of the new instance (cannot be null)
@@ -143,6 +153,10 @@
  * (which must be a <code>Menu</code>) and sets the style
  * for the instance so that the instance will be a drop-down
  * menu on the given parent's parent.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentMenu
+ * using <code>parentMenu.setMenu(menu)</code>.
+ * </p>
  *
  * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
  *
@@ -167,6 +181,10 @@
  * (which must be a <code>MenuItem</code>) and sets the style
  * for the instance so that the instance will be a drop-down
  * menu on the given parent's parent menu.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentItem
+ * using <code>parentItem.setMenu(menu)</code>.
+ * </p>
  *
  * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
  *
@@ -221,7 +239,7 @@
             location = window.mouseLocationOutsideOfEventStream();
         }
         NSEvent nsEvent = NSEvent.otherEventWithType(NSApplicationDefined, location, 0, 0.0, window.windowNumber(), window.graphicsContext(), cast(short)0, 0, 0);
-        NSMenu.static_popUpContextMenu_withEvent_forView_ (nsMenu, nsEvent, shell.view);
+        NSMenu.popUpContextMenu(nsMenu, nsEvent, shell.view);
     } else {
         nsMenu.cancelTracking ();
     }
@@ -281,17 +299,15 @@
 }
 
 void createHandle () {
-//  display.addMenu (this);
-    SWTMenu widget = cast(SWTMenu)(new SWTMenu()).alloc();
+    display.addMenu (this);
+    NSMenu widget = cast(NSMenu)(new SWTMenu()).alloc();
     widget.initWithTitle(NSString.stringWith(""));
     widget.setAutoenablesItems(false);
-    widget.setTag(jniRef);
     widget.setDelegate(widget); 
     nsMenu = widget;    
 }
 
 void createItem (MenuItem item, int index) {
-    checkWidget ();
     if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE);
     NSMenuItem nsItem = null;
     if ((item.style & DWT.SEPARATOR) !is 0) {
@@ -302,10 +318,10 @@
         nsItem.initWithTitle(NSString.stringWith(""), null, NSString.stringWith(""));
         nsItem.setTarget(nsItem);
         nsItem.setAction(OS.sel_sendSelection);
-        //item.createJNIRef();
-        nsItem.setTag(item.jniRef);
     }
     item.nsItem = nsItem;
+    item.createJNIRef();
+    item.register();
     nsMenu.insertItem(nsItem, index);
     if (itemCount is items.length) {
         MenuItem [] newItems = new MenuItem [items.length + 4];
@@ -314,11 +330,12 @@
     }
     System.arraycopy (items, index, items, index + 1, itemCount++ - index);
     items [index] = item;
-    
     NSMenu emptyMenu = item.createEmptyMenu ();
     if (emptyMenu !is null) {
-        item.nsItem.setSubmenu (emptyMenu);
+        nsItem.setSubmenu (emptyMenu);
     }
+    //TODO - find a way to disable the menu instead of each item
+    if (!getEnabled ()) nsItem.setEnabled (false);
 }
 
 void createWidget () {
@@ -327,6 +344,11 @@
     items = new MenuItem [4];
 }
 
+void deregister () {
+    super.deregister ();
+    display.removeWidget (nsMenu);
+}
+
 void destroyItem (MenuItem item) {
     int index = 0;
     while (index < itemCount) {
@@ -567,18 +589,15 @@
         return this is parent.menuShell ().menuBar;
     }
     if ((style & DWT.POP_UP) !is 0) {
-//      Menu [] popups = display.popups;
-//      if (popups is null) return false;
-//      for (int i=0; i<popups.length; i++) {
-//          if (popups [i] is this) return true;
-//      }
+        Menu [] popups = display.popups;
+        if (popups is null) return false;
+        for (int i=0; i<popups.length; i++) {
+            if (popups [i] is this) return true;
+        }
     }
-//  MenuTrackingData outData = new MenuTrackingData ();
-//  return OS.GetMenuTrackingData (handle, outData) is OS.noErr;
-    return false;
+    return visible;
 }
 
-
 /**
  * Searches the receiver's list starting at the first item
  * (index 0) until an item is found that is equal to the 
@@ -648,51 +667,52 @@
     return getVisible ();
 }
 
-void menu_willHighlightItem(int menu, objc.id itemID) {
-    NSInteger jniRef = cast(NSInteger) OS.objc_msgSend(itemID, OS.sel_tag);
-    if (jniRef !is -1 && jniRef !is 0) {
-        Object object = OS.JNIGetObject(jniRef);
-        if ( null !is cast(MenuItem)object ) {
-            MenuItem item = cast(MenuItem)object;
-            item.sendEvent (DWT.Arm);
+void menu_willHighlightItem(objc.id id, objc.SEL sel, objc.id menu, objc.id itemID) {
+    Widget widget = display.getWidget(itemID);
+    if (widget instanceof MenuItem) {
+        MenuItem item = (MenuItem)widget;
+        item.sendEvent (DWT.Arm);
+    }
+}
+
+void menuNeedsUpdate(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) {
+    //This code is intentionally commented
+    //sendEvent (DWT.Show);
+}
+
+void menuWillOpen(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) {
+    visible = true;
+    sendEvent (DWT.Show);
+    for (int i=0; i<items.length; i++) {
+        MenuItem item = items [i];
+        if (item !is null) {
+            if (item.accelerator is 0) {
+                if (item.nsItem.keyEquivalent ().length () !is 0 || item.nsItem.keyEquivalentModifierMask () !is 0) {
+                    item.nsItem.setHidden (false);
+                }
+            }
         }
     }
 }
 
-void menuNeedsUpdate(int menu) {
-    sendEvent (DWT.Show);
-}
-
-void menuWillClose(int menu) {
+void menuDidClose(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) {
     sendEvent (DWT.Hide);
-}
-
-void menuWillOpen(int menu) {
+    visible = false;
+    for (int i=0; i<items.length; i++) {
+        MenuItem item = items [i];
+        if (item !is null) {
+            if (item.accelerator is 0) {
+                if (item.nsItem.keyEquivalent().length () !is 0 || item.nsItem.keyEquivalentModifierMask () !is 0) {
+                    item.nsItem.setHidden (true);
+                }
+            }
+        }
+    }
 }
 
-int modifierIndex (String accelText) {
-    int start = accelText.length () - 1;
-    int index = start;
-    while (index >= 0) {
-        char c = accelText.charAt (index);
-        switch (c) {
-            case ' ':
-                if (index !is start) return index;
-                break;
-            case '\u2303':
-            case '\u2325':
-            case '\u21E7':
-            case '\u2318':
-                return index;
-        }
-        index--;
-    }
-    return -1;
-}
-
-int numberOfItemsInMenu(int menu) {
-    System.Out.println("numver");
-    return 4;
+void register () {
+    super.register ();
+    display.addWidget (nsMenu, this);
 }
 
 void releaseChildren (bool destroy) {
@@ -723,9 +743,9 @@
 
 void releaseWidget () {
     super.releaseWidget ();
-//  display.removeMenu (this);
+    display.removeMenu (this);
     parent = null;
-    cascade = defaultItem = lastTarget = null;
+    cascade = defaultItem = null;
 }
 
 /**
@@ -814,10 +834,22 @@
     checkWidget();
     if (enabled) {
         state &= ~DISABLED;
-        //OS.EnableMenuItem (handle, cast(short)0);
     } else {
         state |= DISABLED;
-        //OS.DisableMenuItem (handle, cast(short)0);
+    }
+    //TODO - find a way to disable the menu instead of each item
+    for (int i=0; i<items.length; i++) {
+        MenuItem item = items [i];
+        if (item !is null) {
+            /*
+            * Feature in the Macintosh.  When a cascade menu
+            * item is disabled, rather than disabling the item,
+            * the submenu is disabled.
+            * 
+            * There is no fix for this at this time.
+            */
+            item.nsItem.setEnabled (enabled && item.getEnabled ());
+        }
     }
 }
 
@@ -898,12 +930,9 @@
     checkWidget ();
     if ((style & (DWT.BAR | DWT.DROP_DOWN)) !is 0) return;
     if (visible) {
-//      display.addPopup (this);
-        //TODO -WRONG
-        _setVisible (true);
+        display.addPopup (this);
     } else {
-//      display.removePopup (this);
-        _setVisible (false);
+        display.removePopup (this);
     }
 }