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.
This commit is contained in:
John Scipione 2013-05-06 17:13:40 -04:00
parent 1afff67178
commit c333966291
3 changed files with 62 additions and 20 deletions

View File

@ -62,6 +62,8 @@ private:
void _Init(bool setMaxContentWidth);
void _DrawItems(BRect updateRect);
BMenuField* fMenuField;
bool fFixedSize;
BMessageRunner* fRunner;

View File

@ -12,16 +12,21 @@
#include <BMCPrivate.h>
#include <stdio.h>
#include <string.h>
#include <ControlLook.h>
#include <Font.h>
#include <LayoutUtils.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
#include <MessageRunner.h>
#include <Region.h>
#include <String.h>
#include <Window.h>
#include <MenuPrivate.h>
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);
}
}

View File

@ -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];