1 ///////////////////////////////////////////////////////////////////////////////
 
   2 // Name:        src/osx/cocoa/menuitem.mm
 
   3 // Purpose:     wxMenuItem implementation
 
   4 // Author:      Stefan Csomor
 
   7 // Copyright:   (c) Stefan Csomor
 
   8 // Licence:     wxWindows licence
 
   9 ///////////////////////////////////////////////////////////////////////////////
 
  11 #include "wx/wxprec.h"
 
  13 #include "wx/menuitem.h"
 
  14 #include "wx/stockitem.h"
 
  22 #include "wx/osx/private.h"
 
  24 // a mapping from wx ids to standard osx actions in order to support the native menu item handling
 
  25 // if a new mapping is added, make sure the wxNonOwnedWindowController has a handler for this action as well
 
  33 Mapping sActionToWXMapping[] =
 
  35 // as we don't have NSUndoManager support we must not use the native actions
 
  37     { wxID_UNDO, @selector(undo:) },
 
  38     { wxID_REDO, @selector(redo:) },
 
  40     { wxID_CUT, @selector(cut:) },
 
  41     { wxID_COPY, @selector(copy:) },
 
  42     { wxID_PASTE, @selector(paste:) },
 
  43     { wxID_CLEAR, @selector(delete:) },
 
  44     { wxID_SELECTALL, @selector(selectAll:) },
 
  48 int wxOSXGetIdFromSelector(SEL action )
 
  51     while ( sActionToWXMapping[i].action != nil )
 
  53         if ( sActionToWXMapping[i].action == action )
 
  54             return sActionToWXMapping[i].menuid;
 
  61 SEL wxOSXGetSelectorFromID(int menuId )
 
  64     while ( sActionToWXMapping[i].action != nil )
 
  66         if ( sActionToWXMapping[i].menuid == menuId )
 
  67             return sActionToWXMapping[i].action;
 
  75 @implementation wxNSMenuItem
 
  77 - (id) initWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)charCode
 
  79     self = [super initWithTitle:aString action:aSelector keyEquivalent:charCode];
 
  83 - (void) clickedAction: (id) sender
 
  88         wxMenuItem* menuitem = impl->GetWXPeer();
 
  89         if ( menuitem->GetMenu()->HandleCommandProcess(menuitem) == false )
 
  95 - (void) setEnabled:(BOOL) flag
 
  97     [super setEnabled:flag];
 
 100 - (BOOL)validateMenuItem:(NSMenuItem *) menuItem
 
 102     wxUnusedVar(menuItem);
 
 105         wxMenuItem* wxmenuitem = impl->GetWXPeer();
 
 108             wxmenuitem->GetMenu()->HandleCommandUpdateStatus(wxmenuitem);
 
 109             return wxmenuitem->IsEnabled();
 
 115 - (void)setImplementation: (wxMenuItemImpl *) theImplementation
 
 117     impl = theImplementation;
 
 120 - (wxMenuItemImpl*) implementation
 
 127 void wxMacCocoaMenuItemSetAccelerator( NSMenuItem* menuItem, wxAcceleratorEntry* entry )
 
 131         [menuItem setKeyEquivalent:@""];
 
 135     unsigned int modifiers = 0 ;
 
 136     int key = entry->GetKeyCode() ;
 
 139         if (entry->GetFlags() & wxACCEL_CTRL)
 
 140             modifiers |= NSCommandKeyMask;
 
 142         if (entry->GetFlags() & wxACCEL_RAW_CTRL)
 
 143             modifiers |= NSControlKeyMask;
 
 145         if (entry->GetFlags() & wxACCEL_ALT)
 
 146             modifiers |= NSAlternateKeyMask ;
 
 148         // this may be ignored later for alpha chars
 
 150         if (entry->GetFlags() & wxACCEL_SHIFT)
 
 151             modifiers |= NSShiftKeyMask ;
 
 153         unichar shortcut = 0;
 
 154         if ( key >= WXK_F1 && key <= WXK_F15 )
 
 156             modifiers |= NSFunctionKeyMask ;
 
 157             shortcut = NSF1FunctionKey + ( key - WXK_F1 );
 
 164                     modifiers |= NSFunctionKeyMask;
 
 165                     shortcut = NSDeleteCharacter ;
 
 169                     modifiers |= NSFunctionKeyMask;
 
 170                     shortcut = NSPageUpFunctionKey ;
 
 174                     modifiers |= NSFunctionKeyMask;
 
 175                     shortcut = NSPageDownFunctionKey ;
 
 179                     modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
 
 180                     shortcut = NSLeftArrowFunctionKey ;
 
 184                     modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
 
 185                     shortcut = NSUpArrowFunctionKey ;
 
 189                     modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
 
 190                     shortcut = NSRightArrowFunctionKey ;
 
 194                     modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
 
 195                     shortcut = NSDownArrowFunctionKey ;
 
 199                     modifiers |= NSFunctionKeyMask;
 
 200                     shortcut = NSHomeFunctionKey ;
 
 204                     modifiers |= NSFunctionKeyMask;
 
 205                     shortcut = NSEndFunctionKey ;
 
 208                 case WXK_NUMPAD_ENTER :
 
 209                     shortcut = NSEnterCharacter;
 
 217                     if(entry->GetFlags() & wxACCEL_SHIFT)
 
 218                         shortcut = toupper(key);
 
 220                         shortcut = tolower(key);
 
 225         [menuItem setKeyEquivalent:[NSString stringWithCharacters:&shortcut length:1]];
 
 226         [menuItem setKeyEquivalentModifierMask:modifiers];
 
 230 @interface NSMenuItem(PossibleMethods)
 
 231 - (void)setHidden:(BOOL)hidden;
 
 234 class wxMenuItemCocoaImpl : public wxMenuItemImpl
 
 237     wxMenuItemCocoaImpl( wxMenuItem* peer, NSMenuItem* item ) : wxMenuItemImpl(peer), m_osxMenuItem(item)
 
 239         if ( ![m_osxMenuItem isSeparatorItem] )
 
 240             [(wxNSMenuItem*)m_osxMenuItem setImplementation:this];
 
 243     ~wxMenuItemCocoaImpl();
 
 245     void SetBitmap( const wxBitmap& bitmap )
 
 247         [m_osxMenuItem setImage:bitmap.GetNSImage()];
 
 250     void Enable( bool enable )
 
 252         [m_osxMenuItem setEnabled:enable];
 
 255     void Check( bool check )
 
 257         [m_osxMenuItem setState:( check ?  NSOnState :  NSOffState) ];
 
 260     void Hide( bool hide )
 
 262         // NB: setHidden is new as of 10.5 so we should not call it below there
 
 263         if ([m_osxMenuItem respondsToSelector:@selector(setHidden:)])
 
 264             [m_osxMenuItem setHidden:hide ];
 
 266             wxLogDebug("wxMenuItemCocoaImpl::Hide not yet supported under OS X < 10.5");
 
 269     void SetLabel( const wxString& text, wxAcceleratorEntry *entry )
 
 271         wxCFStringRef cfText(text);
 
 272         [m_osxMenuItem setTitle:cfText.AsNSString()];
 
 274         wxMacCocoaMenuItemSetAccelerator( m_osxMenuItem, entry );
 
 279     void * GetHMenuItem() { return m_osxMenuItem; }
 
 282     NSMenuItem* m_osxMenuItem ;
 
 285 wxMenuItemCocoaImpl::~wxMenuItemCocoaImpl()
 
 287     if ( ![m_osxMenuItem isSeparatorItem] )
 
 288         [(wxNSMenuItem*)m_osxMenuItem setImplementation:nil];
 
 289     [m_osxMenuItem release];
 
 292 bool wxMenuItemCocoaImpl::DoDefault()
 
 295     int menuid = m_peer->GetId();
 
 297     NSApplication *theNSApplication = [NSApplication sharedApplication];
 
 298     if (menuid == wxID_OSX_HIDE)
 
 300         [theNSApplication hide:nil];
 
 303     else if (menuid == wxID_OSX_HIDEOTHERS)
 
 305         [theNSApplication hideOtherApplications:nil];
 
 308     else if (menuid == wxID_OSX_SHOWALL)
 
 310         [theNSApplication unhideAllApplications:nil];
 
 313     else if (menuid == wxApp::s_macExitMenuItemId)
 
 315         wxTheApp->ExitMainLoop();
 
 320 wxMenuItemImpl* wxMenuItemImpl::Create( wxMenuItem* peer, wxMenu *pParentMenu,
 
 322                        const wxString& text,
 
 323                        wxAcceleratorEntry *entry,
 
 324                        const wxString& WXUNUSED(strHelp),
 
 328     wxMenuItemImpl* c = NULL;
 
 329     NSMenuItem* item = nil;
 
 331     if ( kind == wxITEM_SEPARATOR )
 
 333         item = [[NSMenuItem separatorItem] retain];
 
 337         wxCFStringRef cfText(text);
 
 339         bool targetSelf = false;
 
 340         if ( (pParentMenu == NULL || !pParentMenu->GetNoEventsMode()) && pSubMenu == NULL )
 
 342             selector = wxOSXGetSelectorFromID(menuid);
 
 344             if ( selector == nil )
 
 346                 selector = @selector(clickedAction:);
 
 351         wxNSMenuItem* menuitem = [ [ wxNSMenuItem alloc ] initWithTitle:cfText.AsNSString() action:selector keyEquivalent:@""];
 
 353             [menuitem setTarget:menuitem];
 
 357             pSubMenu->GetPeer()->SetTitle( text );
 
 358             [menuitem setSubmenu:pSubMenu->GetHMenu()];
 
 362             wxMacCocoaMenuItemSetAccelerator( menuitem, entry );
 
 366     c = new wxMenuItemCocoaImpl( peer, item );