summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorerg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-30 17:06:21 +0000
committererg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-30 17:06:21 +0000
commit7209cb729d172a9aa8999dac0c9f6bd80f23c4c2 (patch)
tree5b0c62d482856faf0982378528031c1c8c4c9eff /chrome/browser
parent7838c2502799cbfe33ba16575b0e7d0b03740dd1 (diff)
downloadchromium_src-7209cb729d172a9aa8999dac0c9f6bd80f23c4c2.zip
chromium_src-7209cb729d172a9aa8999dac0c9f6bd80f23c4c2.tar.gz
chromium_src-7209cb729d172a9aa8999dac0c9f6bd80f23c4c2.tar.bz2
GTK: Cleanups to the new wrench menu.
- Make the rendering for multiple buttons pretty by unifying sequnces of buttons. - Add the zoom label control and make the wrench menu model listen for notifications about zoom percentage changing. - Fixes crash that would have gone away once this was taken out from behind a flag BUG=45757 TEST=none Review URL: http://codereview.chromium.org/2799043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51266 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc5
-rw-r--r--chrome/browser/gtk/gtk_custom_menu_item.cc130
-rw-r--r--chrome/browser/gtk/gtk_custom_menu_item.h11
-rw-r--r--chrome/browser/gtk/menu_gtk.cc59
-rw-r--r--chrome/browser/gtk/menu_gtk.h3
-rw-r--r--chrome/browser/tabs/tab_strip_model.cc3
-rw-r--r--chrome/browser/tabs/tab_strip_model.h4
-rw-r--r--chrome/browser/wrench_menu_model.cc43
-rw-r--r--chrome/browser/wrench_menu_model.h12
9 files changed, 249 insertions, 21 deletions
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index 907f1f5..e195ee1 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -758,7 +758,10 @@ void BrowserToolbarGtk::PopupForButtonNextTo(GtkWidget* button,
GtkMenuDirectionType dir) {
GtkWidget* other_button = button == page_menu_button_.get() ?
app_menu_button_.get() : page_menu_button_.get();
- PopupForButton(other_button);
+ // TODO(erg): When we move to wrench menu only, remove |menu_bar_helper_| so
+ // this won't be necessary.
+ if (other_button)
+ PopupForButton(other_button);
}
void BrowserToolbarGtk::AnimationEnded(const Animation* animation) {
diff --git a/chrome/browser/gtk/gtk_custom_menu_item.cc b/chrome/browser/gtk/gtk_custom_menu_item.cc
index f925c48..8c9c923 100644
--- a/chrome/browser/gtk/gtk_custom_menu_item.cc
+++ b/chrome/browser/gtk/gtk_custom_menu_item.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/gtk/gtk_custom_menu_item.h"
+#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "chrome/browser/gtk/gtk_custom_menu.h"
@@ -27,9 +28,23 @@ static void set_selected(GtkCustomMenuItem* item, GtkWidget* selected) {
}
}
+// When GtkButtons set the label text, they rebuild the widget hierarchy each
+// and every time. Therefore, we can't just fish out the label from the button
+// and set some properties; we have to create this callback function that
+// listens on the button's "notify" signal, which is emitted right after the
+// label has been (re)created. (Label values can change dynamically.)
+static void on_button_label_set(GObject* object) {
+ GtkButton* button = GTK_BUTTON(object);
+ gtk_widget_set_sensitive(GTK_BIN(button)->child, FALSE);
+ gtk_misc_set_padding(GTK_MISC(GTK_BIN(button)->child), 2, 0);
+}
+
static void gtk_custom_menu_item_finalize(GObject *object);
static gint gtk_custom_menu_item_expose(GtkWidget* widget,
GdkEventExpose* event);
+static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
+ GdkEventExpose* event,
+ GtkCustomMenuItem* menu_item);
static void gtk_custom_menu_item_select(GtkItem *item);
static void gtk_custom_menu_item_deselect(GtkItem *item);
static void gtk_custom_menu_item_activate(GtkMenuItem* menu_item);
@@ -56,6 +71,7 @@ static void gtk_custom_menu_item_style_set(GtkCustomMenuItem* item,
}
static void gtk_custom_menu_item_init(GtkCustomMenuItem* item) {
+ item->all_widgets = NULL;
item->button_widgets = NULL;
item->currently_selected_button = NULL;
item->previously_selected_button = NULL;
@@ -73,6 +89,10 @@ static void gtk_custom_menu_item_init(GtkCustomMenuItem* item) {
g_signal_connect(item, "style-set",
G_CALLBACK(gtk_custom_menu_item_style_set), NULL);
+ g_signal_connect(item->hbox, "expose-event",
+ G_CALLBACK(gtk_custom_menu_item_hbox_expose),
+ item);
+
gtk_widget_show_all(menu_hbox);
}
@@ -103,6 +123,7 @@ static void gtk_custom_menu_item_class_init(GtkCustomMenuItemClass* klass) {
static void gtk_custom_menu_item_finalize(GObject *object) {
GtkCustomMenuItem* item = GTK_CUSTOM_MENU_ITEM(object);
+ g_list_free(item->all_widgets);
g_list_free(item->button_widgets);
G_OBJECT_CLASS(gtk_custom_menu_item_parent_class)->finalize(object);
@@ -123,6 +144,97 @@ static gint gtk_custom_menu_item_expose(GtkWidget* widget,
return FALSE;
}
+static void gtk_custom_menu_item_expose_button(GtkWidget* hbox,
+ GdkEventExpose* event,
+ GList* button_item) {
+ // We search backwards to find the leftmost and rightmost buttons. The
+ // current button may be that button.
+ GtkWidget* current_button = GTK_WIDGET(button_item->data);
+ GtkWidget* first_button = current_button;
+ for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
+ i = g_list_previous(i)) {
+ first_button = GTK_WIDGET(i->data);
+ }
+
+ GtkWidget* last_button = current_button;
+ for (GList* i = button_item; i && GTK_IS_BUTTON(i->data);
+ i = g_list_next(i)) {
+ last_button = GTK_WIDGET(i->data);
+ }
+
+ if (base::i18n::IsRTL())
+ std::swap(first_button, last_button);
+
+ int x = first_button->allocation.x;
+ int y = first_button->allocation.y;
+ int width = last_button->allocation.width + last_button->allocation.x -
+ first_button->allocation.x;
+ int height = last_button->allocation.height;
+
+ gtk_paint_box(hbox->style, hbox->window,
+ static_cast<GtkStateType>(
+ GTK_WIDGET_STATE(current_button)),
+ GTK_SHADOW_OUT,
+ &current_button->allocation, hbox, "button",
+ x, y, width, height);
+
+ // Propagate to the button's children.
+ gtk_container_propagate_expose(
+ GTK_CONTAINER(current_button),
+ gtk_bin_get_child(GTK_BIN(current_button)),
+ event);
+}
+
+static gboolean gtk_custom_menu_item_hbox_expose(GtkWidget* widget,
+ GdkEventExpose* event,
+ GtkCustomMenuItem* menu_item) {
+ // First render all the buttons that aren't the currently selected item.
+ for (GList* current_item = menu_item->all_widgets;
+ current_item != NULL; current_item = g_list_next(current_item)) {
+ if (GTK_IS_BUTTON(current_item->data)) {
+ if (GTK_WIDGET(current_item->data) !=
+ menu_item->currently_selected_button) {
+ gtk_custom_menu_item_expose_button(widget, event, current_item);
+ }
+ }
+ }
+
+ // As a separate pass, draw the buton separators above. We need to draw the
+ // separators in a separate pass because we are drawing on top of the
+ // buttons. Otherwise, the vlines are overwritten by the next button.
+ for (GList* current_item = menu_item->all_widgets;
+ current_item != NULL; current_item = g_list_next(current_item)) {
+ if (GTK_IS_BUTTON(current_item->data)) {
+ // Check to see if this is the last button in a run.
+ GList* next_item = g_list_next(current_item);
+ if (next_item && GTK_IS_BUTTON(next_item->data)) {
+ GtkWidget* current_button = GTK_WIDGET(current_item->data);
+ GtkAllocation child_alloc =
+ gtk_bin_get_child(GTK_BIN(current_button))->allocation;
+ int half_offset = widget->style->xthickness / 2;
+ gtk_paint_vline(widget->style, widget->window,
+ static_cast<GtkStateType>(
+ GTK_WIDGET_STATE(current_button)),
+ &event->area, widget, "button",
+ child_alloc.y,
+ child_alloc.y + child_alloc.height,
+ current_button->allocation.x +
+ current_button->allocation.width - half_offset);
+ }
+ }
+ }
+
+ // Finally, draw the selected item on top of the separators so there are no
+ // artifacts inside the button area.
+ GList* selected = g_list_find(menu_item->all_widgets,
+ menu_item->currently_selected_button);
+ if (selected) {
+ gtk_custom_menu_item_expose_button(widget, event, selected);
+ }
+
+ return TRUE;
+}
+
static void gtk_custom_menu_item_select(GtkItem* item) {
GtkCustomMenuItem* custom_item = GTK_CUSTOM_MENU_ITEM(item);
@@ -185,7 +297,23 @@ GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
gtk_widget_show(button);
+ menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
menu_item->button_widgets = g_list_append(menu_item->button_widgets, button);
+
+ return button;
+}
+
+GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
+ int command_id) {
+ GtkWidget* button = gtk_button_new_with_label("");
+ g_object_set_data(G_OBJECT(button), "command-id",
+ GINT_TO_POINTER(command_id));
+ gtk_box_pack_start(GTK_BOX(menu_item->hbox), button, FALSE, FALSE, 0);
+ g_signal_connect(button, "notify", G_CALLBACK(on_button_label_set), NULL);
+ gtk_widget_show(button);
+
+ menu_item->all_widgets = g_list_append(menu_item->all_widgets, button);
+
return button;
}
@@ -195,6 +323,8 @@ void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item) {
gtk_box_pack_start(GTK_BOX(menu_item->hbox), fixed, FALSE, FALSE, 0);
gtk_widget_show(fixed);
+
+ menu_item->all_widgets = g_list_append(menu_item->all_widgets, fixed);
}
void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item,
diff --git a/chrome/browser/gtk/gtk_custom_menu_item.h b/chrome/browser/gtk/gtk_custom_menu_item.h
index a7c152b..c89db5d 100644
--- a/chrome/browser/gtk/gtk_custom_menu_item.h
+++ b/chrome/browser/gtk/gtk_custom_menu_item.h
@@ -62,7 +62,11 @@ struct _GtkCustomMenuItem {
// Label on left side of menu item.
GtkWidget* label;
- // Possible button widgets
+ // List of all widgets we added. Used to find the leftmost and rightmost
+ // continuous buttons.
+ GList* all_widgets;
+
+ // Possible button widgets. Used for keyboard navigation.
GList* button_widgets;
// The widget that currently has highlight.
@@ -86,6 +90,11 @@ GtkWidget* gtk_custom_menu_item_new(const char* title);
GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item,
int command_id);
+// Adds a button to our list of items in the |hbox|, but that isn't part of
+// |button_widgets| to prevent it from being activatable.
+GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item,
+ int command_id);
+
// Adds a vertical space in the |hbox|.
void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item);
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
index 104b39f..d38b505 100644
--- a/chrome/browser/gtk/menu_gtk.cc
+++ b/chrome/browser/gtk/menu_gtk.cc
@@ -72,6 +72,33 @@ void OnSubmenuShow(GtkWidget* widget, gpointer user_data) {
#endif
}
+void OnSubmenuShowButtonMenuItem(GtkWidget* widget, GtkButton* button) {
+ menus::ButtonMenuItemModel* model =
+ reinterpret_cast<menus::ButtonMenuItemModel*>(
+ g_object_get_data(G_OBJECT(button), "button-model"));
+ int index = GPOINTER_TO_INT(g_object_get_data(
+ G_OBJECT(button), "button-model-id"));
+
+ std::string label =
+ ConvertAcceleratorsFromWindowsStyle(
+ UTF16ToUTF8(model->GetLabelAt(index)));
+ gtk_button_set_label(GTK_BUTTON(button), label.c_str());
+}
+
+void SetupDynamicLabelMenuButton(GtkWidget* button,
+ GtkWidget* menu,
+ menus::ButtonMenuItemModel* model,
+ int index) {
+ if (model->IsLabelDynamicAt(index)) {
+ g_object_set_data(G_OBJECT(button), "button-model",
+ reinterpret_cast<void*>(model));
+ g_object_set_data(G_OBJECT(button), "button-model-id",
+ GINT_TO_POINTER(index));
+ g_signal_connect(menu, "show", G_CALLBACK(OnSubmenuShowButtonMenuItem),
+ button);
+ }
+}
+
// Popup menus may get squished if they open up too close to the bottom of the
// screen. This function takes the size of the screen, the size of the menu,
// an optional widget, the Y position of the mouse click, and adjusts the popup
@@ -269,9 +296,7 @@ void MenuGtk::BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu) {
case menus::MenuModel::TYPE_BUTTON_ITEM: {
menus::ButtonMenuItemModel* button_menu_item_model =
model->GetButtonMenuItemAt(i);
-
- menu_item = BuildButtomMenuItem(button_menu_item_model);
-
+ menu_item = BuildButtomMenuItem(button_menu_item_model, menu);
connect_to_activate = false;
break;
}
@@ -316,9 +341,17 @@ void MenuGtk::BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu) {
}
}
-GtkWidget* MenuGtk::BuildButtomMenuItem(menus::ButtonMenuItemModel* model) {
+GtkWidget* MenuGtk::BuildButtomMenuItem(menus::ButtonMenuItemModel* model,
+ GtkWidget* menu) {
GtkWidget* menu_item = gtk_custom_menu_item_new(
RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str());
+
+ // Set up the callback to the model for when it is clicked.
+ g_object_set_data(G_OBJECT(menu_item), "button-model",
+ reinterpret_cast<void*>(model));
+ g_signal_connect(menu_item, "button-pushed",
+ G_CALLBACK(OnMenuButtonPressed), this);
+
for (int i = 0; i < model->GetItemCount(); ++i) {
switch (model->GetTypeAt(i)) {
case menus::ButtonMenuItemModel::TYPE_SPACE: {
@@ -346,17 +379,23 @@ GtkWidget* MenuGtk::BuildButtomMenuItem(menus::ButtonMenuItemModel* model) {
UTF16ToUTF8(model->GetLabelAt(i))).c_str());
}
- // TODO(erg): Set up dynamic labels here.
+ SetupDynamicLabelMenuButton(button, menu, model, i);
+ break;
+ }
+ case menus::ButtonMenuItemModel::TYPE_BUTTON_LABEL: {
+ GtkWidget* button = gtk_custom_menu_item_add_button_label(
+ GTK_CUSTOM_MENU_ITEM(menu_item),
+ model->GetCommandIdAt(i));
+ gtk_button_set_label(
+ GTK_BUTTON(button),
+ RemoveWindowsStyleAccelerators(
+ UTF16ToUTF8(model->GetLabelAt(i))).c_str());
+ SetupDynamicLabelMenuButton(button, menu, model, i);
break;
}
}
}
- // Set up the callback to the model for when it is clicked.
- g_object_set_data(G_OBJECT(menu_item), "button-model",
- reinterpret_cast<void*>(model));
- g_signal_connect(menu_item, "button-pushed",
- G_CALLBACK(OnMenuButtonPressed), this);
return menu_item;
}
diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h
index a9a703a..721b736 100644
--- a/chrome/browser/gtk/menu_gtk.h
+++ b/chrome/browser/gtk/menu_gtk.h
@@ -117,7 +117,8 @@ class MenuGtk {
// Implementation of the above; called recursively.
void BuildSubmenuFromModel(menus::MenuModel* model, GtkWidget* menu);
// Builds a menu item with buttons in it from the data in the model.
- GtkWidget* BuildButtomMenuItem(menus::ButtonMenuItemModel* model);
+ GtkWidget* BuildButtomMenuItem(menus::ButtonMenuItemModel* model,
+ GtkWidget* menu);
// Contains implementation for OnMenuShow.
void UpdateMenu();
diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc
index 5304100..32c55fd 100644
--- a/chrome/browser/tabs/tab_strip_model.cc
+++ b/chrome/browser/tabs/tab_strip_model.cc
@@ -68,6 +68,9 @@ TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile)
}
TabStripModel::~TabStripModel() {
+ FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
+ TabStripModelDeleted());
+
STLDeleteContainerPointers(contents_data_.begin(), contents_data_.end());
delete order_controller_;
}
diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h
index f9cb205..bfca5ec 100644
--- a/chrome/browser/tabs/tab_strip_model.h
+++ b/chrome/browser/tabs/tab_strip_model.h
@@ -125,6 +125,10 @@ class TabStripModelObserver {
// use this as a trigger to try and close the window containing the
// TabStripModel, for example...
virtual void TabStripEmpty() {}
+
+ // Sent when the tabstrip model is about to be deleted and any reference held
+ // must be dropped.
+ virtual void TabStripModelDeleted() {}
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/wrench_menu_model.cc b/chrome/browser/wrench_menu_model.cc
index c3d9012..28c7315 100644
--- a/chrome/browser/wrench_menu_model.cc
+++ b/chrome/browser/wrench_menu_model.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/upgrade_detector.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "grit/chromium_strings.h"
@@ -68,15 +69,22 @@ WrenchMenuModel::WrenchMenuModel(menus::SimpleMenuModel::Delegate* delegate,
Browser* browser)
: menus::SimpleMenuModel(delegate),
delegate_(delegate),
- browser_(browser) {
+ browser_(browser),
+ tabstrip_model_(browser_->tabstrip_model()) {
Build();
UpdateZoomControls();
+ tabstrip_model_->AddObserver(this);
+
registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
Source<Profile>(browser_->profile()));
+ registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
+ NotificationService::AllSources());
}
WrenchMenuModel::~WrenchMenuModel() {
+ if (tabstrip_model_)
+ tabstrip_model_->RemoveObserver(this);
}
static bool CalculateEnabled() {
@@ -137,12 +145,12 @@ bool WrenchMenuModel::GetIconAt(int index, SkBitmap* icon) const {
}
bool WrenchMenuModel::IsLabelForCommandIdDynamic(int command_id) const {
- return false;
+ return command_id == IDC_ZOOM_PERCENT_DISPLAY;
}
string16 WrenchMenuModel::GetLabelForCommandId(int command_id) const {
- // TODO(erg): Hook up percentage calculation once I add that widget.
- return string16();
+ DCHECK_EQ(IDC_ZOOM_PERCENT_DISPLAY, command_id);
+ return zoom_label_;
}
void WrenchMenuModel::ExecuteCommand(int command_id) {
@@ -150,10 +158,30 @@ void WrenchMenuModel::ExecuteCommand(int command_id) {
delegate_->ExecuteCommand(command_id);
}
+void WrenchMenuModel::TabSelectedAt(TabContents* old_contents,
+ TabContents* new_contents,
+ int index,
+ bool user_gesture) {
+ // The user has switched between tabs and the new tab may have a different
+ // zoom setting.
+ UpdateZoomControls();
+}
+
+void WrenchMenuModel::TabReplacedAt(TabContents* old_contents,
+ TabContents* new_contents, int index) {
+ UpdateZoomControls();
+}
+
+void WrenchMenuModel::TabStripModelDeleted() {
+ // During views shutdown, the tabstrip model/browser is deleted first, while
+ // it is the opposite in gtk land.
+ tabstrip_model_->RemoveObserver(this);
+ tabstrip_model_ = NULL;
+}
+
void WrenchMenuModel::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK_EQ(NotificationType::ZOOM_LEVEL_CHANGED, type.value);
UpdateZoomControls();
}
@@ -179,6 +207,8 @@ void WrenchMenuModel::Build() {
zoom_menu_item_model_.reset(
new menus::ButtonMenuItemModel(IDS_ZOOM_MENU, this));
zoom_menu_item_model_->AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS2);
+ zoom_menu_item_model_->AddButtonLabel(IDC_ZOOM_PERCENT_DISPLAY,
+ IDS_ZOOM_PLUS2);
zoom_menu_item_model_->AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS2);
zoom_menu_item_model_->AddSpace();
zoom_menu_item_model_->AddItemWithImage(
@@ -247,9 +277,6 @@ void WrenchMenuModel::UpdateZoomControls() {
bool enable_increment, enable_decrement;
int zoom_percent =
static_cast<int>(GetZoom(&enable_increment, &enable_decrement) * 100);
-
- // TODO(erg): Route the stringified zoom_percent through
- // GetLabelForCommandId(). Also make a way to use enable_increment/decrement.
zoom_label_ = l10n_util::GetStringFUTF16(
IDS_ZOOM_PERCENT, IntToString16(zoom_percent));
}
diff --git a/chrome/browser/wrench_menu_model.h b/chrome/browser/wrench_menu_model.h
index 5b7d2d5..e9cb1b1 100644
--- a/chrome/browser/wrench_menu_model.h
+++ b/chrome/browser/wrench_menu_model.h
@@ -11,6 +11,7 @@
#include "app/menus/simple_menu_model.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
@@ -37,6 +38,7 @@ class ToolsMenuModel : public menus::SimpleMenuModel {
// A menu model that builds the contents of the wrench menu.
class WrenchMenuModel : public menus::SimpleMenuModel,
public menus::ButtonMenuItemModel::Delegate,
+ public TabStripModelObserver,
public NotificationObserver {
public:
WrenchMenuModel(menus::SimpleMenuModel::Delegate* delegate,
@@ -57,6 +59,15 @@ class WrenchMenuModel : public menus::SimpleMenuModel,
virtual string16 GetLabelForCommandId(int command_id) const;
virtual void ExecuteCommand(int command_id);
+ // Overridden from TabStripModelObserver:
+ virtual void TabSelectedAt(TabContents* old_contents,
+ TabContents* new_contents,
+ int index,
+ bool user_gesture);
+ virtual void TabReplacedAt(TabContents* old_contents,
+ TabContents* new_contents, int index);
+ virtual void TabStripModelDeleted();
+
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -91,6 +102,7 @@ class WrenchMenuModel : public menus::SimpleMenuModel,
menus::SimpleMenuModel::Delegate* delegate_; // weak
Browser* browser_; // weak
+ TabStripModel* tabstrip_model_; // weak
NotificationRegistrar registrar_;