Commit f2baca71 authored by Yulun Wu's avatar Yulun Wu Committed by Commit Bot

Menu Model: fix bug where menu item title was greyed out because it is disabled.

The old approach of adding title as a disabled item meant that this CL:

https://chromium-review.googlesource.com/c/chromium/src/+/1788198

causes the menu title to be displayed in grey text instead of solid black text. This CL introduces a new menu type that, while still disabled and non-reactive, be displayed in solid black text.

Bug: 1006203
Change-Id: I9fa38132160228ebde5bd43d8db9c2f60d5f001c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1841583Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Commit-Queue: Yulun Wu <yulunwu@chromium.org>
Auto-Submit: Yulun Wu <yulunwu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707147}
parent da43e8c1
...@@ -20,7 +20,7 @@ ShelfApplicationMenuModel::ShelfApplicationMenuModel( ...@@ -20,7 +20,7 @@ ShelfApplicationMenuModel::ShelfApplicationMenuModel(
Items items, Items items,
ShelfItemDelegate* delegate) ShelfItemDelegate* delegate)
: ui::SimpleMenuModel(this), delegate_(delegate) { : ui::SimpleMenuModel(this), delegate_(delegate) {
AddItem(std::numeric_limits<int>::max(), title); AddTitle(title);
for (size_t i = 0; i < items.size(); i++) for (size_t i = 0; i < items.size(); i++)
AddItemWithIcon(i, items[i].first, items[i].second); AddItemWithIcon(i, items[i].first, items[i].second);
AddSeparator(ui::SPACING_SEPARATOR); AddSeparator(ui::SPACING_SEPARATOR);
......
...@@ -51,7 +51,7 @@ TEST(ShelfApplicationMenuModelTest, VerifyContentsWithNoMenuItems) { ...@@ -51,7 +51,7 @@ TEST(ShelfApplicationMenuModelTest, VerifyContentsWithNoMenuItems) {
ShelfApplicationMenuModel menu(title, {}, nullptr); ShelfApplicationMenuModel menu(title, {}, nullptr);
// Expect the title and a separator. // Expect the title and a separator.
ASSERT_EQ(2, menu.GetItemCount()); ASSERT_EQ(2, menu.GetItemCount());
EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu.GetTypeAt(0)); EXPECT_EQ(ui::MenuModel::TYPE_TITLE, menu.GetTypeAt(0));
EXPECT_EQ(title, menu.GetLabelAt(0)); EXPECT_EQ(title, menu.GetLabelAt(0));
EXPECT_FALSE(menu.IsEnabledAt(0)); EXPECT_FALSE(menu.IsEnabledAt(0));
EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, menu.GetTypeAt(1)); EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, menu.GetTypeAt(1));
...@@ -75,7 +75,7 @@ TEST(ShelfApplicationMenuModelTest, VerifyContentsWithMenuItems) { ...@@ -75,7 +75,7 @@ TEST(ShelfApplicationMenuModelTest, VerifyContentsWithMenuItems) {
ASSERT_EQ(static_cast<int>(5), menu.GetItemCount()); ASSERT_EQ(static_cast<int>(5), menu.GetItemCount());
// The label title should not be enabled. // The label title should not be enabled.
EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu.GetTypeAt(0)); EXPECT_EQ(ui::MenuModel::TYPE_TITLE, menu.GetTypeAt(0));
EXPECT_EQ(title, menu.GetLabelAt(0)); EXPECT_EQ(title, menu.GetLabelAt(0));
EXPECT_FALSE(menu.IsEnabledAt(0)); EXPECT_FALSE(menu.IsEnabledAt(0));
......
...@@ -67,6 +67,7 @@ MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu, ...@@ -67,6 +67,7 @@ MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu,
switch (menu->GetTypeAt(i)) { switch (menu->GetTypeAt(i)) {
case ui::MenuModel::TYPE_COMMAND: case ui::MenuModel::TYPE_COMMAND:
case ui::MenuModel::TYPE_HIGHLIGHTED: case ui::MenuModel::TYPE_HIGHLIGHTED:
case ui::MenuModel::TYPE_TITLE:
// Nothing special to do. // Nothing special to do.
break; break;
case ui::MenuModel::TYPE_CHECK: case ui::MenuModel::TYPE_CHECK:
......
...@@ -149,6 +149,9 @@ class TestMenuModelBuilder { ...@@ -149,6 +149,9 @@ class TestMenuModelBuilder {
case ui::MenuModel::TYPE_COMMAND: case ui::MenuModel::TYPE_COMMAND:
menu->AddItem(0, label_); menu->AddItem(0, label_);
break; break;
case ui::MenuModel::TYPE_TITLE:
menu->AddTitle(label_);
break;
case ui::MenuModel::TYPE_CHECK: case ui::MenuModel::TYPE_CHECK:
menu->AddCheckItem(0, label_); menu->AddCheckItem(0, label_);
break; break;
......
...@@ -39,6 +39,8 @@ class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> { ...@@ -39,6 +39,8 @@ class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> {
TYPE_HIGHLIGHTED, // Performs an action when selected, and has a different TYPE_HIGHLIGHTED, // Performs an action when selected, and has a different
// colored background. When placed at the bottom, the // colored background. When placed at the bottom, the
// background matches the menu's rounded corners. // background matches the menu's rounded corners.
TYPE_TITLE, // Plain text that does not perform any action when
// selected.
}; };
MenuModel(); MenuModel();
......
...@@ -17,6 +17,10 @@ namespace ui { ...@@ -17,6 +17,10 @@ namespace ui {
const int kSeparatorId = -1; const int kSeparatorId = -1;
// Text items are rendered as enabled but are non-interactive with no actions
// and cannot be highlighted.
const int kTitleId = -2;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SimpleMenuModel::Delegate, public: // SimpleMenuModel::Delegate, public:
...@@ -142,6 +146,10 @@ void SimpleMenuModel::AddHighlightedItemWithIcon(int command_id, ...@@ -142,6 +146,10 @@ void SimpleMenuModel::AddHighlightedItemWithIcon(int command_id,
AppendItem(std::move(item)); AppendItem(std::move(item));
} }
void SimpleMenuModel::AddTitle(const base::string16& label) {
AppendItem(Item(kTitleId, TYPE_TITLE, label));
}
void SimpleMenuModel::AddSeparator(MenuSeparatorType separator_type) { void SimpleMenuModel::AddSeparator(MenuSeparatorType separator_type) {
if (items_.empty()) { if (items_.empty()) {
if (separator_type == NORMAL_SEPARATOR) { if (separator_type == NORMAL_SEPARATOR) {
...@@ -460,6 +468,9 @@ ButtonMenuItemModel* SimpleMenuModel::GetButtonMenuItemAt(int index) const { ...@@ -460,6 +468,9 @@ ButtonMenuItemModel* SimpleMenuModel::GetButtonMenuItemAt(int index) const {
bool SimpleMenuModel::IsEnabledAt(int index) const { bool SimpleMenuModel::IsEnabledAt(int index) const {
int command_id = GetCommandIdAt(index); int command_id = GetCommandIdAt(index);
if (command_id == kTitleId)
return false;
if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index)) if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index))
return items_[ValidateItemIndex(index)].enabled; return items_[ValidateItemIndex(index)].enabled;
...@@ -469,7 +480,8 @@ bool SimpleMenuModel::IsEnabledAt(int index) const { ...@@ -469,7 +480,8 @@ bool SimpleMenuModel::IsEnabledAt(int index) const {
bool SimpleMenuModel::IsVisibleAt(int index) const { bool SimpleMenuModel::IsVisibleAt(int index) const {
int command_id = GetCommandIdAt(index); int command_id = GetCommandIdAt(index);
if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index)) if (!delegate_ || command_id == kSeparatorId || command_id == kTitleId ||
GetButtonMenuItemAt(index))
return items_[ValidateItemIndex(index)].visible; return items_[ValidateItemIndex(index)].visible;
return delegate_->IsCommandIdVisible(command_id) && return delegate_->IsCommandIdVisible(command_id) &&
......
...@@ -107,6 +107,7 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { ...@@ -107,6 +107,7 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel {
void AddHighlightedItemWithIcon(int command_id, void AddHighlightedItemWithIcon(int command_id,
const base::string16& label, const base::string16& label,
const gfx::ImageSkia& icon); const gfx::ImageSkia& icon);
void AddTitle(const base::string16& label);
// Adds a separator of the specified type to the model. // Adds a separator of the specified type to the model.
// - Adding a separator after another separator is always invalid if they // - Adding a separator after another separator is always invalid if they
......
...@@ -200,6 +200,7 @@ void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) { ...@@ -200,6 +200,7 @@ void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetCheckedState(is_checked ? ax::mojom::CheckedState::kTrue node_data->SetCheckedState(is_checked ? ax::mojom::CheckedState::kTrue
: ax::mojom::CheckedState::kFalse); : ax::mojom::CheckedState::kFalse);
} break; } break;
case TITLE:
case NORMAL: case NORMAL:
case SEPARATOR: case SEPARATOR:
case EMPTY: case EMPTY:
...@@ -1139,7 +1140,9 @@ SkColor MenuItemView::GetTextColor(bool minor, bool render_selection) const { ...@@ -1139,7 +1140,9 @@ SkColor MenuItemView::GetTextColor(bool minor, bool render_selection) const {
: style::CONTEXT_MENU; : style::CONTEXT_MENU;
style::TextStyle text_style = style::STYLE_PRIMARY; style::TextStyle text_style = style::STYLE_PRIMARY;
if (type_ == HIGHLIGHTED) if (type_ == Type::TITLE)
text_style = style::STYLE_PRIMARY;
else if (type_ == HIGHLIGHTED)
text_style = style::STYLE_HIGHLIGHTED; text_style = style::STYLE_HIGHLIGHTED;
else if (!GetEnabled()) else if (!GetEnabled())
text_style = style::STYLE_DISABLED; text_style = style::STYLE_DISABLED;
......
...@@ -95,8 +95,9 @@ class VIEWS_EXPORT MenuItemView : public View { ...@@ -95,8 +95,9 @@ class VIEWS_EXPORT MenuItemView : public View {
HIGHLIGHTED, // Performs an action when selected, and has a HIGHLIGHTED, // Performs an action when selected, and has a
// different colored background that merges with the // different colored background that merges with the
// menu's rounded corners when placed at the bottom. // menu's rounded corners when placed at the bottom.
EMPTY, // EMPTY is a special type for empty menus that is only used TITLE, // Title text, does not perform any action.
// internally. EMPTY, // EMPTY is a special type for empty menus that is only
// used internally.
}; };
// Where the menu should be drawn, above or below the bounds (when // Where the menu should be drawn, above or below the bounds (when
......
...@@ -70,6 +70,9 @@ MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model, ...@@ -70,6 +70,9 @@ MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model,
base::Optional<MenuItemView::Type> type; base::Optional<MenuItemView::Type> type;
ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index); ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index);
switch (menu_type) { switch (menu_type) {
case ui::MenuModel::TYPE_TITLE:
type = MenuItemView::TITLE;
break;
case ui::MenuModel::TYPE_COMMAND: case ui::MenuModel::TYPE_COMMAND:
case ui::MenuModel::TYPE_BUTTON_ITEM: case ui::MenuModel::TYPE_BUTTON_ITEM:
type = MenuItemView::NORMAL; type = MenuItemView::NORMAL;
......
...@@ -213,6 +213,9 @@ void CheckSubmenu(const RootModel& model, ...@@ -213,6 +213,9 @@ void CheckSubmenu(const RootModel& model,
// Check type. // Check type.
switch (model_item.type) { switch (model_item.type) {
case ui::MenuModel::TYPE_TITLE:
EXPECT_EQ(views::MenuItemView::TITLE, item->GetType());
break;
case ui::MenuModel::TYPE_COMMAND: case ui::MenuModel::TYPE_COMMAND:
EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
break; break;
...@@ -287,6 +290,9 @@ TEST_F(MenuModelAdapterTest, BasicTest) { ...@@ -287,6 +290,9 @@ TEST_F(MenuModelAdapterTest, BasicTest) {
// Check type. // Check type.
switch (model_item.type) { switch (model_item.type) {
case ui::MenuModel::TYPE_TITLE:
EXPECT_EQ(views::MenuItemView::TITLE, item->GetType());
break;
case ui::MenuModel::TYPE_COMMAND: case ui::MenuModel::TYPE_COMMAND:
EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment