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
363 lines
9.3 KiB
Plaintext
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;
|
|
}
|