]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/menuitem.mm
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / osx / cocoa / menuitem.mm
CommitLineData
dbeddfb9
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/cocoa/menuitem.mm
3// Purpose: wxMenuItem implementation
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
dbeddfb9
SC
7// Copyright: (c) Stefan Csomor
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#include "wx/menuitem.h"
14#include "wx/stockitem.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/app.h"
70412bd4 18 #include "wx/log.h"
dbeddfb9
SC
19 #include "wx/menu.h"
20#endif // WX_PRECOMP
21
22#include "wx/osx/private.h"
23
fbbe829a
SC
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
26
27struct Mapping
28{
29 int menuid;
30 SEL action;
31};
32
33Mapping sActionToWXMapping[] =
34{
0068a2c4
SC
35// as we don't have NSUndoManager support we must not use the native actions
36#if 0
2daf63c4
SC
37 { wxID_UNDO, @selector(undo:) },
38 { wxID_REDO, @selector(redo:) },
0068a2c4 39#endif
2daf63c4
SC
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:) },
45 { 0, NULL }
fbbe829a
SC
46};
47
48int wxOSXGetIdFromSelector(SEL action )
49{
50 int i = 0 ;
51 while ( sActionToWXMapping[i].action != nil )
52 {
53 if ( sActionToWXMapping[i].action == action )
54 return sActionToWXMapping[i].menuid;
55 ++i;
56 }
57
58 return 0;
59}
60
61SEL wxOSXGetSelectorFromID(int menuId )
62{
63 int i = 0 ;
64 while ( sActionToWXMapping[i].action != nil )
65 {
66 if ( sActionToWXMapping[i].menuid == menuId )
67 return sActionToWXMapping[i].action;
68 ++i;
69 }
70
71 return nil;
72}
73
74
dbeddfb9
SC
75@implementation wxNSMenuItem
76
fbbe829a 77- (id) initWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)charCode
dbeddfb9 78{
a985b2c8
SC
79 self = [super initWithTitle:aString action:aSelector keyEquivalent:charCode];
80 return self;
dbeddfb9
SC
81}
82
83- (void) clickedAction: (id) sender
84{
d8207702 85 wxUnusedVar(sender);
dbeddfb9
SC
86 if ( impl )
87 {
c46d0503
SC
88 wxMenuItem* menuitem = impl->GetWXPeer();
89 if ( menuitem->GetMenu()->HandleCommandProcess(menuitem) == false )
90 {
91 }
dbeddfb9
SC
92 }
93}
94
fbbe829a
SC
95- (void) setEnabled:(BOOL) flag
96{
97 [super setEnabled:flag];
98}
99
dbeddfb9
SC
100- (BOOL)validateMenuItem:(NSMenuItem *) menuItem
101{
d8207702 102 wxUnusedVar(menuItem);
dbeddfb9
SC
103 if( impl )
104 {
40a35c1f
SC
105 wxMenuItem* wxmenuitem = impl->GetWXPeer();
106 if ( wxmenuitem )
107 {
108 wxmenuitem->GetMenu()->HandleCommandUpdateStatus(wxmenuitem);
109 return wxmenuitem->IsEnabled();
110 }
dbeddfb9
SC
111 }
112 return YES ;
113}
114
115- (void)setImplementation: (wxMenuItemImpl *) theImplementation
116{
117 impl = theImplementation;
118}
119
120- (wxMenuItemImpl*) implementation
121{
122 return impl;
123}
124
125@end
126
127void wxMacCocoaMenuItemSetAccelerator( NSMenuItem* menuItem, wxAcceleratorEntry* entry )
128{
40a35c1f
SC
129 if ( entry == NULL )
130 {
131 [menuItem setKeyEquivalent:@""];
132 return;
133 }
134
dbeddfb9
SC
135 unsigned int modifiers = 0 ;
136 int key = entry->GetKeyCode() ;
137 if ( key )
138 {
fa6ff5f1 139 if (entry->GetFlags() & wxACCEL_CTRL)
dbeddfb9
SC
140 modifiers |= NSCommandKeyMask;
141
3c5f6264
SC
142 if (entry->GetFlags() & wxACCEL_RAW_CTRL)
143 modifiers |= NSControlKeyMask;
144
dbeddfb9
SC
145 if (entry->GetFlags() & wxACCEL_ALT)
146 modifiers |= NSAlternateKeyMask ;
147
148 // this may be ignored later for alpha chars
149
150 if (entry->GetFlags() & wxACCEL_SHIFT)
151 modifiers |= NSShiftKeyMask ;
152
153 unichar shortcut = 0;
154 if ( key >= WXK_F1 && key <= WXK_F15 )
155 {
156 modifiers |= NSFunctionKeyMask ;
157 shortcut = NSF1FunctionKey + ( key - WXK_F1 );
158 }
159 else
160 {
161 switch ( key )
162 {
dbeddfb9 163 case WXK_CLEAR :
9c894932
SC
164 modifiers |= NSFunctionKeyMask;
165 shortcut = NSDeleteCharacter ;
dbeddfb9
SC
166 break ;
167
168 case WXK_PAGEUP :
9c894932
SC
169 modifiers |= NSFunctionKeyMask;
170 shortcut = NSPageUpFunctionKey ;
dbeddfb9
SC
171 break ;
172
173 case WXK_PAGEDOWN :
9c894932
SC
174 modifiers |= NSFunctionKeyMask;
175 shortcut = NSPageDownFunctionKey ;
dbeddfb9
SC
176 break ;
177
178 case WXK_LEFT :
9c894932
SC
179 modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
180 shortcut = NSLeftArrowFunctionKey ;
dbeddfb9
SC
181 break ;
182
183 case WXK_UP :
9c894932
SC
184 modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
185 shortcut = NSUpArrowFunctionKey ;
dbeddfb9
SC
186 break ;
187
188 case WXK_RIGHT :
9c894932
SC
189 modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
190 shortcut = NSRightArrowFunctionKey ;
dbeddfb9
SC
191 break ;
192
193 case WXK_DOWN :
9c894932
SC
194 modifiers |= NSNumericPadKeyMask | NSFunctionKeyMask;
195 shortcut = NSDownArrowFunctionKey ;
dbeddfb9
SC
196 break ;
197
198 case WXK_HOME :
9c894932
SC
199 modifiers |= NSFunctionKeyMask;
200 shortcut = NSHomeFunctionKey ;
dbeddfb9
SC
201 break ;
202
203 case WXK_END :
9c894932
SC
204 modifiers |= NSFunctionKeyMask;
205 shortcut = NSEndFunctionKey ;
dbeddfb9 206 break ;
9c894932
SC
207
208 case WXK_NUMPAD_ENTER :
209 shortcut = NSEnterCharacter;
210 break;
211
212 case WXK_BACK :
213 case WXK_RETURN :
214 case WXK_TAB :
215 case WXK_ESCAPE :
dbeddfb9
SC
216 default :
217 if(entry->GetFlags() & wxACCEL_SHIFT)
218 shortcut = toupper(key);
219 else
220 shortcut = tolower(key);
221 break ;
222 }
223 }
224
225 [menuItem setKeyEquivalent:[NSString stringWithCharacters:&shortcut length:1]];
226 [menuItem setKeyEquivalentModifierMask:modifiers];
227 }
228}
229
9c894932
SC
230@interface NSMenuItem(PossibleMethods)
231- (void)setHidden:(BOOL)hidden;
232@end
233
03647350 234class wxMenuItemCocoaImpl : public wxMenuItemImpl
dbeddfb9
SC
235{
236public :
237 wxMenuItemCocoaImpl( wxMenuItem* peer, NSMenuItem* item ) : wxMenuItemImpl(peer), m_osxMenuItem(item)
238 {
be136f07
SC
239 if ( ![m_osxMenuItem isSeparatorItem] )
240 [(wxNSMenuItem*)m_osxMenuItem setImplementation:this];
dbeddfb9 241 }
03647350 242
dbeddfb9 243 ~wxMenuItemCocoaImpl();
03647350
VZ
244
245 void SetBitmap( const wxBitmap& bitmap )
dbeddfb9
SC
246 {
247 [m_osxMenuItem setImage:bitmap.GetNSImage()];
248 }
03647350
VZ
249
250 void Enable( bool enable )
dbeddfb9
SC
251 {
252 [m_osxMenuItem setEnabled:enable];
253 }
03647350
VZ
254
255 void Check( bool check )
dbeddfb9
SC
256 {
257 [m_osxMenuItem setState:( check ? NSOnState : NSOffState) ];
258 }
03647350 259
dbeddfb9
SC
260 void Hide( bool hide )
261 {
70412bd4
KO
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 ];
265 else
266 wxLogDebug("wxMenuItemCocoaImpl::Hide not yet supported under OS X < 10.5");
dbeddfb9 267 }
03647350
VZ
268
269 void SetLabel( const wxString& text, wxAcceleratorEntry *entry )
dbeddfb9
SC
270 {
271 wxCFStringRef cfText(text);
272 [m_osxMenuItem setTitle:cfText.AsNSString()];
03647350 273
40a35c1f 274 wxMacCocoaMenuItemSetAccelerator( m_osxMenuItem, entry );
dbeddfb9 275 }
c46d0503
SC
276
277 bool DoDefault();
03647350 278
dbeddfb9
SC
279 void * GetHMenuItem() { return m_osxMenuItem; }
280
281protected :
282 NSMenuItem* m_osxMenuItem ;
283} ;
284
285wxMenuItemCocoaImpl::~wxMenuItemCocoaImpl()
286{
be136f07
SC
287 if ( ![m_osxMenuItem isSeparatorItem] )
288 [(wxNSMenuItem*)m_osxMenuItem setImplementation:nil];
3c9413b7 289 [m_osxMenuItem release];
dbeddfb9
SC
290}
291
c46d0503
SC
292bool wxMenuItemCocoaImpl::DoDefault()
293{
294 bool handled=false;
295 int menuid = m_peer->GetId();
296
297 NSApplication *theNSApplication = [NSApplication sharedApplication];
298 if (menuid == wxID_OSX_HIDE)
299 {
300 [theNSApplication hide:nil];
301 handled=true;
302 }
303 else if (menuid == wxID_OSX_HIDEOTHERS)
304 {
305 [theNSApplication hideOtherApplications:nil];
306 handled=true;
307 }
308 else if (menuid == wxID_OSX_SHOWALL)
309 {
310 [theNSApplication unhideAllApplications:nil];
311 handled=true;
312 }
846c6043
SC
313 else if (menuid == wxApp::s_macExitMenuItemId)
314 {
315 wxTheApp->ExitMainLoop();
316 }
c46d0503
SC
317 return handled;
318}
dbeddfb9
SC
319
320wxMenuItemImpl* wxMenuItemImpl::Create( wxMenuItem* peer, wxMenu *pParentMenu,
fbbe829a 321 int menuid,
dbeddfb9
SC
322 const wxString& text,
323 wxAcceleratorEntry *entry,
d8207702 324 const wxString& WXUNUSED(strHelp),
dbeddfb9
SC
325 wxItemKind kind,
326 wxMenu *pSubMenu )
327{
328 wxMenuItemImpl* c = NULL;
329 NSMenuItem* item = nil;
03647350 330
dbeddfb9
SC
331 if ( kind == wxITEM_SEPARATOR )
332 {
333 item = [[NSMenuItem separatorItem] retain];
334 }
335 else
336 {
337 wxCFStringRef cfText(text);
fbbe829a
SC
338 SEL selector = nil;
339 bool targetSelf = false;
e3288469 340 if ( (pParentMenu == NULL || !pParentMenu->GetNoEventsMode()) && pSubMenu == NULL )
dbeddfb9 341 {
fbbe829a
SC
342 selector = wxOSXGetSelectorFromID(menuid);
343
344 if ( selector == nil )
345 {
346 selector = @selector(clickedAction:);
347 targetSelf = true;
348 }
dbeddfb9 349 }
fbbe829a
SC
350
351 wxNSMenuItem* menuitem = [ [ wxNSMenuItem alloc ] initWithTitle:cfText.AsNSString() action:selector keyEquivalent:@""];
352 if ( targetSelf )
353 [menuitem setTarget:menuitem];
354
dbeddfb9
SC
355 if ( pSubMenu )
356 {
357 pSubMenu->GetPeer()->SetTitle( text );
fbbe829a 358 [menuitem setSubmenu:pSubMenu->GetHMenu()];
dbeddfb9
SC
359 }
360 else
361 {
40a35c1f 362 wxMacCocoaMenuItemSetAccelerator( menuitem, entry );
dbeddfb9 363 }
fbbe829a 364 item = menuitem;
dbeddfb9
SC
365 }
366 c = new wxMenuItemCocoaImpl( peer, item );
dbeddfb9
SC
367 return c;
368}