Correct alignment of menu accelerator strings in owner-drawn menus.

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
This commit is contained in:
Vadim Zeitlin
2010-01-23 13:21:46 +00:00
parent aa4919edd1
commit 9c32ed26a2
4 changed files with 122 additions and 14 deletions

View 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)

View 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;

View 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
// ---------------------------------------------------------------------------

View File

@@ -211,15 +211,25 @@ 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 TextBorder; // popup border space between
// item text and gutter
int AccelBorder; // popup border space between
// item text and accelerator
int TextBorder; // popup border space between
// item text and gutter
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
@@ -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(),