Index: views/controls/menu/native_menu_x.cc |
diff --git a/views/controls/menu/native_menu_x.cc b/views/controls/menu/native_menu_x.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..11683370e9a91ed2a387532f31eb80ded727d1d8 |
--- /dev/null |
+++ b/views/controls/menu/native_menu_x.cc |
@@ -0,0 +1,191 @@ |
+// Copyright (c) 2010 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 "views/controls/menu/native_menu_x.h" |
+ |
+#include "base/logging.h" |
+#include "base/utf_string_conversions.h" |
+#include "gfx/canvas_skia.h" |
+#include "gfx/skia_util.h" |
+#include "views/controls/menu/menu_2.h" |
+#include "views/controls/menu/submenu_view.h" |
+ |
+namespace views { |
+ |
+NativeMenuX::NativeMenuX(Menu2* menu) |
+ : model_(menu->model()), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(root_(new MenuItemView(this))) { |
+} |
+ |
+NativeMenuX::~NativeMenuX() { |
+ delete root_; |
sky
2010/11/22 17:06:15
Use scoped_ptr
sadrul
2010/11/22 18:48:22
Done.
|
+} |
+ |
+// MenuWrapper implementation: |
+void NativeMenuX::RunMenuAt(const gfx::Point& point, int alignment) { |
+ UpdateStates(); |
+ root_->RunMenuAt(NULL, NULL, gfx::Rect(point, gfx::Size()), |
+ alignment == Menu2::ALIGN_TOPLEFT ? MenuItemView::TOPLEFT : |
+ MenuItemView::TOPRIGHT, true); |
+} |
+ |
+void NativeMenuX::CancelMenu() { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void NativeMenuX::Rebuild() { |
+ if (SubmenuView* submenu = root_->GetSubmenu()) { |
+ submenu->RemoveAllChildViews(true); |
+ } |
+ AddMenuItemsFromModel(root_, model_); |
+} |
+ |
+void NativeMenuX::UpdateStates() { |
+ SubmenuView* submenu = root_->CreateSubmenu(); |
+ UpdateMenuFromModel(submenu, model_); |
+} |
+ |
+gfx::NativeMenu NativeMenuX::GetNativeMenu() const { |
+ NOTIMPLEMENTED(); |
+ return NULL; |
+} |
+ |
+MenuWrapper::MenuAction NativeMenuX::GetMenuAction() const { |
+ NOTIMPLEMENTED(); |
+ return MENU_ACTION_NONE; |
+} |
+ |
+void NativeMenuX::AddMenuListener(MenuListener* listener) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void NativeMenuX::RemoveMenuListener(MenuListener* listener) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void NativeMenuX::SetMinimumWidth(int width) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+// MenuDelegate implementation |
+ |
+bool NativeMenuX::IsItemChecked(int cmd) const { |
+ int index; |
+ menus::MenuModel* model = model_; |
+ if (!menus::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) |
+ return false; |
+ return model->IsItemCheckedAt(index); |
+} |
+ |
+bool NativeMenuX::IsCommandEnabled(int cmd) const { |
+ int index; |
+ menus::MenuModel* model = model_; |
+ if (!menus::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) |
+ return false; |
+ return model->IsEnabledAt(index); |
+} |
+ |
+void NativeMenuX::ExecuteCommand(int cmd) { |
+ int index; |
+ menus::MenuModel* model = model_; |
+ if (!menus::MenuModel::GetModelAndIndexForCommandId(cmd, &model, &index)) |
+ return; |
+ model->ActivatedAt(index); |
+} |
+ |
+bool NativeMenuX::GetAccelerator(int id, views::Accelerator* accelerator) { |
+ int index; |
+ menus::MenuModel* model = model_; |
+ if (!menus::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) |
+ return false; |
+ |
+ menus::Accelerator menu_accelerator; |
+ if (!model->GetAcceleratorAt(index, &menu_accelerator)) |
+ return false; |
+ |
+ *accelerator = views::Accelerator(menu_accelerator.GetKeyCode(), |
+ menu_accelerator.modifiers()); |
+ return true; |
+} |
+ |
+// private |
+void NativeMenuX::AddMenuItemsFromModel(MenuItemView* parent, |
+ menus::MenuModel* model) { |
+ for (int i = 0; i < model->GetItemCount(); ++i) { |
+ menus::MenuModel::ItemType menu_type = model->GetTypeAt(i); |
sky
2010/11/22 17:06:15
Offset by GetFirstItemIndex.
sadrul
2010/11/22 18:48:22
Done.
|
+ MenuItemView::Type type; |
+ std::wstring label; |
+ |
+ switch (menu_type) { |
+ case menus::MenuModel::TYPE_COMMAND: |
sky
2010/11/22 17:06:15
Move the code that converts from menus::MenuModel:
sadrul
2010/11/22 18:48:22
Added MenuItemView::AppendMenuItemFromModel to do
|
+ type = MenuItemView::NORMAL; |
+ label = UTF16ToWide(model->GetLabelAt(i)); |
+ break; |
+ case menus::MenuModel::TYPE_CHECK: |
+ type = MenuItemView::CHECKBOX; |
+ label = UTF16ToWide(model->GetLabelAt(i)); |
+ break; |
+ case menus::MenuModel::TYPE_RADIO: |
+ type = MenuItemView::RADIO; |
+ label = UTF16ToWide(model->GetLabelAt(i)); |
+ break; |
+ case menus::MenuModel::TYPE_SEPARATOR: |
+ type = MenuItemView::SEPARATOR; |
+ break; |
+ case menus::MenuModel::TYPE_SUBMENU: |
+ type = MenuItemView::SUBMENU; |
+ label = UTF16ToWide(model->GetLabelAt(i)); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ type = MenuItemView::NORMAL; |
+ break; |
+ } |
+ |
+ MenuItemView* child = parent->AppendMenuItemImpl(model->GetCommandIdAt(i), |
+ label, SkBitmap(), type); |
+ |
+ if (type == MenuItemView::SUBMENU) { |
+ AddMenuItemsFromModel(child, model->GetSubmenuModelAt(i)); |
+ } |
+ } |
+} |
+ |
+void NativeMenuX::UpdateMenuFromModel(SubmenuView* menu, |
+ menus::MenuModel* model) { |
sky
2010/11/22 17:06:15
spacing is off.
sadrul
2010/11/22 18:48:22
Done.
|
+ for (int i = 0, sep = 0; i < model->GetItemCount(); ++i) { |
+ if (model->GetTypeAt(i) == menus::MenuModel::TYPE_SEPARATOR) { |
sky
2010/11/22 17:06:15
Don't you need to offset by model->GetFirstItemInd
sadrul
2010/11/22 18:48:22
Done.
|
+ ++sep; |
+ continue; |
+ } |
+ |
+ // The submenu excludes the separators when counting the menu-items |
+ // in it. So exclude the number of separators to get the correct index. |
+ MenuItemView* mitem = menu->GetMenuItemAt(i - sep); |
+ mitem->SetVisible(model->IsVisibleAt(i)); |
+ mitem->SetEnabled(model->IsEnabledAt(i)); |
+ if (model->IsLabelDynamicAt(i)) { |
+ mitem->SetTitle(UTF16ToWide(model->GetLabelAt(i))); |
+ } |
+ |
+ SkBitmap icon; |
+ if (model->GetIconAt(i, &icon)) { |
+ mitem->SetIcon(icon); |
+ } |
+ |
+ if (model->GetTypeAt(i) == menus::MenuModel::TYPE_SUBMENU) { |
+ DCHECK(mitem->HasSubmenu()); |
+ UpdateMenuFromModel(mitem->GetSubmenu(), model->GetSubmenuModelAt(i)); |
+ } |
+ } |
+} |
+ |
+// MenuWrapper, public: |
+ |
+// static |
+MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { |
+ return new NativeMenuX(menu); |
+} |
+ |
+} // namespace views |