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 "ui/views/examples/menu_example.h"
6
7#include <set>
8
9#include "base/strings/utf_string_conversions.h"
10#include "ui/base/models/simple_menu_model.h"
11#include "ui/views/controls/button/menu_button.h"
12#include "ui/views/controls/button/menu_button_listener.h"
13#include "ui/views/controls/menu/menu_runner.h"
14#include "ui/views/layout/fill_layout.h"
15#include "ui/views/view.h"
16#include "ui/views/widget/widget.h"
17
18namespace views {
19namespace examples {
20
21namespace {
22
23class ExampleMenuModel : public ui::SimpleMenuModel,
24                         public ui::SimpleMenuModel::Delegate {
25 public:
26  ExampleMenuModel();
27
28  // Overridden from ui::SimpleMenuModel::Delegate:
29  virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
30  virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
31  virtual bool GetAcceleratorForCommandId(
32      int command_id,
33      ui::Accelerator* accelerator) OVERRIDE;
34  virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
35
36 private:
37  enum GroupID {
38    GROUP_MAKE_DECISION,
39  };
40
41  enum CommandID {
42    COMMAND_DO_SOMETHING,
43    COMMAND_SELECT_ASCII,
44    COMMAND_SELECT_UTF8,
45    COMMAND_SELECT_UTF16,
46    COMMAND_CHECK_APPLE,
47    COMMAND_CHECK_ORANGE,
48    COMMAND_CHECK_KIWI,
49    COMMAND_GO_HOME,
50  };
51
52  scoped_ptr<ui::SimpleMenuModel> submenu_;
53  std::set<int> checked_fruits_;
54  int current_encoding_command_id_;
55
56  DISALLOW_COPY_AND_ASSIGN(ExampleMenuModel);
57};
58
59class ExampleMenuButton : public MenuButton, public MenuButtonListener {
60 public:
61  explicit ExampleMenuButton(const string16& test);
62  virtual ~ExampleMenuButton();
63
64 private:
65  // Overridden from MenuButtonListener:
66  virtual void OnMenuButtonClicked(View* source,
67                                   const gfx::Point& point) OVERRIDE;
68
69  ui::SimpleMenuModel* GetMenuModel();
70
71  scoped_ptr<ExampleMenuModel> menu_model_;
72  scoped_ptr<MenuRunner> menu_runner_;
73
74  DISALLOW_COPY_AND_ASSIGN(ExampleMenuButton);
75};
76
77// ExampleMenuModel ---------------------------------------------------------
78
79ExampleMenuModel::ExampleMenuModel()
80    : ui::SimpleMenuModel(this),
81      current_encoding_command_id_(COMMAND_SELECT_ASCII) {
82  AddItem(COMMAND_DO_SOMETHING, ASCIIToUTF16("Do Something"));
83  AddSeparator(ui::NORMAL_SEPARATOR);
84  AddRadioItem(COMMAND_SELECT_ASCII, ASCIIToUTF16("ASCII"),
85               GROUP_MAKE_DECISION);
86  AddRadioItem(COMMAND_SELECT_UTF8, ASCIIToUTF16("UTF-8"),
87               GROUP_MAKE_DECISION);
88  AddRadioItem(COMMAND_SELECT_UTF16, ASCIIToUTF16("UTF-16"),
89               GROUP_MAKE_DECISION);
90  AddSeparator(ui::NORMAL_SEPARATOR);
91  AddCheckItem(COMMAND_CHECK_APPLE, ASCIIToUTF16("Apple"));
92  AddCheckItem(COMMAND_CHECK_ORANGE, ASCIIToUTF16("Orange"));
93  AddCheckItem(COMMAND_CHECK_KIWI, ASCIIToUTF16("Kiwi"));
94  AddSeparator(ui::NORMAL_SEPARATOR);
95  AddItem(COMMAND_GO_HOME, ASCIIToUTF16("Go Home"));
96
97  submenu_.reset(new ui::SimpleMenuModel(this));
98  submenu_->AddItem(COMMAND_DO_SOMETHING, ASCIIToUTF16("Do Something 2"));
99  AddSubMenu(0, ASCIIToUTF16("Submenu"), submenu_.get());
100}
101
102bool ExampleMenuModel::IsCommandIdChecked(int command_id) const {
103  // Radio items.
104  if (command_id == current_encoding_command_id_)
105    return true;
106
107  // Check items.
108  if (checked_fruits_.find(command_id) != checked_fruits_.end())
109    return true;
110
111  return false;
112}
113
114bool ExampleMenuModel::IsCommandIdEnabled(int command_id) const {
115  // All commands are enabled except for COMMAND_GO_HOME.
116  return command_id != COMMAND_GO_HOME;
117}
118
119bool ExampleMenuModel::GetAcceleratorForCommandId(
120    int command_id,
121    ui::Accelerator* accelerator) {
122  // We don't use this in the example.
123  return false;
124}
125
126void ExampleMenuModel::ExecuteCommand(int command_id, int event_flags) {
127  switch (command_id) {
128    case COMMAND_DO_SOMETHING: {
129      LOG(INFO) << "Done something";
130      break;
131    }
132
133    // Radio items.
134    case COMMAND_SELECT_ASCII: {
135      current_encoding_command_id_ = COMMAND_SELECT_ASCII;
136      LOG(INFO) << "Selected ASCII";
137      break;
138    }
139    case COMMAND_SELECT_UTF8: {
140      current_encoding_command_id_ = COMMAND_SELECT_UTF8;
141      LOG(INFO) << "Selected UTF-8";
142      break;
143    }
144    case COMMAND_SELECT_UTF16: {
145      current_encoding_command_id_ = COMMAND_SELECT_UTF16;
146      LOG(INFO) << "Selected UTF-16";
147      break;
148    }
149
150    // Check items.
151    case COMMAND_CHECK_APPLE:
152    case COMMAND_CHECK_ORANGE:
153    case COMMAND_CHECK_KIWI: {
154      // Print what fruit is checked.
155      const char* checked_fruit = "";
156      if (command_id == COMMAND_CHECK_APPLE)
157        checked_fruit = "Apple";
158      else if (command_id == COMMAND_CHECK_ORANGE)
159        checked_fruit = "Orange";
160      else if (command_id == COMMAND_CHECK_KIWI)
161        checked_fruit = "Kiwi";
162
163      // Update the check status.
164      std::set<int>::iterator iter = checked_fruits_.find(command_id);
165      if (iter == checked_fruits_.end()) {
166        DVLOG(1) << "Checked " << checked_fruit;
167        checked_fruits_.insert(command_id);
168      } else {
169        DVLOG(1) << "Unchecked " << checked_fruit;
170        checked_fruits_.erase(iter);
171      }
172      break;
173    }
174  }
175}
176
177// ExampleMenuButton -----------------------------------------------------------
178
179ExampleMenuButton::ExampleMenuButton(const string16& test)
180    : MenuButton(NULL, test, this, true) {
181}
182
183ExampleMenuButton::~ExampleMenuButton() {
184}
185
186void ExampleMenuButton::OnMenuButtonClicked(View* source,
187                                            const gfx::Point& point) {
188  menu_runner_.reset(new MenuRunner(GetMenuModel()));
189
190  if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), this,
191        gfx::Rect(point, gfx::Size()), MenuItemView::TOPRIGHT,
192        ui::MENU_SOURCE_NONE, MenuRunner::HAS_MNEMONICS) ==
193      MenuRunner::MENU_DELETED)
194    return;
195}
196
197ui::SimpleMenuModel* ExampleMenuButton::GetMenuModel() {
198  if (!menu_model_.get())
199    menu_model_.reset(new ExampleMenuModel);
200  return menu_model_.get();
201}
202
203}  // namespace
204
205MenuExample::MenuExample() : ExampleBase("Menu") {
206}
207
208MenuExample::~MenuExample() {
209}
210
211void MenuExample::CreateExampleView(View* container) {
212  // We add a button to open a menu.
213  ExampleMenuButton* menu_button = new ExampleMenuButton(
214      ASCIIToUTF16("Open a menu"));
215  container->SetLayoutManager(new FillLayout);
216  container->AddChildView(menu_button);
217}
218
219}  // namespace examples
220}  // namespace views
221