Files
wxWidgets/src/osx/cocoa/menuitem.mm
Václav Slavík 6814e0ea4b Don't add NSFunctionKeyMask to NSMenuItem modifiers.
This code probably misunderstood NSEvent documentation, where this mask is
mentioned, but setKeyEquivalentModifierMask: documentation doesn't list it as
allowed. More importantly, it causes "fn" to appear in the menu item and the
accelerator doesn't work.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75276 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-11-23 15:09:51 +00:00

363 lines
9.3 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
// Name: src/osx/cocoa/menuitem.mm
// Purpose: wxMenuItem implementation
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/menuitem.h"
#include "wx/stockitem.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/log.h"
#include "wx/menu.h"
#endif // WX_PRECOMP
#include "wx/osx/private.h"
// a mapping from wx ids to standard osx actions in order to support the native menu item handling
// if a new mapping is added, make sure the wxNonOwnedWindowController has a handler for this action as well
struct Mapping
{
int menuid;
SEL action;
};
Mapping sActionToWXMapping[] =
{
// as we don't have NSUndoManager support we must not use the native actions
#if 0
{ wxID_UNDO, @selector(undo:) },
{ wxID_REDO, @selector(redo:) },
#endif
{ wxID_CUT, @selector(cut:) },
{ wxID_COPY, @selector(copy:) },
{ wxID_PASTE, @selector(paste:) },
{ wxID_CLEAR, @selector(delete:) },
{ wxID_SELECTALL, @selector(selectAll:) },
{ 0, NULL }
};
int wxOSXGetIdFromSelector(SEL action )
{
int i = 0 ;
while ( sActionToWXMapping[i].action != nil )
{
if ( sActionToWXMapping[i].action == action )
return sActionToWXMapping[i].menuid;
++i;
}
return 0;
}
SEL wxOSXGetSelectorFromID(int menuId )
{
int i = 0 ;
while ( sActionToWXMapping[i].action != nil )
{
if ( sActionToWXMapping[i].menuid == menuId )
return sActionToWXMapping[i].action;
++i;
}
return nil;
}
@implementation wxNSMenuItem
- (id) initWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)charCode
{
self = [super initWithTitle:aString action:aSelector keyEquivalent:charCode];
return self;
}
- (void) clickedAction: (id) sender
{
wxUnusedVar(sender);
if ( impl )
{
wxMenuItem* menuitem = impl->GetWXPeer();
if ( menuitem->GetMenu()->HandleCommandProcess(menuitem) == false )
{
}
}
}
- (void) setEnabled:(BOOL) flag
{
[super setEnabled:flag];
}
- (BOOL)validateMenuItem:(NSMenuItem *) menuItem
{
wxUnusedVar(menuItem);
if( impl )
{
wxMenuItem* wxmenuitem = impl->GetWXPeer();
if ( wxmenuitem )
{
wxmenuitem->GetMenu()->HandleCommandUpdateStatus(wxmenuitem);
return wxmenuitem->IsEnabled();
}
}
return YES ;
}
- (void)setImplementation: (wxMenuItemImpl *) theImplementation
{
impl = theImplementation;
}
- (wxMenuItemImpl*) implementation
{
return impl;
}
@end
void wxMacCocoaMenuItemSetAccelerator( NSMenuItem* menuItem, wxAcceleratorEntry* entry )
{
if ( entry == NULL )
{
[menuItem setKeyEquivalent:@""];
return;
}
unsigned int modifiers = 0 ;
int key = entry->GetKeyCode() ;
if ( key )
{
if (entry->GetFlags() & wxACCEL_CTRL)
modifiers |= NSCommandKeyMask;
if (entry->GetFlags() & wxACCEL_RAW_CTRL)
modifiers |= NSControlKeyMask;
if (entry->GetFlags() & wxACCEL_ALT)
modifiers |= NSAlternateKeyMask ;
// this may be ignored later for alpha chars
if (entry->GetFlags() & wxACCEL_SHIFT)
modifiers |= NSShiftKeyMask ;
unichar shortcut = 0;
if ( key >= WXK_F1 && key <= WXK_F15 )
{
shortcut = NSF1FunctionKey + ( key - WXK_F1 );
}
else
{
switch ( key )
{
case WXK_CLEAR :
shortcut = NSDeleteCharacter ;
break ;
case WXK_PAGEUP :
shortcut = NSPageUpFunctionKey ;
break ;
case WXK_PAGEDOWN :
shortcut = NSPageDownFunctionKey ;
break ;
case WXK_LEFT :
modifiers |= NSNumericPadKeyMask;
shortcut = NSLeftArrowFunctionKey ;
break ;
case WXK_UP :
modifiers |= NSNumericPadKeyMask;
shortcut = NSUpArrowFunctionKey ;
break ;
case WXK_RIGHT :
modifiers |= NSNumericPadKeyMask;
shortcut = NSRightArrowFunctionKey ;
break ;
case WXK_DOWN :
modifiers |= NSNumericPadKeyMask;
shortcut = NSDownArrowFunctionKey ;
break ;
case WXK_HOME :
shortcut = NSHomeFunctionKey ;
break ;
case WXK_END :
shortcut = NSEndFunctionKey ;
break ;
case WXK_NUMPAD_ENTER :
shortcut = NSEnterCharacter;
break;
case WXK_BACK :
case WXK_RETURN :
case WXK_TAB :
case WXK_ESCAPE :
default :
if(entry->GetFlags() & wxACCEL_SHIFT)
shortcut = toupper(key);
else
shortcut = tolower(key);
break ;
}
}
[menuItem setKeyEquivalent:[NSString stringWithCharacters:&shortcut length:1]];
[menuItem setKeyEquivalentModifierMask:modifiers];
}
}
@interface NSMenuItem(PossibleMethods)
- (void)setHidden:(BOOL)hidden;
@end
class wxMenuItemCocoaImpl : public wxMenuItemImpl
{
public :
wxMenuItemCocoaImpl( wxMenuItem* peer, NSMenuItem* item ) : wxMenuItemImpl(peer), m_osxMenuItem(item)
{
if ( ![m_osxMenuItem isSeparatorItem] )
[(wxNSMenuItem*)m_osxMenuItem setImplementation:this];
}
~wxMenuItemCocoaImpl();
void SetBitmap( const wxBitmap& bitmap )
{
[m_osxMenuItem setImage:bitmap.GetNSImage()];
}
void Enable( bool enable )
{
[m_osxMenuItem setEnabled:enable];
}
void Check( bool check )
{
[m_osxMenuItem setState:( check ? NSOnState : NSOffState) ];
}
void Hide( bool hide )
{
// NB: setHidden is new as of 10.5 so we should not call it below there
if ([m_osxMenuItem respondsToSelector:@selector(setHidden:)])
[m_osxMenuItem setHidden:hide ];
else
wxLogDebug("wxMenuItemCocoaImpl::Hide not yet supported under OS X < 10.5");
}
void SetLabel( const wxString& text, wxAcceleratorEntry *entry )
{
wxCFStringRef cfText(text);
[m_osxMenuItem setTitle:cfText.AsNSString()];
wxMacCocoaMenuItemSetAccelerator( m_osxMenuItem, entry );
}
bool DoDefault();
void * GetHMenuItem() { return m_osxMenuItem; }
protected :
NSMenuItem* m_osxMenuItem ;
} ;
wxMenuItemCocoaImpl::~wxMenuItemCocoaImpl()
{
if ( ![m_osxMenuItem isSeparatorItem] )
[(wxNSMenuItem*)m_osxMenuItem setImplementation:nil];
[m_osxMenuItem release];
}
bool wxMenuItemCocoaImpl::DoDefault()
{
bool handled=false;
int menuid = m_peer->GetId();
NSApplication *theNSApplication = [NSApplication sharedApplication];
if (menuid == wxID_OSX_HIDE)
{
[theNSApplication hide:nil];
handled=true;
}
else if (menuid == wxID_OSX_HIDEOTHERS)
{
[theNSApplication hideOtherApplications:nil];
handled=true;
}
else if (menuid == wxID_OSX_SHOWALL)
{
[theNSApplication unhideAllApplications:nil];
handled=true;
}
else if (menuid == wxApp::s_macExitMenuItemId)
{
wxTheApp->ExitMainLoop();
}
return handled;
}
wxMenuItemImpl* wxMenuItemImpl::Create( wxMenuItem* peer, wxMenu *pParentMenu,
int menuid,
const wxString& text,
wxAcceleratorEntry *entry,
const wxString& WXUNUSED(strHelp),
wxItemKind kind,
wxMenu *pSubMenu )
{
wxMenuItemImpl* c = NULL;
NSMenuItem* item = nil;
if ( kind == wxITEM_SEPARATOR )
{
item = [[NSMenuItem separatorItem] retain];
}
else
{
wxCFStringRef cfText(text);
SEL selector = nil;
bool targetSelf = false;
if ( (pParentMenu == NULL || !pParentMenu->GetNoEventsMode()) && pSubMenu == NULL )
{
selector = wxOSXGetSelectorFromID(menuid);
if ( selector == nil )
{
selector = @selector(clickedAction:);
targetSelf = true;
}
}
wxNSMenuItem* menuitem = [ [ wxNSMenuItem alloc ] initWithTitle:cfText.AsNSString() action:selector keyEquivalent:@""];
if ( targetSelf )
[menuitem setTarget:menuitem];
if ( pSubMenu )
{
pSubMenu->GetPeer()->SetTitle( text );
[menuitem setSubmenu:pSubMenu->GetHMenu()];
}
else
{
wxMacCocoaMenuItemSetAccelerator( menuitem, entry );
}
item = menuitem;
}
c = new wxMenuItemCocoaImpl( peer, item );
return c;
}