summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 22:49:58 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 22:49:58 +0000
commit0f28580a84220d218288bfdec6bb689b2e1b8d29 (patch)
tree2034a137103f04f513b6ab0d4cc3cbb13ccdd30f
parent4a4d141960653d52e80b52c92358b6f19fc21b1b (diff)
downloadchromium_src-0f28580a84220d218288bfdec6bb689b2e1b8d29.zip
chromium_src-0f28580a84220d218288bfdec6bb689b2e1b8d29.tar.gz
chromium_src-0f28580a84220d218288bfdec6bb689b2e1b8d29.tar.bz2
GTK: make tab context menu use tab_menu_model
flesh out some more menu model implementation for MenuGtk BUG=28977 TEST=menu still works as before Review URL: http://codereview.chromium.org/523049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35569 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--app/app_base.gypi1
-rw-r--r--app/menus/accelerator_gtk.h46
-rw-r--r--chrome/browser/gtk/browser_actions_toolbar_gtk.cc5
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc2
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h3
-rw-r--r--chrome/browser/gtk/menu_gtk.cc60
-rw-r--r--chrome/browser/gtk/menu_gtk.h1
-rw-r--r--chrome/browser/gtk/tabs/tab_gtk.cc84
8 files changed, 138 insertions, 64 deletions
diff --git a/app/app_base.gypi b/app/app_base.gypi
index 9c15d4c..f0aacef 100644
--- a/app/app_base.gypi
+++ b/app/app_base.gypi
@@ -159,6 +159,7 @@
'l10n_util_win.cc',
'l10n_util_win.h',
'menus/accelerator.h',
+ 'menus/accelerator_gtk.h',
'menus/menu_model.cc',
'menus/menu_model.h',
'menus/simple_menu_model.cc',
diff --git a/app/menus/accelerator_gtk.h b/app/menus/accelerator_gtk.h
new file mode 100644
index 0000000..ad74b4e
--- /dev/null
+++ b/app/menus/accelerator_gtk.h
@@ -0,0 +1,46 @@
+// 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_GTK_H_
+#define APP_MENUS_ACCELERATOR_GTK_H_
+
+#include <gdk/gdk.h>
+
+#include "app/menus/accelerator.h"
+#include "base/keyboard_code_conversion_gtk.h"
+#include "base/keyboard_codes_posix.h"
+
+namespace menus {
+
+class AcceleratorGtk : public Accelerator {
+ public:
+ AcceleratorGtk(base::KeyboardCode key_code,
+ bool shift_pressed, bool ctrl_pressed, bool alt_pressed) {
+ key_code_ = key_code;
+ modifiers_ = 0;
+ if (shift_pressed)
+ modifiers_ |= GDK_SHIFT_MASK;
+ if (ctrl_pressed)
+ modifiers_ |= GDK_CONTROL_MASK;
+ if (alt_pressed)
+ modifiers_ |= GDK_MOD1_MASK;
+ }
+
+ AcceleratorGtk() { }
+ virtual ~AcceleratorGtk() { }
+
+ guint GetGdkKeyCode() {
+ // The second parameter is false because accelerator keys are expressed in
+ // terms of the non-shift-modified key.
+ return base::GdkKeyCodeForWindowsKeyCode(GetKeyCode(), false);
+ }
+
+ GdkModifierType gdk_modifier_type() {
+ return static_cast<GdkModifierType>(modifiers());
+ }
+};
+
+}
+
+#endif // APP_MENUS_ACCELERATOR_GTK_H_
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
index cc43f3e..4da93f9 100644
--- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
@@ -51,8 +51,7 @@ GtkTargetEntry GetDragTargetEntry() {
} // namespace
class BrowserActionButton : public NotificationObserver,
- public ImageLoadingTracker::Observer,
- public MenuGtk::Delegate {
+ public ImageLoadingTracker::Observer {
public:
BrowserActionButton(BrowserActionsToolbarGtk* toolbar,
Extension* extension)
@@ -182,7 +181,7 @@ class BrowserActionButton : public NotificationObserver,
}
action->context_menu_.reset(
- new MenuGtk(action, action->context_menu_model_.get()));
+ new MenuGtk(NULL, action->context_menu_model_.get()));
action->context_menu_->Popup(widget, event);
return TRUE;
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 186b575..0f037c8 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -887,7 +887,7 @@ gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed(
context_menu_model_.reset(new ExtensionActionContextMenuModel(extension));
context_menu_.reset(
- new MenuGtk(this, context_menu_model_.get()));
+ new MenuGtk(NULL, context_menu_model_.get()));
context_menu_->Popup(sender, event);
}
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index 078ebd60..03ca90e 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -107,8 +107,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
static const GdkColor kBackgroundColorByLevel[3];
private:
- class PageActionViewGtk : public ImageLoadingTracker::Observer,
- public MenuGtk::Delegate {
+ class PageActionViewGtk : public ImageLoadingTracker::Observer {
public:
PageActionViewGtk(
LocationBarViewGtk* owner, Profile* profile,
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
index 592d9d3..e5b421f 100644
--- a/chrome/browser/gtk/menu_gtk.cc
+++ b/chrome/browser/gtk/menu_gtk.cc
@@ -6,6 +6,7 @@
#include "app/gfx/gtk_util.h"
#include "app/l10n_util.h"
+#include "app/menus/accelerator_gtk.h"
#include "app/menus/menu_model.h"
#include "base/logging.h"
#include "base/message_loop.h"
@@ -35,9 +36,10 @@ MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
menus::MenuModel* model)
: delegate_(delegate),
model_(model),
- dummy_accel_group_(NULL),
+ dummy_accel_group_(gtk_accel_group_new()),
menu_(gtk_menu_new()),
factory_(this) {
+ DCHECK(delegate || model);
ConnectSignalHandlers();
if (model)
BuildMenuFromModel();
@@ -45,8 +47,7 @@ MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
MenuGtk::~MenuGtk() {
STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
- if (dummy_accel_group_)
- g_object_unref(dummy_accel_group_);
+ g_object_unref(dummy_accel_group_);
}
void MenuGtk::ConnectSignalHandlers() {
@@ -219,7 +220,7 @@ GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
gtk_image_new_from_pixbuf(pixbuf));
g_object_unref(pixbuf);
- if (delegate_->AlwaysShowImages())
+ if (delegate_ && delegate_->AlwaysShowImages())
gtk_util::SetAlwaysShowImage(menu_item);
return menu_item;
@@ -230,19 +231,41 @@ void MenuGtk::BuildMenuFromModel() {
GtkWidget* menu_item = NULL;
// TODO(estade): support these commands.
- DCHECK_NE(model_->GetTypeAt(i), menus::MenuModel::TYPE_CHECK);
DCHECK_NE(model_->GetTypeAt(i), menus::MenuModel::TYPE_RADIO);
DCHECK_NE(model_->GetTypeAt(i), menus::MenuModel::TYPE_SUBMENU);
SkBitmap icon;
- if (model_->GetTypeAt(i) == menus::MenuModel::TYPE_SEPARATOR) {
- menu_item = gtk_separator_menu_item_new();
- } else if (model_->GetIconAt(i, &icon)) {
- menu_item = BuildMenuItemWithImage(UTF16ToUTF8(model_->GetLabelAt(i)),
- icon);
- } else {
- menu_item = gtk_menu_item_new_with_label(
- UTF16ToUTF8(model_->GetLabelAt(i)).c_str());
+ std::string label =
+ ConvertAcceleratorsFromWindowsStyle(UTF16ToUTF8(model_->GetLabelAt(i)));
+
+ switch (model_->GetTypeAt(i)) {
+ case menus::MenuModel::TYPE_SEPARATOR:
+ menu_item = gtk_separator_menu_item_new();
+ break;
+
+ case menus::MenuModel::TYPE_CHECK:
+ menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
+ break;
+
+ case menus::MenuModel::TYPE_COMMAND:
+ if (model_->GetIconAt(i, &icon))
+ menu_item = BuildMenuItemWithImage(label, icon);
+ else
+ menu_item = gtk_menu_item_new_with_mnemonic(label.c_str());
+ break;
+
+ default:
+ NOTREACHED();
+ }
+
+ menus::AcceleratorGtk accelerator;
+ if (model_->GetAcceleratorAt(i, &accelerator)) {
+ gtk_widget_add_accelerator(menu_item,
+ "activate",
+ dummy_accel_group_,
+ accelerator.GetGdkKeyCode(),
+ accelerator.gdk_modifier_type(),
+ GTK_ACCEL_VISIBLE);
}
AppendMenuItem(i, menu_item);
@@ -365,6 +388,12 @@ void MenuGtk::ExecuteCommand(int id) {
delegate_->ExecuteCommand(id);
}
+// http://crbug.com/31365
+bool MenuGtk::IsItemChecked(int id) {
+ return model_ ? model_->IsItemCheckedAt(id) :
+ delegate_->IsItemChecked(id);
+}
+
// static
void MenuGtk::OnMenuShow(GtkWidget* widget, MenuGtk* menu) {
MessageLoop::current()->PostTask(FROM_HERE,
@@ -373,7 +402,8 @@ void MenuGtk::OnMenuShow(GtkWidget* widget, MenuGtk* menu) {
// static
void MenuGtk::OnMenuHidden(GtkWidget* widget, MenuGtk* menu) {
- menu->delegate_->StoppedShowing();
+ if (menu->delegate_)
+ menu->delegate_->StoppedShowing();
}
// static
@@ -410,7 +440,7 @@ void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
// root of the MenuGtk and we want to disable *all* MenuGtks, including
// submenus.
block_activation_ = true;
- gtk_check_menu_item_set_active(item, menu->delegate_->IsItemChecked(id));
+ gtk_check_menu_item_set_active(item, menu->IsItemChecked(id));
block_activation_ = false;
}
diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h
index 2438e4e..427abbb 100644
--- a/chrome/browser/gtk/menu_gtk.h
+++ b/chrome/browser/gtk/menu_gtk.h
@@ -139,6 +139,7 @@ class MenuGtk {
// http://crbug.com/31365
bool IsCommandEnabled(int id);
void ExecuteCommand(int id);
+ bool IsItemChecked(int id);
// Callback for when a menu item is clicked.
static void OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu);
diff --git a/chrome/browser/gtk/tabs/tab_gtk.cc b/chrome/browser/gtk/tabs/tab_gtk.cc
index 299c2be..023e272 100644
--- a/chrome/browser/gtk/tabs/tab_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_gtk.cc
@@ -9,9 +9,12 @@
#include "app/gtk_dnd_util.h"
#include "app/gfx/path.h"
#include "app/l10n_util.h"
+#include "app/menus/accelerator_gtk.h"
#include "app/resource_bundle.h"
+#include "base/keyboard_codes_posix.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/gtk/standard_menus.h"
+#include "chrome/browser/tab_menu_model.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -28,39 +31,12 @@ int GetTitleWidth(gfx::Font* font, std::wstring title) {
} // namespace
-class TabGtk::ContextMenuController : public MenuGtk::Delegate {
+class TabGtk::ContextMenuController : public menus::SimpleMenuModel::Delegate {
public:
explicit ContextMenuController(TabGtk* tab)
- : tab_(tab) {
- static const MenuCreateMaterial context_menu_blueprint[] = {
- { MENU_NORMAL, TabStripModel::CommandNewTab, IDS_TAB_CXMENU_NEWTAB,
- 0, NULL, GDK_t, GDK_CONTROL_MASK, true },
- { MENU_SEPARATOR },
- { MENU_NORMAL, TabStripModel::CommandReload, IDS_TAB_CXMENU_RELOAD,
- 0, NULL, GDK_r, GDK_CONTROL_MASK, true },
- { MENU_NORMAL, TabStripModel::CommandDuplicate,
- IDS_TAB_CXMENU_DUPLICATE },
- { MENU_CHECKBOX, TabStripModel::CommandTogglePinned,
- IDS_TAB_CXMENU_PIN_TAB },
- { MENU_SEPARATOR },
- { MENU_NORMAL, TabStripModel::CommandCloseTab, IDS_TAB_CXMENU_CLOSETAB,
- 0, NULL, GDK_w, GDK_CONTROL_MASK, true },
- { MENU_NORMAL, TabStripModel::CommandCloseOtherTabs,
- IDS_TAB_CXMENU_CLOSEOTHERTABS },
- { MENU_NORMAL, TabStripModel::CommandCloseTabsToRight,
- IDS_TAB_CXMENU_CLOSETABSTORIGHT },
- { MENU_NORMAL, TabStripModel::CommandCloseTabsOpenedBy,
- IDS_TAB_CXMENU_CLOSETABSOPENEDBY },
- { MENU_SEPARATOR },
- { MENU_NORMAL, TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB,
- 0, NULL, GDK_t, GDK_CONTROL_MASK | GDK_SHIFT_MASK, true },
- { MENU_NORMAL, TabStripModel::CommandBookmarkAllTabs,
- IDS_TAB_CXMENU_BOOKMARK_ALL_TABS, 0, NULL, GDK_d,
- GDK_CONTROL_MASK | GDK_SHIFT_MASK, true },
- { MENU_END },
- };
-
- menu_.reset(new MenuGtk(this, context_menu_blueprint, NULL));
+ : tab_(tab),
+ model_(this) {
+ menu_.reset(new MenuGtk(NULL, &model_));
}
virtual ~ContextMenuController() {}
@@ -75,25 +51,44 @@ class TabGtk::ContextMenuController : public MenuGtk::Delegate {
}
private:
- // MenuGtk::Delegate implementation:
- virtual bool IsCommandEnabled(int command_id) const {
- if (!tab_)
- return false;
-
- return tab_->delegate()->IsCommandEnabledForTab(
- static_cast<TabStripModel::ContextMenuCommand>(command_id), tab_);
- }
-
- virtual bool IsItemChecked(int command_id) const {
+ // Overridden from menus::SimpleMenuModel::Delegate:
+ virtual bool IsCommandIdChecked(int command_id) const {
if (!tab_ || command_id != TabStripModel::CommandTogglePinned)
return false;
return tab_->is_pinned();
}
-
+ virtual bool IsCommandIdEnabled(int command_id) const {
+ return tab_ && tab_->delegate()->IsCommandEnabledForTab(
+ static_cast<TabStripModel::ContextMenuCommand>(command_id),
+ tab_);
+ }
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ menus::Accelerator* accelerator) {
+ switch (command_id) {
+ case TabStripModel::CommandNewTab:
+ *accelerator = menus::AcceleratorGtk(base::VKEY_T, false, true, false);
+ break;
+ case TabStripModel::CommandReload:
+ *accelerator = menus::AcceleratorGtk(base::VKEY_R, false, true, false);
+ break;
+ case TabStripModel::CommandCloseTab:
+ *accelerator = menus::AcceleratorGtk(base::VKEY_W, false, true, false);
+ break;
+ case TabStripModel::CommandRestoreTab:
+ *accelerator = menus::AcceleratorGtk(base::VKEY_T, true, true, false);
+ break;
+ case TabStripModel::CommandBookmarkAllTabs:
+ *accelerator = menus::AcceleratorGtk(base::VKEY_D, true, true, false);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
virtual void ExecuteCommand(int command_id) {
if (!tab_)
return;
-
tab_->delegate()->ExecuteCommandForTab(
static_cast<TabStripModel::ContextMenuCommand>(command_id), tab_);
}
@@ -105,6 +100,9 @@ class TabGtk::ContextMenuController : public MenuGtk::Delegate {
// is canceled.
TabGtk* tab_;
+ // The model.
+ TabMenuModel model_;
+
DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
};