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