Mercurial > projects > dwt-mac
comparison 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 |
comparison
equal
deleted
inserted
replaced
44:ca5e494f2bbf | 45:d8635bb48c7c |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
8 * Contributors: | 8 * Contributors: |
9 * IBM Corporation - initial API and implementation | 9 * IBM Corporation - initial API and implementation |
10 * | 10 * |
11 * Port to the D programming language: | 11 * Port to the D programming language: |
12 * Jacob Carlborg <jacob.carlborg@gmail.com> | 12 * Jacob Carlborg <doob@me.com> |
13 *******************************************************************************/ | 13 *******************************************************************************/ |
14 module dwt.widgets.Menu; | 14 module dwt.widgets.Menu; |
15 | 15 |
16 | 16 |
17 import dwt.DWT; | 17 import dwt.DWT; |
55 * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified. | 55 * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified. |
56 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified. | 56 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified. |
57 * </p><p> | 57 * </p><p> |
58 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | 58 * IMPORTANT: This class is <em>not</em> intended to be subclassed. |
59 * </p> | 59 * </p> |
60 * | |
61 * @see <a href="http://www.eclipse.org/swt/snippets/#menu">Menu snippets</a> | |
62 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a> | |
63 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
60 */ | 64 */ |
61 public class Menu : Widget { | 65 public class Menu : Widget { |
62 /** | 66 /** |
63 * the handle to the OS resource | 67 * the handle to the OS resource |
64 * (Warning: This field is platform dependent) | 68 * (Warning: This field is platform dependent) |
68 * within the packages provided by DWT. It is not available on all | 72 * within the packages provided by DWT. It is not available on all |
69 * platforms and should never be accessed from application code. | 73 * platforms and should never be accessed from application code. |
70 * </p> | 74 * </p> |
71 */ | 75 */ |
72 NSMenu nsMenu; | 76 NSMenu nsMenu; |
73 short id; | |
74 int x, y, itemCount; | 77 int x, y, itemCount; |
75 // int width, height; | 78 bool hasLocation, visible; |
76 bool hasLocation, modified, closed; | |
77 MenuItem [] items; | 79 MenuItem [] items; |
78 MenuItem cascade, defaultItem, lastTarget; | 80 MenuItem cascade, defaultItem; |
79 Decorations parent; | 81 Decorations parent; |
80 | 82 |
81 /** | 83 /** |
82 * Constructs a new instance of this class given its parent, | 84 * Constructs a new instance of this class given its parent, |
83 * and sets the style for the instance so that the instance | 85 * and sets the style for the instance so that the instance |
84 * will be a popup menu on the given parent's shell. | 86 * will be a popup menu on the given parent's shell. |
87 * <p> | |
88 * After constructing a menu, it can be set into its parent | |
89 * using <code>parent.setMenu(menu)</code>. In this case, the parent may | |
90 * be any control in the same widget tree as the parent. | |
91 * </p> | |
85 * | 92 * |
86 * @param parent a control which will be the parent of the new instance (cannot be null) | 93 * @param parent a control which will be the parent of the new instance (cannot be null) |
87 * | 94 * |
88 * @exception IllegalArgumentException <ul> | 95 * @exception IllegalArgumentException <ul> |
89 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | 96 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
111 * class, or must be built by <em>bitwise OR</em>'ing together | 118 * class, or must be built by <em>bitwise OR</em>'ing together |
112 * (that is, using the <code>int</code> "|" operator) two or more | 119 * (that is, using the <code>int</code> "|" operator) two or more |
113 * of those <code>DWT</code> style constants. The class description | 120 * of those <code>DWT</code> style constants. The class description |
114 * lists the style constants that are applicable to the class. | 121 * lists the style constants that are applicable to the class. |
115 * Style bits are also inherited from superclasses. | 122 * Style bits are also inherited from superclasses. |
123 * </p><p> | |
124 * After constructing a menu or menuBar, it can be set into its parent | |
125 * using <code>parent.setMenu(menu)</code> or <code>parent.setMenuBar(menuBar)</code>. | |
116 * </p> | 126 * </p> |
117 * | 127 * |
118 * @param parent a decorations control which will be the parent of the new instance (cannot be null) | 128 * @param parent a decorations control which will be the parent of the new instance (cannot be null) |
119 * @param style the style of menu to construct | 129 * @param style the style of menu to construct |
120 * | 130 * |
141 /** | 151 /** |
142 * Constructs a new instance of this class given its parent | 152 * Constructs a new instance of this class given its parent |
143 * (which must be a <code>Menu</code>) and sets the style | 153 * (which must be a <code>Menu</code>) and sets the style |
144 * for the instance so that the instance will be a drop-down | 154 * for the instance so that the instance will be a drop-down |
145 * menu on the given parent's parent. | 155 * menu on the given parent's parent. |
156 * <p> | |
157 * After constructing a drop-down menu, it can be set into its parentMenu | |
158 * using <code>parentMenu.setMenu(menu)</code>. | |
159 * </p> | |
146 * | 160 * |
147 * @param parentMenu a menu which will be the parent of the new instance (cannot be null) | 161 * @param parentMenu a menu which will be the parent of the new instance (cannot be null) |
148 * | 162 * |
149 * @exception IllegalArgumentException <ul> | 163 * @exception IllegalArgumentException <ul> |
150 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | 164 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
165 /** | 179 /** |
166 * Constructs a new instance of this class given its parent | 180 * Constructs a new instance of this class given its parent |
167 * (which must be a <code>MenuItem</code>) and sets the style | 181 * (which must be a <code>MenuItem</code>) and sets the style |
168 * for the instance so that the instance will be a drop-down | 182 * for the instance so that the instance will be a drop-down |
169 * menu on the given parent's parent menu. | 183 * menu on the given parent's parent menu. |
184 * <p> | |
185 * After constructing a drop-down menu, it can be set into its parentItem | |
186 * using <code>parentItem.setMenu(menu)</code>. | |
187 * </p> | |
170 * | 188 * |
171 * @param parentItem a menu item which will be the parent of the new instance (cannot be null) | 189 * @param parentItem a menu item which will be the parent of the new instance (cannot be null) |
172 * | 190 * |
173 * @exception IllegalArgumentException <ul> | 191 * @exception IllegalArgumentException <ul> |
174 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | 192 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
219 location.y = topView.frame().height - shellCoord.y; | 237 location.y = topView.frame().height - shellCoord.y; |
220 } else { | 238 } else { |
221 location = window.mouseLocationOutsideOfEventStream(); | 239 location = window.mouseLocationOutsideOfEventStream(); |
222 } | 240 } |
223 NSEvent nsEvent = NSEvent.otherEventWithType(NSApplicationDefined, location, 0, 0.0, window.windowNumber(), window.graphicsContext(), cast(short)0, 0, 0); | 241 NSEvent nsEvent = NSEvent.otherEventWithType(NSApplicationDefined, location, 0, 0.0, window.windowNumber(), window.graphicsContext(), cast(short)0, 0, 0); |
224 NSMenu.static_popUpContextMenu_withEvent_forView_ (nsMenu, nsEvent, shell.view); | 242 NSMenu.popUpContextMenu(nsMenu, nsEvent, shell.view); |
225 } else { | 243 } else { |
226 nsMenu.cancelTracking (); | 244 nsMenu.cancelTracking (); |
227 } | 245 } |
228 } | 246 } |
229 | 247 |
279 addListener (DWT.Hide,typedListener); | 297 addListener (DWT.Hide,typedListener); |
280 addListener (DWT.Show,typedListener); | 298 addListener (DWT.Show,typedListener); |
281 } | 299 } |
282 | 300 |
283 void createHandle () { | 301 void createHandle () { |
284 // display.addMenu (this); | 302 display.addMenu (this); |
285 SWTMenu widget = cast(SWTMenu)(new SWTMenu()).alloc(); | 303 NSMenu widget = cast(NSMenu)(new SWTMenu()).alloc(); |
286 widget.initWithTitle(NSString.stringWith("")); | 304 widget.initWithTitle(NSString.stringWith("")); |
287 widget.setAutoenablesItems(false); | 305 widget.setAutoenablesItems(false); |
288 widget.setTag(jniRef); | |
289 widget.setDelegate(widget); | 306 widget.setDelegate(widget); |
290 nsMenu = widget; | 307 nsMenu = widget; |
291 } | 308 } |
292 | 309 |
293 void createItem (MenuItem item, int index) { | 310 void createItem (MenuItem item, int index) { |
294 checkWidget (); | |
295 if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE); | 311 if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE); |
296 NSMenuItem nsItem = null; | 312 NSMenuItem nsItem = null; |
297 if ((item.style & DWT.SEPARATOR) !is 0) { | 313 if ((item.style & DWT.SEPARATOR) !is 0) { |
298 nsItem = NSMenuItem.separatorItem(); | 314 nsItem = NSMenuItem.separatorItem(); |
299 nsItem.retain(); | 315 nsItem.retain(); |
300 } else { | 316 } else { |
301 nsItem = cast(NSMenuItem)(new SWTMenuItem()).alloc(); | 317 nsItem = cast(NSMenuItem)(new SWTMenuItem()).alloc(); |
302 nsItem.initWithTitle(NSString.stringWith(""), null, NSString.stringWith("")); | 318 nsItem.initWithTitle(NSString.stringWith(""), null, NSString.stringWith("")); |
303 nsItem.setTarget(nsItem); | 319 nsItem.setTarget(nsItem); |
304 nsItem.setAction(OS.sel_sendSelection); | 320 nsItem.setAction(OS.sel_sendSelection); |
305 //item.createJNIRef(); | |
306 nsItem.setTag(item.jniRef); | |
307 } | 321 } |
308 item.nsItem = nsItem; | 322 item.nsItem = nsItem; |
323 item.createJNIRef(); | |
324 item.register(); | |
309 nsMenu.insertItem(nsItem, index); | 325 nsMenu.insertItem(nsItem, index); |
310 if (itemCount is items.length) { | 326 if (itemCount is items.length) { |
311 MenuItem [] newItems = new MenuItem [items.length + 4]; | 327 MenuItem [] newItems = new MenuItem [items.length + 4]; |
312 System.arraycopy (items, 0, newItems, 0, items.length); | 328 System.arraycopy (items, 0, newItems, 0, items.length); |
313 items = newItems; | 329 items = newItems; |
314 } | 330 } |
315 System.arraycopy (items, index, items, index + 1, itemCount++ - index); | 331 System.arraycopy (items, index, items, index + 1, itemCount++ - index); |
316 items [index] = item; | 332 items [index] = item; |
317 | |
318 NSMenu emptyMenu = item.createEmptyMenu (); | 333 NSMenu emptyMenu = item.createEmptyMenu (); |
319 if (emptyMenu !is null) { | 334 if (emptyMenu !is null) { |
320 item.nsItem.setSubmenu (emptyMenu); | 335 nsItem.setSubmenu (emptyMenu); |
321 } | 336 } |
337 //TODO - find a way to disable the menu instead of each item | |
338 if (!getEnabled ()) nsItem.setEnabled (false); | |
322 } | 339 } |
323 | 340 |
324 void createWidget () { | 341 void createWidget () { |
325 checkOrientation (parent); | 342 checkOrientation (parent); |
326 super.createWidget (); | 343 super.createWidget (); |
327 items = new MenuItem [4]; | 344 items = new MenuItem [4]; |
345 } | |
346 | |
347 void deregister () { | |
348 super.deregister (); | |
349 display.removeWidget (nsMenu); | |
328 } | 350 } |
329 | 351 |
330 void destroyItem (MenuItem item) { | 352 void destroyItem (MenuItem item) { |
331 int index = 0; | 353 int index = 0; |
332 while (index < itemCount) { | 354 while (index < itemCount) { |
565 checkWidget (); | 587 checkWidget (); |
566 if ((style & DWT.BAR) !is 0) { | 588 if ((style & DWT.BAR) !is 0) { |
567 return this is parent.menuShell ().menuBar; | 589 return this is parent.menuShell ().menuBar; |
568 } | 590 } |
569 if ((style & DWT.POP_UP) !is 0) { | 591 if ((style & DWT.POP_UP) !is 0) { |
570 // Menu [] popups = display.popups; | 592 Menu [] popups = display.popups; |
571 // if (popups is null) return false; | 593 if (popups is null) return false; |
572 // for (int i=0; i<popups.length; i++) { | 594 for (int i=0; i<popups.length; i++) { |
573 // if (popups [i] is this) return true; | 595 if (popups [i] is this) return true; |
574 // } | 596 } |
575 } | 597 } |
576 // MenuTrackingData outData = new MenuTrackingData (); | 598 return visible; |
577 // return OS.GetMenuTrackingData (handle, outData) is OS.noErr; | 599 } |
578 return false; | |
579 } | |
580 | |
581 | 600 |
582 /** | 601 /** |
583 * Searches the receiver's list starting at the first item | 602 * Searches the receiver's list starting at the first item |
584 * (index 0) until an item is found that is equal to the | 603 * (index 0) until an item is found that is equal to the |
585 * argument, and returns the index of that item. If no item | 604 * argument, and returns the index of that item. If no item |
646 public bool isVisible () { | 665 public bool isVisible () { |
647 checkWidget (); | 666 checkWidget (); |
648 return getVisible (); | 667 return getVisible (); |
649 } | 668 } |
650 | 669 |
651 void menu_willHighlightItem(int menu, objc.id itemID) { | 670 void menu_willHighlightItem(objc.id id, objc.SEL sel, objc.id menu, objc.id itemID) { |
652 NSInteger jniRef = cast(NSInteger) OS.objc_msgSend(itemID, OS.sel_tag); | 671 Widget widget = display.getWidget(itemID); |
653 if (jniRef !is -1 && jniRef !is 0) { | 672 if (widget instanceof MenuItem) { |
654 Object object = OS.JNIGetObject(jniRef); | 673 MenuItem item = (MenuItem)widget; |
655 if ( null !is cast(MenuItem)object ) { | 674 item.sendEvent (DWT.Arm); |
656 MenuItem item = cast(MenuItem)object; | 675 } |
657 item.sendEvent (DWT.Arm); | 676 } |
677 | |
678 void menuNeedsUpdate(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) { | |
679 //This code is intentionally commented | |
680 //sendEvent (DWT.Show); | |
681 } | |
682 | |
683 void menuWillOpen(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) { | |
684 visible = true; | |
685 sendEvent (DWT.Show); | |
686 for (int i=0; i<items.length; i++) { | |
687 MenuItem item = items [i]; | |
688 if (item !is null) { | |
689 if (item.accelerator is 0) { | |
690 if (item.nsItem.keyEquivalent ().length () !is 0 || item.nsItem.keyEquivalentModifierMask () !is 0) { | |
691 item.nsItem.setHidden (false); | |
692 } | |
693 } | |
658 } | 694 } |
659 } | 695 } |
660 } | 696 } |
661 | 697 |
662 void menuNeedsUpdate(int menu) { | 698 void menuDidClose(int /*long*/ id, int /*long*/ sel, int /*long*/ menu) { |
663 sendEvent (DWT.Show); | |
664 } | |
665 | |
666 void menuWillClose(int menu) { | |
667 sendEvent (DWT.Hide); | 699 sendEvent (DWT.Hide); |
668 } | 700 visible = false; |
669 | 701 for (int i=0; i<items.length; i++) { |
670 void menuWillOpen(int menu) { | 702 MenuItem item = items [i]; |
671 } | 703 if (item !is null) { |
672 | 704 if (item.accelerator is 0) { |
673 int modifierIndex (String accelText) { | 705 if (item.nsItem.keyEquivalent().length () !is 0 || item.nsItem.keyEquivalentModifierMask () !is 0) { |
674 int start = accelText.length () - 1; | 706 item.nsItem.setHidden (true); |
675 int index = start; | 707 } |
676 while (index >= 0) { | 708 } |
677 char c = accelText.charAt (index); | |
678 switch (c) { | |
679 case ' ': | |
680 if (index !is start) return index; | |
681 break; | |
682 case '\u2303': | |
683 case '\u2325': | |
684 case '\u21E7': | |
685 case '\u2318': | |
686 return index; | |
687 } | 709 } |
688 index--; | 710 } |
689 } | 711 } |
690 return -1; | 712 |
691 } | 713 void register () { |
692 | 714 super.register (); |
693 int numberOfItemsInMenu(int menu) { | 715 display.addWidget (nsMenu, this); |
694 System.Out.println("numver"); | |
695 return 4; | |
696 } | 716 } |
697 | 717 |
698 void releaseChildren (bool destroy) { | 718 void releaseChildren (bool destroy) { |
699 if (items !is null) { | 719 if (items !is null) { |
700 for (int i=0; i<items.length; i++) { | 720 for (int i=0; i<items.length; i++) { |
721 } | 741 } |
722 } | 742 } |
723 | 743 |
724 void releaseWidget () { | 744 void releaseWidget () { |
725 super.releaseWidget (); | 745 super.releaseWidget (); |
726 // display.removeMenu (this); | 746 display.removeMenu (this); |
727 parent = null; | 747 parent = null; |
728 cascade = defaultItem = lastTarget = null; | 748 cascade = defaultItem = null; |
729 } | 749 } |
730 | 750 |
731 /** | 751 /** |
732 * Removes the listener from the collection of listeners who will | 752 * Removes the listener from the collection of listeners who will |
733 * be notified when the help events are generated for the control. | 753 * be notified when the help events are generated for the control. |
812 */ | 832 */ |
813 public void setEnabled (bool enabled) { | 833 public void setEnabled (bool enabled) { |
814 checkWidget(); | 834 checkWidget(); |
815 if (enabled) { | 835 if (enabled) { |
816 state &= ~DISABLED; | 836 state &= ~DISABLED; |
817 //OS.EnableMenuItem (handle, cast(short)0); | |
818 } else { | 837 } else { |
819 state |= DISABLED; | 838 state |= DISABLED; |
820 //OS.DisableMenuItem (handle, cast(short)0); | 839 } |
840 //TODO - find a way to disable the menu instead of each item | |
841 for (int i=0; i<items.length; i++) { | |
842 MenuItem item = items [i]; | |
843 if (item !is null) { | |
844 /* | |
845 * Feature in the Macintosh. When a cascade menu | |
846 * item is disabled, rather than disabling the item, | |
847 * the submenu is disabled. | |
848 * | |
849 * There is no fix for this at this time. | |
850 */ | |
851 item.nsItem.setEnabled (enabled && item.getEnabled ()); | |
852 } | |
821 } | 853 } |
822 } | 854 } |
823 | 855 |
824 /** | 856 /** |
825 * Sets the location of the receiver, which must be a popup, | 857 * Sets the location of the receiver, which must be a popup, |
896 */ | 928 */ |
897 public void setVisible (bool visible) { | 929 public void setVisible (bool visible) { |
898 checkWidget (); | 930 checkWidget (); |
899 if ((style & (DWT.BAR | DWT.DROP_DOWN)) !is 0) return; | 931 if ((style & (DWT.BAR | DWT.DROP_DOWN)) !is 0) return; |
900 if (visible) { | 932 if (visible) { |
901 // display.addPopup (this); | 933 display.addPopup (this); |
902 //TODO -WRONG | |
903 _setVisible (true); | |
904 } else { | 934 } else { |
905 // display.removePopup (this); | 935 display.removePopup (this); |
906 _setVisible (false); | |
907 } | 936 } |
908 } | 937 } |
909 | 938 |
910 } | 939 } |