]> git.saurik.com Git - wxWidgets.git/commitdiff
Correct alignment of menu accelerator strings in owner-drawn menus.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:21:46 +0000 (13:21 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:21:46 +0000 (13:21 +0000)
Draw them right-aligned as the native menus do.

Closes #11479.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63224 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/menu.h
include/wx/msw/menuitem.h
src/msw/menu.cpp
src/msw/menuitem.cpp

index 0ce964a495684ea566b6a1bf2d254aac832c682a..852bb646a60dc7c57502331883e44865cf986e14 100644 (file)
@@ -91,6 +91,25 @@ public:
     wxAcceleratorTable *CreateAccelTable() const;
 #endif // wxUSE_ACCEL
 
+#if wxUSE_OWNER_DRAWN
+
+    int GetMaxAccelWidth()
+    {
+        if (m_maxAccelWidth == -1)
+            CalculateMaxAccelWidth();
+        return m_maxAccelWidth;
+    }
+
+    void ResetMaxAccelWidth()
+    {
+        m_maxAccelWidth = -1;
+    }
+
+private:
+    void CalculateMaxAccelWidth();
+
+#endif // wxUSE_OWNER_DRAWN
+
 protected:
     virtual wxMenuItem* DoAppend(wxMenuItem *item);
     virtual wxMenuItem* DoInsert(size_t pos, wxMenuItem *item);
@@ -126,6 +145,9 @@ private:
 
     // the max width of menu items bitmaps
     int m_maxBitmapWidth;
+
+    // the max width of menu items accels
+    int m_maxAccelWidth;
 #endif // wxUSE_OWNER_DRAWN
 
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxMenu)
index e885b980191fc9b7472d99f1dbddcf057b061322..a4cbaa820de3e779a4da7bd5fe86df5a82eceeee 100644 (file)
@@ -107,6 +107,7 @@ public:
     const wxBitmap& GetDisabledBitmap() const
         { return m_bmpDisabled; }
 
+    int MeasureAccelWidth() const;
 
     // override wxOwnerDrawn base class virtuals
     virtual wxString GetName() const;
index a64d5bcbb151eee3212909b64b8efda0c1e8e1d5..444a991ef8a79b749d4b76814c20c49c3b60dff3 100644 (file)
@@ -271,6 +271,7 @@ void wxMenu::Init()
 #if wxUSE_OWNER_DRAWN
     m_ownerDrawn = false;
     m_maxBitmapWidth = 0;
+    m_maxAccelWidth = -1;
 #endif // wxUSE_OWNER_DRAWN
 
     // create the menu
@@ -389,6 +390,8 @@ void wxMenu::UpdateAccel(wxMenuItem *item)
         {
             GetMenuBar()->RebuildAccelTable();
         }
+
+        ResetMaxAccelWidth();
     }
     //else: it is a separator, they can't have accels, nothing to do
 }
@@ -658,6 +661,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 )
@@ -802,6 +807,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 +859,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
 // ---------------------------------------------------------------------------
index 5214c1c813f08b9495edd5fad5b0694fbab7655f..83af40f8b3cefd79bf2fdd924e1e99f94cf2f7e8 100644 (file)
@@ -211,16 +211,26 @@ public:
     Margins CheckMargin;        // popup check margins
     Margins CheckBgMargin;      // popup check background margins
 
+    Margins ArrowMargin;        // popup submenu arrow margins
+
     Margins SeparatorMargin;    // popup separator margins
 
     SIZE CheckSize;             // popup check size metric
+    SIZE ArrowSize;             // popup submenu arrow size metric
     SIZE SeparatorSize;         // popup separator size metric
 
-    int AccelBorder;            // popup border space between
-                                // item text and accelerator
     int TextBorder;             // popup border space between
                                 // item text and gutter
 
+    int AccelBorder;            // popup border space between
+                                // item text and accelerator
+
+    int ArrowBorder;            // popup border space between
+                                // item accelerator and submenu arrow
+
+    int Offset;                 // system added space at the end of the menu,
+                                // add this offset for remove the extra space
+
     wxFont Font;                // default menu font
 
     bool AlwaysShowCues;        // must keyboard cues always be shown?
@@ -309,6 +319,10 @@ void MenuDrawData::Init()
                                TMT_CONTENTMARGINS, NULL,
                                reinterpret_cast<MARGINS*>(&CheckBgMargin));
 
+        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSUBMENU, 0,
+                               TMT_CONTENTMARGINS, NULL,
+                               reinterpret_cast<MARGINS*>(&ArrowMargin));
+
         theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
                                TMT_SIZINGMARGINS, NULL,
                                reinterpret_cast<MARGINS*>(&SeparatorMargin));
@@ -316,12 +330,19 @@ void MenuDrawData::Init()
         theme->GetThemePartSize(hTheme, NULL, MENU_POPUPCHECK, 0,
                                 NULL, TS_TRUE, &CheckSize);
 
+        theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSUBMENU, 0,
+                                NULL, TS_TRUE, &ArrowSize);
+
         theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
                                 NULL, TS_TRUE, &SeparatorSize);
 
-        theme->GetThemeInt(hTheme, MENU_POPUPBORDERS, 0, TMT_BORDERSIZE, &AccelBorder);
         theme->GetThemeInt(hTheme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &TextBorder);
 
+        AccelBorder = 34;
+        ArrowBorder = 0;
+
+        Offset = -14;
+
         wxNativeFontInfo fontInfo;
         theme->GetThemeSysFont(hTheme, TMT_MENUFONT, &fontInfo.lf);
         Font = wxFont(fontInfo);
@@ -352,6 +373,10 @@ void MenuDrawData::Init()
         CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
         CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
 
+        ArrowMargin = Margins();
+
+        ArrowSize = CheckSize;
+
         // separator height with margins
         int sepFullSize = metrics.iMenuHeight / 2;
 
@@ -365,6 +390,9 @@ void MenuDrawData::Init()
 
         TextBorder = 0;
         AccelBorder = 8;
+        ArrowBorder = 6;
+
+        Offset = -12;
 
         Font = wxFont(wxNativeFontInfo(metrics.lfMenuFont));
 
@@ -683,6 +711,21 @@ void wxMenuItem::SetItemLabel(const wxString& txt)
 
 #if wxUSE_OWNER_DRAWN
 
+int wxMenuItem::MeasureAccelWidth() const
+{
+    wxString accel = GetItemLabel().AfterFirst(wxT('\t'));
+
+    wxMemoryDC dc;
+    wxFont font;
+    GetFontToUse(font);
+    dc.SetFont(font);
+
+    wxCoord w;
+    dc.GetTextExtent(accel, &w, NULL);
+
+    return w;
+}
+
 wxString wxMenuItem::GetName() const
 {
     return GetItemLabelText();
@@ -706,10 +749,7 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
             return true;
         }
 
-        wxString str = GetItemLabel();
-
-        // text and accel separator char removal
-        str.Replace(wxT('\t'), wxEmptyString);
+        wxString str = GetName();
 
         wxMemoryDC dc;
         wxFont font;
@@ -719,12 +759,15 @@ bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
         wxCoord w, h;
         dc.GetTextExtent(str, &w, &h);
 
-        *width = w + data->TextBorder + data->AccelBorder;
+        *width = data->TextBorder + w + data->AccelBorder;
         *height = h;
 
-        // system added space at the end of the menu for the submenu expansion
-        // arrow, but we must add a 4-pixel separator for better apperance
-        *width += 4;
+        w = m_parentMenu->GetMaxAccelWidth();
+        if ( w > 0 )
+            *width += w + data->ArrowBorder;
+
+        *width += data->Offset;
+        *width += data->ArrowMargin.left + data->ArrowSize.cx + data->ArrowMargin.right;
     }
     else // don't draw the text, just the bitmap (if any)
     {
@@ -941,10 +984,17 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
                  (stat & wxODDisabled) && !(stat & wxODSelected) )
                 flags |= DSS_DISABLED;
 
-            // right align accel string with right edge of menu
-            // (offset by the margin width)
+            int x = rcText.right - data->ArrowMargin.left
+                                 - data->ArrowSize.cx
+                                 - data->ArrowMargin.right
+                                 - data->ArrowBorder;
+
+            // right align accel on FullTheme menu, left otherwise
+            if ( data->MenuLayout() == MenuDrawData::FullTheme)
+                x -= accelSize.cx;
+            else
+                x -= m_parentMenu->GetMaxAccelWidth();
 
-            int x = rcText.right - 16 - accelSize.cx;
             int y = rcText.top + (rcText.bottom - rcText.top - accelSize.cy) / 2;
 
             ::DrawState(hdc, NULL, NULL, (LPARAM)accel.wx_str(),