]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/menu.cpp
fixed sorting the items which have indirect data (i.e. images set for open/closed...
[wxWidgets.git] / src / msw / menu.cpp
index 7b85d299277d252f4988addeed3cab503a6b8bd2..93e92056ef02f1f94f3d2b4e323ac341e7eee8df 100644 (file)
@@ -28,6 +28,8 @@
     #pragma hdrstop
 #endif
 
+#if wxUSE_MENUS
+
 #ifndef WX_PRECOMP
     #include "wx/frame.h"
     #include "wx/menu.h"
@@ -62,10 +64,8 @@ static const int idMenuTitle = -2;
 // macros
 // ----------------------------------------------------------------------------
 
-#if !USE_SHARED_LIBRARY
-    IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
-    IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
-#endif
+IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
+IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow)
 
 // ============================================================================
 // implementation
@@ -84,7 +84,7 @@ void wxMenu::Init()
     m_hMenu = (WXHMENU)CreatePopupMenu();
     if ( !m_hMenu )
     {
-        wxLogLastError("CreatePopupMenu");
+        wxLogLastError(wxT("CreatePopupMenu"));
     }
 
     // if we have a title, insert it in the beginning of the menu
@@ -105,7 +105,7 @@ wxMenu::~wxMenu()
     {
         if ( !::DestroyMenu(GetHmenu()) )
         {
-            wxLogLastError("DestroyMenu");
+            wxLogLastError(wxT("DestroyMenu"));
         }
     }
 
@@ -137,35 +137,50 @@ int wxMenu::FindAccel(int id) const
 
 void wxMenu::UpdateAccel(wxMenuItem *item)
 {
-    // find the (new) accel for this item
-    wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
-    if ( accel )
-        accel->m_command = item->GetId();
-
-    // find the old one
-    int n = FindAccel(item->GetId());
-    if ( n == wxNOT_FOUND )
+    if ( item->IsSubMenu() )
     {
-        // no old, add new if any
-        if ( accel )
-            m_accels.Add(accel);
-        else
-            return;     // skipping RebuildAccelTable() below
+        wxMenu *submenu = item->GetSubMenu();
+        wxMenuItemList::Node *node = submenu->GetMenuItems().GetFirst();
+        while ( node )
+        {
+            UpdateAccel(node->GetData());
+
+            node = node->GetNext();
+        }
     }
-    else
+    else if ( !item->IsSeparator() )
     {
-        // replace old with new or just remove the old one if no new
-        delete m_accels[n];
+        // find the (new) accel for this item
+        wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
         if ( accel )
-            m_accels[n] = accel;
+            accel->m_command = item->GetId();
+
+        // find the old one
+        int n = FindAccel(item->GetId());
+        if ( n == wxNOT_FOUND )
+        {
+            // no old, add new if any
+            if ( accel )
+                m_accels.Add(accel);
+            else
+                return;     // skipping RebuildAccelTable() below
+        }
         else
-            m_accels.Remove(n);
-    }
+        {
+            // replace old with new or just remove the old one if no new
+            delete m_accels[n];
+            if ( accel )
+                m_accels[n] = accel;
+            else
+                m_accels.RemoveAt(n);
+        }
 
-    if ( IsAttached() )
-    {
-        m_menuBar->RebuildAccelTable();
+        if ( IsAttached() )
+        {
+            m_menuBar->RebuildAccelTable();
+        }
     }
+    //else: it is a separator, they can't have accels, nothing to do
 }
 
 #endif // wxUSE_ACCEL
@@ -221,7 +236,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
         // menu is just a normal string (passed in data parameter)
         flags |= MF_STRING;
 
-        pData = (char*)pItem->GetText().c_str();
+        pData = (wxChar*)pItem->GetText().c_str();
     }
 
     BOOL ok;
@@ -236,7 +251,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 
     if ( !ok )
     {
-        wxLogLastError("Insert or AppendMenu");
+        wxLogLastError(wxT("Insert or AppendMenu"));
 
         return FALSE;
     }
@@ -260,7 +275,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 #endif // __WIN32__
 
         // if we're already attached to the menubar, we must update it
-        if ( IsAttached() )
+        if ( IsAttached() && m_menuBar->IsAttached() )
         {
             m_menuBar->Refresh();
         }
@@ -302,7 +317,7 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
     {
         delete m_accels[n];
 
-        m_accels.Remove(n);
+        m_accels.RemoveAt(n);
     }
     //else: this item doesn't have an accel, nothing to do
 #endif // wxUSE_ACCEL
@@ -310,10 +325,10 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
     // remove the item from the menu
     if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
     {
-        wxLogLastError("RemoveMenu");
+        wxLogLastError(wxT("RemoveMenu"));
     }
 
-    if ( IsAttached() )
+    if ( IsAttached() && m_menuBar->IsAttached() )
     {
         // otherwise, the chane won't be visible
         m_menuBar->Refresh();
@@ -363,7 +378,7 @@ void wxMenu::SetTitle(const wxString& label)
                                (unsigned)idMenuTitle, m_title) ||
                  !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
             {
-                wxLogLastError("InsertMenu");
+                wxLogLastError(wxT("InsertMenu"));
             }
         }
     }
@@ -375,7 +390,7 @@ void wxMenu::SetTitle(const wxString& label)
             if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
                  !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
             {
-                wxLogLastError("RemoveMenu");
+                wxLogLastError(wxT("RemoveMenu"));
             }
         }
         else
@@ -385,7 +400,7 @@ void wxMenu::SetTitle(const wxString& label)
                              MF_BYPOSITION | MF_STRING,
                              (unsigned)idMenuTitle, m_title) )
             {
-                wxLogLastError("ModifyMenu");
+                wxLogLastError(wxT("ModifyMenu"));
             }
         }
     }
@@ -401,7 +416,7 @@ void wxMenu::SetTitle(const wxString& label)
 
         if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) )
         {
-            wxLogLastError("SetMenuItemInfo");
+            wxLogLastError(wxT("SetMenuItemInfo"));
         }
     }
 #endif // Win32
@@ -418,64 +433,20 @@ bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id)
     // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
     if ( id != (WXWORD)idMenuTitle )
     {
-        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
-        event.SetEventObject( this );
-        event.SetId( id );
-        event.SetInt( id );
-        ProcessCommand(event);
+        // VZ: previosuly, the command int was set to id too which was quite
+        //     useless anyhow (as it could be retrieved using GetId()) and
+        //     uncompatible with wxGTK, so now we use the command int instead
+        //     to pass the checked status
+        SendEvent(id, ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND) & MF_CHECKED);
     }
 
     return TRUE;
 }
 
-bool wxMenu::ProcessCommand(wxCommandEvent & event)
-{
-    bool processed = FALSE;
-
-#if wxUSE_MENU_CALLBACK
-    // Try a callback
-    if (m_callback)
-    {
-        (void)(*(m_callback))(*this, event);
-        processed = TRUE;
-    }
-#endif // wxUSE_MENU_CALLBACK
-
-    // Try the menu's event handler
-    if ( !processed && GetEventHandler())
-    {
-        processed = GetEventHandler()->ProcessEvent(event);
-    }
-
-    // Try the window the menu was popped up from (and up through the
-    // hierarchy)
-    wxWindow *win = GetInvokingWindow();
-    if ( !processed && win )
-        processed = win->GetEventHandler()->ProcessEvent(event);
-
-    return processed;
-}
-
 // ---------------------------------------------------------------------------
 // other
 // ---------------------------------------------------------------------------
 
-void wxMenu::Attach(wxMenuBar *menubar)
-{
-    // menu can be in at most one menubar because otherwise they would both
-    // delete the menu pointer
-    wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
-
-    m_menuBar = menubar;
-}
-
-void wxMenu::Detach()
-{
-    wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
-
-    m_menuBar = NULL;
-}
-
 wxWindow *wxMenu::GetWindow() const
 {
     if ( m_invokingWindow != NULL )
@@ -493,7 +464,6 @@ wxWindow *wxMenu::GetWindow() const
 void wxMenuBar::Init()
 {
     m_eventHandler = this;
-    m_menuBarFrame = NULL;
     m_hMenu = 0;
 }
 
@@ -534,21 +504,19 @@ void wxMenuBar::Refresh()
 {
     wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") );
 
-    DrawMenuBar(GetHwndOf(m_menuBarFrame));
+    DrawMenuBar(GetHwndOf(GetFrame()));
 }
 
 WXHMENU wxMenuBar::Create()
 {
-    if (m_hMenu != 0 )
+    if ( m_hMenu != 0 )
         return m_hMenu;
 
-    wxCHECK_MSG( !m_hMenu, TRUE, wxT("menubar already created") );
-
     m_hMenu = (WXHMENU)::CreateMenu();
 
     if ( !m_hMenu )
     {
-        wxLogLastError("CreateMenu");
+        wxLogLastError(wxT("CreateMenu"));
     }
     else
     {
@@ -559,7 +527,7 @@ WXHMENU wxMenuBar::Create()
                                (UINT)m_menus[i]->GetHMenu(),
                                m_titles[i]) )
             {
-                wxLogLastError("AppendMenu");
+                wxLogLastError(wxT("AppendMenu"));
             }
         }
     }
@@ -620,7 +588,7 @@ void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
     if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
                       id, label) == (int)0xFFFFFFFF )
     {
-        wxLogLastError("ModifyMenu");
+        wxLogLastError(wxT("ModifyMenu"));
     }
 
     Refresh();
@@ -634,22 +602,6 @@ wxString wxMenuBar::GetLabelTop(size_t pos) const
     return m_titles[pos];
 }
 
-int wxMenuBar::FindMenu(const wxString& title)
-{
-    wxString menuTitle = wxStripMenuCodes(title);
-
-    size_t count = GetMenuCount();
-    for ( size_t i = 0; i < count; i++ )
-    {
-        wxString title = wxStripMenuCodes(m_titles[i]);
-        if ( menuTitle == title )
-            return i; 
-    }
-
-    return wxNOT_FOUND;
-
-}
-
 // ---------------------------------------------------------------------------
 // wxMenuBar construction
 // ---------------------------------------------------------------------------
@@ -666,14 +618,14 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
         // can't use ModifyMenu() because it deletes the submenu it replaces
         if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
         {
-            wxLogLastError("RemoveMenu");
+            wxLogLastError(wxT("RemoveMenu"));
         }
 
         if ( !::InsertMenu(GetHmenu(), (UINT)pos,
                            MF_BYPOSITION | MF_POPUP | MF_STRING,
                            (UINT)GetHmenuOf(menu), title) )
         {
-            wxLogLastError("InsertMenu");
+            wxLogLastError(wxT("InsertMenu"));
         }
 
 #if wxUSE_ACCEL
@@ -697,15 +649,13 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 
     m_titles.Insert(title, pos);
 
-    menu->Attach(this);
-
     if ( IsAttached() )
     {
         if ( !::InsertMenu(GetHmenu(), pos,
                            MF_BYPOSITION | MF_POPUP | MF_STRING,
                            (UINT)GetHmenuOf(menu), title) )
         {
-            wxLogLastError("InsertMenu");
+            wxLogLastError(wxT("InsertMenu"));
         }
 
 #if wxUSE_ACCEL
@@ -730,7 +680,8 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
     if ( !wxMenuBarBase::Append(menu, title) )
         return FALSE;
 
-    menu->Attach(this);
+    // Already done in Append above
+    //menu->Attach(this);
 
     m_titles.Add(title);
 
@@ -766,11 +717,9 @@ wxMenu *wxMenuBar::Remove(size_t pos)
     {
         if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
         {
-            wxLogLastError("RemoveMenu");
+            wxLogLastError(wxT("RemoveMenu"));
         }
 
-        menu->Detach();
-
 #if wxUSE_ACCEL
         if ( menu->HasAccels() )
         {
@@ -819,7 +768,7 @@ void wxMenuBar::RebuildAccelTable()
 
 void wxMenuBar::Attach(wxFrame *frame)
 {
-//    wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
+    wxMenuBarBase::Attach(frame);
 
     m_menuBarFrame = frame;
 
@@ -830,44 +779,9 @@ void wxMenuBar::Attach(wxFrame *frame)
 
 void wxMenuBar::Detach()
 {
-//    ::DestroyMenu((HMENU)m_hMenu);
     m_hMenu = (WXHMENU)NULL;
-    m_menuBarFrame = NULL;
-}
-
-
-// ---------------------------------------------------------------------------
-// wxMenuBar searching for menu items
-// ---------------------------------------------------------------------------
-
-// Find the itemString in menuString, and return the item id or wxNOT_FOUND
-int wxMenuBar::FindMenuItem(const wxString& menuString,
-                            const wxString& itemString) const
-{
-    wxString menuLabel = wxStripMenuCodes(menuString);
-    size_t count = GetMenuCount();
-    for ( size_t i = 0; i < count; i++ )
-    {
-        wxString title = wxStripMenuCodes(m_titles[i]);
-        if ( menuString == title )
-            return m_menus[i]->FindItem(itemString);
-    }
-
-    return wxNOT_FOUND;
-}
-
-wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
-{
-    if ( itemMenu )
-        *itemMenu = NULL;
-
-    wxMenuItem *item = NULL;
-    size_t count = GetMenuCount();
-    for ( size_t i = 0; !item && (i < count); i++ )
-    {
-        item = m_menus[i]->FindItem(id, itemMenu);
-    }
 
-    return item;
+    wxMenuBarBase::Detach();
 }
 
+#endif // wxUSE_MENUS