diff options
author | Kurt Zenker <kz@openoffice.org> | 2007-10-09 14:17:04 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2007-10-09 14:17:04 +0000 |
commit | 8f6f151ad251a967452cba47f9f4a3d8b49d1e1f (patch) | |
tree | 2aa32f29a6f0095d582fa813f5cc600fd52a2750 /vcl | |
parent | 3ca29c20afd167d7e013d1b3ffc361e99dae4d8f (diff) |
INTEGRATION: CWS aquavcl03 (1.2.4); FILE MERGED
2007/10/01 13:45:55 pl 1.2.4.14: #i80230# shortcut forwarding with native menus, preparations for menu disabling in modal case
2007/09/27 13:58:42 pl 1.2.4.13: remove unused headers
2007/09/27 13:09:49 pl 1.2.4.12: #i80407# preliminary code to set the app name in the menu
2007/09/24 16:29:35 pl 1.2.4.11: #i80230# fix some leaks
2007/09/18 11:37:53 pl 1.2.4.10: #i80695# protect against calling dead objects
2007/09/10 07:28:44 ericb 1.2.4.9: #i81404# a try to fix SalNSMenuItem leaks + make code more robust against potential crashes
2007/09/06 15:43:13 pl 1.2.4.8: #i80230# prevent menuitem triggered while modal dialogs are opened
2007/08/08 16:07:13 pl 1.2.4.7: #i80230# enable app menu entries about an preferences again
2007/08/07 10:33:24 pl 1.2.4.6: RESYNC: (1.2-1.3); FILE MERGED
2007/08/06 17:04:00 pl 1.2.4.5: #i80230# try a solution for the multiple supermenu problem
2007/08/02 17:48:42 pl 1.2.4.4: #i80230# menu cleanup
2007/08/01 17:54:13 pl 1.2.4.3: #i80230# multiple documents
2007/08/01 15:26:43 pl 1.2.4.2: #i80230# life cycle of menus and menuitems
2007/07/31 19:40:38 pl 1.2.4.1: #i80230# move AquaSalMenu/AquaSalMenuItem to Cocoa
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/aqua/source/window/salmenu.cxx | 574 |
1 files changed, 400 insertions, 174 deletions
diff --git a/vcl/aqua/source/window/salmenu.cxx b/vcl/aqua/source/window/salmenu.cxx index bbc41a8e5158..4367c30f51ce 100644 --- a/vcl/aqua/source/window/salmenu.cxx +++ b/vcl/aqua/source/window/salmenu.cxx @@ -4,9 +4,9 @@ * * $RCSfile: salmenu.cxx,v $ * - * $Revision: 1.4 $ + * $Revision: 1.5 $ * - * last change: $Author: ihi $ $Date: 2007-09-13 16:32:05 $ + * last change: $Author: kz $ $Date: 2007-10-09 15:17:04 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -33,50 +33,140 @@ * ************************************************************************/ -#include <saldata.hxx> -#include <salinst.h> -#include <salmenu.h> -#include <vcl/impbmp.hxx> -#include <vcl/svids.hrc> +#include "saldata.hxx" +#include "salinst.h" +#include "salmenu.h" +#include "salframe.h" +#include "vcl/svids.hrc" +#include "vcl/cmdevt.hxx" +#include "vcl/window.hxx" +#include "rtl/ustrbuf.hxx" +const AquaSalMenu* AquaSalMenu::pCurrentMenuBar = NULL; -// nPos is 0 based, MenuItemIndex is 1 based -#define GETITEMINDEXBYPOS(nPos) (nPos+1) +@interface MainMenuSelector : NSObject +{ +} +-(void)showDialog: (int)nDialog; +-(void)showPreferences: (id)sender; +-(void)showAbout: (id)sender; +@end -// ======================================================================= +@implementation MainMenuSelector +-(void)showDialog: (int)nDialog +{ + if( AquaSalMenu::pCurrentMenuBar ) + { + const AquaSalFrame* pFrame = AquaSalMenu::pCurrentMenuBar->mpFrame; + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) + { + pFrame->CallCallback( SALEVENT_SHOWDIALOG, reinterpret_cast<void*>(nDialog) ); + } + } +} -SalMenu* AquaSalInstance::CreateMenu( BOOL bMenuBar ) +-(void)showPreferences: (id) sender { - AquaSalMenu *pAquaSalMenu = new AquaSalMenu(); - static MenuID inMenuID=0; + [self showDialog: SHOWDIALOG_ID_PREFERENCES]; +} +-(void)showAbout: (id) sender +{ + [self showDialog: SHOWDIALOG_ID_ABOUT]; +} +@end - pAquaSalMenu->mbMenuBar = bMenuBar; +// FIXME: currently this is leaked +static MainMenuSelector* pMainMenuSelector = nil; - CreateNewMenu (inMenuID++, 0, &pAquaSalMenu->mrMenuRef); +// ======================================================================= - /* Associate the pointer to this SalMenu with the menu */ - SetMenuItemProperty (pAquaSalMenu->mrMenuRef, 0, - APP_PROPERTY_CREATOR, APP_PROPERTY_TAG_MENU_POINTER, - sizeof(pAquaSalMenu), &pAquaSalMenu); +SalMenu* AquaSalInstance::CreateMenu( BOOL bMenuBar ) +{ + AquaSalMenu *pAquaSalMenu = new AquaSalMenu( bMenuBar ); static bool bOnce = true; if( bOnce ) { bOnce = false; - EnableMenuCommand(NULL, kHICommandPreferences); // enable pref menu ResMgr* pMgr = ImplGetResMgr(); if( pMgr ) { - String aAbout( ResId( SV_STDTEXT_ABOUT, *pMgr ) ); - MenuRef rApplicationMenu; - MenuItemIndex outIndex[1]; - GetIndMenuItemWithCommandID(NULL, kHICommandPreferences, 1, &rApplicationMenu, outIndex); - CFStringRef rStr = CreateCFString( aAbout ); - if ( rStr ) + // get the main menu + NSMenu* pMainMenu = [NSApp mainMenu]; + if( pMainMenu != nil ) { - InsertMenuItemTextWithCFString(rApplicationMenu, rStr, (short) 0, 0, kHICommandAbout); - CFRelease( rStr ); + // create the action selector + pMainMenuSelector = [[MainMenuSelector alloc] init]; + + // get the proper submenu + NSMenu* pAppMenu = [[pMainMenu itemAtIndex: 0] submenu]; + if( pAppMenu ) + { + // insert about entry + String aAbout( ResId( SV_STDTEXT_ABOUT, *pMgr ) ); + NSString* pString = CreateNSString( aAbout ); + NSMenuItem* pNewItem = [pAppMenu insertItemWithTitle: pString + action: @selector(showAbout:) + keyEquivalent: @"" + atIndex: 0]; + if (pString) + [pString release]; + if( pNewItem ) + { + [pNewItem setTarget: pMainMenuSelector]; + [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 1]; + } + + // insert preferences entry + String aPref( ResId( SV_STDTEXT_PREFERENCES, *pMgr ) ); + pString = CreateNSString( aPref ); + pNewItem = [pAppMenu insertItemWithTitle: pString + action: @selector(showPreferences:) + keyEquivalent: @"," + atIndex: 2]; + if (pString) + [pString release]; + if( pNewItem ) + { + [pNewItem setKeyEquivalentModifierMask: NSCommandKeyMask]; + [pNewItem setTarget: pMainMenuSelector]; + [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 3]; + } + + + // FIXME: there probably is a more canonical way to set the string + // in the application menu + + // replace instances of "NewApplication" (artifact from out .nib) + // by the application name + + // get the application name + ResHookProc pProc = ResMgr::GetReadStringHook(); + String aAppName( RTL_CONSTASCII_USTRINGPARAM( "%PRODUCTNAME" ) ); + if( pProc ) + pProc( aAppName ); + + int nItems = [pAppMenu numberOfItems]; + for( int i = 4; i < nItems; i++ ) + { + NSMenuItem* pItem = [pAppMenu itemAtIndex: i]; + if( pItem != nil ) + { + OUString aTitle( GetOUString( [pItem title] ) ); + sal_Int32 nInd = aTitle.indexOfAsciiL( "NewApplication", 14 ); + if( nInd != -1 ) + { + rtl::OUStringBuffer aBuf( aTitle.getLength()*2 ); + aBuf.append( aTitle.copy( 0, nInd ) ); + aBuf.append( aAppName ); + if( aTitle.getLength() > nInd + 14 ) + aBuf.append( aTitle.copy( nInd+14, aTitle.getLength() - nInd - 14 ) ); + [pItem setTitle: [CreateNSString( aBuf.makeStringAndClear() ) autorelease]]; + } + } + } + } } } } @@ -85,11 +175,6 @@ SalMenu* AquaSalInstance::CreateMenu( BOOL bMenuBar ) void AquaSalInstance::DestroyMenu( SalMenu* pSalMenu ) { - - AquaSalMenu *pAquaSalMenu = (AquaSalMenu *) pSalMenu; - - RemoveMenuItemProperty (pAquaSalMenu->mrMenuRef, 0, - APP_PROPERTY_CREATOR, APP_PROPERTY_TAG_MENU_POINTER); delete pSalMenu; } @@ -98,20 +183,7 @@ SalMenuItem* AquaSalInstance::CreateMenuItem( const SalItemParams* pItemData ) if( !pItemData ) return NULL; - AquaSalMenuItem *pSalMenuItem = new AquaSalMenuItem(); - - pSalMenuItem->maMenuAttributes = 0; - pSalMenuItem->mpSubMenu = NULL; - pSalMenuItem->mnId = pItemData->nId; - pSalMenuItem->mText = pItemData->aText; - - // Delete mnemonics - pSalMenuItem->mText.EraseAllChars( '~' ); - - pSalMenuItem->mpMenu = pItemData->pMenu; - - if (pItemData->eType == MENUITEM_SEPARATOR) - pSalMenuItem->maMenuAttributes |= kMenuItemAttrSeparator; + AquaSalMenuItem *pSalMenuItem = new AquaSalMenuItem( pItemData ); return pSalMenuItem; } @@ -129,11 +201,94 @@ void AquaSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem ) * AquaSalMenu */ +AquaSalMenu::AquaSalMenu( bool bMenuBar ) : + mbMenuBar( bMenuBar ), + mpMenu( nil ), + mpVCLMenu( NULL ), + mpFrame( NULL ), + mpParentSalMenu( NULL ) +{ + if( ! mbMenuBar ) + { + mpMenu = [[SalNSMenu alloc] initWithMenu: this]; + [mpMenu setDelegate: mpMenu]; + } + else + { + mpMenu = [NSApp mainMenu]; + } + [mpMenu setAutoenablesItems: NO]; +} + AquaSalMenu::~AquaSalMenu() { - if (this->mrMenuRef) + // is this leaking in some cases ? the release often leads to a duplicate release + // it seems the parent item gets ownership of the menu + if( mpMenu && ! mbMenuBar ) + { + // the system may still hold a reference on mpMenu + // so set the pointer to this AquaSalMenu to NULL + // to protect from calling a dead object + + // in ! mbMenuBar case our mpMenu is actually a SalNSMenu* + // so we can safely cast here + [static_cast<SalNSMenu*>(mpMenu) setSalMenu: NULL]; + [mpMenu release]; + } +} + +int AquaSalMenu::getItemIndexByPos( USHORT nPos ) const +{ + int nIndex = 0; + if( nPos == MENU_APPEND ) + nIndex = [mpMenu numberOfItems]; + else + nIndex = sal::static_int_cast<int>( mbMenuBar ? nPos+1 : nPos ); + return nIndex; +} + +const AquaSalFrame* AquaSalMenu::getFrame() const +{ + const AquaSalMenu* pMenu = this; + while( pMenu && ! pMenu->mpFrame ) + pMenu = pMenu->mpParentSalMenu; + return pMenu ? pMenu->mpFrame : NULL; +} + +void AquaSalMenu::setMainMenu() +{ + DBG_ASSERT( mbMenuBar, "setMainMenu on non menubar" ); + if( mbMenuBar ) { - DisposeMenu(this->mrMenuRef); + if( pCurrentMenuBar != this ) + { + // remove items from main menu + for( int nItems = [mpMenu numberOfItems]; nItems > 1; nItems-- ) + [mpMenu removeItemAtIndex: 1]; + // insert our items + for( unsigned int i = 0; i < maItems.size(); i++ ) + { + NSMenuItem* pItem = maItems[i]->mpMenuItem; + [mpMenu insertItem: pItem atIndex: i+1]; + } + pCurrentMenuBar = this; + } + enableMainMenu( true ); + } +} + +void AquaSalMenu::enableMainMenu( bool bEnable ) +{ + NSMenu* pMainMenu = [NSApp mainMenu]; + if( pMainMenu ) + { + // enable/disable items from main menu + int nItems = [pMainMenu numberOfItems]; + for( int n = 1; n < nItems; n++ ) + { + NSMenuItem* pItem = [pMainMenu itemAtIndex: n]; + [pItem setEnabled: bEnable ? YES : NO]; + } } } @@ -155,112 +310,94 @@ BOOL AquaSalMenu::VisibleMenuBar() void AquaSalMenu::SetFrame( const SalFrame *pFrame ) { - AquaLog( ">*>_> %s\n",__func__); + mpFrame = static_cast<const AquaSalFrame*>(pFrame); } void AquaSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) { - AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; - - // save MenuRef of the menu for future reference - pAquaSalMenuItem->mrParentMenuRef = mrMenuRef; - - if (mbMenuBar) - AppendMenuItemTextWithCFString( mrMenuRef, NULL, pAquaSalMenuItem->maMenuAttributes, 0, &pAquaSalMenuItem->mnMenuItemIndex); + AquaSalMenuItem *pAquaSalMenuItem = static_cast<AquaSalMenuItem*>(pSalMenuItem); + pAquaSalMenuItem->mpParentMenu = this; + DBG_ASSERT( pAquaSalMenuItem->mpVCLMenu == NULL || + pAquaSalMenuItem->mpVCLMenu == mpVCLMenu || + mpVCLMenu == NULL, + "resetting menu ?" ); + if( pAquaSalMenuItem->mpVCLMenu ) + mpVCLMenu = pAquaSalMenuItem->mpVCLMenu; + + if( nPos == MENU_APPEND || nPos == maItems.size() ) + maItems.push_back( pAquaSalMenuItem ); + else if( nPos < maItems.size() ) + maItems.insert( maItems.begin() + nPos, pAquaSalMenuItem ); else - { - CFStringRef menuText = CreateCFString(pAquaSalMenuItem->mText); - if ( menuText ) - { - AppendMenuItemTextWithCFString( mrMenuRef, menuText, pAquaSalMenuItem->maMenuAttributes, 0, &pAquaSalMenuItem->mnMenuItemIndex); - CFRelease(menuText); - } - } + DBG_ERROR( "invalid item index in insert" ); - /* Associate the pointer to this SalMenuItem with the menu item */ - SetMenuItemProperty (mrMenuRef, pAquaSalMenuItem->mnMenuItemIndex, - APP_PROPERTY_CREATOR, APP_PROPERTY_TAG_MENU_ITEM_POINTER, - sizeof(pSalMenuItem), &pSalMenuItem); + if( ! mbMenuBar || pCurrentMenuBar == this ) + [mpMenu insertItem: pAquaSalMenuItem->mpMenuItem atIndex: getItemIndexByPos(nPos)]; } void AquaSalMenu::RemoveItem( unsigned nPos ) { - if (mrMenuRef) - DeleteMenuItem (mrMenuRef, GETITEMINDEXBYPOS(nPos)); + if( nPos == MENU_APPEND ) + maItems.pop_back(); + else if( nPos < maItems.size() ) + maItems.erase( maItems.begin()+nPos ); + else + DBG_ERROR( "invalid item index in remove" ); + if( ! mbMenuBar || pCurrentMenuBar == this ) + [mpMenu removeItemAtIndex: getItemIndexByPos(nPos)]; } void AquaSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ) { - AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; - - AquaSalMenu *subAquaSalMenu = (AquaSalMenu *) pSubMenu; + AquaSalMenuItem *pAquaSalMenuItem = static_cast<AquaSalMenuItem*>(pSalMenuItem); + AquaSalMenu *subAquaSalMenu = static_cast<AquaSalMenu*>(pSubMenu); // FIXME: in svtools - workben - svdem, pSubMenu is NULL! if (subAquaSalMenu) { - CFStringRef menuText = CreateCFString(pAquaSalMenuItem->mText); - if ( menuText ) + pAquaSalMenuItem->mpSubMenu = subAquaSalMenu; + if( subAquaSalMenu->mpParentSalMenu == NULL ) { - pAquaSalMenuItem->mpSubMenu = pSubMenu; - SetMenuTitleWithCFString(subAquaSalMenu->mrMenuRef, menuText); - CFRelease(menuText); + subAquaSalMenu->mpParentSalMenu = this; + [pAquaSalMenuItem->mpMenuItem setSubmenu: subAquaSalMenu->mpMenu]; + + // set title of submenu + [subAquaSalMenu->mpMenu setTitle: [pAquaSalMenuItem->mpMenuItem title]]; + } + else if( subAquaSalMenu->mpParentSalMenu != this ) + { + // cocoa doesn't allow menus to be submenus of multiple + // menu items, so place a copy in the menu item instead ? + // let's hope that NSMenu copy does the right thing + NSMenu* pCopy = [subAquaSalMenu->mpMenu copy]; + [pAquaSalMenuItem->mpMenuItem setSubmenu: pCopy]; + + // set title of submenu + [pCopy setTitle: [pAquaSalMenuItem->mpMenuItem title]]; } - SetMenuItemHierarchicalMenu (mrMenuRef, pAquaSalMenuItem->mnMenuItemIndex, subAquaSalMenu->mrMenuRef); } } void AquaSalMenu::CheckItem( unsigned nPos, BOOL bCheck ) { - CheckMenuItem(this->mrMenuRef, GETITEMINDEXBYPOS(nPos), bCheck); + if( nPos < maItems.size() ) + { + NSMenuItem* pItem = maItems[nPos]->mpMenuItem; + [pItem setState: bCheck ? NSOnState : NSOffState]; + } } void AquaSalMenu::EnableItem( unsigned nPos, BOOL bEnable ) { - if (bEnable) - EnableMenuItem(this->mrMenuRef, GETITEMINDEXBYPOS(nPos)); - else - DisableMenuItem(this->mrMenuRef, GETITEMINDEXBYPOS(nPos)); + if( nPos < maItems.size() ) + { + NSMenuItem* pItem = maItems[nPos]->mpMenuItem; + [pItem setEnabled: bEnable ? YES : NO]; + } } void AquaSalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage ) { - AquaLog( ">*>_> %s\n",__func__); - - if (!pSalMenuItem) - return; - - AquaSalMenuItem *pAquaSalMenuItem = static_cast<AquaSalMenuItem *>(pSalMenuItem); - - BitmapEx aBitmapEx = rImage.GetBitmapEx(); - aBitmapEx.Mirror(BMP_MIRROR_VERT); - - pAquaSalMenuItem->maBitmap = aBitmapEx.GetBitmap(); - - Bitmap aBitmap (pAquaSalMenuItem->maBitmap); - - ImpBitmap *aImpBitmap = aBitmap.ImplGetImpBitmap(); - - if (aImpBitmap) - { - AquaSalBitmap *pSalBmp = static_cast<AquaSalBitmap *>(aImpBitmap->ImplGetSalBitmap()); - CGImageRef xImage = NULL; - - // check alpha - if (aBitmapEx.IsAlpha()) - { - AquaSalBitmap *pSalMask = static_cast<AquaSalBitmap *>(aBitmapEx.GetAlpha().GetBitmap().ImplGetImpBitmap()->ImplGetSalBitmap()); - - if (pSalMask) - xImage = pSalBmp->CreateWithMask ( *pSalMask, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight); - } - - if (!xImage) - xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight ); - - SetMenuItemIconHandle(mrMenuRef, pAquaSalMenuItem->mnMenuItemIndex, kMenuCGImageRefType, (Handle)xImage); - - CGImageRelease(xImage); - } } void AquaSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText ) @@ -270,50 +407,40 @@ void AquaSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const X AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; - pAquaSalMenuItem->mText = rText; + String aText( rText ); // Delete mnemonics - pAquaSalMenuItem->mText.EraseAllChars( '~' ); - - CFStringRef menuText = CreateCFString(pAquaSalMenuItem->mText); - if ( menuText ) - { - SetMenuItemTextWithCFString( mrMenuRef, pAquaSalMenuItem->mnMenuItemIndex, menuText); - - // if the menu item has a submenu, change its title as well - if (pAquaSalMenuItem->mpSubMenu) - { - AquaSalMenu *subMenu = (AquaSalMenu *) pAquaSalMenuItem->mpSubMenu; - SetMenuTitleWithCFString(subMenu->mrMenuRef, menuText); - } - CFRelease(menuText); - } + aText.EraseAllChars( '~' ); + + NSString* pString = CreateNSString( aText ); + [pAquaSalMenuItem->mpMenuItem setTitle: pString]; + // if the menu item has a submenu, change its title as well + if (pAquaSalMenuItem->mpSubMenu) + [pAquaSalMenuItem->mpSubMenu->mpMenu setTitle: pString]; + if (pString) + [pString release]; } void AquaSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& rKeyName ) { - AquaLog( ">*>_> %s\n",__func__); - USHORT nModifier; - int nCommandKey = -1, nKeyGlyph = -1; + sal_Unicode nCommandKey = 0; - if (rKeyCode.GetCode()) + USHORT nKeyCode=rKeyCode.GetCode(); + if( nKeyCode ) { - USHORT nKeyCode=rKeyCode.GetCode(); - if ((nKeyCode>=KEY_A) && (nKeyCode<=KEY_Z)) // letter A..Z - nCommandKey=nKeyCode-KEY_A+'A'; + nCommandKey = nKeyCode-KEY_A + 'a'; else if ((nKeyCode>=KEY_0) && (nKeyCode<=KEY_9)) // numbers 0..9 - nCommandKey=nKeyCode-KEY_0+'0'; - else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F12)) // function keys F1..F12 - nKeyGlyph=kMenuF1Glyph+nKeyCode-KEY_F1; // only for n<13! - else if ((nKeyCode>=KEY_F13) && (nKeyCode<=KEY_F15)) - nKeyGlyph=kMenuF13Glyph+nKeyCode-KEY_F13; // function keys F13, F14, F15 -#if 0 - else if (nKeyCode==KEY_SPACE) - nKeyGlyph=kMenuSpaceGlyph; -#endif + nCommandKey = nKeyCode-KEY_0 + '0'; + else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F26)) // function keys F1..F26 + nCommandKey = nKeyCode-KEY_F1 + NSF1FunctionKey; + else if( nKeyCode == KEY_REPEAT ) + nCommandKey = NSRedoFunctionKey; + else if( nKeyCode == KEY_SPACE ) + nCommandKey = ' '; else + { switch (nKeyCode) { case KEY_ADD: @@ -341,41 +468,44 @@ void AquaSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, cons nCommandKey='='; break; } - - if (nCommandKey > -1) - SetMenuItemCommandKey (mrMenuRef, GETITEMINDEXBYPOS(nPos), 0, nCommandKey); - - if (nKeyGlyph > -1) - SetMenuItemKeyGlyph (mrMenuRef, GETITEMINDEXBYPOS(nPos), nKeyGlyph); - - if((nKeyGlyph <= -1) && (nCommandKey <= -1)) - AquaLog( "%s: Couldn't process rKeyCode.GetCode()=%d\n",__func__, rKeyCode.GetCode()); + } } + else // not even a code ? nonsense -> ignore + return; + + DBG_ASSERT( nCommandKey, "unmapped accelerator key" ); nModifier=rKeyCode.GetAllModifier(); - int nItemModifier = kMenuNoCommandModifier; + // should always use the command key + int nItemModifier = NSCommandKeyMask; + // ignore KEY_MOD1, Ctrl replaced by Command + #if 0 if (nModifier & KEY_MOD1) - nItemModifier = kMenuNoModifiers; // for the cmd key - // = and not += because should replace kMenuNoCommandModifier + nItemModifier |= NSControlKeyMask; // for the Ctrl key + #endif if (nModifier & KEY_SHIFT) - nItemModifier += kMenuShiftModifier; - - if (nModifier & KEY_MOD5) - //should use mod3 or 2 - nItemModifier += kMenuOptionModifier; // for the ALT key + { + nItemModifier |= NSShiftKeyMask; // actually useful only for function keys + if( nKeyCode >= KEY_A && nKeyCode <= KEY_Z ) + nCommandKey = nKeyCode - KEY_A + 'A'; + } if(nModifier & KEY_MOD2) - nItemModifier += kMenuControlModifier; // maybe for the ctrl key + nItemModifier |= NSAlternateKeyMask; - SetMenuItemModifiers (mrMenuRef, GETITEMINDEXBYPOS(nPos), nItemModifier); + AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem; + NSString* pString = CreateNSString( rtl::OUString( &nCommandKey, 1 ) ); + [pAquaSalMenuItem->mpMenuItem setKeyEquivalent: pString]; + [pAquaSalMenuItem->mpMenuItem setKeyEquivalentModifierMask: nItemModifier]; + if (pString) + [pString release]; } void AquaSalMenu::GetSystemMenuData( SystemMenuData* pData ) { - AquaLog( ">*>_> %s\n",__func__); } // ======================================================================= @@ -384,8 +514,104 @@ void AquaSalMenu::GetSystemMenuData( SystemMenuData* pData ) * SalMenuItem */ +AquaSalMenuItem::AquaSalMenuItem( const SalItemParams* pItemData ) : + mnId( pItemData->nId ), + mpVCLMenu( pItemData->pMenu ), + mpParentMenu( NULL ), + mpSubMenu( NULL ), + mpMenuItem( nil ) +{ + String aText( pItemData->aText ); + + // Delete mnemonics + aText.EraseAllChars( '~' ); + + if (pItemData->eType == MENUITEM_SEPARATOR) + { + mpMenuItem = [NSMenuItem separatorItem]; + // these can go occasionally go in and out of a menu, ensure their lifecycle + // also for the release in AquaSalMenuItem destructor + [mpMenuItem retain]; + } + else + { + mpMenuItem = [[SalNSMenuItem alloc] initWithMenuItem: this]; + [mpMenuItem setEnabled: YES]; + NSString* pString = CreateNSString( aText ); + [mpMenuItem setTitle: pString]; + if (pString) + [pString release]; + + // anything but a separator should set a menu to dispatch to + DBG_ASSERT( mpVCLMenu, "no menu" ); + } +} + AquaSalMenuItem::~AquaSalMenuItem() { + if( mpMenuItem ) + [mpMenuItem release]; } // ------------------------------------------------------------------- + +@implementation SalNSMenu +-(id)initWithMenu: (AquaSalMenu*)pMenu +{ + mpMenu = pMenu; + return [super initWithTitle: [NSString string]]; +} + +-(void)menuNeedsUpdate: (NSMenu*)pMenu +{ + YIELD_GUARD; + + if( mpMenu ) + { + const AquaSalFrame* pFrame = mpMenu->getFrame(); + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) + { + SalMenuEvent aMenuEvt; + aMenuEvt.mnId = 0; + aMenuEvt.mpMenu = mpMenu->mpVCLMenu; + if( aMenuEvt.mpMenu ) + { + pFrame->CallCallback(SALEVENT_MENUACTIVATE, &aMenuEvt); + pFrame->CallCallback(SALEVENT_MENUDEACTIVATE, &aMenuEvt); + } + else + DBG_ERROR( "unconnected menu" ); + } + } +} + +-(void)setSalMenu: (AquaSalMenu*)pMenu +{ + mpMenu = pMenu; +} +@end + +@implementation SalNSMenuItem +-(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem +{ + mpMenuItem = pMenuItem; + id ret = [super initWithTitle: [NSString string] action: nil keyEquivalent: [NSString string]]; + [ret setAction:@selector(menuItemTriggered:)]; + [ret setTarget: self]; + return ret; +} +-(void)menuItemTriggered: (id)aSender +{ + YIELD_GUARD; + + const AquaSalFrame* pFrame = mpMenuItem->mpParentMenu ? mpMenuItem->mpParentMenu->getFrame() : NULL; + if( pFrame && AquaSalFrame::isAlive( pFrame ) && ! pFrame->GetWindow()->IsInModalMode() ) + { + SalMenuEvent aMenuEvt; + aMenuEvt.mnId = mpMenuItem->mnId; + aMenuEvt.mpMenu = mpMenuItem->mpVCLMenu; + pFrame->CallCallback(SALEVENT_MENUCOMMAND, &aMenuEvt); + } +} +@end + |