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