Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / menu / menu_model_adapter_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/controls/menu/menu_model_adapter.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "ui/base/models/menu_model.h"
9 #include "ui/base/models/menu_model_delegate.h"
10 #include "ui/views/controls/menu/menu_item_view.h"
11 #include "ui/views/controls/menu/menu_runner.h"
12 #include "ui/views/controls/menu/submenu_view.h"
13 #include "ui/views/test/views_test_base.h"
14
15 namespace {
16
17 // Base command id for test menu and its submenu.
18 const int kRootIdBase = 100;
19 const int kSubmenuIdBase = 200;
20
21 class MenuModelBase : public ui::MenuModel {
22  public:
23   explicit MenuModelBase(int command_id_base)
24       : command_id_base_(command_id_base),
25         last_activation_(-1) {
26   }
27
28   virtual ~MenuModelBase() {
29   }
30
31   // ui::MenuModel implementation:
32
33   virtual bool HasIcons() const OVERRIDE {
34     return false;
35   }
36
37   virtual int GetItemCount() const OVERRIDE {
38     return static_cast<int>(items_.size());
39   }
40
41   virtual ItemType GetTypeAt(int index) const OVERRIDE {
42     return items_[index].type;
43   }
44
45   virtual ui::MenuSeparatorType GetSeparatorTypeAt(
46       int index) const OVERRIDE {
47     return ui::NORMAL_SEPARATOR;
48   }
49
50   virtual int GetCommandIdAt(int index) const OVERRIDE {
51     return index + command_id_base_;
52   }
53
54   virtual base::string16 GetLabelAt(int index) const OVERRIDE {
55     return items_[index].label;
56   }
57
58   virtual bool IsItemDynamicAt(int index) const OVERRIDE {
59     return false;
60   }
61
62   virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE {
63     return NULL;
64   }
65
66   virtual bool GetAcceleratorAt(int index,
67                                 ui::Accelerator* accelerator) const OVERRIDE {
68     return false;
69   }
70
71   virtual bool IsItemCheckedAt(int index) const OVERRIDE {
72     return false;
73   }
74
75   virtual int GetGroupIdAt(int index) const OVERRIDE {
76     return 0;
77   }
78
79   virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE {
80     return false;
81   }
82
83   virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
84       int index) const OVERRIDE {
85     return NULL;
86   }
87
88   virtual bool IsEnabledAt(int index) const OVERRIDE {
89     return true;
90   }
91
92   virtual bool IsVisibleAt(int index) const OVERRIDE {
93     return true;
94   }
95
96   virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
97     return items_[index].submenu;
98   }
99
100   virtual void HighlightChangedTo(int index) OVERRIDE {
101   }
102
103   virtual void ActivatedAt(int index) OVERRIDE {
104     set_last_activation(index);
105   }
106
107   virtual void ActivatedAt(int index, int event_flags) OVERRIDE {
108     ActivatedAt(index);
109   }
110
111   virtual void MenuWillShow() OVERRIDE {
112   }
113
114   virtual void MenuClosed() OVERRIDE {
115   }
116
117   virtual void SetMenuModelDelegate(
118       ui::MenuModelDelegate* delegate) OVERRIDE {
119   }
120
121   virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE {
122     return NULL;
123   }
124
125   // Item definition.
126   struct Item {
127     Item(ItemType item_type,
128          const std::string& item_label,
129          ui::MenuModel* item_submenu)
130         : type(item_type),
131           label(base::ASCIIToUTF16(item_label)),
132           submenu(item_submenu) {
133     }
134
135     ItemType type;
136     base::string16 label;
137     ui::MenuModel* submenu;
138   };
139
140   const Item& GetItemDefinition(int index) {
141     return items_[index];
142   }
143
144   // Access index argument to ActivatedAt().
145   int last_activation() const { return last_activation_; }
146   void set_last_activation(int last_activation) {
147     last_activation_ = last_activation;
148   }
149
150  protected:
151   std::vector<Item> items_;
152
153  private:
154   int command_id_base_;
155   int last_activation_;
156
157   DISALLOW_COPY_AND_ASSIGN(MenuModelBase);
158 };
159
160 class SubmenuModel : public MenuModelBase {
161  public:
162   SubmenuModel() : MenuModelBase(kSubmenuIdBase) {
163     items_.push_back(Item(TYPE_COMMAND, "submenu item 0", NULL));
164     items_.push_back(Item(TYPE_COMMAND, "submenu item 1", NULL));
165   }
166
167   virtual ~SubmenuModel() {
168   }
169
170  private:
171   DISALLOW_COPY_AND_ASSIGN(SubmenuModel);
172 };
173
174 class RootModel : public MenuModelBase {
175  public:
176   RootModel() : MenuModelBase(kRootIdBase) {
177     submenu_model_.reset(new SubmenuModel);
178
179     items_.push_back(Item(TYPE_COMMAND, "command 0", NULL));
180     items_.push_back(Item(TYPE_CHECK, "check 1", NULL));
181     items_.push_back(Item(TYPE_SEPARATOR, "", NULL));
182     items_.push_back(Item(TYPE_SUBMENU, "submenu 3", submenu_model_.get()));
183     items_.push_back(Item(TYPE_RADIO, "radio 4", NULL));
184   }
185
186   virtual ~RootModel() {
187   }
188
189  private:
190   scoped_ptr<MenuModel> submenu_model_;
191
192   DISALLOW_COPY_AND_ASSIGN(RootModel);
193 };
194
195 }  // namespace
196
197 namespace views {
198
199 typedef ViewsTestBase MenuModelAdapterTest;
200
201 TEST_F(MenuModelAdapterTest, BasicTest) {
202   // Build model and adapter.
203   RootModel model;
204   views::MenuModelAdapter delegate(&model);
205
206   // Create menu.  Build menu twice to check that rebuilding works properly.
207   MenuItemView* menu = new views::MenuItemView(&delegate);
208   // MenuRunner takes ownership of menu.
209   scoped_ptr<MenuRunner> menu_runner(new MenuRunner(menu, 0));
210   delegate.BuildMenu(menu);
211   delegate.BuildMenu(menu);
212   EXPECT_TRUE(menu->HasSubmenu());
213
214   // Check top level menu items.
215   views::SubmenuView* item_container = menu->GetSubmenu();
216   EXPECT_EQ(5, item_container->child_count());
217
218   for (int i = 0; i < item_container->child_count(); ++i) {
219     const MenuModelBase::Item& model_item = model.GetItemDefinition(i);
220
221     const int id = i + kRootIdBase;
222     MenuItemView* item = menu->GetMenuItemByID(id);
223     if (!item) {
224       EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type);
225       continue;
226     }
227
228     // Check placement.
229     EXPECT_EQ(i, menu->GetSubmenu()->GetIndexOf(item));
230
231     // Check type.
232     switch (model_item.type) {
233       case ui::MenuModel::TYPE_COMMAND:
234         EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
235         break;
236       case ui::MenuModel::TYPE_CHECK:
237         EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType());
238         break;
239       case ui::MenuModel::TYPE_RADIO:
240         EXPECT_EQ(views::MenuItemView::RADIO, item->GetType());
241         break;
242       case ui::MenuModel::TYPE_SEPARATOR:
243       case ui::MenuModel::TYPE_BUTTON_ITEM:
244         break;
245       case ui::MenuModel::TYPE_SUBMENU:
246         EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType());
247         break;
248     }
249
250     // Check activation.
251     static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id);
252     EXPECT_EQ(i, model.last_activation());
253     model.set_last_activation(-1);
254   }
255
256   // Check submenu items.
257   views::MenuItemView* submenu = menu->GetMenuItemByID(103);
258   views::SubmenuView* subitem_container = submenu->GetSubmenu();
259   EXPECT_EQ(2, subitem_container->child_count());
260
261   for (int i = 0; i < subitem_container->child_count(); ++i) {
262     MenuModelBase* submodel = static_cast<MenuModelBase*>(
263         model.GetSubmenuModelAt(3));
264     EXPECT_TRUE(submodel);
265
266     const MenuModelBase::Item& model_item = submodel->GetItemDefinition(i);
267
268     const int id = i + kSubmenuIdBase;
269     MenuItemView* item = menu->GetMenuItemByID(id);
270     if (!item) {
271       EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type);
272       continue;
273     }
274
275     // Check placement.
276     EXPECT_EQ(i, submenu->GetSubmenu()->GetIndexOf(item));
277
278     // Check type.
279     switch (model_item.type) {
280       case ui::MenuModel::TYPE_COMMAND:
281         EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
282         break;
283       case ui::MenuModel::TYPE_CHECK:
284         EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType());
285         break;
286       case ui::MenuModel::TYPE_RADIO:
287         EXPECT_EQ(views::MenuItemView::RADIO, item->GetType());
288         break;
289       case ui::MenuModel::TYPE_SEPARATOR:
290       case ui::MenuModel::TYPE_BUTTON_ITEM:
291         break;
292       case ui::MenuModel::TYPE_SUBMENU:
293         EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType());
294         break;
295     }
296
297     // Check activation.
298     static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id);
299     EXPECT_EQ(i, submodel->last_activation());
300     submodel->set_last_activation(-1);
301   }
302
303   // Check that selecting the root item is safe.  The MenuModel does
304   // not care about the root so MenuModelAdapter should do nothing
305   // (not hit the NOTREACHED check) when the root is selected.
306   static_cast<views::MenuDelegate*>(&delegate)->SelectionChanged(menu);
307 }
308
309 }  // namespace views