X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e40298d54ecd5b109222a7c60aa2ef084a304d69..de2ce07c7a13f9b0800c8f9e68adadebdc9aa89c:/src/mac/menu.cpp diff --git a/src/mac/menu.cpp b/src/mac/menu.cpp index 1d3195a6a7..e4e0879b02 100644 --- a/src/mac/menu.cpp +++ b/src/mac/menu.cpp @@ -69,12 +69,12 @@ void wxMenu::Init() m_startRadioGroup = -1; // create the menu - m_macMenuId = s_macNextMenuId++; + m_macMenuId = s_macNextMenuId++; m_hMenu = UMANewMenu(m_macMenuId, m_title); if ( !m_hMenu ) { - wxLogLastError("UMANewMenu failed"); + wxLogLastError(wxT("UMANewMenu failed")); } // if we have a title, insert it in the beginning of the menu @@ -107,7 +107,7 @@ void wxMenu::Attach(wxMenuBarBase *menubar) // append a new item or submenu to the menu bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) { - wxASSERT_MSG( pItem != NULL, "can't append NULL item to the menu" ); + wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") ); if ( pItem->IsSeparator() ) { @@ -116,17 +116,19 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) else MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos); } - else + else { wxMenu *pSubMenu = pItem->GetSubMenu() ; if ( pSubMenu != NULL ) { - wxASSERT_MSG( pSubMenu->m_hMenu != NULL , "invalid submenu added"); + wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added")); pSubMenu->m_menuParent = this ; - - if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar) - ::InsertMenu( MAC_WXHMENU( pSubMenu->m_hMenu ) , -1 ) ; - + + if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar) + { + pSubMenu->MacBeforeDisplay( true ) ; + } + if ( pos == (size_t)-1 ) UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), pSubMenu->m_macMenuId); else @@ -138,12 +140,16 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) { if ( pos == (size_t)-1 ) { - UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), "a" ); + UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") ); pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ; } else { - UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), "a" , pos); + // MacOS counts menu items from 1 and inserts after, therefore having the + // same effect as wx 0 based and inserting before, we must correct pos + // after however for updates to be correct + UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , pos); + pos += 1 ; } SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , pItem->GetId() ) ; @@ -151,7 +157,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) pItem->UpdateItemBitmap() ; pItem->UpdateItemStatus() ; - if ( pItem->GetId() == idMenuTitle ) + if ( pItem->GetId() == idMenuTitle ) { UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ; } @@ -171,9 +177,9 @@ void wxMenu::EndRadioGroup() m_startRadioGroup = -1; } -bool wxMenu::DoAppend(wxMenuItem *item) +wxMenuItem* wxMenu::DoAppend(wxMenuItem *item) { - wxCHECK_MSG( item, FALSE, _T("NULL item in wxMenu::DoAppend") ); + wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") ); bool check = FALSE; @@ -216,7 +222,7 @@ bool wxMenu::DoAppend(wxMenuItem *item) if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) ) { - return FALSE; + return NULL; } if ( check ) @@ -225,12 +231,15 @@ bool wxMenu::DoAppend(wxMenuItem *item) item->Check(TRUE); } - return TRUE; + return item; } -bool wxMenu::DoInsert(size_t pos, wxMenuItem *item) +wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item) { - return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos); + if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos)) + return item; + else + return NULL; } wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) @@ -270,15 +279,6 @@ bool wxMenu::ProcessCommand(wxCommandEvent & event) { bool processed = FALSE; -#if WXWIN_COMPATIBILITY - // Try a callback - if (m_callback) - { - (void)(*(m_callback))(*this, event); - processed = TRUE; - } -#endif WXWIN_COMPATIBILITY - // Try the menu's event handler if ( !processed && GetEventHandler()) { @@ -309,10 +309,10 @@ wxWindow *wxMenu::GetWindow() const return NULL; } -// helper functions returning the mac menu position for a certain item, note that this is +// helper functions returning the mac menu position for a certain item, note that this is // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0 -int wxMenu::MacGetIndexFromId( int id ) +int wxMenu::MacGetIndexFromId( int id ) { size_t pos; wxMenuItemList::Node *node = GetMenuItems().GetFirst(); @@ -323,14 +323,14 @@ int wxMenu::MacGetIndexFromId( int id ) node = node->GetNext(); } - + if (!node) return 0; - + return pos + 1 ; } -int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem ) +int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem ) { size_t pos; wxMenuItemList::Node *node = GetMenuItems().GetFirst(); @@ -344,20 +344,88 @@ int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem ) if (!node) return 0; - + return pos + 1 ; } -void wxMenu::MacEnableMenu( bool bDoEnable ) +void wxMenu::MacEnableMenu( bool bDoEnable ) { UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ; - + ::DrawMenuBar() ; } +// MacOS needs to know about submenus somewhere within this menu +// before it can be displayed , also hide special menu items like preferences +// that are handled by the OS +void wxMenu::MacBeforeDisplay( bool isSubMenu ) +{ + wxMenuItem* previousItem = NULL ; + size_t pos ; + wxMenuItemList::Node *node; + wxMenuItem *item; + for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) + { + item = (wxMenuItem *)node->GetData(); + wxMenu* subMenu = item->GetSubMenu() ; + if (subMenu) + { + subMenu->MacBeforeDisplay( true ) ; + } + else + { + #if TARGET_CARBON + if ( UMAGetSystemVersion() >= 0x1000 ) + { + if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId) + { + ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 ); + if ( GetMenuItems().GetCount() == pos + 1 && + previousItem != NULL && + previousItem->IsSeparator() ) + { + ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 ); + } + } + } + #endif + } + previousItem = item ; + } + + if ( isSubMenu ) + ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1); + +} +// undo all changes from the MacBeforeDisplay call +void wxMenu::MacAfterDisplay( bool isSubMenu ) +{ + if ( isSubMenu ) + ::DeleteMenu(MacGetMenuId()); + + wxMenuItem* previousItem = NULL ; + int pos ; + wxMenuItemList::Node *node; + wxMenuItem *item; + for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) + { + item = (wxMenuItem *)node->GetData(); + wxMenu* subMenu = item->GetSubMenu() ; + if (subMenu) + { + subMenu->MacAfterDisplay( true ) ; + } + else + { + // no need to undo hidings + } + previousItem = item ; + } +} + // Menu Bar -/* +/* Mac Implementation note : @@ -365,16 +433,17 @@ The Mac has only one global menubar, so we attempt to install the currently active menubar from a frame, we currently don't take into account mdi-frames which would ask for menu-merging -Secondly there is no mac api for changing a menubar that is not the current +Secondly there is no mac api for changing a menubar that is not the current menubar, so we have to wait for preparing the actual menubar until the wxMenubar is to be used -We can in subsequent versions use MacInstallMenuBar to provide some sort of +We can in subsequent versions use MacInstallMenuBar to provide some sort of auto-merge for MDI in case this will be necessary */ wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ; +wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ; void wxMenuBar::Init() { @@ -411,6 +480,8 @@ wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[]) wxMenuBar::~wxMenuBar() { + if (s_macCommonMenuBar == this) + s_macCommonMenuBar = NULL; if (s_macInstalledMenuBar == this) { ::ClearMenuBar(); @@ -426,16 +497,16 @@ void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(r DrawMenuBar(); } -void wxMenuBar::MacInstallMenuBar() +void wxMenuBar::MacInstallMenuBar() { if ( s_macInstalledMenuBar == this ) return ; - + wxStAppResource resload ; - + Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ; wxString message ; - wxCHECK_RET( menubar != NULL, "can't read MBAR resource" ); + wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") ); ::SetMenuBar( menubar ) ; #if TARGET_API_MAC_CARBON ::DisposeMenuBar( menubar ) ; @@ -450,7 +521,7 @@ void wxMenuBar::MacInstallMenuBar() ::AppendResMenu(menu, 'DRVR'); } #endif - + // clean-up the help menu before adding new items MenuHandle mh = NULL ; if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr ) @@ -476,28 +547,27 @@ void wxMenuBar::MacInstallMenuBar() #endif for (size_t i = 0; i < m_menus.GetCount(); i++) { - Str255 label; wxMenuItemList::Node *node; wxMenuItem *item; int pos ; wxMenu* menu = m_menus[i] , *subMenu = NULL ; - if( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName ) + if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName ) { if ( mh == NULL ) { continue ; } - - for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) + + for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) { item = (wxMenuItem *)node->GetData(); subMenu = item->GetSubMenu() ; - if (subMenu) + if (subMenu) { // we don't support hierarchical menus in the help menu yet } - else + else { if ( item->IsSeparator() ) { @@ -509,7 +579,7 @@ void wxMenuBar::MacInstallMenuBar() wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ; if ( item->GetId() == wxApp::s_macAboutMenuItemId ) - { + { UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() ); UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true ); SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ; @@ -523,7 +593,7 @@ void wxMenuBar::MacInstallMenuBar() SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ; } } - + delete entry ; } } @@ -532,52 +602,8 @@ void wxMenuBar::MacInstallMenuBar() else { UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ; - wxArrayPtrVoid submenus ; - wxMenuItem* previousItem = NULL ; - for (pos = 0, node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) - { - item = (wxMenuItem *)node->GetData(); - subMenu = item->GetSubMenu() ; - if (subMenu) - { - submenus.Add(subMenu) ; - } - else - { -#if TARGET_CARBON - if ( UMAGetSystemVersion() >= 0x1000 ) - { - if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId) - { - ChangeMenuItemAttributes( MAC_WXHMENU( menu->GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 ); - if ( menu->GetMenuItems().GetCount() == pos + 1 && previousItem != NULL && previousItem->IsSeparator() ) - { - ChangeMenuItemAttributes( MAC_WXHMENU( menu->GetHMenu() ) , pos , kMenuItemAttrHidden, 0 ); - } - } - } -#endif - } - previousItem = item ; - } + m_menus[i]->MacBeforeDisplay(false) ; ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0); - for ( size_t i = 0 ; i < submenus.GetCount() ; ++i ) - { - wxMenu* submenu = (wxMenu*) submenus[i] ; - wxMenuItemList::Node *subnode; - wxMenuItem *subitem; - int subpos ; - for ( subpos = 0 , subnode = submenu->GetMenuItems().GetFirst(); subnode; subnode = subnode->GetNext(), subpos++) - { - subitem = (wxMenuItem *)subnode->GetData(); - wxMenu* itsSubMenu = subitem->GetSubMenu() ; - if (itsSubMenu) - { - submenus.Add(itsSubMenu) ; - } - } - ::InsertMenu( MAC_WXHMENU(submenu->GetHMenu()) , -1 ) ; - } } } ::DrawMenuBar() ; @@ -627,7 +653,7 @@ int wxMenuBar::FindMenu(const wxString& title) { wxString title = wxStripMenuCodes(m_titles[i]); if ( menuTitle == title ) - return i; + return i; } return wxNOT_FOUND; @@ -654,8 +680,10 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) { if (s_macInstalledMenuBar == this) { + menuOld->MacAfterDisplay( false ) ; ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; { + menu->MacBeforeDisplay( false ) ; UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ; if ( pos == m_menus.GetCount() - 1) { @@ -683,15 +711,19 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ; - if ( IsAttached() ) + if ( IsAttached() && s_macInstalledMenuBar == this ) { - if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() ) - { - ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ; - } - else + if (s_macInstalledMenuBar == this) { - ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ; + menu->MacBeforeDisplay( false ) ; + if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() ) + { + ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ; + } + else + { + ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ; + } } Refresh(); } @@ -712,12 +744,10 @@ wxMenu *wxMenuBar::Remove(size_t pos) ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; } - menu->Detach(); - Refresh(); } - m_titles.Remove(pos); + m_titles.RemoveAt(pos); return menu; } @@ -731,7 +761,7 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title) return FALSE; m_titles.Add(title); - + UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ; if ( IsAttached() )