X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d08504dfa577c3510b150d19b9539fea3df24fce..90fae9d2cfd82625c8c8279660237514470bc31a:/src/msw/menu.cpp diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index a549d8b820..afb0df14e9 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -82,7 +82,7 @@ // ---------------------------------------------------------------------------- // the (popup) menu title has this special id -static const UINT idMenuTitle = (UINT)-3; +static const int idMenuTitle = wxID_NONE; // ---------------------------------------------------------------------------- // private functions @@ -112,7 +112,8 @@ void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu), // make the given menu item owner-drawn void SetOwnerDrawnMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu), UINT WXUNUSED_IN_WINCE(id), - ULONG_PTR WXUNUSED_IN_WINCE(data)) + ULONG_PTR WXUNUSED_IN_WINCE(data), + BOOL WXUNUSED_IN_WINCE(byPositon = FALSE)) { #ifndef __WXWINCE__ MENUITEMINFO mii; @@ -122,7 +123,10 @@ void SetOwnerDrawnMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu), mii.fType = MFT_OWNERDRAW; mii.dwItemData = data; - if ( !::SetMenuItemInfo(hmenu, id, FALSE, &mii) ) + if ( reinterpret_cast(data)->IsSeparator() ) + mii.fType |= MFT_SEPARATOR; + + if ( !::SetMenuItemInfo(hmenu, id, byPositon, &mii) ) { wxLogLastError(wxT("SetMenuItemInfo")); } @@ -145,13 +149,10 @@ UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) } #endif // __WXWINCE__ -inline bool IsLessThanStdSize(const wxBitmap& bmp) +inline bool IsGreaterThanStdSize(const wxBitmap& bmp) { - // FIXME: these +4 are chosen so that 16*16 bitmaps pass this test with - // default SM_CXMENUCHECK value but I have no idea what do we really - // need to use here - return bmp.GetWidth() < ::GetSystemMetrics(SM_CXMENUCHECK) + 4 && - bmp.GetHeight() < ::GetSystemMetrics(SM_CYMENUCHECK) + 4; + return bmp.GetWidth() > ::GetSystemMetrics(SM_CXMENUCHECK) || + bmp.GetHeight() > ::GetSystemMetrics(SM_CYMENUCHECK); } } // anonymous namespace @@ -160,100 +161,6 @@ inline bool IsLessThanStdSize(const wxBitmap& bmp) // implementation // ============================================================================ -#include "wx/listimpl.cpp" - -WX_DEFINE_LIST( wxMenuInfoList ) - -#if wxUSE_EXTENDED_RTTI - -WX_DEFINE_FLAGS( wxMenuStyle ) - -wxBEGIN_FLAGS( wxMenuStyle ) - wxFLAGS_MEMBER(wxMENU_TEAROFF) -wxEND_FLAGS( wxMenuStyle ) - -IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler,"wx/menu.h") - -wxCOLLECTION_TYPE_INFO( wxMenuItem * , wxMenuItemList ) ; - -template<> void wxCollectionToVariantArray( wxMenuItemList const &theList, wxxVariantArray &value) -{ - wxListCollectionToVariantArray( theList , value ) ; -} - -wxBEGIN_PROPERTIES_TABLE(wxMenu) - wxEVENT_PROPERTY( Select , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent) - wxPROPERTY( Title, wxString , SetTitle, GetTitle, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) - wxREADONLY_PROPERTY_FLAGS( MenuStyle , wxMenuStyle , long , GetStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style - wxPROPERTY_COLLECTION( MenuItems , wxMenuItemList , wxMenuItem* , Append , GetMenuItems , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) -wxEND_PROPERTIES_TABLE() - -wxBEGIN_HANDLERS_TABLE(wxMenu) -wxEND_HANDLERS_TABLE() - -wxDIRECT_CONSTRUCTOR_2( wxMenu , wxString , Title , long , MenuStyle ) - -WX_DEFINE_FLAGS( wxMenuBarStyle ) - -wxBEGIN_FLAGS( wxMenuBarStyle ) - wxFLAGS_MEMBER(wxMB_DOCKABLE) -wxEND_FLAGS( wxMenuBarStyle ) - -// the negative id would lead the window (its superclass !) to vetoe streaming out otherwise -bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxWriter * , wxPersister * , wxxVariantArray & ) -{ - return true ; -} - -IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow ,"wx/menu.h",wxMenuBarStreamingCallback) - -IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfo, wxObject , "wx/menu.h" ) - -wxBEGIN_PROPERTIES_TABLE(wxMenuInfo) - wxREADONLY_PROPERTY( Menu , wxMenu* , GetMenu , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) - wxREADONLY_PROPERTY( Title , wxString , GetTitle , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) -wxEND_PROPERTIES_TABLE() - -wxBEGIN_HANDLERS_TABLE(wxMenuInfo) -wxEND_HANDLERS_TABLE() - -wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title ) - -wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ; - -template<> void wxCollectionToVariantArray( wxMenuInfoList const &theList, wxxVariantArray &value) -{ - wxListCollectionToVariantArray( theList , value ) ; -} - -wxBEGIN_PROPERTIES_TABLE(wxMenuBar) - wxPROPERTY_COLLECTION( MenuInfos , wxMenuInfoList , wxMenuInfo* , Append , GetMenuInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) -wxEND_PROPERTIES_TABLE() - -wxBEGIN_HANDLERS_TABLE(wxMenuBar) -wxEND_HANDLERS_TABLE() - -wxCONSTRUCTOR_DUMMY( wxMenuBar ) - -#else -IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) -IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow) -IMPLEMENT_DYNAMIC_CLASS(wxMenuInfo, wxObject) -#endif - -const wxMenuInfoList& wxMenuBar::GetMenuInfos() const -{ - wxMenuInfoList* list = const_cast< wxMenuInfoList* >( &m_menuInfos ) ; - WX_CLEAR_LIST( wxMenuInfoList , *list ) ; - for( size_t i = 0 ; i < GetMenuCount() ; ++i ) - { - wxMenuInfo* info = new wxMenuInfo() ; - info->Create( const_cast(this)->GetMenu(i) , GetMenuLabel(i) ) ; - list->Append( info ) ; - } - return m_menuInfos ; -} - // --------------------------------------------------------------------------- // wxMenu construction, adding and removing menu items // --------------------------------------------------------------------------- @@ -267,6 +174,7 @@ void wxMenu::Init() #if wxUSE_OWNER_DRAWN m_ownerDrawn = false; m_maxBitmapWidth = 0; + m_maxAccelWidth = -1; #endif // wxUSE_OWNER_DRAWN // create the menu @@ -279,8 +187,9 @@ void wxMenu::Init() // if we have a title, insert it in the beginning of the menu if ( !m_title.empty() ) { - Append(idMenuTitle, m_title); - AppendSeparator(); + const wxString title = m_title; + m_title.clear(); // so that SetTitle() knows there was no title before + SetTitle(title); } } @@ -385,6 +294,8 @@ void wxMenu::UpdateAccel(wxMenuItem *item) { GetMenuBar()->RebuildAccelTable(); } + + ResetMaxAccelWidth(); } //else: it is a separator, they can't have accels, nothing to do } @@ -486,8 +397,8 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) pos = GetMenuItemCount() - 1; } - // adjust position to account for the title, if any - if ( !m_title.empty() ) + // adjust position to account for the title of a popup menu, if any + if ( !GetMenuBar() && !m_title.empty() ) pos += 2; // for the title itself and its separator BOOL ok = false; @@ -496,7 +407,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) // Under older systems mixing owner-drawn and non-owner-drawn items results // in inconsistent margins, so we force this one to be owner-drawn if any // other items already are. - if ( m_ownerDrawn && !pItem->IsSeparator() ) + if ( m_ownerDrawn ) pItem->SetOwnerDrawn(true); #endif // wxUSE_OWNER_DRAWN @@ -506,7 +417,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) { #ifndef __DMC__ - if ( !m_ownerDrawn ) + if ( !m_ownerDrawn && !pItem->IsSeparator() ) { // MIIM_BITMAP only works under WinME/2000+ so we always use owner // drawn item under the previous versions and we also have to use @@ -522,8 +433,8 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) const wxBitmap& bmpUnchecked = pItem->GetBitmap(false), bmpChecked = pItem->GetBitmap(true); - if ( (bmpUnchecked.Ok() && !IsLessThanStdSize(bmpUnchecked)) || - (bmpChecked.Ok() && !IsLessThanStdSize(bmpChecked)) ) + if ( (bmpUnchecked.Ok() && IsGreaterThanStdSize(bmpUnchecked)) || + (bmpChecked.Ok() && IsGreaterThanStdSize(bmpChecked)) ) { mustUseOwnerDrawn = true; } @@ -631,27 +542,31 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) // make other item ownerdrawn and update margin width for equals alignment if ( !m_ownerDrawn || updateAllMargins ) { + // we must use position in SetOwnerDrawnMenuItem because + // all separators have the same id + int pos = 0; wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst(); while (node) { wxMenuItem* item = node->GetData(); - if ( !item->IsSeparator() ) + if ( !item->IsOwnerDrawn()) { - if ( !item->IsOwnerDrawn() ) - { - item->SetOwnerDrawn(true); - SetOwnerDrawnMenuItem(GetHmenu(), item->GetMSWId(), - reinterpret_cast(item)); - } - item->SetMarginWidth(m_maxBitmapWidth); + item->SetOwnerDrawn(true); + SetOwnerDrawnMenuItem(GetHmenu(), pos, + reinterpret_cast(item), TRUE); } + item->SetMarginWidth(m_maxBitmapWidth); + node = node->GetNext(); + pos++; } // set menu as ownerdrawn m_ownerDrawn = true; + + ResetMaxAccelWidth(); } // only update our margin for equals alignment to other item else if ( !updateAllMargins ) @@ -686,7 +601,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) // if we just appended the title, highlight it - if ( id == idMenuTitle ) + if ( id == (UINT_PTR)idMenuTitle ) { // visually select the menu title SetDefaultMenuItem(GetHmenu(), id); @@ -796,6 +711,8 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) delete m_accels[n]; m_accels.RemoveAt(n); + + ResetMaxAccelWidth(); } //else: this item doesn't have an accel, nothing to do #endif // wxUSE_ACCEL @@ -846,6 +763,34 @@ wxAcceleratorTable *wxMenu::CreateAccelTable() const #endif // wxUSE_ACCEL +// --------------------------------------------------------------------------- +// ownerdrawn helpers +// --------------------------------------------------------------------------- + +#if wxUSE_OWNER_DRAWN + +void wxMenu::CalculateMaxAccelWidth() +{ + wxASSERT_MSG( m_maxAccelWidth == -1, wxT("it's really needed?") ); + + wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst(); + while (node) + { + wxMenuItem* item = node->GetData(); + + if ( item->IsOwnerDrawn() ) + { + int width = item->MeasureAccelWidth(); + if (width > m_maxAccelWidth ) + m_maxAccelWidth = width; + } + + node = node->GetNext(); + } +} + +#endif // wxUSE_OWNER_DRAWN + // --------------------------------------------------------------------------- // set wxMenu title // --------------------------------------------------------------------------- @@ -862,7 +807,7 @@ void wxMenu::SetTitle(const wxString& label) if ( !label.empty() ) { if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, - idMenuTitle, m_title.wx_str()) || + (UINT_PTR)idMenuTitle, m_title.wx_str()) || !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) ) { wxLogLastError(wxT("InsertMenu")); @@ -898,7 +843,7 @@ void wxMenu::SetTitle(const wxString& label) #else if ( !ModifyMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, - idMenuTitle, m_title.wx_str()) ) + (UINT_PTR)idMenuTitle, m_title.wx_str()) ) { wxLogLastError(wxT("ModifyMenu")); } @@ -910,7 +855,7 @@ void wxMenu::SetTitle(const wxString& label) // put the title string in bold face if ( !m_title.empty() ) { - SetDefaultMenuItem(GetHmenu(), idMenuTitle); + SetDefaultMenuItem(GetHmenu(), (UINT_PTR)idMenuTitle); } #endif // Win32 } @@ -924,7 +869,7 @@ bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id_) const int id = (signed short)id_; // ignore commands from the menu title - if ( id != (int)idMenuTitle ) + if ( id != idMenuTitle ) { // update the check item when it's clicked wxMenuItem * const item = FindItem(id); @@ -940,20 +885,6 @@ bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id_) return true; } -// --------------------------------------------------------------------------- -// other -// --------------------------------------------------------------------------- - -wxWindow *wxMenu::GetWindow() const -{ - if ( m_invokingWindow != NULL ) - return m_invokingWindow; - else if ( GetMenuBar() != NULL) - return GetMenuBar()->GetFrame(); - - return NULL; -} - // --------------------------------------------------------------------------- // Menu Bar // --------------------------------------------------------------------------- @@ -988,12 +919,13 @@ wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], lon { Init(); - m_titles.Alloc(count); - for ( size_t i = 0; i < count; i++ ) { + // We just want to store the menu title in the menu itself, not to + // show it as a dummy item in the menu itself as we do with the popup + // menu titles in overridden wxMenu::SetTitle(). + menus[i]->wxMenuBase::SetTitle(titles[i]); m_menus.Append(menus[i]); - m_titles.Add(titles[i]); menus[i]->Attach(this); } @@ -1106,13 +1038,13 @@ WXHMENU wxMenuBar::Create() } else { - size_t count = GetMenuCount(), i; - wxMenuList::iterator it; - for ( i = 0, it = m_menus.begin(); i < count; i++, it++ ) + for ( wxMenuList::iterator it = m_menus.begin(); + it != m_menus.end(); + ++it ) { if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, (UINT_PTR)(*it)->GetHMenu(), - m_titles[i].wx_str()) ) + (*it)->GetTitle().wx_str()) ) { wxLogLastError(wxT("AppendMenu")); } @@ -1173,7 +1105,7 @@ void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label) { wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") ); - m_titles[pos] = label; + m_menus[pos]->wxMenuBase::SetTitle(label); if ( !IsAttached() ) { @@ -1232,7 +1164,7 @@ wxString wxMenuBar::GetMenuLabel(size_t pos) const wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString, wxT("invalid menu index in wxMenuBar::GetMenuLabel") ); - return m_titles[pos]; + return m_menus[pos]->GetTitle(); } // --------------------------------------------------------------------------- @@ -1245,7 +1177,7 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) if ( !menuOld ) return NULL; - m_titles[pos] = title; + menu->wxMenuBase::SetTitle(title); #if defined(WINCE_WITHOUT_COMMANDBAR) if (IsAttached()) @@ -1302,7 +1234,7 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) if ( !wxMenuBarBase::Insert(pos, menu, title) ) return false; - m_titles.Insert(title, pos); + menu->wxMenuBase::SetTitle(title); if ( isAttached ) { @@ -1358,7 +1290,7 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title) if ( !wxMenuBarBase::Append(menu, title) ) return false; - m_titles.Add(title); + menu->wxMenuBase::SetTitle(title); #if defined(WINCE_WITHOUT_COMMANDBAR) if (IsAttached()) @@ -1449,8 +1381,6 @@ wxMenu *wxMenuBar::Remove(size_t pos) Refresh(); } - m_titles.RemoveAt(pos); - return menu; }