root/chrome/browser/ui/views/menu_model_adapter_test.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. HasIcons
  2. IsItemDynamicAt
  3. GetAcceleratorAt
  4. GetSeparatorTypeAt
  5. IsItemCheckedAt
  6. GetGroupIdAt
  7. GetIconAt
  8. GetButtonMenuItemAt
  9. IsEnabledAt
  10. GetSubmenuModelAt
  11. HighlightChangedTo
  12. ActivatedAt
  13. SetMenuModelDelegate
  14. GetMenuModelDelegate
  15. showing
  16. GetItemCount
  17. GetTypeAt
  18. GetCommandIdAt
  19. GetLabelAt
  20. MenuWillShow
  21. MenuClosed
  22. IsSubmenuShowing
  23. GetItemCount
  24. GetTypeAt
  25. GetCommandIdAt
  26. GetLabelAt
  27. GetSubmenuModelAt
  28. menu_
  29. SetUp
  30. TearDown
  31. CreateContentsView
  32. GetPreferredSize
  33. OnMenuButtonClicked
  34. DoTestOnMessageLoop
  35. Step1
  36. Step2
  37. Step3
  38. Step4
  39. Click

// Copyright (c) 2012 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 "base/callback.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/base/view_event_test_base.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/test/ui_controls.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"

namespace {

const int kTopMenuBaseId = 100;
const int kSubMenuBaseId = 200;

// Implement most of the ui::MenuModel pure virtual methods for subclasses
//
// Exceptions:
//  virtual int GetItemCount() const = 0;
//  virtual ItemType GetTypeAt(int index) const = 0;
//  virtual int GetCommandIdAt(int index) const = 0;
//  virtual base::string16 GetLabelAt(int index) const = 0;
class CommonMenuModel : public ui::MenuModel {
 public:
  CommonMenuModel() {
  }

  virtual ~CommonMenuModel() {
  }

 protected:
  // ui::MenuModel implementation.
  virtual bool HasIcons() const OVERRIDE {
    return false;
  }

  virtual bool IsItemDynamicAt(int index) const OVERRIDE {
    return false;
  }

  virtual bool GetAcceleratorAt(int index,
                                ui::Accelerator* accelerator) const OVERRIDE {
    return false;
  }

  virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE {
    return ui::NORMAL_SEPARATOR;
  }

  virtual bool IsItemCheckedAt(int index) const OVERRIDE {
    return false;
  }

  virtual int GetGroupIdAt(int index) const OVERRIDE {
    return 0;
  }

  virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE {
    return false;
  }

  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
      int index) const OVERRIDE {
    return NULL;
  }

  virtual bool IsEnabledAt(int index) const OVERRIDE {
    return true;
  }

  virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
    return NULL;
  }

  virtual void HighlightChangedTo(int index) OVERRIDE {
  }

  virtual void ActivatedAt(int index) OVERRIDE {
  }

  virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE {
  }

  virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE {
    return NULL;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(CommonMenuModel);
};

class SubMenuModel : public CommonMenuModel {
 public:
  SubMenuModel()
      : showing_(false) {
  }

  virtual ~SubMenuModel() {
  }

  bool showing() const {
    return showing_;
  }

 private:
  // ui::MenuModel implementation.
  virtual int GetItemCount() const OVERRIDE {
    return 1;
  }

  virtual ItemType GetTypeAt(int index) const OVERRIDE {
    return TYPE_COMMAND;
  }

  virtual int GetCommandIdAt(int index) const OVERRIDE {
    return index + kSubMenuBaseId;
  }

  virtual base::string16 GetLabelAt(int index) const OVERRIDE {
    return base::ASCIIToUTF16("Item");
  }

  virtual void MenuWillShow() OVERRIDE {
    showing_ = true;
  }

  // Called when the menu has been closed.
  virtual void MenuClosed() OVERRIDE {
    showing_ = false;
  }

  bool showing_;

  DISALLOW_COPY_AND_ASSIGN(SubMenuModel);
};

class TopMenuModel : public CommonMenuModel {
 public:
  TopMenuModel() {
  }

  virtual ~TopMenuModel() {
  }

  bool IsSubmenuShowing() {
    return sub_menu_model_.showing();
  }

 private:
  // ui::MenuModel implementation.
  virtual int GetItemCount() const OVERRIDE {
    return 1;
  }

  virtual ItemType GetTypeAt(int index) const OVERRIDE {
    return TYPE_SUBMENU;
  }

  virtual int GetCommandIdAt(int index) const OVERRIDE {
    return index + kTopMenuBaseId;
  }

  virtual base::string16 GetLabelAt(int index) const OVERRIDE {
    return base::ASCIIToUTF16("submenu");
  }

  virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
    return &sub_menu_model_;
  }

  mutable SubMenuModel sub_menu_model_;

  DISALLOW_COPY_AND_ASSIGN(TopMenuModel);
};

}  // namespace

class MenuModelAdapterTest : public ViewEventTestBase,
                             public views::MenuButtonListener {
 public:
  MenuModelAdapterTest()
      : ViewEventTestBase(),
        button_(NULL),
        menu_model_adapter_(&top_menu_model_),
        menu_(NULL) {
    old_views_delegate_ = views::ViewsDelegate::views_delegate;
    views::ViewsDelegate::views_delegate = &views_delegate_;
  }

  virtual ~MenuModelAdapterTest() {
    views::ViewsDelegate::views_delegate = old_views_delegate_;
  }

  // ViewEventTestBase implementation.

  virtual void SetUp() OVERRIDE {
    button_ = new views::MenuButton(
        NULL, base::ASCIIToUTF16("Menu Adapter Test"), this, true);

    menu_ = menu_model_adapter_.CreateMenu();
    menu_runner_.reset(new views::MenuRunner(menu_));

    ViewEventTestBase::SetUp();
  }

  virtual void TearDown() OVERRIDE {
    menu_runner_.reset(NULL);
    menu_ = NULL;
    ViewEventTestBase::TearDown();
  }

  virtual views::View* CreateContentsView() OVERRIDE {
    return button_;
  }

  virtual gfx::Size GetPreferredSize() OVERRIDE {
    return button_->GetPreferredSize();
  }

  // views::MenuButtonListener implementation.
  virtual void OnMenuButtonClicked(views::View* source,
                                   const gfx::Point& point) OVERRIDE {
    gfx::Point screen_location;
    views::View::ConvertPointToScreen(source, &screen_location);
    gfx::Rect bounds(screen_location, source->size());
    ignore_result(menu_runner_->RunMenuAt(
        source->GetWidget(),
        button_,
        bounds,
        views::MenuItemView::TOPLEFT,
        ui::MENU_SOURCE_NONE,
        views::MenuRunner::HAS_MNEMONICS));
  }

  // ViewEventTestBase implementation
  virtual void DoTestOnMessageLoop() OVERRIDE {
    Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step1));
  }

  // Open the submenu.
  void Step1() {
    views::SubmenuView* topmenu = menu_->GetSubmenu();
    ASSERT_TRUE(topmenu);
    ASSERT_TRUE(topmenu->IsShowing());
    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());

    // Click the first item to open the submenu.
    views::MenuItemView* item = topmenu->GetMenuItemAt(0);
    ASSERT_TRUE(item);
    Click(item, CreateEventTask(this, &MenuModelAdapterTest::Step2));
  }

  // Rebuild the menu which should close the submenu.
  void Step2() {
    views::SubmenuView* topmenu = menu_->GetSubmenu();
    ASSERT_TRUE(topmenu);
    ASSERT_TRUE(topmenu->IsShowing());
    ASSERT_TRUE(top_menu_model_.IsSubmenuShowing());

    menu_model_adapter_.BuildMenu(menu_);

    base::MessageLoopForUI::current()->PostTask(
        FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3));
  }

  // Verify that the submenu MenuModel received the close callback
  // and close the menu.
  void Step3() {
    views::SubmenuView* topmenu = menu_->GetSubmenu();
    ASSERT_TRUE(topmenu);
    ASSERT_TRUE(topmenu->IsShowing());
    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());

    // Click the button to exit the menu.
    Click(button_, CreateEventTask(this, &MenuModelAdapterTest::Step4));
  }

  // All done.
  void Step4() {
    views::SubmenuView* topmenu = menu_->GetSubmenu();
    ASSERT_TRUE(topmenu);
    ASSERT_FALSE(topmenu->IsShowing());
    ASSERT_FALSE(top_menu_model_.IsSubmenuShowing());

    Done();
  }

 private:
  // Generate a mouse click on the specified view and post a new task.
  virtual void Click(views::View* view, const base::Closure& next) {
    ui_test_utils::MoveMouseToCenterAndPress(
        view,
        ui_controls::LEFT,
        ui_controls::DOWN | ui_controls::UP,
        next);
  }

  views::ViewsDelegate* old_views_delegate_;
  views::TestViewsDelegate views_delegate_;

  views::MenuButton* button_;
  TopMenuModel top_menu_model_;
  views::MenuModelAdapter menu_model_adapter_;
  views::MenuItemView* menu_;
  scoped_ptr<views::MenuRunner> menu_runner_;
};

VIEW_TEST(MenuModelAdapterTest, RebuildMenu)

/* [<][>][^][v][top][bottom][index][help] */