Commit a70c7dd5 authored by Xiyuan Xia's avatar Xiyuan Xia Committed by Commit Bot

ash: Decommission menu.mojom

Bug: 958208
Change-Id: I61bc4788f7ffac45d8d264881ff28c8420866836
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1617705Reviewed-by: default avatarMustafa Emre Acer <meacer@chromium.org>
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660910}
parent d9320f84
......@@ -86,8 +86,6 @@ component("cpp") {
"lock_screen_widget_factory.cc",
"lock_screen_widget_factory.h",
"login_constants.h",
"menu_utils.cc",
"menu_utils.h",
"network_icon_image_source.cc",
"network_icon_image_source.h",
"notification_utils.cc",
......@@ -243,7 +241,6 @@ source_set("unit_tests") {
testonly = true
sources = [
"default_scale_factor_retriever_unittest.cc",
"menu_utils_unittest.cc",
"pagination/pagination_model_unittest.cc",
"power_utils_unittest.cc",
"rounded_corner_decorator_unittest.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/public/cpp/menu_utils.h"
#include <memory>
#include <utility>
#include "base/no_destructor.h"
#include "ui/gfx/image/image.h"
namespace ash {
namespace menu_utils {
MenuItemList GetMojoMenuItemsFromModel(ui::MenuModel* model) {
MenuItemList items;
if (!model)
return items;
for (int i = 0; i < model->GetItemCount(); ++i) {
mojom::MenuItemPtr item(mojom::MenuItem::New());
DCHECK_NE(ui::MenuModel::TYPE_BUTTON_ITEM, model->GetTypeAt(i));
item->type = model->GetTypeAt(i);
item->command_id = model->GetCommandIdAt(i);
item->label = model->GetLabelAt(i);
item->checked = model->IsItemCheckedAt(i);
item->enabled = model->IsEnabledAt(i);
item->radio_group_id = model->GetGroupIdAt(i);
if (item->type == ui::MenuModel::TYPE_SUBMENU ||
item->type == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU) {
item->submenu = GetMojoMenuItemsFromModel(model->GetSubmenuModelAt(i));
}
item->separator_type = model->GetSeparatorTypeAt(i);
gfx::Image icon;
if (model->GetIconAt(i, &icon))
item->image = icon.AsImageSkia();
items.push_back(std::move(item));
}
return items;
}
void PopulateMenuFromMojoMenuItems(ui::SimpleMenuModel* model,
ui::SimpleMenuModel::Delegate* delegate,
const MenuItemList& items,
SubmenuList* submenus) {
for (const mojom::MenuItemPtr& item : items) {
switch (item->type) {
case ui::MenuModel::TYPE_COMMAND:
model->AddItem(item->command_id, item->label);
break;
case ui::MenuModel::TYPE_CHECK:
model->AddCheckItem(item->command_id, item->label);
break;
case ui::MenuModel::TYPE_RADIO:
model->AddRadioItem(item->command_id, item->label,
item->radio_group_id);
break;
case ui::MenuModel::TYPE_SEPARATOR:
model->AddSeparator(item->separator_type);
break;
case ui::MenuModel::TYPE_BUTTON_ITEM:
NOTREACHED() << "TYPE_BUTTON_ITEM is not yet supported.";
break;
case ui::MenuModel::TYPE_SUBMENU:
case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU:
if (item->submenu.has_value()) {
std::unique_ptr<ui::SimpleMenuModel> submenu =
std::make_unique<ui::SimpleMenuModel>(delegate);
PopulateMenuFromMojoMenuItems(submenu.get(), delegate,
item->submenu.value(), submenus);
if (item->type == ui::MenuModel::TYPE_SUBMENU) {
model->AddSubMenu(item->command_id, item->label, submenu.get());
} else {
model->AddActionableSubMenu(item->command_id, item->label,
submenu.get());
}
submenus->push_back(std::move(submenu));
}
break;
case ui::MenuModel::TYPE_HIGHLIGHTED:
NOTREACHED() << "TYPE_HIGHLIGHTED is not yet supported.";
break;
}
if (!item->image.isNull()) {
model->SetIcon(model->GetIndexOfCommandId(item->command_id),
gfx::Image(item->image));
}
}
}
const mojom::MenuItemPtr& GetMenuItemByCommandId(const MenuItemList& items,
int command_id) {
static const base::NoDestructor<mojom::MenuItemPtr> item_not_found(
mojom::MenuItem::New());
for (const mojom::MenuItemPtr& item : items) {
if (item->command_id == command_id)
return item;
if ((item->type == ui::MenuModel::TYPE_SUBMENU ||
(item->type == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU)) &&
item->submenu.has_value()) {
const mojom::MenuItemPtr& submenu_item =
GetMenuItemByCommandId(item->submenu.value(), command_id);
if (submenu_item->command_id == command_id)
return submenu_item;
}
}
return *item_not_found;
}
} // namespace menu_utils
} // namespace ash
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_PUBLIC_CPP_MENU_UTILS_H_
#define ASH_PUBLIC_CPP_MENU_UTILS_H_
#include <memory>
#include <vector>
#include "ash/public/cpp/ash_public_export.h"
#include "ash/public/interfaces/menu.mojom.h"
#include "ui/base/models/simple_menu_model.h"
namespace ash {
namespace menu_utils {
using MenuItemList = std::vector<mojom::MenuItemPtr>;
using SubmenuList = std::vector<std::unique_ptr<ui::MenuModel>>;
// Gets a serialized list of mojo MenuItemPtr objects to transport a menu model.
// NOTE: This does not support button items, some separator types, sublabels,
// minor text, dynamic items, label fonts, accelerators, visibility, etc.
ASH_PUBLIC_EXPORT MenuItemList GetMojoMenuItemsFromModel(ui::MenuModel* model);
// Populates a simple menu model with a list of mojo menu items. This can be
// considered as an inverse operation of |GetMojoMenuItemsFromModel|.
ASH_PUBLIC_EXPORT void PopulateMenuFromMojoMenuItems(
ui::SimpleMenuModel* model,
ui::SimpleMenuModel::Delegate* delegate,
const MenuItemList& items,
SubmenuList* submenus);
// Finds a menu item by command id; returns a stub item if no match was found.
ASH_PUBLIC_EXPORT const mojom::MenuItemPtr& GetMenuItemByCommandId(
const MenuItemList& items,
int command_id);
} // namespace menu_utils
} // namespace ash
#endif // ASH_PUBLIC_CPP_MENU_UTILS_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/public/cpp/menu_utils.h"
#include <utility>
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/base/models/simple_menu_model.h"
using base::ASCIIToUTF16;
namespace ash {
namespace menu_utils {
using MenuModelList = std::vector<std::unique_ptr<ui::SimpleMenuModel>>;
class MenuUtilsTest : public testing::Test,
public ui::SimpleMenuModel::Delegate {
public:
MenuUtilsTest() {}
~MenuUtilsTest() override {}
// testing::Test overrides:
void SetUp() override {
menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
}
protected:
ui::SimpleMenuModel* root_menu() { return menu_model_.get(); }
MenuModelList* submenus() { return &submenu_models_; }
ui::SimpleMenuModel* CreateSubmenu() {
std::unique_ptr<ui::SimpleMenuModel> submenu =
std::make_unique<ui::SimpleMenuModel>(this);
ui::SimpleMenuModel* submenu_ptr = submenu.get();
submenu_models_.push_back(std::move(submenu));
return submenu_ptr;
}
bool IsCommandIdChecked(int command_id) const override {
// Assume that we have a checked item in every 3 items.
return command_id % 3 == 0;
}
bool IsCommandIdEnabled(int command_id) const override {
// Assume that we have a enabled item in every 4 items.
return command_id % 4 == 0;
}
void ExecuteCommand(int command_id, int event_flags) override {}
void CheckMenuItemsMatched(const MenuItemList& mojo_menu,
const ui::MenuModel* menu) {
EXPECT_EQ(mojo_menu.size(), static_cast<size_t>(menu->GetItemCount()));
for (size_t i = 0; i < mojo_menu.size(); i++) {
VLOG(1) << "Checking item at " << i;
mojom::MenuItem* mojo_item = mojo_menu[i].get();
EXPECT_EQ(mojo_item->type, menu->GetTypeAt(i));
EXPECT_EQ(mojo_item->command_id, menu->GetCommandIdAt(i));
EXPECT_EQ(mojo_item->label, menu->GetLabelAt(i));
if (mojo_item->type == ui::MenuModel::TYPE_SUBMENU) {
VLOG(1) << "It's a submenu, let's do a recursion.";
CheckMenuItemsMatched(mojo_item->submenu.value(),
menu->GetSubmenuModelAt(i));
continue;
}
EXPECT_EQ(mojo_item->enabled, menu->IsEnabledAt(i));
EXPECT_EQ(mojo_item->checked, menu->IsItemCheckedAt(i));
EXPECT_EQ(mojo_item->radio_group_id, menu->GetGroupIdAt(i));
}
}
private:
std::unique_ptr<ui::SimpleMenuModel> menu_model_;
MenuModelList submenu_models_;
DISALLOW_COPY_AND_ASSIGN(MenuUtilsTest);
};
TEST_F(MenuUtilsTest, Basic) {
ui::SimpleMenuModel* menu = root_menu();
// Populates items into |menu| for testing.
int command_id = 0;
menu->AddItem(command_id++, ASCIIToUTF16("Item0"));
menu->AddItem(command_id++, ASCIIToUTF16("Item1"));
menu->AddSeparator(ui::NORMAL_SEPARATOR);
menu->AddCheckItem(command_id++, ASCIIToUTF16("CheckItem0"));
menu->AddCheckItem(command_id++, ASCIIToUTF16("CheckItem1"));
menu->AddRadioItem(command_id++, ASCIIToUTF16("RadioItem0"),
0 /* group_id */);
menu->AddRadioItem(command_id++, ASCIIToUTF16("RadioItem1"),
0 /* group_id */);
// Creates a submenu.
ui::SimpleMenuModel* submenu = CreateSubmenu();
submenu->AddItem(command_id++, ASCIIToUTF16("SubMenu-Item0"));
submenu->AddItem(command_id++, ASCIIToUTF16("SubMenu-Item1"));
submenu->AddSeparator(ui::NORMAL_SEPARATOR);
submenu->AddCheckItem(command_id++, ASCIIToUTF16("SubMenu-CheckItem0"));
submenu->AddCheckItem(command_id++, ASCIIToUTF16("SubMenu-CheckItem1"));
submenu->AddRadioItem(command_id++, ASCIIToUTF16("SubMenu-RadioItem0"),
1 /* group_id */);
submenu->AddRadioItem(command_id++, ASCIIToUTF16("SubMenu-RadioItem1"),
1 /* group_id */);
menu->AddSubMenu(command_id++, ASCIIToUTF16("SubMenu"), submenu);
// Converts the menu into mojo format.
MenuItemList mojo_menu_items = GetMojoMenuItemsFromModel(menu);
CheckMenuItemsMatched(mojo_menu_items, menu);
// Converts backwards.
ui::SimpleMenuModel new_menu(this);
SubmenuList new_submenus;
PopulateMenuFromMojoMenuItems(&new_menu, this, mojo_menu_items,
&new_submenus);
CheckMenuItemsMatched(mojo_menu_items, &new_menu);
// Tests |GetMenuItemByCommandId|.
for (int command_to_find = 0; command_to_find < command_id;
command_to_find++) {
// Gets the mojo item.
const mojom::MenuItemPtr& mojo_item =
GetMenuItemByCommandId(mojo_menu_items, command_to_find);
// Gets the item index with this command from the original root menu.
int index = menu->GetIndexOfCommandId(command_to_find);
ui::MenuModel* menu_to_find = menu;
if (index < 0) {
// We cannot find it from the original root menu. Then it should be in the
// submenu.
index = submenu->GetIndexOfCommandId(command_to_find);
EXPECT_LE(0, index);
menu_to_find = submenu;
}
// Checks whether they match.
EXPECT_EQ(mojo_item->type, menu_to_find->GetTypeAt(index));
EXPECT_EQ(mojo_item->command_id, menu_to_find->GetCommandIdAt(index));
EXPECT_EQ(mojo_item->label, menu_to_find->GetLabelAt(index));
EXPECT_EQ(mojo_item->enabled, menu_to_find->IsEnabledAt(index));
EXPECT_EQ(mojo_item->checked, menu_to_find->IsItemCheckedAt(index));
EXPECT_EQ(mojo_item->radio_group_id, menu_to_find->GetGroupIdAt(index));
}
// For unknown command ids, we'll get a singleton stub item.
const mojom::MenuItemPtr& item_not_found_1 =
GetMenuItemByCommandId(mojo_menu_items, command_id + 1);
const mojom::MenuItemPtr& item_not_found_2 =
GetMenuItemByCommandId(mojo_menu_items, command_id + 2);
EXPECT_EQ(item_not_found_1.get(), item_not_found_2.get());
}
} // namespace menu_utils
} // namespace ash
......@@ -41,7 +41,6 @@ mojom("interfaces_internal") {
"login_screen.mojom",
"login_user_info.mojom",
"media.mojom",
"menu.mojom",
"new_window.mojom",
"night_light_controller.mojom",
"note_taking_controller.mojom",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module ash.mojom;
import "mojo/public/mojom/base/string16.mojom";
import "ui/gfx/image/mojo/image.mojom";
// The types of menu items shown in shelf context and application list menus.
// These values roughly match ui::MenuModel::ItemType (sans TYPE_BUTTON_ITEM).
enum MenuItemType {
COMMAND, // Performs an action when selected.
CHECK, // Can be selected/checked to toggle a boolean state.
RADIO, // Can be selected/checked among a group of choices.
SEPARATOR, // Shows a horizontal line separator.
SUBMENU, // Presents a submenu within another menu.
ACTIONABLE_SUBMENU, // A SUBMENU that is also a COMMAND.
};
// For a separator we have the following types.
enum MenuSeparatorType {
// Normal - top to bottom: Spacing, line, spacing.
NORMAL_SEPARATOR = 0,
// Double thickness - top to bottom: Spacing, line, spacing.
DOUBLE_SEPARATOR,
// Upper - top to bottom: Line, spacing.
UPPER_SEPARATOR,
// Lower - top to bottom: Spacing, line.
LOWER_SEPARATOR,
// Spacing - top to bottom: Spacing only.
SPACING_SEPARATOR,
// Vertical separator within a row.
VERTICAL_SEPARATOR,
// Separator with left padding - top to bottom: Line only,
// horizontal: Starts after left padding.
PADDED_SEPARATOR,
};
// MenuItems are used to populate application menus for shelf items.
// Note: Some menu item types only support a subset of these item features.
// Please update comments below (MenuItemType -> [fields expected for usage])
// when anything changed to MenuItemType or MenuItem.
//
// COMMAND -> [command_id, label, image, enabled, checked].
// CHECK -> [command_id, label, image, enabled, checked].
// RADIO -> [command_id, label, image, enabled, checked, radio_group_id].
// SEPARATOR -> [separator_type].
// SUBMENU -> [command_id, label, image, enabled, submenu].
// ACTIONABLE_SUBMENU -> [command_id, label, image, enabled, submenu].
//
struct MenuItem {
MenuItemType type; // The type of the menu item.
int32 command_id; // The client's arbitrary item command id.
mojo_base.mojom.String16 label; // The string label, may be empty.
gfx.mojom.ImageSkia? image; // The image icon, may be null.
array<MenuItem>? submenu; // The optional nested submenu item list.
bool enabled; // The enabled state.
bool checked; // The checked state.
int64 radio_group_id; // The radio group id.
MenuSeparatorType separator_type; // The separator type.
};
// An interface implemented by clients to handle interaction with menus run in
// Ash.
interface MenuDelegate {
MenuItemActivated(int32 command_id);
};
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
mojom = "//ash/public/interfaces/menu.mojom"
public_headers = [
"//ui/base/models/menu_model.h",
"//ui/base/models/menu_separator_types.h",
]
traits_headers = [ "//ash/public/cpp/menu_struct_mojom_traits.h" ]
public_deps = [
"//ui/base",
"//ui/gfx/image/mojo:struct_traits",
]
type_mappings = [
"ash.mojom.MenuItemType=ui::MenuModel::ItemType",
"ash.mojom.MenuSeparatorType=ui::MenuSeparatorType",
]
......@@ -4,7 +4,6 @@
typemaps = [
"//ash/public/interfaces/app_list.typemap",
"//ash/public/interfaces/menu.typemap",
"//ash/public/interfaces/shelf.typemap",
"//ash/public/interfaces/shelf_integration_test_api.typemap",
"//ash/public/interfaces/user_info.typemap",
......
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