From 5f603da01a2d6af7f5fffafeb1ace3a521c5ef60 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Tue, 17 Jul 2018 21:03:11 +0200 Subject: [PATCH] Better shape for submenu arrow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just use BControLook where appropriate. It already provides a nice arrow drawing function (also used in DeskBar expander and in scrollbar buttons). Fix second part of #8900 Changes by John Scipione: Update menu mark and submenu arrow color with menu text color Use text color for checkmark and submenu arrow colors, tint less black. This means that colored bg/white text menu item will also draw a white checkmark and submenu arrow. Break out BMenuItem::Draw functionality into private methods _IsActive, _LowColor() and _HighColor() methods and use them to set the mark colors. Scale submenu arrow and checkmark with item height (which scales with font size.) does not align shortcuts with submenu arrows... but if you were to do that you'd add item->Bounds().Height() / 2. Signed-off-by: John Scipione Change-Id: I8299094ef88bf227510b116eb1b84c261dc94723 Reviewed-on: https://review.haiku-os.org/c/341 Reviewed-by: Stefano Ceccherini Reviewed-by: Axel Dörfler Reviewed-by: waddlesplash --- headers/os/interface/MenuItem.h | 4 ++ src/kits/interface/Menu.cpp | 2 +- src/kits/interface/MenuItem.cpp | 113 +++++++++++++++++--------------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/headers/os/interface/MenuItem.h b/headers/os/interface/MenuItem.h index 055ccc3c05..cf832a3fc5 100644 --- a/headers/os/interface/MenuItem.h +++ b/headers/os/interface/MenuItem.h @@ -86,6 +86,10 @@ private: void _InitData(); void _InitMenuData(BMenu* menu); + bool _IsActivated(); + rgb_color _LowColor(); + rgb_color _HighColor(); + void _DrawMarkSymbol(); void _DrawShortcutSymbol(); void _DrawSubmenuSymbol(); diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 457868a110..c081e6fa44 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -2267,7 +2267,7 @@ BMenu::_ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, + fPad.bottom; if (item->fSubmenu != NULL) - width += item->Frame().Height(); + width += item->Frame().Height() / 2; frame.right = std::max(frame.right, width + fPad.left + fPad.right); frame.bottom = item->fBounds.bottom; diff --git a/src/kits/interface/MenuItem.cpp b/src/kits/interface/MenuItem.cpp index 7e1a982d19..5c7651783b 100644 --- a/src/kits/interface/MenuItem.cpp +++ b/src/kits/interface/MenuItem.cpp @@ -15,6 +15,8 @@ #include #include +#include + #include #include #include @@ -27,6 +29,8 @@ #include "utf8_functions.h" +static const float kMarkTint = 0.75f; + // map control key shortcuts to drawable Unicode characters // cf. http://unicode.org/charts/PDF/U2190.pdf const char* kUTF8ControlMap[] = { @@ -450,31 +454,14 @@ BMenuItem::Draw() const color_which lowColor = fSuper->LowUIColor(); const color_which highColor = fSuper->HighUIColor(); - bool enabled = IsEnabled(); - bool selected = IsSelected(); - bool activated = selected && (enabled || Submenu() != NULL); + fSuper->SetLowColor(_LowColor()); + fSuper->SetHighColor(_HighColor()); - // set low color - if (activated) { - fSuper->SetLowColor(ui_color(B_MENU_SELECTED_BACKGROUND_COLOR)); + if (_IsActivated()) { // fill in the background - BRect rect(Frame()); - be_control_look->DrawMenuItemBackground(fSuper, rect, Frame(), + BRect frame(Frame()); + be_control_look->DrawMenuItemBackground(fSuper, frame, frame, fSuper->LowColor(), BControlLook::B_ACTIVATED); - } else - fSuper->SetLowColor(ui_color(B_MENU_BACKGROUND_COLOR)); - - // set high color - if (activated && enabled) - fSuper->SetHighColor(ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR)); - else if (enabled) - fSuper->SetHighColor(ui_color(B_MENU_ITEM_TEXT_COLOR)); - else { - rgb_color bgColor = fSuper->LowColor(); - if (bgColor.red + bgColor.green + bgColor.blue > 128 * 3) - fSuper->SetHighColor(tint_color(bgColor, B_DISABLED_LABEL_TINT)); - else - fSuper->SetHighColor(tint_color(bgColor, B_LIGHTEN_2_TINT)); } // draw content @@ -677,6 +664,45 @@ BMenuItem::Select(bool selected) } +bool +BMenuItem::_IsActivated() +{ + return IsSelected() && (IsEnabled() || fSubmenu != NULL); +} + + +rgb_color +BMenuItem::_LowColor() +{ + return _IsActivated() ? ui_color(B_MENU_SELECTED_BACKGROUND_COLOR) + : ui_color(B_MENU_BACKGROUND_COLOR); +} + + +rgb_color +BMenuItem::_HighColor() +{ + rgb_color highColor; + + bool isEnabled = IsEnabled(); + bool isSelected = IsSelected(); + + if (isEnabled && isSelected) + highColor = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + else if (isEnabled) + highColor = ui_color(B_MENU_ITEM_TEXT_COLOR); + else { + rgb_color bgColor = fSuper->LowColor(); + if (bgColor.red + bgColor.green + bgColor.blue > 128 * 3) + highColor = tint_color(bgColor, B_DISABLED_LABEL_TINT); + else + highColor = tint_color(bgColor, B_LIGHTEN_2_TINT); + } + + return highColor; +} + + void BMenuItem::_DrawMarkSymbol() { @@ -692,7 +718,7 @@ BMenuItem::_DrawMarkSymbol() BPoint center(floorf((r.left + r.right) / 2.0), floorf((r.top + r.bottom) / 2.0)); - float size = min_c(r.Height() - 2, r.Width()); + float size = std::min(r.Height() - 2, r.Width()); r.top = floorf(center.y - size / 2 + 0.5); r.bottom = floorf(center.y + size / 2 + 0.5); r.left = floorf(center.x - size / 2 + 0.5); @@ -706,6 +732,7 @@ BMenuItem::_DrawMarkSymbol() arrowShape.LineTo(BPoint(center.x - size * 0.25, center.y + size)); arrowShape.LineTo(BPoint(center.x + size, center.y - size)); + fSuper->SetHighColor(tint_color(_HighColor(), kMarkTint)); fSuper->SetDrawingMode(B_OP_OVER); fSuper->SetPenSize(2.0); // NOTE: StrokeShape() offsets the shape by the current pen position, @@ -726,8 +753,8 @@ BMenuItem::_DrawShortcutSymbol() BPoint where = ContentLocation(); where.x = fBounds.right - font.Size(); - if (fSubmenu) - where.x -= fBounds.Height() - 3; + if (fSubmenu != NULL) + where.x -= fBounds.Height() / 2; const float ascent = MenuPrivate(fSuper).Ascent(); if (fShortcutChar < B_SPACE && kUTF8ControlMap[(int)fShortcutChar]) @@ -775,36 +802,18 @@ BMenuItem::_DrawSubmenuSymbol() { fSuper->PushState(); - BRect r(fBounds); - float rightMargin; - MenuPrivate(fSuper).GetItemMargins(NULL, NULL, &rightMargin, NULL); - r.left = r.right - rightMargin + 3; - r.right -= 1; + float symbolSize = roundf(Frame().Height() * 2 / 3); - BPoint center(floorf((r.left + r.right) / 2.0), - floorf((r.top + r.bottom) / 2.0)); + BRect rect(fBounds); + rect.left = rect.right - symbolSize; - float size = min_c(r.Height() - 2, r.Width()); - r.top = floorf(center.y - size / 2 + 0.5); - r.bottom = floorf(center.y + size / 2 + 0.5); - r.left = floorf(center.x - size / 2 + 0.5); - r.right = floorf(center.x + size / 2 + 0.5); + // 14px by default, scaled with font size up to right margin - padding + BRect symbolRect(0, 0, symbolSize, symbolSize); + symbolRect.OffsetTo(BPoint(rect.left, + fBounds.top + (fBounds.Height() - symbolSize) / 2)); - BShape arrowShape; - center.x += 0.5; - center.y += 0.5; - size *= 0.25; - float hSize = size * 0.7; - arrowShape.MoveTo(BPoint(center.x - hSize, center.y - size)); - arrowShape.LineTo(BPoint(center.x + hSize, center.y)); - arrowShape.LineTo(BPoint(center.x - hSize, center.y + size)); - - fSuper->SetDrawingMode(B_OP_OVER); - fSuper->SetPenSize(ceilf(size * 0.4)); - // NOTE: StrokeShape() offsets the shape by the current pen position, - // it is not documented in the BeBook, but it is true! - fSuper->MovePenTo(B_ORIGIN); - fSuper->StrokeShape(&arrowShape); + be_control_look->DrawArrowShape(Menu(), symbolRect, symbolRect, + _HighColor(), BControlLook::B_RIGHT_ARROW, 0, kMarkTint); fSuper->PopState(); }