- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / menu_model_adapter_test.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 "base/callback.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "chrome/test/base/interactive_test_utils.h"
8 #include "chrome/test/base/ui_test_utils.h"
9 #include "chrome/test/base/view_event_test_base.h"
10 #include "ui/base/models/menu_model.h"
11 #include "ui/base/test/ui_controls.h"
12 #include "ui/views/controls/button/menu_button.h"
13 #include "ui/views/controls/button/menu_button_listener.h"
14 #include "ui/views/controls/menu/menu_controller.h"
15 #include "ui/views/controls/menu/menu_item_view.h"
16 #include "ui/views/controls/menu/menu_model_adapter.h"
17 #include "ui/views/controls/menu/menu_runner.h"
18 #include "ui/views/controls/menu/submenu_view.h"
19 #include "ui/views/test/test_views_delegate.h"
20 #include "ui/views/widget/root_view.h"
21 #include "ui/views/widget/widget.h"
22
23 namespace {
24
25 const int kTopMenuBaseId = 100;
26 const int kSubMenuBaseId = 200;
27
28 // Implement most of the ui::MenuModel pure virtual methods for subclasses
29 //
30 // Exceptions:
31 //  virtual int GetItemCount() const = 0;
32 //  virtual ItemType GetTypeAt(int index) const = 0;
33 //  virtual int GetCommandIdAt(int index) const = 0;
34 //  virtual string16 GetLabelAt(int index) const = 0;
35 class CommonMenuModel : public ui::MenuModel {
36  public:
37   CommonMenuModel() {
38   }
39
40   virtual ~CommonMenuModel() {
41   }
42
43  protected:
44   // ui::MenuModel implementation.
45   virtual bool HasIcons() const OVERRIDE {
46     return false;
47   }
48
49   virtual bool IsItemDynamicAt(int index) const OVERRIDE {
50     return false;
51   }
52
53   virtual bool GetAcceleratorAt(int index,
54                                 ui::Accelerator* accelerator) const OVERRIDE {
55     return false;
56   }
57
58   virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE {
59     return ui::NORMAL_SEPARATOR;
60   }
61
62   virtual bool IsItemCheckedAt(int index) const OVERRIDE {
63     return false;
64   }
65
66   virtual int GetGroupIdAt(int index) const OVERRIDE {
67     return 0;
68   }
69
70   virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE {
71     return false;
72   }
73
74   virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
75       int index) const OVERRIDE {
76     return NULL;
77   }
78
79   virtual bool IsEnabledAt(int index) const OVERRIDE {
80     return true;
81   }
82
83   virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
84     return NULL;
85   }
86
87   virtual void HighlightChangedTo(int index) OVERRIDE {
88   }
89
90   virtual void ActivatedAt(int index) OVERRIDE {
91   }
92
93   virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE {
94   }
95
96   virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE {
97     return NULL;
98   }
99
100  private:
101   DISALLOW_COPY_AND_ASSIGN(CommonMenuModel);
102 };
103
104 class SubMenuModel : public CommonMenuModel {
105  public:
106   SubMenuModel()
107       : showing_(false) {
108   }
109
110   virtual ~SubMenuModel() {
111   }
112
113   bool showing() const {
114     return showing_;
115   }
116
117  private:
118   // ui::MenuModel implementation.
119   virtual int GetItemCount() const OVERRIDE {
120     return 1;
121   }
122
123   virtual ItemType GetTypeAt(int index) const OVERRIDE {
124     return TYPE_COMMAND;
125   }
126
127   virtual int GetCommandIdAt(int index) const OVERRIDE {
128     return index + kSubMenuBaseId;
129   }
130
131   virtual string16 GetLabelAt(int index) const OVERRIDE {
132     return ASCIIToUTF16("Item");
133   }
134
135   virtual void MenuWillShow() OVERRIDE {
136     showing_ = true;
137   }
138
139   // Called when the menu has been closed.
140   virtual void MenuClosed() OVERRIDE {
141     showing_ = false;
142   }
143
144   bool showing_;
145
146   DISALLOW_COPY_AND_ASSIGN(SubMenuModel);
147 };
148
149 class TopMenuModel : public CommonMenuModel {
150  public:
151   TopMenuModel() {
152   }
153
154   virtual ~TopMenuModel() {
155   }
156
157   bool IsSubmenuShowing() {
158     return sub_menu_model_.showing();
159   }
160
161  private:
162   // ui::MenuModel implementation.
163   virtual int GetItemCount() const OVERRIDE {
164     return 1;
165   }
166
167   virtual ItemType GetTypeAt(int index) const OVERRIDE {
168     return TYPE_SUBMENU;
169   }
170
171   virtual int GetCommandIdAt(int index) const OVERRIDE {
172     return index + kTopMenuBaseId;
173   }
174
175   virtual string16 GetLabelAt(int index) const OVERRIDE {
176     return ASCIIToUTF16("submenu");
177   }
178
179   virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
180     return &sub_menu_model_;
181   }
182
183   mutable SubMenuModel sub_menu_model_;
184
185   DISALLOW_COPY_AND_ASSIGN(TopMenuModel);
186 };
187
188 }  // namespace
189
190 class MenuModelAdapterTest : public ViewEventTestBase,
191                              public views::MenuButtonListener {
192  public:
193   MenuModelAdapterTest()
194       : ViewEventTestBase(),
195         button_(NULL),
196         menu_model_adapter_(&top_menu_model_),
197         menu_(NULL) {
198     old_views_delegate_ = views::ViewsDelegate::views_delegate;
199     views::ViewsDelegate::views_delegate = &views_delegate_;
200   }
201
202   virtual ~MenuModelAdapterTest() {
203     views::ViewsDelegate::views_delegate = old_views_delegate_;
204   }
205
206   // ViewEventTestBase implementation.
207
208   virtual void SetUp() OVERRIDE {
209     button_ = new views::MenuButton(
210         NULL, ASCIIToUTF16("Menu Adapter Test"), this, true);
211
212     menu_ = menu_model_adapter_.CreateMenu();
213     menu_runner_.reset(new views::MenuRunner(menu_));
214
215     ViewEventTestBase::SetUp();
216   }
217
218   virtual void TearDown() OVERRIDE {
219     menu_runner_.reset(NULL);
220     menu_ = NULL;
221     ViewEventTestBase::TearDown();
222   }
223
224   virtual views::View* CreateContentsView() OVERRIDE {
225     return button_;
226   }
227
228   virtual gfx::Size GetPreferredSize() OVERRIDE {
229     return button_->GetPreferredSize();
230   }
231
232   // views::MenuButtonListener implementation.
233   virtual void OnMenuButtonClicked(views::View* source,
234                                    const gfx::Point& point) OVERRIDE {
235     gfx::Point screen_location;
236     views::View::ConvertPointToScreen(source, &screen_location);
237     gfx::Rect bounds(screen_location, source->size());
238     ignore_result(menu_runner_->RunMenuAt(
239         source->GetWidget(),
240         button_,
241         bounds,
242         views::MenuItemView::TOPLEFT,
243         ui::MENU_SOURCE_NONE,
244         views::MenuRunner::HAS_MNEMONICS));
245   }
246
247   // ViewEventTestBase implementation
248   virtual void DoTestOnMessageLoop() OVERRIDE {
249     Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step1));
250   }
251
252   // Open the submenu.
253   void Step1() {
254     views::SubmenuView* topmenu = menu_->GetSubmenu();
255     ASSERT_TRUE(topmenu);
256     ASSERT_TRUE(topmenu->IsShowing());
257     ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
258
259     // Click the first item to open the submenu.
260     views::MenuItemView* item = topmenu->GetMenuItemAt(0);
261     ASSERT_TRUE(item);
262     Click(item, CreateEventTask(this, &MenuModelAdapterTest::Step2));
263   }
264
265   // Rebuild the menu which should close the submenu.
266   void Step2() {
267     views::SubmenuView* topmenu = menu_->GetSubmenu();
268     ASSERT_TRUE(topmenu);
269     ASSERT_TRUE(topmenu->IsShowing());
270     ASSERT_TRUE(top_menu_model_.IsSubmenuShowing());
271
272     menu_model_adapter_.BuildMenu(menu_);
273
274     base::MessageLoopForUI::current()->PostTask(
275         FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3));
276   }
277
278   // Verify that the submenu MenuModel received the close callback
279   // and close the menu.
280   void Step3() {
281     views::SubmenuView* topmenu = menu_->GetSubmenu();
282     ASSERT_TRUE(topmenu);
283     ASSERT_TRUE(topmenu->IsShowing());
284     ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
285
286     // Click the button to exit the menu.
287     Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step4));
288   }
289
290   // All done.
291   void Step4() {
292     views::SubmenuView* topmenu = menu_->GetSubmenu();
293     ASSERT_TRUE(topmenu);
294     ASSERT_FALSE(topmenu->IsShowing());
295     ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
296
297     Done();
298   }
299
300  private:
301   // Generate a mouse click on the specified view and post a new task.
302   virtual void Click(views::View* view, const base::Closure& next) {
303     ui_test_utils::MoveMouseToCenterAndPress(
304         view,
305         ui_controls::LEFT,
306         ui_controls::DOWN | ui_controls::UP,
307         next);
308   }
309
310   views::ViewsDelegate* old_views_delegate_;
311   views::TestViewsDelegate views_delegate_;
312
313   views::MenuButton* button_;
314   TopMenuModel top_menu_model_;
315   views::MenuModelAdapter menu_model_adapter_;
316   views::MenuItemView* menu_;
317   scoped_ptr<views::MenuRunner> menu_runner_;
318 };
319
320 VIEW_TEST(MenuModelAdapterTest, RebuildMenu)