From c33396629144d09d2efb678e0d7f97290e69b1ac Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 6 May 2013 17:13:40 -0400 Subject: [PATCH] Draw truncated menu label in BMCPrivate, fixes #9735 ...instead of in BMenuItem and remove the truncation code from BMenuItem. The label truncation code cannot work in BMenuItem because the super menu helpfully resizes itself to fit the menu item. So, instead we do the label truncation in BMCPrivate making sure that BMenuItem there can't expand the BMCMenuBar because we set the width to fMenuField->_MenuBarWidth() explicity. Note that this only truncates the label in BMCMenuField, i.e. the label inside the menufield, it does nothing to the labels of the menu items in the attached BMenu or BPopUpMenu which is exactly what we want. --- headers/private/interface/BMCPrivate.h | 2 + src/kits/interface/BMCPrivate.cpp | 59 ++++++++++++++++++++++++++ src/kits/interface/MenuItem.cpp | 21 +-------- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/headers/private/interface/BMCPrivate.h b/headers/private/interface/BMCPrivate.h index 3fe04cdaf3..f3fea82fc2 100644 --- a/headers/private/interface/BMCPrivate.h +++ b/headers/private/interface/BMCPrivate.h @@ -62,6 +62,8 @@ private: void _Init(bool setMaxContentWidth); + void _DrawItems(BRect updateRect); + BMenuField* fMenuField; bool fFixedSize; BMessageRunner* fRunner; diff --git a/src/kits/interface/BMCPrivate.cpp b/src/kits/interface/BMCPrivate.cpp index 54240fe715..09d99b5139 100644 --- a/src/kits/interface/BMCPrivate.cpp +++ b/src/kits/interface/BMCPrivate.cpp @@ -12,16 +12,21 @@ #include #include +#include #include +#include #include #include #include #include #include #include +#include #include +#include + static const float kPopUpIndicatorWidth = 10.0f; static const float kMarginWidth = 3.0f; @@ -59,6 +64,7 @@ _BMCFilter_::Filter(BMessage* message, BHandler** handler) // #pragma mark - +using BPrivate::MenuPrivate; _BMCMenuBar_::_BMCMenuBar_(BRect frame, bool fixedSize, BMenuField* menuField) : @@ -331,3 +337,56 @@ _BMCMenuBar_::_Init(bool setMaxContentWidth) SetMaxContentWidth(fPreviousWidth - (left + right)); } + +void +_BMCMenuBar_::_DrawItems(BRect updateRect) +{ + MenuPrivate menuPrivate(this); + menuPrivate.CacheFontInfo(); + const BRect& padding = menuPrivate.Padding(); + float frameWidth = fMenuField->_MenuBarWidth() + - (padding.left + padding.right); + int32 itemCount = CountItems(); + + for (int32 i = 0; i < itemCount; i++) { + BMenuItem* item = ItemAt(i); + if (item == NULL) + continue; + + if (!item->Frame().Intersects(updateRect)) + continue; + + const char* label = item->Label(); + if (label == NULL) + continue; + + BPoint contentLocation(item->Frame().left + padding.left, + item->Frame().top + padding.top); + MovePenTo(contentLocation); + MovePenBy(0, menuPrivate.Ascent()); + + if (item->IsEnabled()) + SetHighColor(ui_color(B_MENU_ITEM_TEXT_COLOR)); + else + SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT)); + + SetDrawingMode(B_OP_OVER); + + if (frameWidth >= StringWidth(label)) + DrawString(label); + else { + // truncate label to fit + char* truncatedLabel = new char[strlen(label) + 4]; + BFont font; + GetFont(&font); + BString labelString(label); + font.TruncateString(&labelString, B_TRUNCATE_MIDDLE, frameWidth); + labelString.CopyInto(truncatedLabel, 0, labelString.Length()); + truncatedLabel[labelString.Length()] = '\0'; + DrawString(truncatedLabel); + delete[] truncatedLabel; + } + + SetDrawingMode(B_OP_COPY); + } +} diff --git a/src/kits/interface/MenuItem.cpp b/src/kits/interface/MenuItem.cpp index 1ab24907e4..fb79e1bc8f 100644 --- a/src/kits/interface/MenuItem.cpp +++ b/src/kits/interface/MenuItem.cpp @@ -399,28 +399,9 @@ BMenuItem::DrawContent() fSuper->MovePenBy(0, menuPrivate.Ascent()); BPoint lineStart = fSuper->PenLocation(); - float labelWidth, labelHeight; - GetContentSize(&labelWidth, &labelHeight); - fSuper->SetDrawingMode(B_OP_OVER); - float frameWidth = fBounds.Width(); - if (menuPrivate.State() == MENU_STATE_CLOSED) { - float leftMargin; - float rightMargin; - menuPrivate.GetItemMargins(&leftMargin, NULL, &rightMargin, NULL); - frameWidth = fSuper->Frame().Width() - rightMargin + leftMargin; - } - - if (frameWidth >= labelWidth) - fSuper->DrawString(fLabel); - else { - // truncate the label to fit - char* truncatedLabel = new char[strlen(fLabel) + 4]; - TruncateLabel(frameWidth, truncatedLabel); - fSuper->DrawString(truncatedLabel); - delete[] truncatedLabel; - } + fSuper->DrawString(fLabel); if (fSuper->AreTriggersEnabled() && fTriggerIndex != -1) { float escapements[fTriggerIndex + 1];