15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/interactive_test_utils.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/view_event_test_base.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/menu_model.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/test/ui_controls.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button_listener.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_controller.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_model_adapter.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_runner.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/submenu_view.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/root_view.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTopMenuBaseId = 100;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSubMenuBaseId = 200;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implement most of the ui::MenuModel pure virtual methods for subclasses
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exceptions:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  virtual int GetItemCount() const = 0;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  virtual ItemType GetTypeAt(int index) const = 0;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  virtual int GetCommandIdAt(int index) const = 0;
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//  virtual base::string16 GetLabelAt(int index) const = 0;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommonMenuModel : public ui::MenuModel {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommonMenuModel() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CommonMenuModel() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::MenuModel implementation.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasIcons() const OVERRIDE {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsItemDynamicAt(int index) const OVERRIDE {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetAcceleratorAt(int index,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ui::Accelerator* accelerator) const OVERRIDE {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::NORMAL_SEPARATOR;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsItemCheckedAt(int index) const OVERRIDE {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetGroupIdAt(int index) const OVERRIDE {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int index) const OVERRIDE {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsEnabledAt(int index) const OVERRIDE {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void HighlightChangedTo(int index) OVERRIDE {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ActivatedAt(int index) OVERRIDE {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CommonMenuModel);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SubMenuModel : public CommonMenuModel {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SubMenuModel()
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : showing_(false) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SubMenuModel() {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool showing() const {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return showing_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::MenuModel implementation.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetItemCount() const OVERRIDE {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ItemType GetTypeAt(int index) const OVERRIDE {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TYPE_COMMAND;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetCommandIdAt(int index) const OVERRIDE {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return index + kSubMenuBaseId;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetLabelAt(int index) const OVERRIDE {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::ASCIIToUTF16("Item");
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void MenuWillShow() OVERRIDE {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    showing_ = true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when the menu has been closed.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void MenuClosed() OVERRIDE {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    showing_ = false;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool showing_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SubMenuModel);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TopMenuModel : public CommonMenuModel {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TopMenuModel() {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~TopMenuModel() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsSubmenuShowing() {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sub_menu_model_.showing();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::MenuModel implementation.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetItemCount() const OVERRIDE {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ItemType GetTypeAt(int index) const OVERRIDE {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TYPE_SUBMENU;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetCommandIdAt(int index) const OVERRIDE {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return index + kTopMenuBaseId;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetLabelAt(int index) const OVERRIDE {
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::ASCIIToUTF16("submenu");
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &sub_menu_model_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable SubMenuModel sub_menu_model_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TopMenuModel);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuModelAdapterTest : public ViewEventTestBase,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             public views::MenuButtonListener {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuModelAdapterTest()
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ViewEventTestBase(),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        button_(NULL),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        menu_model_adapter_(&top_menu_model_),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        menu_(NULL) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MenuModelAdapterTest() {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ViewEventTestBase implementation.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button_ = new views::MenuButton(
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NULL, base::ASCIIToUTF16("Menu Adapter Test"), this, true);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_ = menu_model_adapter_.CreateMenu();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_runner_.reset(new views::MenuRunner(menu_));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ViewEventTestBase::SetUp();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_runner_.reset(NULL);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_ = NULL;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ViewEventTestBase::TearDown();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual views::View* CreateContentsView() OVERRIDE {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return button_;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return button_->GetPreferredSize();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::MenuButtonListener implementation.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMenuButtonClicked(views::View* source,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const gfx::Point& point) OVERRIDE {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point screen_location;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View::ConvertPointToScreen(source, &screen_location);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect bounds(screen_location, source->size());
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ignore_result(menu_runner_->RunMenuAt(source->GetWidget(),
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          button_,
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          bounds,
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          views::MENU_ANCHOR_TOPLEFT,
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          ui::MENU_SOURCE_NONE,
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          views::MenuRunner::HAS_MNEMONICS));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ViewEventTestBase implementation
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoTestOnMessageLoop() OVERRIDE {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step1));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open the submenu.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Step1() {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::SubmenuView* topmenu = menu_->GetSubmenu();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu->IsShowing());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Click the first item to open the submenu.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::MenuItemView* item = topmenu->GetMenuItemAt(0);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(item);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Click(item, CreateEventTask(this, &MenuModelAdapterTest::Step2));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rebuild the menu which should close the submenu.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Step2() {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::SubmenuView* topmenu = menu_->GetSubmenu();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu->IsShowing());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(top_menu_model_.IsSubmenuShowing());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    menu_model_adapter_.BuildMenu(menu_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoopForUI::current()->PostTask(
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the submenu MenuModel received the close callback
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and close the menu.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Step3() {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::SubmenuView* topmenu = menu_->GetSubmenu();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu->IsShowing());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Click the button to exit the menu.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step4));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All done.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Step4() {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::SubmenuView* topmenu = menu_->GetSubmenu();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(topmenu);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(topmenu->IsShowing());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate a mouse click on the specified view and post a new task.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Click(views::View* view, const base::Closure& next) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_test_utils::MoveMouseToCenterAndPress(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_controls::LEFT,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_controls::DOWN | ui_controls::UP,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::MenuButton* button_;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TopMenuModel top_menu_model_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::MenuModelAdapter menu_model_adapter_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::MenuItemView* menu_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<views::MenuRunner> menu_runner_;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)VIEW_TEST(MenuModelAdapterTest, RebuildMenu)
313