comparison dwt/widgets/MenuItem.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 4444d15131d5
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.MenuItem; 14 module dwt.widgets.MenuItem;
15 15
16 16
17 import dwt.DWT; 17 import dwt.DWT;
18 import dwt.DWTException; 18 import dwt.DWTException;
19 import dwt.events.ArmListener; 19 import dwt.events.ArmListener;
20 import dwt.events.HelpListener; 20 import dwt.events.HelpListener;
21 import dwt.events.SelectionEvent; 21 import dwt.events.SelectionEvent;
22 import dwt.events.SelectionListener; 22 import dwt.events.SelectionListener;
23 import dwt.graphics.Image; 23 import dwt.graphics.Image;
24 import dwt.internal.cocoa.NSApplication;
25 import dwt.internal.cocoa.NSEvent;
24 import dwt.internal.cocoa.NSMenu; 26 import dwt.internal.cocoa.NSMenu;
25 import dwt.internal.cocoa.NSMenuItem; 27 import dwt.internal.cocoa.NSMenuItem;
26 import dwt.internal.cocoa.NSString; 28 import dwt.internal.cocoa.NSString;
27 import dwt.internal.cocoa.OS; 29 import dwt.internal.cocoa.OS;
28 import dwt.internal.cocoa.SWTMenu; 30 import dwt.internal.cocoa.SWTMenu;
49 * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR 51 * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
50 * may be specified. 52 * may be specified.
51 * </p><p> 53 * </p><p>
52 * IMPORTANT: This class is <em>not</em> intended to be subclassed. 54 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
53 * </p> 55 * </p>
56 *
57 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
54 */ 58 */
55 public class MenuItem : Item { 59 public class MenuItem : Item {
56 NSMenuItem nsItem; 60 NSMenuItem nsItem;
57 Menu parent, menu; 61 Menu parent, menu;
58 int accelerator; 62 int accelerator;
59 // int x, y, width, height;
60 63
61 /** 64 /**
62 * Constructs a new instance of this class given its parent 65 * Constructs a new instance of this class given its parent
63 * (which must be a <code>Menu</code>) and a style value 66 * (which must be a <code>Menu</code>) and a style value
64 * describing its behavior and appearance. The item is added 67 * describing its behavior and appearance. The item is added
237 return cast(NSMenu) (new SWTMenu ()).alloc ().init (); 240 return cast(NSMenu) (new SWTMenu ()).alloc ().init ();
238 } 241 }
239 return null; 242 return null;
240 } 243 }
241 244
245 void deregister () {
246 super.deregister ();
247 display.removeWidget (nsItem);
248 }
249
242 void destroyWidget () { 250 void destroyWidget () {
243 parent.destroyItem (this); 251 parent.destroyItem (this);
244 releaseHandle (); 252 releaseHandle ();
245 } 253 }
246 254
338 * </ul> 346 * </ul>
339 */ 347 */
340 public bool getSelection () { 348 public bool getSelection () {
341 checkWidget (); 349 checkWidget ();
342 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return false; 350 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return false;
343 return (cast(NSMenuItem)nsItem).state() is OS.NSOnState; 351 return nsItem.state() is OS.NSOnState;
344 } 352 }
345
346 //int kEventProcessCommand (int nextHandler, int theEvent, int userData) {
347 // //TEMPORARY CODE
348 // if (!isEnabled ()) return OS.noErr;
349 //
350 // if ((style & DWT.CHECK) !is 0) {
351 // setSelection (!getSelection ());
352 // } else {
353 // if ((style & DWT.RADIO) !is 0) {
354 // if ((parent.getStyle () & DWT.NO_RADIO_GROUP) !is 0) {
355 // setSelection (!getSelection ());
356 // } else {
357 // selectRadio ();
358 // }
359 // }
360 // }
361 // int [] modifiers = new int [1];
362 // OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
363 // Event event = new Event ();
364 // setInputState (event, cast(short) 0, OS.GetCurrentEventButtonState (), modifiers [0]);
365 // postEvent (DWT.Selection, event);
366 // return OS.noErr;
367 //}
368 353
369 /** 354 /**
370 * Returns <code>true</code> if the receiver is enabled and all 355 * Returns <code>true</code> if the receiver is enabled and all
371 * of the receiver's ancestors are enabled, and <code>false</code> 356 * of the receiver's ancestors are enabled, and <code>false</code>
372 * otherwise. A disabled menu item is typically not selectable from the 357 * otherwise. A disabled menu item is typically not selectable from the
383 */ 368 */
384 public bool isEnabled () { 369 public bool isEnabled () {
385 return getEnabled () && parent.isEnabled (); 370 return getEnabled () && parent.isEnabled ();
386 } 371 }
387 372
388 //int keyGlyph (int key) { 373 int keyChar (int key) {
389 // switch (key) { 374 //TODO - use the NS key constants
390 // case DWT.BS: return OS.kMenuDeleteLeftGlyph; 375 switch (key) {
391 // case DWT.CR: return OS.kMenuReturnGlyph; 376 case DWT.BS: return OS.NSBackspaceCharacter;
392 // case DWT.DEL: return OS.kMenuDeleteRightGlyph; 377 case DWT.CR: return OS.NSCarriageReturnCharacter;
393 // case DWT.ESC: return OS.kMenuEscapeGlyph; 378 case DWT.DEL: return OS.NSDeleteCharacter;
394 // case DWT.LF: return OS.kMenuReturnGlyph; 379 case DWT.ESC: return DWT.ESC;
395 // case DWT.TAB: return OS.kMenuTabRightGlyph; 380 case DWT.LF: return OS.NSNewlineCharacter;
381 case DWT.TAB: return OS.NSTabCharacter;
396 // case ' ': return OS.kMenuBlankGlyph; 382 // case ' ': return OS.kMenuBlankGlyph;
397 //// case ' ': return OS.kMenuSpaceGlyph; 383 // case ' ': return OS.kMenuSpaceGlyph;
398 // case DWT.ALT: return OS.kMenuOptionGlyph; 384 case DWT.ALT: return 0x2325;
399 // case DWT.SHIFT: return OS.kMenuShiftGlyph; 385 case DWT.SHIFT: return 0x21E7;
400 // case DWT.CONTROL: return OS.kMenuControlISOGlyph; 386 case DWT.CONTROL: return 0xF2303;
401 // case DWT.COMMAND: return OS.kMenuCommandGlyph; 387 case DWT.COMMAND: return 0x2318;
402 // case DWT.ARROW_UP: return OS.kMenuUpArrowGlyph; 388 case DWT.ARROW_UP: return 0x2191;
403 // case DWT.ARROW_DOWN: return OS.kMenuDownArrowGlyph; 389 case DWT.ARROW_DOWN: return 0x2193;
404 // case DWT.ARROW_LEFT: return OS.kMenuLeftArrowGlyph; 390 case DWT.ARROW_LEFT: return 0x2190;
405 // case DWT.ARROW_RIGHT: return OS.kMenuRightArrowGlyph; 391 case DWT.ARROW_RIGHT: return 0x2192;
406 // case DWT.PAGE_UP: return OS.kMenuPageUpGlyph; 392 case DWT.PAGE_UP: return 0x21DE;
407 // case DWT.PAGE_DOWN: return OS.kMenuPageDownGlyph; 393 case DWT.PAGE_DOWN: return 0x21DF;
408 // case DWT.F1: return OS.kMenuF1Glyph; 394 case DWT.KEYPAD_CR: return OS.NSEnterCharacter;
409 // case DWT.F2: return OS.kMenuF2Glyph; 395 case DWT.HELP: return OS.NSHelpFunctionKey;
410 // case DWT.F3: return OS.kMenuF3Glyph; 396 case DWT.HOME: return 0xF729;
411 // case DWT.F4: return OS.kMenuF4Glyph; 397 case DWT.END: return 0xF72B;
412 // case DWT.F5: return OS.kMenuF5Glyph; 398 // case DWT.CAPS_LOCK: return ??;
413 // case DWT.F6: return OS.kMenuF6Glyph; 399 case DWT.F1: return 0xF704;
414 // case DWT.F7: return OS.kMenuF7Glyph; 400 case DWT.F2: return 0xF705;
415 // case DWT.F8: return OS.kMenuF8Glyph; 401 case DWT.F3: return 0xF706;
416 // case DWT.F9: return OS.kMenuF9Glyph; 402 case DWT.F4: return 0xF707;
417 // case DWT.F10: return OS.kMenuF10Glyph; 403 case DWT.F5: return 0xF708;
418 // case DWT.F11: return OS.kMenuF11Glyph; 404 case DWT.F6: return 0xF709;
419 // case DWT.F12: return OS.kMenuF12Glyph; 405 case DWT.F7: return 0xF70A;
420 // } 406 case DWT.F8: return 0xF70B;
421 // return OS.kMenuNullGlyph; 407 case DWT.F9: return 0xF70C;
422 //} 408 case DWT.F10: return 0xF70D;
409 case DWT.F11: return 0xF70E;
410 case DWT.F12: return 0xF70F;
411 case DWT.F13: return 0xF710;
412 case DWT.F14: return 0xF711;
413 case DWT.F15: return 0xF712;
414 /*
415 * The following lines are intentionally commented.
416 */
417 // case DWT.INSERT: return ??;
418 }
419 return 0;
420 }
421
422
423 void register () {
424 super.register ();
425 display.addWidget (nsItem, this);
426 }
423 427
424 void releaseHandle () { 428 void releaseHandle () {
425 super.releaseHandle (); 429 super.releaseHandle ();
426 if (nsItem !is null) nsItem.release(); 430 if (nsItem !is null) nsItem.release();
427 nsItem = null; 431 nsItem = null;
537 selectRadio (); 541 selectRadio ();
538 } 542 }
539 } 543 }
540 } 544 }
541 Event event = new Event (); 545 Event event = new Event ();
542 //TODO state mask 546 NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent ();
543 // setInputState (event, cast(short) 0, OS.GetCurrentEventButtonState (), modifiers [0]); 547 if (nsEvent !is null) setInputState (event, nsEvent, 0);
544 postEvent (DWT.Selection, event); 548 postEvent (DWT.Selection, event);
545 } 549 }
546 550
547 /** 551 /**
548 * Sets the widget accelerator. An accelerator is the bit-wise 552 * Sets the widget accelerator. An accelerator is the bit-wise
560 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 564 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
561 * </ul> 565 * </ul>
562 */ 566 */
563 public void setAccelerator (int accelerator) { 567 public void setAccelerator (int accelerator) {
564 checkWidget (); 568 checkWidget ();
569 if (this.accelerator is accelerator) return;
565 this.accelerator = accelerator; 570 this.accelerator = accelerator;
566 int key = accelerator & DWT.KEY_MASK; 571 int key = accelerator & DWT.KEY_MASK;
567 int virtualKey = Display.untranslateKey (key); 572 int virtualKey = keyChar (key);
568 NSString str = null; 573 NSString str = null;
569 if (virtualKey !is 0) { 574 if (virtualKey !is 0) {
570 str = NSString.stringWith (Integer.toString(virtualKey)); 575 str = NSString.stringWith (Integer.toString(virtualKey));
571 } else { 576 } else {
572 str = NSString.stringWith (Integer.toString(key)).lowercaseString(); 577 str = NSString.stringWith (Integer.toString(key));
573 } 578 }
574 nsItem.setKeyEquivalent (str); 579 nsItem.setKeyEquivalent (str.lowercaseString());
575 int mask = 0; 580 int mask = 0;
576 if ((accelerator & DWT.SHIFT) !is 0) mask |= OS.NSShiftKeyMask; 581 if ((accelerator & DWT.SHIFT) !is 0) mask |= OS.NSShiftKeyMask;
577 if ((accelerator & DWT.CONTROL) !is 0) mask |= OS.NSControlKeyMask; 582 if ((accelerator & DWT.CONTROL) !is 0) mask |= OS.NSControlKeyMask;
578 // if ((accelerator & DWT.COMMAND) !is 0) mask &= ~OS.kMenuNoCommandModifier;
579 if ((accelerator & DWT.COMMAND) !is 0) mask |= OS.NSCommandKeyMask; 583 if ((accelerator & DWT.COMMAND) !is 0) mask |= OS.NSCommandKeyMask;
580 if ((accelerator & DWT.ALT) !is 0) mask |= OS.NSAlternateKeyMask; 584 if ((accelerator & DWT.ALT) !is 0) mask |= OS.NSAlternateKeyMask;
581 nsItem.setKeyEquivalentModifierMask (cast(NSUInteger) mask); 585 nsItem.setKeyEquivalentModifierMask (cast(NSUInteger) mask);
586 nsItem.setHidden (false);
582 if ((this.accelerator is 0 && accelerator !is 0) || (this.accelerator !is 0 && accelerator is 0)) { 587 if ((this.accelerator is 0 && accelerator !is 0) || (this.accelerator !is 0 && accelerator is 0)) {
583 updateText (); 588 updateText ();
584 } 589 }
585 } 590 }
586 591
597 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 602 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
598 * </ul> 603 * </ul>
599 */ 604 */
600 public void setEnabled (bool enabled) { 605 public void setEnabled (bool enabled) {
601 checkWidget (); 606 checkWidget ();
602 (cast(NSMenuItem)nsItem).setEnabled(enabled); 607 if (enabled) {
608 state &= ~DISABLED;
609 } else {
610 state |= DISABLED;
611 }
612 nsItem.setEnabled(enabled);
603 } 613 }
604 614
605 /** 615 /**
606 * Sets the image the receiver will display to the argument. 616 * Sets the image the receiver will display to the argument.
607 * <p> 617 * <p>
618 */ 628 */
619 public void setImage (Image image) { 629 public void setImage (Image image) {
620 checkWidget (); 630 checkWidget ();
621 if ((style & DWT.SEPARATOR) !is 0) return; 631 if ((style & DWT.SEPARATOR) !is 0) return;
622 super.setImage (image); 632 super.setImage (image);
623 (cast(NSMenuItem)nsItem).setImage(image !is null? image.handle : null); 633 nsItem.setImage(image !is null? image.handle : null);
624 } 634 }
625 635
626 /** 636 /**
627 * Sets the receiver's pull down menu to the argument. 637 * Sets the receiver's pull down menu to the argument.
628 * Only <code>CASCADE</code> menu items can have a 638 * Only <code>CASCADE</code> menu items can have a
707 * </ul> 717 * </ul>
708 */ 718 */
709 public void setSelection (bool selected) { 719 public void setSelection (bool selected) {
710 checkWidget (); 720 checkWidget ();
711 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return; 721 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return;
712 (cast(NSMenuItem)nsItem).setState(selected ? OS.NSOnState : OS.NSOffState); 722 nsItem.setState(selected ? OS.NSOnState : OS.NSOffState);
713 } 723 }
714 724
715 /** 725 /**
716 * Sets the receiver's text. The string may include 726 * Sets the receiver's text. The string may include
717 * the mnemonic character and accelerator text. 727 * the mnemonic character and accelerator text.
776 if(submenu !is null && (parent.getStyle () & DWT.BAR) !is 0) { 786 if(submenu !is null && (parent.getStyle () & DWT.BAR) !is 0) {
777 submenu.setTitle (label); 787 submenu.setTitle (label);
778 } else { 788 } else {
779 nsItem.setTitle (label); 789 nsItem.setTitle (label);
780 } 790 }
781 } 791 if (accelerator is 0) {
782 792 int mask = 0, key = 0;
783 } 793 if (i < buffer.length && buffer [i] is '\t') {
784 794 for (j = i + 1; j < buffer.length; j++) {
795 switch (buffer [j]) {
796 case '\u2303': mask |= OS.NSControlKeyMask; i++; break;
797 case '\u2325': mask |= OS.NSAlternateKeyMask; i++; break;
798 case '\u21E7': mask |= OS.NSShiftKeyMask; i++; break;
799 case '\u2318': mask |= OS.NSCommandKeyMask; i++; break;
800 default:
801 j = buffer.length;
802 break;
803 }
804 }
805 switch (buffer.length - i - 1) {
806 case 1:
807 key = buffer [i + 1];
808 if (key is 0x2423) key = ' ';
809 break;
810 case 2:
811 if (buffer [i + 1] is 'F') {
812 switch (buffer [i + 2]) {
813 case '1': key = 0xF704; break;
814 case '2': key = 0xF705; break;
815 case '3': key = 0xF706; break;
816 case '4': key = 0xF707; break;
817 case '5': key = 0xF708; break;
818 case '6': key = 0xF709; break;
819 case '7': key = 0xF70A; break;
820 case '8': key = 0xF70B; break;
821 case '9': key = 0xF70C; break;
822 }
823 }
824 break;
825 case 3:
826 if (buffer [i + 1] is 'F' && buffer [i + 2] is '1') {
827 switch (buffer [i + 3]) {
828 case '0': key = 0xF70D; break;
829 case '1': key = 0xF70E; break;
830 case '2': key = 0xF70F; break;
831 case '3': key = 0xF710; break;
832 case '4': key = 0xF711; break;
833 case '5': key = 0xF712; break;
834 }
835 }
836 break;
837 }
838 }
839 NSString string = NSString.stringWith (key is 0 ? "" : (char)key + "");
840 nsItem.setKeyEquivalentModifierMask (mask);
841 nsItem.setKeyEquivalent (string.lowercaseString ());
842 //TODO - only hide when key !is 0 (fix all places)
843 nsItem.setHidden (key !is 0 || mask !is 0);
844 }
845 }
846
847 }
848