]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/menu.cpp
use StretchDIBits() if we're drawing a DIB and not a DDB in Blit()
[wxWidgets.git] / src / univ / menu.cpp
index 6eed51bf9766c65d220c33adf793345f6736f9d8..bba605997faaeaad5ebdf24fe0b89f32b0bf7628 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     25.08.00
 // RCS-ID:      $Id$
 // Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
@@ -314,6 +314,12 @@ wxPopupMenuWindow::wxPopupMenuWindow(wxWindow *parent, wxMenu *menu)
 
 wxPopupMenuWindow::~wxPopupMenuWindow()
 {
+    // When m_popupMenu in wxMenu is deleted because it
+    // is a child of an old menu bar being deleted (note: it does
+    // not get destroyed by the wxMenu destructor, but
+    // by DestroyChildren()), m_popupMenu should be reset to NULL.
+
+    m_menu->m_popupMenu = NULL;
 }
 
 // ----------------------------------------------------------------------------
@@ -1012,6 +1018,8 @@ void wxMenu::Init()
     m_geometry = NULL;
 
     m_popupMenu = NULL;
+
+    m_startRadioGroup = -1;
 }
 
 wxMenu::~wxMenu()
@@ -1075,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;
 
@@ -1397,23 +1450,16 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
                        int id,
                        const wxString& text,
                        const wxString& help,
-                       bool isCheckable,
+                       wxItemKind kind,
                        wxMenu *subMenu)
+          : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
 {
-    m_id = id;
-    m_parentMenu = parentMenu;
-    m_subMenu = subMenu;
-
-    m_text = text;
-    m_help = help;
-
-    m_isCheckable = isCheckable;
-    m_isEnabled = TRUE;
-    m_isChecked = FALSE;
-
     m_posY =
     m_height = -1;
 
+    m_radioGroup.start = -1;
+    m_isRadioGroupStart = FALSE;
+
     UpdateAccelInfo();
 }
 
@@ -1430,10 +1476,10 @@ wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
                                 int id,
                                 const wxString& name,
                                 const wxString& help,
-                                bool isCheckable,
+                                wxItemKind kind,
                                 wxMenu *subMenu)
 {
-    return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
+    return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
 }
 
 /* static */
@@ -1474,7 +1520,7 @@ void wxMenuItem::SetText(const wxString& text)
 
 void wxMenuItem::SetCheckable(bool checkable)
 {
-    if ( checkable != m_isCheckable )
+    if ( checkable != IsCheckable() )
     {
         wxMenuItemBase::SetCheckable(checkable);
 
@@ -1503,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;
 }
 
 // ----------------------------------------------------------------------------
@@ -1524,6 +1637,8 @@ void wxMenuBar::Init()
     m_menuShown = NULL;
 
     m_shouldShowMenu = FALSE;
+    
+    m_windowStyle |= wxNO_FULL_REPAINT_ON_RESIZE;
 }
 
 void wxMenuBar::Attach(wxFrame *frame)
@@ -2250,7 +2365,7 @@ void wxMenuBar::PopupCurrentMenu(bool selectFirst)
     wxCHECK_RET( m_current != -1, _T("no menu to popup") );
 
     // forgot to call DismissMenu()?
-    wxASSERT_MSG( !m_menuShown, _T("shouldn't show two menu at once!") );
+    wxASSERT_MSG( !m_menuShown, _T("shouldn't show two menus at once!") );
 
     // in any case, we should show it - even if we won't
     m_shouldShowMenu = TRUE;