Better shape for submenu arrow

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 <[email protected]>

Change-Id: I8299094ef88bf227510b116eb1b84c261dc94723
Reviewed-on: https://review.haiku-os.org/c/341
Reviewed-by: Stefano Ceccherini <[email protected]>
Reviewed-by: Axel Dörfler <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Adrien Destugues
2019-01-14 15:59:57 +00:00
committed by waddlesplash
parent ee3106db4a
commit 5f603da01a
3 changed files with 66 additions and 53 deletions
+4
View File
@@ -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();
+1 -1
View File
@@ -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;
+61 -52
View File
@@ -15,6 +15,8 @@
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <Bitmap.h>
#include <ControlLook.h>
#include <MenuItem.h>
@@ -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();
}