Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: chrome/browser/chromeos/status/network_menu.cc

Issue 6811025: Change status button menu implementation from Menu2 to MenuItemView. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixed crash in VPN submenu. Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/status/network_menu.cc
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index 7f5d05cb8d9fd00e28beab5ca51ed868874338f7..4ce1f61a7c3772d5e00b33f7a186a4ee32b7d4ca 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -25,9 +25,21 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/skbitmap_operations.h"
-#include "views/controls/menu/menu_2.h"
+#include "views/controls/button/menu_button.h"
+#include "views/controls/menu/menu_item_view.h"
+#include "views/controls/menu/submenu_view.h"
+#include "views/widget/widget.h"
#include "views/window/window.h"
+using views::MenuItemView;
+
+namespace {
+
+// Offset for VPN menu items.
+const int kVPNCommandIndexOffset = 10000;
+
+} // namespace
+
namespace chromeos {
class MainMenuModel : public NetworkMenuModel {
@@ -35,9 +47,18 @@ class MainMenuModel : public NetworkMenuModel {
explicit MainMenuModel(NetworkMenu* owner);
virtual ~MainMenuModel() {}
- // NetworkMenuModel implementation.
+ // NetworkMenuModel implementation -------------------------------------------
virtual void InitMenuItems(bool is_browser_mode,
- bool should_open_button_options);
+ bool should_open_button_options) OVERRIDE;
+ virtual void PopulateMenuItem(views::MenuItemView* menu,
+ int index,
+ int command_id) OVERRIDE;
+
+ // MenuDelegate implementaion ------------------------------------------------
+ virtual const gfx::Font& GetLabelFont(int id) const OVERRIDE;
+ virtual bool IsItemChecked(int id) const OVERRIDE;
+ virtual bool IsCommandEnabled(int id) const OVERRIDE;
+ virtual void ExecuteCommand(int id) OVERRIDE;
private:
scoped_ptr<NetworkMenuModel> vpn_menu_model_;
@@ -53,6 +74,10 @@ class VPNMenuModel : public NetworkMenuModel {
// NetworkMenuModel implementation.
virtual void InitMenuItems(bool is_browser_mode,
bool should_open_button_options);
+ virtual void PopulateMenuItem(
+ views::MenuItemView* menu,
+ int index,
+ int command_id) OVERRIDE;
static SkBitmap IconForDisplay(const Network* network);
@@ -60,8 +85,7 @@ class VPNMenuModel : public NetworkMenuModel {
DISALLOW_COPY_AND_ASSIGN(VPNMenuModel);
};
-////////////////////////////////////////////////////////////////////////////////
-// NetworkMenuModel, public methods:
+// NetworkMenuModel, public methods: -------------------------------------------
bool NetworkMenuModel::ConnectToNetworkAt(int index,
const std::string& passphrase,
@@ -157,55 +181,36 @@ bool NetworkMenuModel::ConnectToNetworkAt(int index,
return true;
}
-////////////////////////////////////////////////////////////////////////////////
-// NetworkMenuModel, ui::MenuModel implementation:
-
-int NetworkMenuModel::GetItemCount() const {
- return static_cast<int>(menu_items_.size());
-}
-
-ui::MenuModel::ItemType NetworkMenuModel::GetTypeAt(int index) const {
- return menu_items_[index].type;
-}
-
-string16 NetworkMenuModel::GetLabelAt(int index) const {
- return menu_items_[index].label;
-}
+// NetworkMenuModel, views::MenuDelegate implementation ------------------------
-const gfx::Font* NetworkMenuModel::GetLabelFontAt(int index) const {
- return (menu_items_[index].flags & FLAG_ASSOCIATED) ?
- &ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BoldFont) :
- NULL;
+const gfx::Font& NetworkMenuModel::GetLabelFont(int id) const {
+ DCHECK_LE(0, id);
+ DCHECK_GT(static_cast<int>(menu_items_.size()), id);
+ return (menu_items_[id].flags & FLAG_ASSOCIATED) ?
+ ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BoldFont) :
+ ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont);
}
-bool NetworkMenuModel::IsItemCheckedAt(int index) const {
- // All ui::MenuModel::TYPE_CHECK menu items are checked.
+bool NetworkMenuModel::IsItemChecked(int id) const {
return true;
}
-bool NetworkMenuModel::GetIconAt(int index, SkBitmap* icon) {
- if (!menu_items_[index].icon.empty()) {
- *icon = menu_items_[index].icon;
+bool NetworkMenuModel::IsCommandEnabled(int id) const {
+ if (id < static_cast<int>(menu_items_.size()))
+ return !(menu_items_[id].flags & FLAG_DISABLED);
+ else
return true;
- }
- return false;
-}
-
-bool NetworkMenuModel::IsEnabledAt(int index) const {
- return !(menu_items_[index].flags & FLAG_DISABLED);
}
-ui::MenuModel* NetworkMenuModel::GetSubmenuModelAt(int index) const {
- return menu_items_[index].sub_menu_model;
-}
-
-void NetworkMenuModel::ActivatedAt(int index) {
+void NetworkMenuModel::ExecuteCommand(int id) {
+ DCHECK_LE(0, id);
+ DCHECK_GT(static_cast<int>(menu_items_.size()), id);
// When we are refreshing the menu, ignore menu item activation.
if (owner_->refreshing_menu_)
return;
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
- int flags = menu_items_[index].flags;
+ int flags = menu_items_[id].flags;
if (flags & FLAG_OPTIONS) {
owner_->OpenButtonOptions();
} else if (flags & FLAG_TOGGLE_ETHERNET) {
@@ -235,7 +240,7 @@ void NetworkMenuModel::ActivatedAt(int index) {
} else if (flags & (FLAG_WIFI | FLAG_ADD_WIFI |
FLAG_CELLULAR | FLAG_ADD_CELLULAR |
FLAG_VPN | FLAG_ADD_VPN)) {
- ConnectToNetworkAt(index, std::string(), std::string(), -1);
+ ConnectToNetworkAt(id, std::string(), std::string(), -1);
} else if (flags & FLAG_DISCONNECT_VPN) {
const VirtualNetwork* active_vpn = cros->virtual_network();
if (active_vpn)
@@ -243,8 +248,41 @@ void NetworkMenuModel::ActivatedAt(int index) {
}
}
-////////////////////////////////////////////////////////////////////////////////
-// NetworkMenuModel, private methods:
+void NetworkMenuModel::PopulateMenu(views::MenuItemView* menu) {
+ menu->CreateSubmenu()->RemoveAllChildViews(true);
+ const int menu_items_count = static_cast<int>(menu_items_.size());
+ for (int i = 0; i < menu_items_count; ++i)
+ PopulateMenuItem(menu, i, i);
+
+ menu->ChildrenChanged();
+}
+
+void NetworkMenuModel::PopulateMenuItem(
+ views::MenuItemView* menu,
+ int index,
+ int command_id) {
+ DCHECK_GT(static_cast<int>(menu_items_.size()), index);
+ const MenuItem& item = menu_items_[index];
+ switch (item.type) {
+ case ui::MenuModel::TYPE_SEPARATOR:
+ menu->AppendSeparator();
+ break;
+ case ui::MenuModel::TYPE_COMMAND:
+ if (item.icon.empty())
+ menu->AppendMenuItemWithLabel(command_id, UTF16ToWide(item.label));
+ else
+ menu->AppendMenuItemWithIcon(
+ command_id,
+ UTF16ToWide(item.label),
+ item.icon);
stevenjb 2011/04/21 22:25:31 nit: slightly more readable with { }
rhashimoto 2011/04/21 22:49:58 Done.
+ break;
+ default:
+ // Submenus should be handled by subclasses.
+ NOTREACHED();
+ }
+}
+
+// NetworkMenuModel, private methods: ------------------------------------------
void NetworkMenuModel::ShowTabbedNetworkSettings(const Network* network) const {
DCHECK(network);
@@ -286,14 +324,15 @@ void NetworkMenuModel::ShowOtherCellular() const {
ChooseMobileNetworkDialog::ShowDialog(owner_->GetNativeWindow());
}
-////////////////////////////////////////////////////////////////////////////////
-// MainMenuModel
+// MainMenuModel ---------------------------------------------------------------
MainMenuModel::MainMenuModel(NetworkMenu* owner)
: NetworkMenuModel(owner) {
vpn_menu_model_.reset(new VPNMenuModel(owner));
}
+// MainMenuModel, NetworkMenuModel implementation: -----------------------------
+
void MainMenuModel::InitMenuItems(bool is_browser_mode,
bool should_open_button_options) {
// This gets called on initialization, so any changes should be reflected
@@ -594,13 +633,67 @@ void MainMenuModel::InitMenuItems(bool is_browser_mode,
}
}
-////////////////////////////////////////////////////////////////////////////////
-// VPNMenuModel
+// MainMenuModel, views::MenuDelegate implementation ---------------------------
+
+const gfx::Font& MainMenuModel::GetLabelFont(int id) const {
+ if (id >= kVPNCommandIndexOffset)
+ return vpn_menu_model_->GetLabelFont(id - kVPNCommandIndexOffset);
+ else
+ return NetworkMenuModel::GetLabelFont(id);
+}
+
+bool MainMenuModel::IsItemChecked(int id) const {
+ if (id >= kVPNCommandIndexOffset)
+ return vpn_menu_model_->IsItemChecked(id - kVPNCommandIndexOffset);
+ else
+ return NetworkMenuModel::IsItemChecked(id);
+}
+
+bool MainMenuModel::IsCommandEnabled(int id) const {
+ if (id >= kVPNCommandIndexOffset)
+ return vpn_menu_model_->IsCommandEnabled(id - kVPNCommandIndexOffset);
+ else
+ return NetworkMenuModel::IsCommandEnabled(id);
+}
+
+void MainMenuModel::ExecuteCommand(int id) {
+ if (id >= kVPNCommandIndexOffset)
+ vpn_menu_model_->ExecuteCommand(id - kVPNCommandIndexOffset);
+ else
+ NetworkMenuModel::ExecuteCommand(id);
+}
+
+// MainMenuModel, NetworkMenuModel implementation: -----------------------------
+
+void MainMenuModel::PopulateMenuItem(
+ views::MenuItemView* menu,
+ int index,
+ int command_id) {
+ DCHECK_GT(static_cast<int>(menu_items_.size()), index);
+ const MenuItem& item = menu_items_[index];
+ if (item.type == ui::MenuModel::TYPE_SUBMENU) {
+ views::MenuItemView* vpn_menu = NULL;
+ if (item.icon.empty())
+ vpn_menu = menu->AppendSubMenu(command_id, UTF16ToWide(item.label));
+ else
+ vpn_menu = menu->AppendSubMenuWithIcon(
+ command_id,
+ UTF16ToWide(item.label),
+ item.icon);
stevenjb 2011/04/21 22:25:31 nit: {}
rhashimoto 2011/04/21 22:49:58 Done.
+ vpn_menu_model_->PopulateMenu(vpn_menu);
+ } else {
+ NetworkMenuModel::PopulateMenuItem(menu, index, command_id);
+ }
+}
+
+// VPNMenuModel ----------------------------------------------------------------
VPNMenuModel::VPNMenuModel(NetworkMenu* owner)
: NetworkMenuModel(owner) {
}
+// VPNMenuModel, NetworkMenuModel implementation: ------------------------------
+
void VPNMenuModel::InitMenuItems(bool is_browser_mode,
bool should_open_button_options) {
// This gets called on initialization, so any changes should be reflected
@@ -666,6 +759,16 @@ void VPNMenuModel::InitMenuItems(bool is_browser_mode,
}
}
+void VPNMenuModel::PopulateMenuItem(
+ views::MenuItemView* menu,
+ int index,
+ int command_id) {
+ NetworkMenuModel::PopulateMenuItem(
+ menu,
+ index,
+ command_id + kVPNCommandIndexOffset);
+}
+
// static
SkBitmap VPNMenuModel::IconForDisplay(const Network* network) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -753,7 +856,8 @@ SkBitmap NetworkMenu::kAnimatingImagesBlack[kNumAnimatingImages];
NetworkMenu::NetworkMenu()
: min_width_(-1) {
main_menu_model_.reset(new MainMenuModel(this));
- network_menu_.reset(new views::Menu2(main_menu_model_.get()));
+ network_menu_.reset(new views::MenuItemView(main_menu_model_.get()));
+ network_menu_->set_has_icons(true);
}
NetworkMenu::~NetworkMenu() {
@@ -761,18 +865,16 @@ NetworkMenu::~NetworkMenu() {
void NetworkMenu::SetFirstLevelMenuWidth(int width) {
min_width_ = width;
- // This actually has no effect since menu is rebuilt before showing.
- network_menu_->SetMinimumWidth(width);
}
void NetworkMenu::CancelMenu() {
- network_menu_->CancelMenu();
+ network_menu_->Cancel();
}
void NetworkMenu::UpdateMenu() {
refreshing_menu_ = true;
main_menu_model_->InitMenuItems(IsBrowserMode(), ShouldOpenButtonOptions());
- network_menu_->Rebuild();
+ main_menu_model_->PopulateMenu(network_menu_.get());
refreshing_menu_ = false;
}
@@ -971,26 +1073,33 @@ SkBitmap NetworkMenu::IconForDisplay(const SkBitmap* icon,
return canvas.ExtractBitmap();
}
-////////////////////////////////////////////////////////////////////////////////
-// NetworkMenu, views::ViewMenuDelegate implementation:
+// NetworkMenu, views::ViewMenuDelegate implementation: ------------------------
void NetworkMenu::RunMenu(views::View* source, const gfx::Point& pt) {
- refreshing_menu_ = true;
+ DCHECK_EQ(GetMenuButton(), source);
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
cros->RequestNetworkScan();
- // Build initial menu items. They will be updated when UpdateMenu is
- // called from NetworkChanged.
- main_menu_model_->InitMenuItems(IsBrowserMode(), ShouldOpenButtonOptions());
- network_menu_->Rebuild();
-
- // Restore menu width, if it was set up.
- // NOTE: width isn't checked for correctness here since all width-related
- // logic implemented inside |network_menu_|.
- if (min_width_ != -1)
- network_menu_->SetMinimumWidth(min_width_);
- refreshing_menu_ = false;
- network_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
+ UpdateMenu();
+
+ // TODO(rhashimoto): Remove this workaround when WebUI provides a
+ // top-level widget on the ChromeOS login screen that is a window.
+ // The current BackgroundView class for the ChromeOS login screen
+ // creates a owning Widget that has a native GtkWindow but is not a
+ // Window. This makes it impossible to get the NativeWindow via
+ // the views API. This workaround casts the top-level NativeWidget
+ // to a NativeWindow that we can pass to MenuItemView::RunMenuAt().
+ gfx::NativeWindow window = GTK_WINDOW(source->GetWidget()->GetNativeView());
+
+ gfx::Point screen_loc;
+ views::View::ConvertPointToScreen(source, &screen_loc);
+ gfx::Rect bounds(screen_loc, source->size());
+ network_menu_->RunMenuAt(
+ window,
+ GetMenuButton(),
+ bounds,
+ base::i18n::IsRTL() ? MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT,
+ true);
}
} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698