Chromium Code Reviews| 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 |