summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-04 17:50:26 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-04 17:50:26 +0000
commitb284843ba6a1e90c12f91eaf796726433dc2537d (patch)
tree96edc5a4528e4d685c89544bfc13712e2984964a /app
parente83ce1e3f2fcacb3d400287d78567d22a2a06cae (diff)
downloadchromium_src-b284843ba6a1e90c12f91eaf796726433dc2537d.zip
chromium_src-b284843ba6a1e90c12f91eaf796726433dc2537d.tar.gz
chromium_src-b284843ba6a1e90c12f91eaf796726433dc2537d.tar.bz2
Refactor the menu model to live outside views/ so it can be shared
BUG=none TEST=none Review URL: http://codereview.chromium.org/465005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33827 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rw-r--r--app/app.gyp5
-rw-r--r--app/menus/accelerator.h67
-rw-r--r--app/menus/menu_model.cc28
-rw-r--r--app/menus/menu_model.h103
-rw-r--r--app/menus/simple_menu_model.cc142
-rw-r--r--app/menus/simple_menu_model.h107
6 files changed, 452 insertions, 0 deletions
diff --git a/app/app.gyp b/app/app.gyp
index 65a12d5..64f652a 100644
--- a/app/app.gyp
+++ b/app/app.gyp
@@ -115,6 +115,11 @@
'l10n_util_posix.cc',
'l10n_util_win.cc',
'l10n_util_win.h',
+ 'menus/accelerator.h',
+ 'menus/menu_model.cc',
+ 'menus/menu_model.h',
+ 'menus/simple_menu_model.cc',
+ 'menus/simple_menu_model.h',
'message_box_flags.h',
'os_exchange_data_provider_gtk.cc',
'os_exchange_data_provider_gtk.h',
diff --git a/app/menus/accelerator.h b/app/menus/accelerator.h
new file mode 100644
index 0000000..1d659a4
--- /dev/null
+++ b/app/menus/accelerator.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2009 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.
+
+#ifndef APP_MENUS_ACCELERATOR_H_
+#define APP_MENUS_ACCELERATOR_H_
+
+#include "base/keyboard_codes.h"
+
+namespace menus {
+
+// This is a cross-platform base class for accelerator keys used in menus. It is
+// meant to be subclassed for concrete toolkit implementations.
+
+class Accelerator {
+ public:
+ Accelerator() : key_code_(base::VKEY_UNKNOWN), modifiers_(0) { }
+ virtual ~Accelerator() { }
+ Accelerator(const Accelerator& accelerator) {
+ key_code_ = accelerator.key_code_;
+ modifiers_ = accelerator.modifiers_;
+ }
+
+ Accelerator& operator=(const Accelerator& accelerator) {
+ if (this != &accelerator) {
+ key_code_ = accelerator.key_code_;
+ modifiers_ = accelerator.modifiers_;
+ }
+ return *this;
+ }
+
+ // We define the < operator so that the KeyboardShortcut can be used as a key
+ // in a std::map.
+ bool operator <(const Accelerator& rhs) const {
+ if (key_code_ != rhs.key_code_)
+ return key_code_ < rhs.key_code_;
+ return modifiers_ < rhs.modifiers_;
+ }
+
+ bool operator ==(const Accelerator& rhs) const {
+ return (key_code_ == rhs.key_code_) && (modifiers_ == rhs.modifiers_);
+ }
+
+ bool operator !=(const Accelerator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ base::KeyboardCode GetKeyCode() const {
+ return key_code_;
+ }
+
+ int modifiers() const {
+ return modifiers_;
+ }
+
+ protected:
+ // The window keycode (VK_...).
+ base::KeyboardCode key_code_;
+
+ // The state of the Shift/Ctrl/Alt keys (platform-dependent).
+ int modifiers_;
+};
+
+}
+
+#endif // APP_MENUS_ACCELERATOR_H_
+
diff --git a/app/menus/menu_model.cc b/app/menus/menu_model.cc
new file mode 100644
index 0000000..63acbf6
--- /dev/null
+++ b/app/menus/menu_model.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2009 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 "app/menus/menu_model.h"
+
+namespace menus {
+
+bool MenuModel::GetModelAndIndexForCommandId(int command_id,
+ MenuModel** model, int* index) {
+ int item_count = (*model)->GetItemCount();
+ for (int i = 0; i < item_count; ++i) {
+ if ((*model)->GetTypeAt(i) == TYPE_SUBMENU) {
+ MenuModel* submenu_model = (*model)->GetSubmenuModelAt(i);
+ if (GetModelAndIndexForCommandId(command_id, &submenu_model, index)) {
+ *model = submenu_model;
+ return true;
+ }
+ }
+ if ((*model)->GetCommandIdAt(i) == command_id) {
+ *index = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
diff --git a/app/menus/menu_model.h b/app/menus/menu_model.h
new file mode 100644
index 0000000..718f3b1
--- /dev/null
+++ b/app/menus/menu_model.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2009 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.
+
+#ifndef APP_MENUS_MENU_MODEL_H_
+#define APP_MENUS_MENU_MODEL_H_
+
+#include "app/gfx/native_widget_types.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+
+class SkBitmap;
+
+namespace menus {
+
+class Accelerator;
+
+// An interface implemented by an object that provides the content of a menu.
+class MenuModel {
+ public:
+ virtual ~MenuModel() {}
+
+ // The type of item.
+ enum ItemType {
+ TYPE_COMMAND,
+ TYPE_CHECK,
+ TYPE_RADIO,
+ TYPE_SEPARATOR,
+ TYPE_SUBMENU
+ };
+
+ // Returns true if any of the items within the model have icons. Not all
+ // platforms support icons in menus natively and so this is a hint for
+ // triggering a custom rendering mode.
+ virtual bool HasIcons() const = 0;
+
+ // Returns the index of the first item. This is 0 for most menus except the
+ // system menu on Windows. |native_menu| is the menu to locate the start index
+ // within. It is guaranteed to be reset to a clean default state.
+ // IMPORTANT: If the model implementation returns something _other_ than 0
+ // here, it must offset the values for |index| it passes to the
+ // methods below by this number - this is NOT done automatically!
+ virtual int GetFirstItemIndex(gfx::NativeMenu native_menu) const { return 0; }
+
+ // Returns the number of items in the menu.
+ virtual int GetItemCount() const = 0;
+
+ // Returns the type of item at the specified index.
+ virtual ItemType GetTypeAt(int index) const = 0;
+
+ // Returns the command id of the item at the specified index.
+ virtual int GetCommandIdAt(int index) const = 0;
+
+ // Returns the label of the item at the specified index.
+ virtual string16 GetLabelAt(int index) const = 0;
+
+ // Returns true if the label at the specified index can change over the course
+ // of the menu's lifetime. If this function returns true, the label of the
+ // menu item will be updated each time the menu is shown.
+ virtual bool IsLabelDynamicAt(int index) const = 0;
+
+ // Gets the acclerator information for the specified index, returning true if
+ // there is a shortcut accelerator for the item, false otherwise.
+ virtual bool GetAcceleratorAt(int index,
+ menus::Accelerator* accelerator) const = 0;
+
+ // Returns the checked state of the item at the specified index.
+ virtual bool IsItemCheckedAt(int index) const = 0;
+
+ // Returns the id of the group of radio items that the item at the specified
+ // index belongs to.
+ virtual int GetGroupIdAt(int index) const = 0;
+
+ // Gets the icon for the item at the specified index, returning true if there
+ // is an icon, false otherwise.
+ virtual bool GetIconAt(int index, SkBitmap* icon) const = 0;
+
+ // Returns the enabled state of the item at the specified index.
+ virtual bool IsEnabledAt(int index) const = 0;
+
+ // Returns the model for the submenu at the specified index.
+ virtual MenuModel* GetSubmenuModelAt(int index) const = 0;
+
+ // Called when the highlighted menu item changes to the item at the specified
+ // index.
+ virtual void HighlightChangedTo(int index) = 0;
+
+ // Called when the item at the specified index has been activated.
+ virtual void ActivatedAt(int index) = 0;
+
+ // Called when the menu is about to be shown.
+ virtual void MenuWillShow() {}
+
+ // Retrieves the model and index that contains a specific command id. Returns
+ // true if an item with the specified command id is found. |model| is inout,
+ // and specifies the model to start searching from.
+ static bool GetModelAndIndexForCommandId(int command_id, MenuModel** model,
+ int* index);
+};
+
+} // namespace
+
+#endif // APP_MENUS_MENU_MODEL_H_
diff --git a/app/menus/simple_menu_model.cc b/app/menus/simple_menu_model.cc
new file mode 100644
index 0000000..66ef4c4
--- /dev/null
+++ b/app/menus/simple_menu_model.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2009 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 "app/menus/simple_menu_model.h"
+
+#include "app/l10n_util.h"
+
+namespace menus {
+
+////////////////////////////////////////////////////////////////////////////////
+// SimpleMenuModel, public:
+
+SimpleMenuModel::SimpleMenuModel(Delegate* delegate) : delegate_(delegate) {
+}
+
+SimpleMenuModel::~SimpleMenuModel() {
+}
+
+void SimpleMenuModel::AddItem(int command_id, const string16& label) {
+ Item item = { command_id, label, TYPE_COMMAND, -1, NULL };
+ items_.push_back(item);
+}
+
+void SimpleMenuModel::AddItemWithStringId(int command_id, int string_id) {
+ AddItem(command_id, l10n_util::GetStringUTF16(string_id));
+}
+
+void SimpleMenuModel::AddSeparator() {
+ Item item = { -1, string16(), TYPE_SEPARATOR, -1, NULL };
+ items_.push_back(item);
+}
+
+void SimpleMenuModel::AddCheckItem(int command_id, const string16& label) {
+ Item item = { command_id, label, TYPE_CHECK, -1, NULL };
+ items_.push_back(item);
+}
+
+void SimpleMenuModel::AddCheckItemWithStringId(int command_id, int string_id) {
+ AddCheckItem(command_id, l10n_util::GetStringUTF16(string_id));
+}
+
+void SimpleMenuModel::AddRadioItem(int command_id, const string16& label,
+ int group_id) {
+ Item item = { command_id, label, TYPE_RADIO, group_id, NULL };
+ items_.push_back(item);
+}
+
+void SimpleMenuModel::AddRadioItemWithStringId(int command_id, int string_id,
+ int group_id) {
+ AddRadioItem(command_id, l10n_util::GetStringUTF16(string_id), group_id);
+}
+
+void SimpleMenuModel::AddSubMenu(const string16& label, MenuModel* model) {
+ Item item = { -1, label, TYPE_SUBMENU, -1, model };
+ items_.push_back(item);
+}
+
+void SimpleMenuModel::AddSubMenuWithStringId(int string_id, MenuModel* model) {
+ AddSubMenu(l10n_util::GetStringUTF16(string_id), model);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SimpleMenuModel, MenuModel implementation:
+
+bool SimpleMenuModel::HasIcons() const {
+ return false;
+}
+
+int SimpleMenuModel::GetItemCount() const {
+ return static_cast<int>(items_.size());
+}
+
+MenuModel::ItemType SimpleMenuModel::GetTypeAt(int index) const {
+ return items_.at(FlipIndex(index)).type;
+}
+
+int SimpleMenuModel::GetCommandIdAt(int index) const {
+ return items_.at(FlipIndex(index)).command_id;
+}
+
+string16 SimpleMenuModel::GetLabelAt(int index) const {
+ if (IsLabelDynamicAt(index))
+ return delegate_->GetLabelForCommandId(GetCommandIdAt(index));
+ return items_.at(FlipIndex(index)).label;
+}
+
+bool SimpleMenuModel::IsLabelDynamicAt(int index) const {
+ if (delegate_)
+ return delegate_->IsLabelForCommandIdDynamic(GetCommandIdAt(index));
+ return false;
+}
+
+bool SimpleMenuModel::GetAcceleratorAt(int index,
+ menus::Accelerator* accelerator) const {
+ if (delegate_) {
+ return delegate_->GetAcceleratorForCommandId(GetCommandIdAt(index),
+ accelerator);
+ }
+ return false;
+}
+
+bool SimpleMenuModel::IsItemCheckedAt(int index) const {
+ if (!delegate_)
+ return false;
+ int item_index = FlipIndex(index);
+ MenuModel::ItemType item_type = items_[item_index].type;
+ return (item_type == TYPE_CHECK || item_type == TYPE_RADIO) ?
+ delegate_->IsCommandIdChecked(GetCommandIdAt(index)) : false;
+}
+
+int SimpleMenuModel::GetGroupIdAt(int index) const {
+ return items_.at(FlipIndex(index)).group_id;
+}
+
+bool SimpleMenuModel::GetIconAt(int index, SkBitmap* icon) const {
+ return false;
+}
+
+bool SimpleMenuModel::IsEnabledAt(int index) const {
+ int command_id = GetCommandIdAt(index);
+ // Submenus have a command id of -1, they should always be enabled.
+ if (!delegate_ || command_id == -1)
+ return true;
+ return delegate_->IsCommandIdEnabled(command_id);
+}
+
+void SimpleMenuModel::HighlightChangedTo(int index) {
+ if (delegate_)
+ delegate_->CommandIdHighlighted(GetCommandIdAt(index));
+}
+
+void SimpleMenuModel::ActivatedAt(int index) {
+ if (delegate_)
+ delegate_->ExecuteCommand(GetCommandIdAt(index));
+}
+
+MenuModel* SimpleMenuModel::GetSubmenuModelAt(int index) const {
+ return items_.at(FlipIndex(index)).submenu;
+}
+
+} // namespace views
diff --git a/app/menus/simple_menu_model.h b/app/menus/simple_menu_model.h
new file mode 100644
index 0000000..7d73703
--- /dev/null
+++ b/app/menus/simple_menu_model.h
@@ -0,0 +1,107 @@
+// Copyright (c) 2009 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.
+
+#ifndef APP_MENUS_SIMPLE_MENU_MODEL_H_
+#define APP_MENUS_SIMPLE_MENU_MODEL_H_
+
+#include <vector>
+
+#include "base/string16.h"
+#include "app/menus/menu_model.h"
+
+namespace menus {
+
+// A simple MenuModel implementation with an imperative API for adding menu
+// items. This makes it easy to construct fixed menus. Menus populated by
+// dynamic data sources may be better off implementing MenuModel directly.
+// The breadth of MenuModel is not exposed through this API.
+class SimpleMenuModel : public MenuModel {
+ public:
+ class Delegate {
+ public:
+ // Methods for determining the state of specific command ids.
+ virtual bool IsCommandIdChecked(int command_id) const = 0;
+ virtual bool IsCommandIdEnabled(int command_id) const = 0;
+
+ // Gets the accelerator for the specified command id. Returns true if the
+ // command id has a valid accelerator, false otherwise.
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ menus::Accelerator* accelerator) = 0;
+
+ // Some command ids have labels that change over time.
+ virtual bool IsLabelForCommandIdDynamic(int command_id) const {
+ return false;
+ }
+ virtual string16 GetLabelForCommandId(int command_id) const {
+ return string16();
+ }
+
+ // Notifies the delegate that the item with the specified command id was
+ // visually highlighted within the menu.
+ virtual void CommandIdHighlighted(int command_id) {}
+
+ // Performs the action associated with the specified command id.
+ virtual void ExecuteCommand(int command_id) = 0;
+ };
+
+ // The Delegate can be NULL, though if it is items can't be checked or
+ // disabled.
+ explicit SimpleMenuModel(Delegate* delegate);
+ virtual ~SimpleMenuModel();
+
+ // Methods for adding items to the model.
+ void AddItem(int command_id, const string16& label);
+ void AddItemWithStringId(int command_id, int string_id);
+ void AddSeparator();
+ void AddCheckItem(int command_id, const string16& label);
+ void AddCheckItemWithStringId(int command_id, int string_id);
+ void AddRadioItem(int command_id, const string16& label, int group_id);
+ void AddRadioItemWithStringId(int command_id, int string_id, int group_id);
+ void AddSubMenu(const string16& label, MenuModel* model);
+ void AddSubMenuWithStringId(int string_id, MenuModel* model);
+
+ // Overridden from MenuModel:
+ virtual bool HasIcons() const;
+ virtual int GetItemCount() const;
+ virtual ItemType GetTypeAt(int index) const;
+ virtual int GetCommandIdAt(int index) const;
+ virtual string16 GetLabelAt(int index) const;
+ virtual bool IsLabelDynamicAt(int index) const;
+ virtual bool GetAcceleratorAt(int index,
+ menus::Accelerator* accelerator) const;
+ virtual bool IsItemCheckedAt(int index) const;
+ virtual int GetGroupIdAt(int index) const;
+ virtual bool GetIconAt(int index, SkBitmap* icon) const;
+ virtual bool IsEnabledAt(int index) const;
+ virtual void HighlightChangedTo(int index);
+ virtual void ActivatedAt(int index);
+ virtual MenuModel* GetSubmenuModelAt(int index) const;
+
+ protected:
+ // Some variants of this model (SystemMenuModel) relies on items to be
+ // inserted backwards. This is counter-intuitive for the API, so rather than
+ // forcing customers to insert things backwards, we return the indices
+ // backwards instead. That's what this method is for. By default, it just
+ // returns what it's passed.
+ virtual int FlipIndex(int index) const { return index; }
+
+ private:
+ struct Item {
+ int command_id;
+ string16 label;
+ ItemType type;
+ int group_id;
+ MenuModel* submenu;
+ };
+ std::vector<Item> items_;
+
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleMenuModel);
+};
+
+} // namespace menus
+
+#endif // APP_MENUS_SIMPLE_MENU_MODEL_H_