From: Vadim Zeitlin Date: Sun, 24 Mar 2002 01:24:16 +0000 (+0000) Subject: fixes to radio menu items X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/be15b995df23c3ca511098676fbdc872f59add80?ds=inline fixes to radio menu items git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14759 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/msw/menuitem.h b/include/wx/msw/menuitem.h index 33f293efdc..05a943f6f6 100644 --- a/include/wx/msw/menuitem.h +++ b/include/wx/msw/menuitem.h @@ -61,11 +61,9 @@ public: int GetRealId() const; // mark item as belonging to the given radio group - void SetRadioGroup(int start, int end) - { - m_startRadioGroup = start; - m_endRadioGroup = end; - } + void SetAsRadioGroupStart(); + void SetRadioGroupStart(int start); + void SetRadioGroupEnd(int end); // compatibility only, don't use in new code wxMenuItem(wxMenu *parentMenu, @@ -80,9 +78,17 @@ private: void Init(); // the positions of the first and last items of the radio group this item - // belongs to or -1 - int m_startRadioGroup, - m_endRadioGroup; + // belongs to or -1: start is the radio group start and is valid for all + // but first radio group items (m_isRadioGroupStart == FALSE), end is valid + // only for the first one + union + { + int start; + int end; + } m_radioGroup; + + // does this item start a radio group? + bool m_isRadioGroupStart; DECLARE_DYNAMIC_CLASS(wxMenuItem) }; diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index 8a37698082..659634d90a 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -299,28 +299,6 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) void wxMenu::EndRadioGroup() { - if ( m_startRadioGroup == -1 ) - { - // nothing to do - return; - } - - wxMenuItemList::Node *nodeStart = GetMenuItems().Item(m_startRadioGroup); - wxCHECK_RET( nodeStart, _T("where is the radio group start item?") ); - - int endRadioGroup = GetMenuItemCount(); - - wxMenuItemList::Node *node = nodeStart; - for ( int n = m_startRadioGroup; n < endRadioGroup && node; n++ ) - { - wxMenuItem *item = (wxMenuItem *)node->GetData(); - item->SetRadioGroup(m_startRadioGroup, endRadioGroup - 1); - - node = node->GetNext(); - } - - nodeStart->GetData()->Check(TRUE); - // we're not inside a radio group any longer m_startRadioGroup = -1; } @@ -329,12 +307,38 @@ bool wxMenu::DoAppend(wxMenuItem *item) { wxCHECK_MSG( item, FALSE, _T("NULL item in wxMenu::DoAppend") ); + bool check = FALSE; + if ( item->GetKind() == wxITEM_RADIO ) { + int count = GetMenuItemCount(); + if ( m_startRadioGroup == -1 ) { // start a new radio group - m_startRadioGroup = GetMenuItemCount(); + m_startRadioGroup = count; + + // for now it has just one element + item->SetAsRadioGroupStart(); + item->SetRadioGroupEnd(m_startRadioGroup); + + // ensure that we have a checked item in the radio group + check = TRUE; + } + else // extend the current radio group + { + // we need to update its end item + item->SetRadioGroupStart(m_startRadioGroup); + wxMenuItemList::Node *node = GetMenuItems().Item(m_startRadioGroup); + + if ( node ) + { + node->GetData()->SetRadioGroupEnd(count); + } + else + { + wxFAIL_MSG( _T("where is the radio group start item?") ); + } } } else // not a radio item @@ -342,7 +346,18 @@ bool wxMenu::DoAppend(wxMenuItem *item) EndRadioGroup(); } - return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item); + if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) ) + { + return FALSE; + } + + if ( check ) + { + // check the item initially + item->Check(TRUE); + } + + return TRUE; } bool wxMenu::DoInsert(size_t pos, wxMenuItem *item) diff --git a/src/msw/menuitem.cpp b/src/msw/menuitem.cpp index 3991334757..f69a0a01f9 100644 --- a/src/msw/menuitem.cpp +++ b/src/msw/menuitem.cpp @@ -112,8 +112,8 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu, void wxMenuItem::Init() { - m_startRadioGroup = - m_endRadioGroup = -1; + m_radioGroup.start = -1; + m_isRadioGroupStart = FALSE; #if wxUSE_OWNER_DRAWN // set default menu colors @@ -161,6 +161,30 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text) return wxStripMenuCodes(text); } +// radio group stuff +// ----------------- + +void wxMenuItem::SetAsRadioGroupStart() +{ + m_isRadioGroupStart = TRUE; +} + +void wxMenuItem::SetRadioGroupStart(int start) +{ + wxASSERT_MSG( !m_isRadioGroupStart, + _T("should only be called for the next radio items") ); + + m_radioGroup.start = start; +} + +void wxMenuItem::SetRadioGroupEnd(int end) +{ + wxASSERT_MSG( m_isRadioGroupStart, + _T("should only be called for the first radio item") ); + + m_radioGroup.end = end; +} + // change item state // ----------------- @@ -197,16 +221,40 @@ void wxMenuItem::Check(bool check) if ( !check ) return; + // get the index of this item in the menu const wxMenuItemList& items = m_parentMenu->GetMenuItems(); int pos = items.IndexOf(this); wxCHECK_RET( pos != wxNOT_FOUND, _T("menuitem not found in the menu items list?") ); + // get the radio group range + int start, + end; + + if ( m_isRadioGroupStart ) + { + // we already have all information we need + start = pos; + end = m_radioGroup.end; + } + else // next radio group item + { + // get the radio group end from the start item + start = m_radioGroup.start; + end = items.Item(start)->GetData()->m_radioGroup.end; + } + #ifdef __WIN32__ + // calling CheckMenuRadioItem() with such parameters hangs my system + // (NT4 SP6) and I suspect this could happen to the others as well - so + // don't do it! + wxCHECK_RET( start != -1 && end != -1, + _T("invalid ::CheckMenuRadioItem() parameter(s)") ); + if ( !::CheckMenuRadioItem(hmenu, - m_startRadioGroup, // first group item - m_endRadioGroup, // last one - pos, // the one to check + start, // the first radio group item + end, // the last one + pos, // the one to check MF_BYPOSITION | flags) ) { wxLogLastError(_T("CheckMenuRadioItem")); @@ -214,8 +262,8 @@ void wxMenuItem::Check(bool check) #endif // __WIN32__ // also uncheck all the other items in this radio group - wxMenuItemList::Node *node = items.Item(m_startRadioGroup); - for ( int n = m_startRadioGroup; n <= m_endRadioGroup && node; n++ ) + wxMenuItemList::Node *node = items.Item(start); + for ( int n = start; n <= end && node; n++ ) { if ( n != pos ) {