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 );