root/ui/views/controls/menu/menu_model_adapter_unittest.cc

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

DEFINITIONS

This source file includes following definitions.
  1. last_activation_
  2. HasIcons
  3. GetItemCount
  4. GetTypeAt
  5. GetSeparatorTypeAt
  6. GetCommandIdAt
  7. GetLabelAt
  8. IsItemDynamicAt
  9. GetLabelFontListAt
  10. GetAcceleratorAt
  11. IsItemCheckedAt
  12. GetGroupIdAt
  13. GetIconAt
  14. GetButtonMenuItemAt
  15. IsEnabledAt
  16. IsVisibleAt
  17. GetSubmenuModelAt
  18. HighlightChangedTo
  19. ActivatedAt
  20. ActivatedAt
  21. MenuWillShow
  22. MenuClosed
  23. SetMenuModelDelegate
  24. GetMenuModelDelegate
  25. GetItemDefinition
  26. last_activation
  27. set_last_activation
  28. TEST_F

// 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 "ui/views/controls/menu/menu_model_adapter.h"

#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/models/menu_model_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/test/views_test_base.h"

namespace {

// Base command id for test menu and its submenu.
const int kRootIdBase = 100;
const int kSubmenuIdBase = 200;

class MenuModelBase : public ui::MenuModel {
 public:
  explicit MenuModelBase(int command_id_base)
      : command_id_base_(command_id_base),
        last_activation_(-1) {
  }

  virtual ~MenuModelBase() {
  }

  // ui::MenuModel implementation:

  virtual bool HasIcons() const OVERRIDE {
    return false;
  }

  virtual int GetItemCount() const OVERRIDE {
    return static_cast<int>(items_.size());
  }

  virtual ItemType GetTypeAt(int index) const OVERRIDE {
    return items_[index].type;
  }

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

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

  virtual base::string16 GetLabelAt(int index) const OVERRIDE {
    return items_[index].label;
  }

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

  virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE {
    return NULL;
  }

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

  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 bool IsVisibleAt(int index) const OVERRIDE {
    return true;
  }

  virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE {
    return items_[index].submenu;
  }

  virtual void HighlightChangedTo(int index) OVERRIDE {
  }

  virtual void ActivatedAt(int index) OVERRIDE {
    set_last_activation(index);
  }

  virtual void ActivatedAt(int index, int event_flags) OVERRIDE {
    ActivatedAt(index);
  }

  virtual void MenuWillShow() OVERRIDE {
  }

  virtual void MenuClosed() OVERRIDE {
  }

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

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

  // Item definition.
  struct Item {
    Item(ItemType item_type,
         const std::string& item_label,
         ui::MenuModel* item_submenu)
        : type(item_type),
          label(base::ASCIIToUTF16(item_label)),
          submenu(item_submenu) {
    }

    ItemType type;
    base::string16 label;
    ui::MenuModel* submenu;
  };

  const Item& GetItemDefinition(int index) {
    return items_[index];
  }

  // Access index argument to ActivatedAt().
  int last_activation() const { return last_activation_; }
  void set_last_activation(int last_activation) {
    last_activation_ = last_activation;
  }

 protected:
  std::vector<Item> items_;

 private:
  int command_id_base_;
  int last_activation_;

  DISALLOW_COPY_AND_ASSIGN(MenuModelBase);
};

class SubmenuModel : public MenuModelBase {
 public:
  SubmenuModel() : MenuModelBase(kSubmenuIdBase) {
    items_.push_back(Item(TYPE_COMMAND, "submenu item 0", NULL));
    items_.push_back(Item(TYPE_COMMAND, "submenu item 1", NULL));
  }

  virtual ~SubmenuModel() {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(SubmenuModel);
};

class RootModel : public MenuModelBase {
 public:
  RootModel() : MenuModelBase(kRootIdBase) {
    submenu_model_.reset(new SubmenuModel);

    items_.push_back(Item(TYPE_COMMAND, "command 0", NULL));
    items_.push_back(Item(TYPE_CHECK, "check 1", NULL));
    items_.push_back(Item(TYPE_SEPARATOR, "", NULL));
    items_.push_back(Item(TYPE_SUBMENU, "submenu 3", submenu_model_.get()));
    items_.push_back(Item(TYPE_RADIO, "radio 4", NULL));
  }

  virtual ~RootModel() {
  }

 private:
  scoped_ptr<MenuModel> submenu_model_;

  DISALLOW_COPY_AND_ASSIGN(RootModel);
};

}  // namespace

namespace views {

typedef ViewsTestBase MenuModelAdapterTest;

TEST_F(MenuModelAdapterTest, BasicTest) {
  // Build model and adapter.
  RootModel model;
  views::MenuModelAdapter delegate(&model);

  // Create menu.  Build menu twice to check that rebuilding works properly.
  MenuItemView* menu = new views::MenuItemView(&delegate);
  // MenuRunner takes ownership of menu.
  scoped_ptr<MenuRunner> menu_runner(new MenuRunner(menu));
  delegate.BuildMenu(menu);
  delegate.BuildMenu(menu);
  EXPECT_TRUE(menu->HasSubmenu());

  // Check top level menu items.
  views::SubmenuView* item_container = menu->GetSubmenu();
  EXPECT_EQ(5, item_container->child_count());

  for (int i = 0; i < item_container->child_count(); ++i) {
    const MenuModelBase::Item& model_item = model.GetItemDefinition(i);

    const int id = i + kRootIdBase;
    MenuItemView* item = menu->GetMenuItemByID(id);
    if (!item) {
      EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type);
      continue;
    }

    // Check placement.
    EXPECT_EQ(i, menu->GetSubmenu()->GetIndexOf(item));

    // Check type.
    switch (model_item.type) {
      case ui::MenuModel::TYPE_COMMAND:
        EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
        break;
      case ui::MenuModel::TYPE_CHECK:
        EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType());
        break;
      case ui::MenuModel::TYPE_RADIO:
        EXPECT_EQ(views::MenuItemView::RADIO, item->GetType());
        break;
      case ui::MenuModel::TYPE_SEPARATOR:
      case ui::MenuModel::TYPE_BUTTON_ITEM:
        break;
      case ui::MenuModel::TYPE_SUBMENU:
        EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType());
        break;
    }

    // Check activation.
    static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id);
    EXPECT_EQ(i, model.last_activation());
    model.set_last_activation(-1);
  }

  // Check submenu items.
  views::MenuItemView* submenu = menu->GetMenuItemByID(103);
  views::SubmenuView* subitem_container = submenu->GetSubmenu();
  EXPECT_EQ(2, subitem_container->child_count());

  for (int i = 0; i < subitem_container->child_count(); ++i) {
    MenuModelBase* submodel = static_cast<MenuModelBase*>(
        model.GetSubmenuModelAt(3));
    EXPECT_TRUE(submodel);

    const MenuModelBase::Item& model_item = submodel->GetItemDefinition(i);

    const int id = i + kSubmenuIdBase;
    MenuItemView* item = menu->GetMenuItemByID(id);
    if (!item) {
      EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type);
      continue;
    }

    // Check placement.
    EXPECT_EQ(i, submenu->GetSubmenu()->GetIndexOf(item));

    // Check type.
    switch (model_item.type) {
      case ui::MenuModel::TYPE_COMMAND:
        EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType());
        break;
      case ui::MenuModel::TYPE_CHECK:
        EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType());
        break;
      case ui::MenuModel::TYPE_RADIO:
        EXPECT_EQ(views::MenuItemView::RADIO, item->GetType());
        break;
      case ui::MenuModel::TYPE_SEPARATOR:
      case ui::MenuModel::TYPE_BUTTON_ITEM:
        break;
      case ui::MenuModel::TYPE_SUBMENU:
        EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType());
        break;
    }

    // Check activation.
    static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id);
    EXPECT_EQ(i, submodel->last_activation());
    submodel->set_last_activation(-1);
  }

  // Check that selecting the root item is safe.  The MenuModel does
  // not care about the root so MenuModelAdapter should do nothing
  // (not hit the NOTREACHED check) when the root is selected.
  static_cast<views::MenuDelegate*>(&delegate)->SelectionChanged(menu);
}

}  // namespace views

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