From 6f7c5199ed9bc29507d426b13db9346bf1860005 Mon Sep 17 00:00:00 2001 From: Julian Smart <julian@anthemion.co.uk> Date: Sun, 2 Feb 2003 14:50:05 +0000 Subject: [PATCH] Applied patch [ 677730 ] Menus with radio items (wxUniv) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19071 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/univ/menu.h | 6 ++ include/wx/univ/menuitem.h | 18 ++++++ src/univ/menu.cpp | 123 ++++++++++++++++++++++++++++++++++++- 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/include/wx/univ/menu.h b/include/wx/univ/menu.h index 3daa74e772..4f1c1c888e 100644 --- a/include/wx/univ/menu.h +++ b/include/wx/univ/menu.h @@ -115,6 +115,9 @@ private: // common part of all ctors void Init(); + // terminate the current radio group, if any + void EndRadioGroup(); + // the exact menu geometry is defined by a struct derived from this one // which is opaque and defined by the renderer wxMenuGeometryInfo *m_geometry; @@ -127,6 +130,9 @@ private: wxAcceleratorTable m_accelTable; #endif // wxUSE_ACCEL + // the position of the first item in the current radio group or -1 + int m_startRadioGroup; + // it calls out OnDismiss() friend class wxPopupMenuWindow; DECLARE_DYNAMIC_CLASS(wxMenu) diff --git a/include/wx/univ/menuitem.h b/include/wx/univ/menuitem.h index 52049e5f71..eff0730a0c 100644 --- a/include/wx/univ/menuitem.h +++ b/include/wx/univ/menuitem.h @@ -48,6 +48,11 @@ public: const wxBitmap& GetBitmap(bool checked = TRUE) const { return checked ? m_bmpChecked : m_bmpUnchecked; } + // mark item as belonging to the given radio group + void SetAsRadioGroupStart(); + void SetRadioGroupStart(int start); + void SetRadioGroupEnd(int end); + // wxUniv-specific methods for implementation only starting from here // get the accel index of our label or -1 if none @@ -89,6 +94,19 @@ protected: wxBitmap m_bmpChecked, m_bmpUnchecked; + // the positions of the first and last items of the radio group this item + // 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; + // the position of the accelerator in our label, -1 if none int m_indexAccel; diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index 62dc90a1c8..f34cb82a0e 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -1018,6 +1018,8 @@ void wxMenu::Init() m_geometry = NULL; m_popupMenu = NULL; + + m_startRadioGroup = -1; } wxMenu::~wxMenu() @@ -1081,8 +1083,53 @@ void wxMenu::OnItemAdded(wxMenuItem *item) } } +void wxMenu::EndRadioGroup() +{ + // we're not inside a radio group any longer + m_startRadioGroup = -1; +} + bool wxMenu::DoAppend(wxMenuItem *item) { + bool check = FALSE; + + if ( item->GetKind() == wxITEM_RADIO ) + { + int count = GetMenuItemCount(); + + if ( m_startRadioGroup == -1 ) + { + // start a new radio group + 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 + { + EndRadioGroup(); + } + if ( !wxMenuBase::DoAppend(item) ) return FALSE; @@ -1410,6 +1457,9 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu, m_posY = m_height = -1; + m_radioGroup.start = -1; + m_isRadioGroupStart = FALSE; + UpdateAccelInfo(); } @@ -1499,12 +1549,79 @@ void wxMenuItem::Enable(bool enable) void wxMenuItem::Check(bool check) { - if ( check != m_isChecked ) + wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") ); + + if ( m_isChecked == check ) + return; + + if ( GetKind() == wxITEM_RADIO ) { - wxMenuItemBase::Check(check); + // it doesn't make sense to uncheck a radio item - what would this do? + if ( !check ) + return; - NotifyMenu(); + // 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; + } + + // also uncheck all the other items in this radio group + wxMenuItemList::Node *node = items.Item(start); + for ( int n = start; n <= end && node; n++ ) + { + if ( n != pos ) + { + node->GetData()->m_isChecked = FALSE; + } + node = node->GetNext(); + } } + + wxMenuItemBase::Check(check); + + NotifyMenu(); +} + +// 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; } // ---------------------------------------------------------------------------- -- 2.47.2