]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/menu.cpp
Save the mode in SetMode
[wxWidgets.git] / src / msw / menu.cpp
index a64d5bcbb151eee3212909b64b8efda0c1e8e1d5..e4e5317d3d54a20959a33756d7dca0f9b22467d6 100644 (file)
@@ -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
@@ -149,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
@@ -164,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<wxMenuItemList::compatibility_iterator>( 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<wxMenuInfoList::compatibility_iterator>( 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<wxMenuBar*>(this)->GetMenu(i) , GetMenuLabel(i) ) ;
-        list->Append( info ) ;
-    }
-    return m_menuInfos ;
-}
-
 // ---------------------------------------------------------------------------
 // wxMenu construction, adding and removing menu items
 // ---------------------------------------------------------------------------
@@ -271,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
@@ -283,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);
     }
 }
 
@@ -389,6 +294,8 @@ void wxMenu::UpdateAccel(wxMenuItem *item)
         {
             GetMenuBar()->RebuildAccelTable();
         }
+
+        ResetMaxAccelWidth();
     }
     //else: it is a separator, they can't have accels, nothing to do
 }
@@ -526,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;
                 }
@@ -658,6 +565,8 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 
                 // set menu as ownerdrawn
                 m_ownerDrawn = true;
+
+                ResetMaxAccelWidth();
             }
             // only update our margin for equals alignment to other item
             else if ( !updateAllMargins )
@@ -692,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);
@@ -802,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
@@ -852,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
 // ---------------------------------------------------------------------------
@@ -868,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"));
@@ -904,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"));
             }
@@ -916,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
 }
@@ -930,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);
@@ -946,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
 // ---------------------------------------------------------------------------
@@ -994,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);
     }
@@ -1112,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"));
             }
@@ -1179,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() )
     {
@@ -1238,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();
 }
 
 // ---------------------------------------------------------------------------
@@ -1251,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())
@@ -1308,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 )
     {
@@ -1364,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())
@@ -1455,8 +1381,6 @@ wxMenu *wxMenuBar::Remove(size_t pos)
             Refresh();
     }
 
-    m_titles.RemoveAt(pos);
-
     return menu;
 }