Index: views/controls/menu/menu_model_adapter_unittest.cc |
diff --git a/views/controls/menu/menu_model_adapter_unittest.cc b/views/controls/menu/menu_model_adapter_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..508c31a397f58b3b092ba8035882dcfd27fa48c4 |
--- /dev/null |
+++ b/views/controls/menu/menu_model_adapter_unittest.cc |
@@ -0,0 +1,292 @@ |
+// Copyright (c) 2011 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 "ui/base/l10n/l10n_util.h" |
+#include "ui/base/models/menu_model.h" |
+#include "ui/base/models/menu_model_delegate.h" |
+#include "views/controls/menu/menu_item_view.h" |
+#include "views/controls/menu/menu_model_adapter.h" |
+#include "views/controls/menu/submenu_view.h" |
+#include "views/test/views_test_base.h" |
+ |
+namespace { |
+ |
+// Base command id for test menu and its submenu. |
+const int kRootIdBase = 100; |
+const int kSubmenuIdBase = 200; |
+ |
+// Offset to return for GetFirstItemIndex(). This is an arbitrary |
+// number to ensure that we aren't assuming it is 0. |
+const int kFirstItemIndex = 25; |
+ |
+class MenuModelBase : public ui::MenuModel { |
+ public: |
+ MenuModelBase(int command_id_base) : command_id_base_(command_id_base), |
+ last_activation_(-1) { |
+ } |
+ |
+ // ui::MenuModel implementation: |
+ |
+ virtual bool HasIcons() const OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual int GetFirstItemIndex(gfx::NativeMenu native_menu) const { |
sky
2011/05/25 15:41:12
OVERRIDE
rhashimoto
2011/05/25 16:24:37
Done.
|
+ return kFirstItemIndex; |
+ } |
+ |
+ virtual int GetItemCount() const OVERRIDE { |
+ return static_cast<int>(items_.size()); |
+ } |
+ |
+ virtual ItemType GetTypeAt(int index) const OVERRIDE { |
+ return items_[index - GetFirstItemIndex(NULL)].type_; |
+ } |
+ |
+ virtual int GetCommandIdAt(int index) const OVERRIDE { |
+ return index - GetFirstItemIndex(NULL) + command_id_base_; |
+ } |
+ |
+ string16 GetLabelAt(int index) const OVERRIDE { |
+ return items_[index - GetFirstItemIndex(NULL)].label_; |
+ } |
+ |
+ virtual bool IsItemDynamicAt(int index) const OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual const gfx::Font* GetLabelFontAt(int index) const OVERRIDE { |
+ return NULL; |
+ } |
+ |
+ virtual bool GetAcceleratorAt(int index, |
+ ui::Accelerator* accelerator) const OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual bool IsItemCheckedAt(int index) const OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual int GetGroupIdAt(int index) const OVERRIDE { |
+ return 0; |
+ } |
+ |
+ virtual bool GetIconAt(int index, SkBitmap* icon) OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt( |
+ int index) const OVERRIDE { |
+ return NULL; |
+ } |
+ |
+ virtual bool IsEnabledAt(int index) const OVERRIDE { |
+ return true; |
+ } |
+ |
+ virtual bool IsVisibleAt(int index) const OVERRIDE { |
+ return true; |
+ } |
+ |
+ virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE { |
+ return items_[index - GetFirstItemIndex(NULL)].submenu_; |
+ } |
+ |
+ virtual void HighlightChangedTo(int index) OVERRIDE { |
+ } |
+ |
+ virtual void ActivatedAt(int index) OVERRIDE { |
+ set_last_activation(index); |
+ } |
+ |
+ virtual void ActivatedAtWithDisposition(int index, int disposition) OVERRIDE { |
+ ActivatedAt(index); |
+ } |
+ |
+ virtual void MenuWillShow() OVERRIDE { |
+ } |
+ |
+ virtual void MenuClosed() OVERRIDE { |
+ } |
+ |
+ virtual void SetMenuModelDelegate( |
+ ui::MenuModelDelegate* delegate) OVERRIDE { |
+ } |
+ |
+ // Item definition. |
+ struct Item { |
+ Item(ItemType type, const std::wstring& label, ui::MenuModel* submenu) |
+ : type_(type), |
+ label_(WideToUTF16(label)), |
+ submenu_(submenu) { |
+ } |
+ |
+ ItemType type_; |
sky
2011/05/25 15:41:12
don't use underscores for structs. That is, this s
rhashimoto
2011/05/25 16:24:37
Done.
|
+ string16 label_; |
+ ui::MenuModel* submenu_; |
+ }; |
+ |
+ const Item& GetItemDefinition(int index) { |
+ return items_[index]; |
+ } |
+ |
+ // Access index argument to ActivatedAt() or ActivatedAtWithDisposition(). |
+ int last_activation() const { return last_activation_; } |
+ void set_last_activation(int last_activation) { |
+ last_activation_ = last_activation; |
+ } |
+ |
+ protected: |
+ std::vector<Item> items_; |
+ |
+ private: |
+ int command_id_base_; |
+ int last_activation_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MenuModelBase); |
+}; |
+ |
+class SubmenuModel : public MenuModelBase { |
+ public: |
+ SubmenuModel() : MenuModelBase(kSubmenuIdBase) { |
+ items_.push_back(Item(TYPE_COMMAND, L"submenu item 0", NULL)); |
sky
2011/05/25 15:41:12
Don't use wide, instead use ascii.
rhashimoto
2011/05/25 16:24:37
Done.
|
+ items_.push_back(Item(TYPE_COMMAND, L"submenu item 1", NULL)); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SubmenuModel); |
+}; |
+ |
+class RootModel : public MenuModelBase { |
+ public: |
+ RootModel() : MenuModelBase(kRootIdBase) { |
+ submenu_model_.reset(new SubmenuModel); |
+ |
+ items_.push_back(Item(TYPE_COMMAND, L"command 0", NULL)); |
+ items_.push_back(Item(TYPE_CHECK, L"check 1", NULL)); |
+ items_.push_back(Item(TYPE_SEPARATOR, L"", NULL)); |
+ items_.push_back(Item(TYPE_SUBMENU, L"submenu 3", submenu_model_.get())); |
+ items_.push_back(Item(TYPE_RADIO, L"radio 4", NULL)); |
+ } |
+ |
+ private: |
+ scoped_ptr<MenuModel> submenu_model_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(RootModel); |
+}; |
+ |
+} // namespace |
+ |
+namespace views { |
+ |
+class MenuModelAdapterTest : public ViewsTestBase { |
sky
2011/05/25 15:41:12
use a typedef.
rhashimoto
2011/05/25 16:24:37
Done.
|
+ public: |
+ MenuModelAdapterTest() { |
+ } |
+}; |
+ |
+TEST_F(MenuModelAdapterTest, BasicTest) { |
+ // Build model and adapter. |
+ scoped_ptr<MenuModelBase> model(new RootModel); |
sky
2011/05/25 15:41:12
You never reset these, so you may as well declare
rhashimoto
2011/05/25 16:24:37
Done.
|
+ scoped_ptr<views::MenuModelAdapter> delegate( |
+ new views::MenuModelAdapter(model.get())); |
+ |
+ // Create menu. Build menu twice to check that rebuilding works properly. |
+ scoped_ptr<views::MenuItemView> menu(new views::MenuItemView(delegate.get())); |
+ delegate->BuildMenu(menu.get()); |
+ delegate->BuildMenu(menu.get()); |
+ EXPECT_TRUE(menu->HasSubmenu()); |
+ |
+ // Check top level menu items. |
+ views::SubmenuView* item_container = menu->GetSubmenu(); |
+ EXPECT_EQ(5, item_container->child_count()); |
+ |
+ for (int i = 0; i < item_container->child_count(); ++i) { |
+ const MenuModelBase::Item& model_item = model->GetItemDefinition(i); |
+ |
+ const int id = i + kRootIdBase; |
+ MenuItemView* item = menu->GetMenuItemByID(id); |
+ if (!item) { |
+ EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type_); |
+ continue; |
+ } |
+ |
+ // Check placement. |
+ EXPECT_EQ(i, menu->GetSubmenu()->GetIndexOf(item)); |
+ |
+ // Check type. |
+ switch (model_item.type_) { |
+ case ui::MenuModel::TYPE_COMMAND: |
+ EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_CHECK: |
+ EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_RADIO: |
+ EXPECT_EQ(views::MenuItemView::RADIO, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_SEPARATOR: |
+ case ui::MenuModel::TYPE_BUTTON_ITEM: |
+ break; |
+ case ui::MenuModel::TYPE_SUBMENU: |
+ EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType()); |
+ break; |
+ } |
+ |
+ // Check activation. |
+ static_cast<views::MenuDelegate*>(delegate.get())->ExecuteCommand(id); |
+ EXPECT_EQ(i + kFirstItemIndex, model->last_activation()); |
+ model->set_last_activation(-1); |
+ } |
+ |
+ // Check submenu items. |
+ views::MenuItemView* submenu = menu->GetMenuItemByID(103); |
+ views::SubmenuView* subitem_container = submenu->GetSubmenu(); |
+ EXPECT_EQ(2, subitem_container->child_count()); |
+ |
+ for (int i = 0; i < subitem_container->child_count(); ++i) { |
+ MenuModelBase* submodel = static_cast<MenuModelBase*>( |
+ model->GetSubmenuModelAt(3 + kFirstItemIndex)); |
+ EXPECT_TRUE(submodel); |
+ |
+ const MenuModelBase::Item& model_item = submodel->GetItemDefinition(i); |
+ |
+ const int id = i + kSubmenuIdBase; |
+ MenuItemView* item = menu->GetMenuItemByID(id); |
+ if (!item) { |
+ EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type_); |
+ continue; |
+ } |
+ |
+ // Check placement. |
+ EXPECT_EQ(i, submenu->GetSubmenu()->GetIndexOf(item)); |
+ |
+ // Check type. |
+ switch (model_item.type_) { |
+ case ui::MenuModel::TYPE_COMMAND: |
+ EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_CHECK: |
+ EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_RADIO: |
+ EXPECT_EQ(views::MenuItemView::RADIO, item->GetType()); |
+ break; |
+ case ui::MenuModel::TYPE_SEPARATOR: |
+ case ui::MenuModel::TYPE_BUTTON_ITEM: |
+ break; |
+ case ui::MenuModel::TYPE_SUBMENU: |
+ EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType()); |
+ break; |
+ } |
+ |
+ // Check activation. |
+ static_cast<views::MenuDelegate*>(delegate.get())->ExecuteCommand(id); |
+ EXPECT_EQ(i + kFirstItemIndex, submodel->last_activation()); |
+ submodel->set_last_activation(-1); |
+ } |
+} |
+ |
+} // namespace views |