summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-18 22:30:16 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-18 22:30:16 +0000
commit70b45efc15674aa7241bbb95dc81b3019eac294b (patch)
treeb4b8cae88b43ffb0a669cc7b50aabafa93506a02 /chrome
parentcb71491f6fd9eb062ecbce3df5ca543c77652d91 (diff)
downloadchromium_src-70b45efc15674aa7241bbb95dc81b3019eac294b.zip
chromium_src-70b45efc15674aa7241bbb95dc81b3019eac294b.tar.gz
chromium_src-70b45efc15674aa7241bbb95dc81b3019eac294b.tar.bz2
Port back_forward_menu_model to linux.
* Refactor BackForwardMenuModel. - Create platform-specific subclasses that implement menu delegate interfaces - Push almost all functionality into BackForwardMenuModel * Implement GTK back/forward dropdowns (in MenuGtk and BrowserToolbarViewGtk) Review URL: http://codereview.chromium.org/21440 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9983 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/back_forward_menu_model.cc318
-rw-r--r--chrome/browser/back_forward_menu_model.h93
-rw-r--r--chrome/browser/back_forward_menu_model_unittest.cc16
-rw-r--r--chrome/browser/back_forward_menu_model_win.cc64
-rw-r--r--chrome/browser/back_forward_menu_model_win.h35
-rw-r--r--chrome/browser/browser.scons7
-rw-r--r--chrome/browser/browser.vcproj8
-rw-r--r--chrome/browser/gtk/back_forward_menu_model_gtk.cc47
-rw-r--r--chrome/browser/gtk/back_forward_menu_model_gtk.h34
-rw-r--r--chrome/browser/gtk/browser_toolbar_view_gtk.cc92
-rw-r--r--chrome/browser/gtk/browser_toolbar_view_gtk.h43
-rw-r--r--chrome/browser/gtk/menu_gtk.cc68
-rw-r--r--chrome/browser/gtk/menu_gtk.h40
-rw-r--r--chrome/browser/views/toolbar_view.cc4
-rw-r--r--chrome/browser/views/toolbar_view.h12
15 files changed, 629 insertions, 252 deletions
diff --git a/chrome/browser/back_forward_menu_model.cc b/chrome/browser/back_forward_menu_model.cc
index 50c7da1..f28c60c 100644
--- a/chrome/browser/back_forward_menu_model.cc
+++ b/chrome/browser/back_forward_menu_model.cc
@@ -1,39 +1,31 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-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.
+#include "build/build_config.h"
+
#include "chrome/browser/back_forward_menu_model.h"
#include "chrome/browser/browser.h"
-#include "chrome/browser/history_tab_ui.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/l10n_util.h"
#include "net/base/registry_controlled_domain.h"
+#if defined(OS_WIN)
+// TODO(port): port these headers and remove the platform defines.
+#include "chrome/browser/history_tab_ui.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#elif defined(OS_POSIX)
+#include "chrome/common/temp_scaffolding_stubs.h"
+#endif
+
#include "generated_resources.h"
const int BackForwardMenuModel::kMaxHistoryItems = 12;
const int BackForwardMenuModel::kMaxChapterStops = 5;
-BackForwardMenuModel::BackForwardMenuModel(Browser* browser,
- ModelType model_type)
- : browser_(browser),
- test_tab_contents_(NULL),
- model_type_(model_type) {
-}
-
-BackForwardMenuModel::~BackForwardMenuModel() {
-}
-
-TabContents* BackForwardMenuModel::GetTabContents() const {
- // We use the test tab contents if the unit test has specified it.
- return test_tab_contents_ ? test_tab_contents_ :
- browser_->GetSelectedTabContents();
-}
-
int BackForwardMenuModel::GetHistoryItemCount() const {
TabContents* contents = GetTabContents();
NavigationController* controller = contents->controller();
@@ -82,7 +74,7 @@ int BackForwardMenuModel::GetChapterStopCount(int history_items) const {
return chapter_stops;
}
-int BackForwardMenuModel::GetItemCount() const {
+int BackForwardMenuModel::GetTotalItemCount() const {
int items = GetHistoryItemCount();
if (items > 0) {
@@ -103,70 +95,105 @@ int BackForwardMenuModel::GetItemCount() const {
return items;
}
-int BackForwardMenuModel::MenuIdToNavEntryIndex(int menu_id) const {
+int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from,
+ bool forward) const {
TabContents* contents = GetTabContents();
NavigationController* controller = contents->controller();
- int history_items = GetHistoryItemCount();
-
- DCHECK(menu_id > 0);
+ int max_count = controller->GetEntryCount();
+ if (start_from < 0 || start_from >= max_count)
+ return -1; // Out of bounds.
- // Convert anything above the History items separator.
- if (menu_id <= history_items) {
- if (model_type_ == FORWARD_MENU_DELEGATE) {
- // The |menu_id| is relative to our current position, so we need to add.
- menu_id += controller->GetCurrentEntryIndex();
+ if (forward) {
+ if (start_from < max_count - 1) {
+ // We want to advance over the current chapter stop, so we add one.
+ // We don't need to do this when direction is backwards.
+ start_from++;
} else {
- // Back menu is reverse.
- menu_id = controller->GetCurrentEntryIndex() - menu_id;
+ return -1;
}
- return menu_id;
}
- if (menu_id == history_items + 1)
- return -1; // Don't translate the separator for history items.
- if (menu_id >= history_items + 1 + GetChapterStopCount(history_items) + 1)
- return -1; // This is beyond the last chapter stop so we abort.
-
- // This menu item is a chapter stop located between the two separators.
- menu_id = FindChapterStop(history_items,
- model_type_ == FORWARD_MENU_DELEGATE,
- menu_id - history_items - 1 - 1);
+ NavigationEntry* start_entry = controller->GetEntryAtIndex(start_from);
+ const GURL& url = start_entry->url();
- return menu_id;
+ if (!forward) {
+ // When going backwards we return the first entry we find that has a
+ // different domain.
+ for (int i = start_from - 1; i >= 0; --i) {
+ if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
+ controller->GetEntryAtIndex(i)->url()))
+ return i;
+ }
+ // We have reached the beginning without finding a chapter stop.
+ return -1;
+ } else {
+ // When going forwards we return the entry before the entry that has a
+ // different domain.
+ for (int i = start_from + 1; i < max_count; ++i) {
+ if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
+ controller->GetEntryAtIndex(i)->url()))
+ return i - 1;
+ }
+ // Last entry is always considered a chapter stop.
+ return max_count - 1;
+ }
}
-NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int menu_id) const {
+int BackForwardMenuModel::FindChapterStop(int offset,
+ bool forward,
+ int skip) const {
+ if (offset < 0 || skip < 0)
+ return -1;
+
+ if (!forward)
+ offset *= -1;
+
TabContents* contents = GetTabContents();
NavigationController* controller = contents->controller();
- int index = MenuIdToNavEntryIndex(menu_id);
- return controller->GetEntryAtIndex(index);
+ int entry = controller->GetCurrentEntryIndex() + offset;
+
+ for (int i = 0; i < skip + 1; i++)
+ entry = GetIndexOfNextChapterStop(entry, forward);
+
+ return entry;
}
-std::wstring BackForwardMenuModel::GetLabel(int menu_id) const {
- // Return label "Show Full History" for the last item of the menu.
- if (menu_id == GetItemCount())
- return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK);
+void BackForwardMenuModel::ExecuteCommandById(int menu_id) {
+ TabContents* contents = GetTabContents();
+ NavigationController* controller = contents->controller();
- // Return an empty string for a separator.
- if (IsItemSeparator(menu_id))
- return L"";
+ DCHECK(!IsSeparator(menu_id));
- NavigationEntry* entry = GetNavigationEntry(menu_id);
- return entry->title();
-}
+ // Execute the command for the last item: "Show Full History".
+ if (menu_id == GetTotalItemCount()) {
+ UserMetrics::RecordComputedAction(BuildActionName(L"ShowFullHistory", -1),
+ controller->profile());
+#if defined(OS_WIN)
+ browser_->ShowNativeUITab(HistoryTabUI::GetURL());
+#else
+ NOTIMPLEMENTED();
+#endif
+ return;
+ }
-const SkBitmap& BackForwardMenuModel::GetIcon(int menu_id) const {
- // Return NULL if the item doesn't have an icon
- if (!HasIcon(menu_id))
- return GetEmptyIcon();
+ // Log whether it was a history or chapter click.
+ if (menu_id <= GetHistoryItemCount()) {
+ UserMetrics::RecordComputedAction(
+ BuildActionName(L"HistoryClick", menu_id), controller->profile());
+ } else {
+ UserMetrics::RecordComputedAction(
+ BuildActionName(L"ChapterClick", menu_id - GetHistoryItemCount() - 1),
+ controller->profile());
+ }
- NavigationEntry* entry = GetNavigationEntry(menu_id);
- return entry->favicon().bitmap();
+ int index = MenuIdToNavEntryIndex(menu_id);
+ if (index >= 0 && index < controller->GetEntryCount())
+ controller->GoToIndex(index);
}
-bool BackForwardMenuModel::IsItemSeparator(int menu_id) const {
+bool BackForwardMenuModel::IsSeparator(int menu_id) const {
int history_items = GetHistoryItemCount();
// If the menu_id is higher than the number of history items + separator,
// we then consider if it is a chapter-stop entry.
@@ -186,135 +213,98 @@ bool BackForwardMenuModel::IsItemSeparator(int menu_id) const {
return menu_id == history_items + 1;
}
-bool BackForwardMenuModel::HasIcon(int menu_id) const {
- // Using "id" not "id - 1" because the last item "Show Full History"
- // doesn't have an icon.
- return menu_id < GetItemCount() && !IsItemSeparator(menu_id);
-}
-
-bool BackForwardMenuModel::SupportsCommand(int menu_id) const {
- return menu_id - 1 < GetItemCount() && !IsItemSeparator(menu_id);
-}
+std::wstring BackForwardMenuModel::GetItemLabel(int menu_id) const {
+ // Return label "Show Full History" for the last item of the menu.
+ if (menu_id == GetTotalItemCount())
+ return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK);
-bool BackForwardMenuModel::IsCommandEnabled(int menu_id) const {
- return menu_id - 1 < GetItemCount() && !IsItemSeparator(menu_id);
-}
+ // Return an empty string for a separator.
+ if (IsSeparator(menu_id))
+ return L"";
-std::wstring BackForwardMenuModel::BuildActionName(
- const std::wstring& action, int index) const {
- DCHECK(!action.empty());
- DCHECK(index >= -1);
- std::wstring metric_string;
- if (model_type_ == FORWARD_MENU_DELEGATE)
- metric_string += L"ForwardMenu_";
- else
- metric_string += L"BackMenu_";
- metric_string += action;
- if (index != -1)
- metric_string += IntToWString(index);
- return metric_string;
+ NavigationEntry* entry = GetNavigationEntry(menu_id);
+ return entry->title();
}
-void BackForwardMenuModel::ExecuteCommand(int menu_id) {
- TabContents* contents = GetTabContents();
- NavigationController* controller = contents->controller();
-
- DCHECK(!IsItemSeparator(menu_id));
+const SkBitmap& BackForwardMenuModel::GetItemIcon(int menu_id) const {
+ DCHECK(ItemHasIcon(menu_id));
- // Execute the command for the last item: "Show Full History".
- if (menu_id == GetItemCount()) {
- UserMetrics::RecordComputedAction(BuildActionName(L"ShowFullHistory", -1),
- controller->profile());
- browser_->ShowNativeUITab(HistoryTabUI::GetURL());
- return;
- }
-
- // Log whether it was a history or chapter click.
- if (menu_id <= GetHistoryItemCount()) {
- UserMetrics::RecordComputedAction(
- BuildActionName(L"HistoryClick", menu_id), controller->profile());
- } else {
- UserMetrics::RecordComputedAction(
- BuildActionName(L"ChapterClick", menu_id - GetHistoryItemCount() - 1),
- controller->profile());
- }
+ NavigationEntry* entry = GetNavigationEntry(menu_id);
+ return entry->favicon().bitmap();
+}
- int index = MenuIdToNavEntryIndex(menu_id);
- if (index >= 0 && index < controller->GetEntryCount())
- controller->GoToIndex(index);
+bool BackForwardMenuModel::ItemHasIcon(int menu_id) const {
+ // Using "id" not "id - 1" because the last item "Show Full History"
+ // doesn't have an icon.
+ return menu_id < GetTotalItemCount() && !IsSeparator(menu_id);
}
-void BackForwardMenuModel::MenuWillShow() {
- UserMetrics::RecordComputedAction(BuildActionName(L"Popup", -1),
- browser_->profile());
+bool BackForwardMenuModel::ItemHasCommand(int menu_id) const {
+ return menu_id - 1 < GetTotalItemCount() && !IsSeparator(menu_id);
}
std::wstring BackForwardMenuModel::GetShowFullHistoryLabel() const {
return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK);
}
-int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from,
- bool forward) const {
+TabContents* BackForwardMenuModel::GetTabContents() const {
+ // We use the test tab contents if the unit test has specified it.
+ return test_tab_contents_ ? test_tab_contents_ :
+ browser_->GetSelectedTabContents();
+}
+
+int BackForwardMenuModel::MenuIdToNavEntryIndex(int menu_id) const {
TabContents* contents = GetTabContents();
NavigationController* controller = contents->controller();
- int max_count = controller->GetEntryCount();
- if (start_from < 0 || start_from >= max_count)
- return -1; // Out of bounds.
+ int history_items = GetHistoryItemCount();
- if (forward) {
- if (start_from < max_count - 1) {
- // We want to advance over the current chapter stop, so we add one.
- // We don't need to do this when direction is backwards.
- start_from++;
+ DCHECK(menu_id > 0);
+
+ // Convert anything above the History items separator.
+ if (menu_id <= history_items) {
+ if (model_type_ == FORWARD_MENU_DELEGATE) {
+ // The |menu_id| is relative to our current position, so we need to add.
+ menu_id += controller->GetCurrentEntryIndex();
} else {
- return -1;
+ // Back menu is reverse.
+ menu_id = controller->GetCurrentEntryIndex() - menu_id;
}
+ return menu_id;
}
+ if (menu_id == history_items + 1)
+ return -1; // Don't translate the separator for history items.
- NavigationEntry* start_entry = controller->GetEntryAtIndex(start_from);
- const GURL& url = start_entry->url();
-
- if (!forward) {
- // When going backwards we return the first entry we find that has a
- // different domain.
- for (int i = start_from - 1; i >= 0; --i) {
- if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
- controller->GetEntryAtIndex(i)->url()))
- return i;
- }
- // We have reached the beginning without finding a chapter stop.
- return -1;
- } else {
- // When going forwards we return the entry before the entry that has a
- // different domain.
- for (int i = start_from + 1; i < max_count; ++i) {
- if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
- controller->GetEntryAtIndex(i)->url()))
- return i - 1;
- }
- // Last entry is always considered a chapter stop.
- return max_count - 1;
- }
-}
+ if (menu_id >= history_items + 1 + GetChapterStopCount(history_items) + 1)
+ return -1; // This is beyond the last chapter stop so we abort.
-int BackForwardMenuModel::FindChapterStop(int offset,
- bool forward,
- int skip) const {
- if (offset < 0 || skip < 0)
- return -1;
+ // This menu item is a chapter stop located between the two separators.
+ menu_id = FindChapterStop(history_items,
+ model_type_ == FORWARD_MENU_DELEGATE,
+ menu_id - history_items - 1 - 1);
- if (!forward)
- offset *= -1;
+ return menu_id;
+}
+NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int menu_id) const {
TabContents* contents = GetTabContents();
NavigationController* controller = contents->controller();
- int entry = controller->GetCurrentEntryIndex() + offset;
-
- for (int i = 0; i < skip + 1; i++)
- entry = GetIndexOfNextChapterStop(entry, forward);
-
- return entry;
+ int index = MenuIdToNavEntryIndex(menu_id);
+ return controller->GetEntryAtIndex(index);
}
+std::wstring BackForwardMenuModel::BuildActionName(
+ const std::wstring& action, int index) const {
+ DCHECK(!action.empty());
+ DCHECK(index >= -1);
+ std::wstring metric_string;
+ if (model_type_ == FORWARD_MENU_DELEGATE)
+ metric_string += L"ForwardMenu_";
+ else
+ metric_string += L"BackMenu_";
+ metric_string += action;
+ if (index != -1)
+ metric_string += IntToWString(index);
+ return metric_string;
+}
diff --git a/chrome/browser/back_forward_menu_model.h b/chrome/browser/back_forward_menu_model.h
index fb17822..8e8408c 100644
--- a/chrome/browser/back_forward_menu_model.h
+++ b/chrome/browser/back_forward_menu_model.h
@@ -2,23 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H__
-#define CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H__
+#ifndef CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H_
+#define CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H_
-#include "chrome/views/menu.h"
+#include <string>
+
+#include "base/basictypes.h"
class Browser;
-class TabContents;
class SkBitmap;
+class TabContents;
class NavigationEntry;
///////////////////////////////////////////////////////////////////////////////
//
// BackForwardMenuModel
//
-// Implements the showing of the dropdown menu for the Back/Forward buttons.
+// Interface for the showing of the dropdown menu for the Back/Forward buttons.
+// Actual implementations are platform-specific.
///////////////////////////////////////////////////////////////////////////////
-class BackForwardMenuModel : public Menu::Delegate {
+class BackForwardMenuModel {
public:
// These are IDs used to identify individual UI elements within the
// browser window using View::GetViewByID.
@@ -27,23 +30,10 @@ class BackForwardMenuModel : public Menu::Delegate {
BACKWARD_MENU_DELEGATE = 2
};
- BackForwardMenuModel(Browser* browser, ModelType model_type);
- virtual ~BackForwardMenuModel();
-
- // Menu::Delegate
- virtual std::wstring GetLabel(int menu_id) const;
- virtual const SkBitmap& GetIcon(int menu_id) const;
- virtual bool SupportsCommand(int menu_id) const;
- virtual bool IsCommandEnabled(int menu_id) const;
- virtual bool IsItemSeparator(int menu_id) const;
- virtual bool HasIcon(int menu_id) const;
- virtual void ExecuteCommand(int menu_id);
- virtual void MenuWillShow();
- // Returns how many items the menu should show, including history items,
- // chapter-stops, separators and the Show Full History link. This function
- // uses GetHistoryItemCount() and GetChapterStopCount() internally to figure
- // out the total number of items to show.
- virtual int GetItemCount() const;
+ // Factory function. Defined in back_forward_menu_model_{platform}.cc.
+ // This is only used in unit tests. In the browser we use the platform-
+ // specific constructors directly.
+ static BackForwardMenuModel* Create(Browser* browser, ModelType model_type);
// Returns how many history items the menu should show. For example, if the
// navigation controller of the current tab has a current entry index of 5 and
@@ -62,6 +52,12 @@ class BackForwardMenuModel : public Menu::Delegate {
// chapter-stops.
int GetChapterStopCount(int history_items) const;
+ // Returns how many items the menu should show, including history items,
+ // chapter-stops, separators and the Show Full History link. This function
+ // uses GetHistoryItemCount() and GetChapterStopCount() internally to figure
+ // out the total number of items to show.
+ int GetTotalItemCount() const;
+
// Finds the next chapter-stop in the NavigationEntryList starting from
// the index specified in |start_from| and continuing in the direction
// specified (|forward|) until either a chapter-stop is found or we reach the
@@ -90,6 +86,26 @@ class BackForwardMenuModel : public Menu::Delegate {
// function returns -1.
int FindChapterStop(int offset, bool forward, int skip) const;
+ // Execute the command associated with |menu_id|.
+ void ExecuteCommandById(int menu_id);
+
+ // Is the item at |menu_id| a separator?
+ bool IsSeparator(int menu_id) const;
+
+ // Get the display text for the item. This should not be called on a
+ // separator.
+ std::wstring GetItemLabel(int menu_id) const;
+
+ // Get the display icon for the item. This should not be called on a
+ // separator or an item that does not have an icon.
+ const SkBitmap& GetItemIcon(int menu_id) const;
+
+ // Returns true if there is an icon for this menu item.
+ bool ItemHasIcon(int menu_id) const;
+
+ // Does the item does something when you click on it?
+ bool ItemHasCommand(int menu_id) const;
+
// Allows the unit test to use its own dummy tab contents.
void set_test_tab_contents(TabContents* test_tab_contents) {
test_tab_contents_ = test_tab_contents;
@@ -109,7 +125,21 @@ class BackForwardMenuModel : public Menu::Delegate {
// How many chapter-stops (max) to show in the back/forward dropdown list.
static const int kMaxChapterStops;
- private:
+ protected:
+ BackForwardMenuModel()
+ : browser_(NULL),
+ test_tab_contents_(NULL),
+ model_type_(FORWARD_MENU_DELEGATE) {}
+
+ Browser* browser_;
+
+ // The unit tests will provide their own TabContents to use.
+ TabContents* test_tab_contents_;
+
+ // Represents whether this is the delegate for the forward button or the
+ // back button.
+ ModelType model_type_;
+
// Converts a menu item id, as passed in through one of the menu delegate
// functions and converts it into an absolute index into the
// NavigationEntryList vector. |menu_id| can point to a separator, or the
@@ -125,18 +155,9 @@ class BackForwardMenuModel : public Menu::Delegate {
// An index of -1 means no index.
std::wstring BuildActionName(const std::wstring& name, int index) const;
- Browser* browser_;
-
- // The unit tests will provide their own TabContents to use.
- TabContents* test_tab_contents_;
-
- // Represents whether this is the delegate for the forward button or the
- // back button.
- ModelType model_type_;
-
- DISALLOW_EVIL_CONSTRUCTORS(BackForwardMenuModel);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackForwardMenuModel);
};
-#endif // CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H__
-
+#endif // CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_H_
diff --git a/chrome/browser/back_forward_menu_model_unittest.cc b/chrome/browser/back_forward_menu_model_unittest.cc
index 20f718d..5e1fbd5 100644
--- a/chrome/browser/back_forward_menu_model_unittest.cc
+++ b/chrome/browser/back_forward_menu_model_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/back_forward_menu_model.h"
+#include "chrome/browser/back_forward_menu_model_win.h"
#include "base/file_util.h"
#include "base/path_service.h"
@@ -124,11 +124,11 @@ TEST_F(BackFwdMenuModelTest, BasicCase) {
TabContents* contents = CreateTabContents();
{
- BackForwardMenuModel back_model(
+ BackForwardMenuModelWin back_model(
NULL, BackForwardMenuModel::BACKWARD_MENU_DELEGATE);
back_model.set_test_tab_contents(contents);
- BackForwardMenuModel forward_model(
+ BackForwardMenuModelWin forward_model(
NULL, BackForwardMenuModel::FORWARD_MENU_DELEGATE);
forward_model.set_test_tab_contents(contents);
@@ -207,11 +207,11 @@ TEST_F(BackFwdMenuModelTest, MaxItemsTest) {
TabContents* contents = CreateTabContents();
{
- BackForwardMenuModel back_model(
+ BackForwardMenuModelWin back_model(
NULL, BackForwardMenuModel::BACKWARD_MENU_DELEGATE);
back_model.set_test_tab_contents(contents);
- BackForwardMenuModel forward_model(
+ BackForwardMenuModelWin forward_model(
NULL, BackForwardMenuModel::FORWARD_MENU_DELEGATE);
forward_model.set_test_tab_contents(contents);
@@ -298,7 +298,7 @@ TEST_F(BackFwdMenuModelTest, MaxItemsTest) {
contents->CloseContents();
}
-void ValidateModel(BackForwardMenuModel* model, int history_items,
+void ValidateModel(BackForwardMenuModelWin* model, int history_items,
int chapter_stops) {
int h = std::min(BackForwardMenuModel::kMaxHistoryItems, history_items);
int c = std::min(BackForwardMenuModel::kMaxChapterStops, chapter_stops);
@@ -315,11 +315,11 @@ TEST_F(BackFwdMenuModelTest, ChapterStops) {
TabContents* contents = CreateTabContents();
{
- BackForwardMenuModel back_model(
+ BackForwardMenuModelWin back_model(
NULL, BackForwardMenuModel::BACKWARD_MENU_DELEGATE);
back_model.set_test_tab_contents(contents);
- BackForwardMenuModel forward_model(
+ BackForwardMenuModelWin forward_model(
NULL, BackForwardMenuModel::FORWARD_MENU_DELEGATE);
forward_model.set_test_tab_contents(contents);
diff --git a/chrome/browser/back_forward_menu_model_win.cc b/chrome/browser/back_forward_menu_model_win.cc
new file mode 100644
index 0000000..2a030da
--- /dev/null
+++ b/chrome/browser/back_forward_menu_model_win.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2006-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.
+
+#include "chrome/browser/back_forward_menu_model_win.h"
+
+#include "chrome/browser/browser.h"
+#include "chrome/browser/metrics/user_metrics.h"
+
+#include "generated_resources.h"
+
+// static
+BackForwardMenuModel* BackForwardMenuModel::Create(Browser* browser,
+ ModelType model_type) {
+ return new BackForwardMenuModelWin(browser, model_type);
+}
+
+BackForwardMenuModelWin::BackForwardMenuModelWin(Browser* browser,
+ ModelType model_type) {
+ browser_ = browser;
+ model_type_ = model_type;
+}
+
+std::wstring BackForwardMenuModelWin::GetLabel(int menu_id) const {
+ return GetItemLabel(menu_id);
+}
+
+const SkBitmap& BackForwardMenuModelWin::GetIcon(int menu_id) const {
+ // Return NULL if the item doesn't have an icon
+ if (!ItemHasIcon(menu_id))
+ return GetEmptyIcon();
+
+ return GetItemIcon(menu_id);
+}
+
+bool BackForwardMenuModelWin::IsItemSeparator(int menu_id) const {
+ return IsSeparator(menu_id);
+}
+
+bool BackForwardMenuModelWin::HasIcon(int menu_id) const {
+ return ItemHasIcon(menu_id);
+}
+
+bool BackForwardMenuModelWin::SupportsCommand(int menu_id) const {
+ return ItemHasCommand(menu_id);
+}
+
+bool BackForwardMenuModelWin::IsCommandEnabled(int menu_id) const {
+ return ItemHasCommand(menu_id);
+}
+
+void BackForwardMenuModelWin::ExecuteCommand(int menu_id) {
+ ExecuteCommandById(menu_id);
+}
+
+void BackForwardMenuModelWin::MenuWillShow() {
+ UserMetrics::RecordComputedAction(BuildActionName(L"Popup", -1),
+ browser_->profile());
+}
+
+int BackForwardMenuModelWin::GetItemCount() const {
+ return GetTotalItemCount();
+}
+
diff --git a/chrome/browser/back_forward_menu_model_win.h b/chrome/browser/back_forward_menu_model_win.h
new file mode 100644
index 0000000..e4f54e0
--- /dev/null
+++ b/chrome/browser/back_forward_menu_model_win.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-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 CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_WIN_H_
+#define CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_WIN_H_
+
+#include "base/basictypes.h"
+
+#include "chrome/browser/back_forward_menu_model.h"
+#include "chrome/views/menu.h"
+
+class SkBitmap;
+
+class BackForwardMenuModelWin : public BackForwardMenuModel,
+ public Menu::Delegate {
+ public:
+ BackForwardMenuModelWin(Browser* browser, ModelType model_type);
+
+ // Menu::Delegate
+ virtual std::wstring GetLabel(int menu_id) const;
+ virtual const SkBitmap& GetIcon(int menu_id) const;
+ virtual bool SupportsCommand(int menu_id) const;
+ virtual bool IsCommandEnabled(int menu_id) const;
+ virtual bool IsItemSeparator(int menu_id) const;
+ virtual bool HasIcon(int menu_id) const;
+ virtual void ExecuteCommand(int menu_id);
+ virtual void MenuWillShow();
+ virtual int GetItemCount() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackForwardMenuModelWin);
+};
+
+#endif // CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_WIN_H_
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons
index 553853a..e6fab55 100644
--- a/chrome/browser/browser.scons
+++ b/chrome/browser/browser.scons
@@ -168,6 +168,8 @@ input_files = ChromeFileList([
'app_modal_dialog_queue.h',
'back_forward_menu_model.cc',
'back_forward_menu_model.h',
+ 'back_forward_menu_model_win.cc',
+ 'back_forward_menu_model_win.h',
'browser.cc',
'browser.h',
'browser_list.cc',
@@ -669,7 +671,6 @@ if not env.Bit('windows'):
'automation/automation_provider.cc',
'automation/automation_provider_list.cc',
'automation/ui_controls.cc',
- 'back_forward_menu_model.cc',
'bookmarks/bookmark_context_menu.cc',
'bookmarks/bookmark_drag_data.cc',
'bookmarks/bookmark_drop_info.cc',
@@ -759,6 +760,7 @@ if not env.Bit('windows'):
# Remove Windows-specific files on other platforms.
input_files.Remove(
+ 'back_forward_menu_model_win.cc',
'browser_main_win.cc',
'history/history_publisher_win.cc',
'importer/firefox_profile_lock_win.cc',
@@ -785,13 +787,14 @@ if not env.Bit('windows'):
if env.Bit('linux'):
input_files.Extend([
'browser_main_gtk.cc',
- 'process_singleton_linux.cc',
+ 'gtk/back_forward_menu_model_gtk.cc',
'gtk/browser_toolbar_view_gtk.cc',
'gtk/browser_window_factory_gtk.cc',
'gtk/browser_window_gtk.cc',
'gtk/menu_gtk.cc',
'gtk/nine_box.cc',
'gtk/standard_menus.cc',
+ 'process_singleton_linux.cc',
'renderer_host/render_widget_host_view_gtk.cc',
'tab_contents/web_contents_view_gtk.cc',
])
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index f079700..2015099 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -642,6 +642,14 @@
>
</File>
<File
+ RelativePath=".\back_forward_menu_model_win.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\back_forward_menu_model_win.h"
+ >
+ </File>
+ <File
RelativePath=".\browser.cc"
>
</File>
diff --git a/chrome/browser/gtk/back_forward_menu_model_gtk.cc b/chrome/browser/gtk/back_forward_menu_model_gtk.cc
new file mode 100644
index 0000000..6db3234
--- /dev/null
+++ b/chrome/browser/gtk/back_forward_menu_model_gtk.cc
@@ -0,0 +1,47 @@
+// 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.
+
+#include "chrome/browser/gtk/back_forward_menu_model_gtk.h"
+
+#include "base/string_util.h"
+
+// static
+BackForwardMenuModel* BackForwardMenuModel::Create(Browser* browser,
+ ModelType model_type) {
+ return new BackForwardMenuModelGtk(browser, model_type);
+}
+
+BackForwardMenuModelGtk::BackForwardMenuModelGtk(Browser* browser,
+ ModelType model_type) {
+ browser_ = browser;
+ model_type_ = model_type;
+}
+
+int BackForwardMenuModelGtk::GetItemCount() const {
+ return GetTotalItemCount();
+}
+
+bool BackForwardMenuModelGtk::IsItemSeparator(int command_id) const {
+ return IsSeparator(command_id);
+}
+
+std::string BackForwardMenuModelGtk::GetLabel(int command_id) const {
+ return WideToUTF8(GetItemLabel(command_id));
+}
+
+bool BackForwardMenuModelGtk::HasIcon(int command_id) const {
+ return ItemHasIcon(command_id);
+}
+
+const SkBitmap* BackForwardMenuModelGtk::GetIcon(int command_id) const {
+ return &GetItemIcon(command_id);
+}
+
+bool BackForwardMenuModelGtk::IsCommandEnabled(int command_id) const {
+ return ItemHasCommand(command_id);
+}
+
+void BackForwardMenuModelGtk::ExecuteCommand(int command_id) {
+ ExecuteCommandById(command_id);
+}
diff --git a/chrome/browser/gtk/back_forward_menu_model_gtk.h b/chrome/browser/gtk/back_forward_menu_model_gtk.h
new file mode 100644
index 0000000..59ff869
--- /dev/null
+++ b/chrome/browser/gtk/back_forward_menu_model_gtk.h
@@ -0,0 +1,34 @@
+// 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 CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_GTK_H_
+#define CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_GTK_H_
+
+#include "base/basictypes.h"
+
+#include "chrome/browser/back_forward_menu_model.h"
+#include "chrome/browser/gtk/menu_gtk.h"
+
+// For the most part, this class simply passes calls through to
+// the BackForwardMenuModel.
+class BackForwardMenuModelGtk : public BackForwardMenuModel,
+ public MenuGtk::Delegate {
+ public:
+ BackForwardMenuModelGtk(Browser* browser, ModelType model_type);
+
+ // MenuGtk::Delegate
+ virtual int GetItemCount() const;
+ virtual bool IsItemSeparator(int menu_id) const;
+ virtual std::string GetLabel(int menu_id) const;
+ virtual bool HasIcon(int menu_id) const;
+ virtual const SkBitmap* GetIcon(int menu_id) const;
+ virtual bool IsCommandEnabled(int command_id) const;
+ virtual void ExecuteCommand(int command_id);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackForwardMenuModelGtk);
+};
+
+#endif // CHROME_BROWSER_BACK_FORWARD_MENU_MODEL_GTK_H_
+
diff --git a/chrome/browser/gtk/browser_toolbar_view_gtk.cc b/chrome/browser/gtk/browser_toolbar_view_gtk.cc
index b2ba34b..4188803 100644
--- a/chrome/browser/gtk/browser_toolbar_view_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_view_gtk.cc
@@ -9,6 +9,7 @@
#include "base/path_service.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
+#include "chrome/browser/gtk/back_forward_menu_model_gtk.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/gtk/standard_menus.h"
#include "chrome/common/l10n_util.h"
@@ -19,6 +20,9 @@
#include "grit/theme_resources.h"
const int BrowserToolbarGtk::kToolbarHeight = 38;
+// For the back/forward dropdown menus, the time in milliseconds between
+// when the user clicks and the popup menu appears.
+static const int kMenuTimerDelay = 500;
// CustomDrawButton manages the lifetimes of some resources used to make a
// custom-drawn Gtk button. We use them on the toolbar.
@@ -133,18 +137,18 @@ BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser)
entry_(NULL),
model_(browser->toolbar_model()),
browser_(browser),
- profile_(NULL) {
+ profile_(NULL),
+ show_menu_factory_(this) {
browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
browser_->command_updater()->AddCommandObserver(IDC_STAR, this);
- // TODO(port): Port BackForwardMenuModel
- // back_menu_model_.reset(new BackForwardMenuModel(
- // browser, BackForwardMenuModel::BACKWARD_MENU_DELEGATE));
- // forward_menu_model_.reset(new BackForwardMenuModel(
- // browser, BackForwardMenuModel::FORWARD_MENU_DELEGATE));
+ back_menu_model_.reset(new BackForwardMenuModelGtk(
+ browser, BackForwardMenuModel::BACKWARD_MENU_DELEGATE));
+ forward_menu_model_.reset(new BackForwardMenuModelGtk(
+ browser, BackForwardMenuModel::FORWARD_MENU_DELEGATE));
}
BrowserToolbarGtk::~BrowserToolbarGtk() {
@@ -160,10 +164,12 @@ void BrowserToolbarGtk::Init(Profile* profile) {
toolbar_tooltips_ = gtk_tooltips_new();
- back_.reset(BuildToolbarButton(IDR_BACK, IDR_BACK_P, IDR_BACK_H, IDR_BACK_D,
- l10n_util::GetString(IDS_TOOLTIP_BACK), false));
- forward_.reset(BuildToolbarButton(IDR_FORWARD, IDR_FORWARD_P, IDR_FORWARD_H,
- IDR_FORWARD_D, l10n_util::GetString(IDS_TOOLTIP_FORWARD), false));
+ back_.reset(BuildBackForwardButton(IDR_BACK, IDR_BACK_P, IDR_BACK_H,
+ IDR_BACK_D,
+ l10n_util::GetString(IDS_TOOLTIP_BACK)));
+ forward_.reset(BuildBackForwardButton(IDR_FORWARD, IDR_FORWARD_P,
+ IDR_FORWARD_H, IDR_FORWARD_D,
+ l10n_util::GetString(IDS_TOOLTIP_FORWARD)));
gtk_box_pack_start(GTK_BOX(toolbar_), gtk_label_new(" "), FALSE, FALSE, 0);
@@ -273,7 +279,7 @@ BrowserToolbarGtk::CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton(
WideToUTF8(localized_tooltip).c_str(),
WideToUTF8(localized_tooltip).c_str());
if (menu_button) {
- g_signal_connect(G_OBJECT(button->widget()), "button_press_event",
+ g_signal_connect(G_OBJECT(button->widget()), "button-press-event",
G_CALLBACK(OnMenuButtonPressEvent), this);
} else {
g_signal_connect(G_OBJECT(button->widget()), "clicked",
@@ -284,7 +290,7 @@ BrowserToolbarGtk::CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton(
return button;
}
-/* static */
+// static
void BrowserToolbarGtk::OnEntryActivate(GtkEntry *entry,
BrowserToolbarGtk* toolbar) {
GURL dest(std::string(gtk_entry_get_text(entry)));
@@ -310,14 +316,17 @@ void BrowserToolbarGtk::OnButtonClick(GtkWidget* button,
else if (button == toolbar->star_->widget())
tag = IDC_STAR;
+ if (tag == IDC_BACK || tag == IDC_FORWARD)
+ toolbar->show_menu_factory_.RevokeAll();
+
DCHECK(tag != -1) << "Impossible button click callback";
toolbar->browser_->ExecuteCommand(tag);
}
-/* static */
-gint BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
- GdkEvent* event,
- BrowserToolbarGtk* toolbar) {
+// static
+gboolean BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
+ GdkEvent* event,
+ BrowserToolbarGtk* toolbar) {
if (event->type == GDK_BUTTON_PRESS) {
GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
if (event_button->button == 1) {
@@ -335,6 +344,57 @@ gint BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
return FALSE;
}
+BrowserToolbarGtk::CustomDrawButton* BrowserToolbarGtk::BuildBackForwardButton(
+ int normal_id,
+ int active_id,
+ int highlight_id,
+ int depressed_id,
+ const std::wstring& localized_tooltip) {
+ CustomDrawButton* button = new CustomDrawButton(normal_id, active_id,
+ highlight_id, depressed_id);
+
+ // TODO(erg): Mismatch between wstring and string.
+ // gtk_tooltips_set_tip(GTK_TOOLTIPS(toolbar_tooltips_),
+ // GTK_WIDGET(back_),
+ // localized_tooltip, localized_tooltip);
+
+ g_signal_connect(G_OBJECT(button->widget()), "button-press-event",
+ G_CALLBACK(OnBackForwardPressEvent), this);
+ g_signal_connect(G_OBJECT(button->widget()), "clicked",
+ G_CALLBACK(OnButtonClick), this);
+
+ gtk_box_pack_start(GTK_BOX(toolbar_), button->widget(), FALSE, FALSE, 0);
+ // Popup the menu as left-aligned relative to this widget rather than the
+ // default of right aligned.
+ g_object_set_data(G_OBJECT(button->widget()), "left-align-popup",
+ reinterpret_cast<void*>(true));
+ return button;
+}
+
+// static
+gboolean BrowserToolbarGtk::OnBackForwardPressEvent(GtkWidget* widget,
+ GdkEventButton* event,
+ BrowserToolbarGtk* toolbar) {
+ // TODO(port): only allow left clicks to open the menu.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ toolbar->show_menu_factory_.NewRunnableMethod(
+ &BrowserToolbarGtk::ShowBackForwardMenu,
+ widget, event->button),
+ kMenuTimerDelay);
+ return FALSE;
+}
+
+void BrowserToolbarGtk::ShowBackForwardMenu(GtkWidget* widget,
+ gint button_type) {
+ if (widget == back_->widget()) {
+ back_forward_menu_.reset(new MenuGtk(back_menu_model_.get()));
+ } else {
+ back_forward_menu_.reset(new MenuGtk(forward_menu_model_.get()));
+ }
+
+ back_forward_menu_->Popup(widget, button_type, gtk_get_current_event_time());
+}
+
void BrowserToolbarGtk::RunPageMenu(GdkEvent* button_press_event) {
if (page_menu_ == NULL) {
page_menu_.reset(new MenuGtk(this, GetStandardPageMenu()));
diff --git a/chrome/browser/gtk/browser_toolbar_view_gtk.h b/chrome/browser/gtk/browser_toolbar_view_gtk.h
index e98097a..c000e9b 100644
--- a/chrome/browser/gtk/browser_toolbar_view_gtk.h
+++ b/chrome/browser/gtk/browser_toolbar_view_gtk.h
@@ -9,10 +9,12 @@
#include <string>
#include "base/scoped_ptr.h"
+#include "base/task.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/common/pref_member.h"
+class BackForwardMenuModelGtk;
class Browser;
class Profile;
class TabContents;
@@ -67,9 +69,9 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
static void OnButtonClick(GtkWidget* button, BrowserToolbarGtk* toolbar);
// Gtk callback to intercept mouse clicks to the menu buttons.
- static gint OnMenuButtonPressEvent(GtkWidget* button,
- GdkEvent *event,
- BrowserToolbarGtk* toolbar);
+ static gboolean OnMenuButtonPressEvent(GtkWidget* button,
+ GdkEvent *event,
+ BrowserToolbarGtk* toolbar);
// Displays the page menu.
void RunPageMenu(GdkEvent* button_press_event);
@@ -99,15 +101,42 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
scoped_ptr<MenuGtk> page_menu_;
scoped_ptr<MenuGtk> app_menu_;
- // TODO(port): Port BackForwardMenuModel
- // scoped_ptr<BackForwardMenuModel> back_menu_model_;
- // scoped_ptr<BackForwardMenuModel> forward_menu_model_;
-
Browser* browser_;
Profile* profile_;
// Controls whether or not a home button should be shown on the toolbar.
BooleanPrefMember show_home_button_;
+
+ // Back/Forward menus ------------------------------------------------------
+ // When clicked, these buttons will navigate forward or backward. When
+ // pressed and held, they show a dropdown menu of recent web sites.
+ // TODO(port): to match windows, we need to immediately show the back/forward
+ // menu when the user starts dragging the mouse.
+
+ // Builds a toolbar button for the back or forward dropdown menus.
+ CustomDrawButton* BuildBackForwardButton(
+ int normal_id,
+ int active_id,
+ int highlight_id,
+ int depressed_id,
+ const std::wstring& localized_tooltip);
+
+ // Starts a timer to show the dropdown menu.
+ static gboolean OnBackForwardPressEvent(GtkWidget* button,
+ GdkEventButton* event,
+ BrowserToolbarGtk* toolbar);
+
+ // Shows the dropdown menu when the timer fires. |button_type| refers to the
+ // click that originated the button press event.
+ void ShowBackForwardMenu(GtkWidget* button, gint button_type);
+
+ // The back/forward menu gets reset every time it is shown.
+ scoped_ptr<MenuGtk> back_forward_menu_;
+
+ scoped_ptr<BackForwardMenuModelGtk> back_menu_model_;
+ scoped_ptr<BackForwardMenuModelGtk> forward_menu_model_;
+
+ ScopedRunnableMethodFactory<BrowserToolbarGtk> show_menu_factory_;
};
#endif // CHROME_BROWSER_GTK_BROWSER_TOOLBAR_VIEW_GTK_H_
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
index 7eaab60..db8da36 100644
--- a/chrome/browser/gtk/menu_gtk.cc
+++ b/chrome/browser/gtk/menu_gtk.cc
@@ -15,6 +15,12 @@ MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
BuildMenuIn(menu_, menu_data);
}
+MenuGtk::MenuGtk(MenuGtk::Delegate* delegate)
+ : delegate_(delegate),
+ menu_(gtk_menu_new()) {
+ BuildMenuFromDelegate();
+}
+
MenuGtk::~MenuGtk() {
g_object_unref(menu_);
}
@@ -23,13 +29,17 @@ void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
DCHECK(event->type == GDK_BUTTON_PRESS)
<< "Non-button press event sent to RunMenuAt";
+ GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
+ Popup(widget, event_button->button, event_button->time);
+}
+
+void MenuGtk::Popup(GtkWidget* widget, gint button_type, guint32 timestamp) {
gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this);
- GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
MenuPositionFunc,
widget,
- event_button->button, event_button->time);
+ button_type, timestamp);
}
void MenuGtk::BuildMenuIn(GtkWidget* menu,
@@ -79,7 +89,33 @@ void MenuGtk::BuildMenuIn(GtkWidget* menu,
}
}
-/* static */
+void MenuGtk::BuildMenuFromDelegate() {
+ // Note that the menu IDs start at 1, not 0.
+ for (int i = 1; i <= delegate_->GetItemCount(); ++i) {
+ GtkWidget* menu_item = NULL;
+
+ if (delegate_->IsItemSeparator(i)) {
+ menu_item = gtk_separator_menu_item_new();
+ } else if (delegate_->HasIcon(i)) {
+ menu_item = gtk_image_menu_item_new_with_label(
+ delegate_->GetLabel(i).c_str());
+ // TODO(port): set the image with delegate->GetIcon()
+ } else {
+ menu_item = gtk_menu_item_new_with_label(delegate_->GetLabel(i).c_str());
+ }
+
+ g_object_set_data(G_OBJECT(menu_item), "menu-id",
+ reinterpret_cast<void*>(i));
+
+ g_signal_connect(G_OBJECT(menu_item), "activate",
+ G_CALLBACK(OnMenuItemActivatedById), this);
+
+ gtk_widget_show(menu_item);
+ gtk_menu_append(menu_, menu_item);
+ }
+}
+
+// static
void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
// We receive activation messages when highlighting a menu that has a
// submenu. Ignore them.
@@ -91,7 +127,18 @@ void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
}
}
-/* static */
+// static
+void MenuGtk::OnMenuItemActivatedById(GtkMenuItem* menuitem, MenuGtk* menu) {
+ // We receive activation messages when highlighting a menu that has a
+ // submenu. Ignore them.
+ if (!gtk_menu_item_get_submenu(menuitem)) {
+ int id = reinterpret_cast<int>(
+ g_object_get_data(G_OBJECT(menuitem), "menu-id"));
+ menu->delegate_->ExecuteCommand(id);
+ }
+}
+
+// static
void MenuGtk::MenuPositionFunc(GtkMenu* menu,
int* x,
int* y,
@@ -110,10 +157,17 @@ void MenuGtk::MenuPositionFunc(GtkMenu* menu,
gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
gdk_window_get_origin(widget->window, x, y);
- *x += widget->allocation.x + widget->allocation.width;
+ *x += widget->allocation.x;
*y += widget->allocation.y + widget->allocation.height;
- *x -= menu_req.width;
+ // g_object_get_data() returns NULL if no such object is found. |left_align|
+ // acts as a boolean, but we can't actually cast it to bool because gcc
+ // complains about losing precision.
+ void* left_align =
+ g_object_get_data(G_OBJECT(widget), "left-align-popup");
+
+ if (!left_align)
+ *x += widget->allocation.width - menu_req.width;
// TODO(erg): Deal with this scrolling off the bottom of the screen.
@@ -123,7 +177,7 @@ void MenuGtk::MenuPositionFunc(GtkMenu* menu,
*push_in = FALSE;
}
-/* static */
+// static
void MenuGtk::SetMenuItemInfo(GtkWidget* widget, void* raw_menu) {
MenuGtk* menu = static_cast<MenuGtk*>(raw_menu);
const MenuCreateMaterial* data =
diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h
index 462c122..bef318f 100644
--- a/chrome/browser/gtk/menu_gtk.h
+++ b/chrome/browser/gtk/menu_gtk.h
@@ -6,9 +6,12 @@
#define CHROME_BROWSER_GTK_MENU_GTK_H_
#include <gtk/gtk.h>
+#include <string>
#include "chrome/browser/gtk/standard_menus.h"
+class SkBitmap;
+
class MenuGtk {
public:
// Delegate class that lets another class control the status of the menu.
@@ -19,17 +22,32 @@ class MenuGtk {
// Returns whether the menu item for this command should be enabled.
virtual bool IsCommandEnabled(int command_id) const = 0;
- // Returns whether this command.
- virtual bool IsItemChecked(int command_id) const = 0;
+ // Returns whether this command is checked (for checkbox menu items only).
+ virtual bool IsItemChecked(int command_id) const { return false; }
// Executes the command.
virtual void ExecuteCommand(int command_id) = 0;
+
+ // Functions needed for creation of non-static menus.
+ virtual int GetItemCount() const { return 0; }
+ virtual bool IsItemSeparator(int command_id) const { return false; }
+ virtual std::string GetLabel(int command_id) const { return std::string(); }
+ virtual bool HasIcon(int command_id) const { return false; }
+ virtual const SkBitmap* GetIcon(int command_id) const { return NULL; }
};
+ // Builds a MenuGtk that uses |delegate| to perform actions and |menu_data|
+ // to create the menu.
MenuGtk(MenuGtk::Delegate* delegate, const MenuCreateMaterial* menu_data);
+ // Builds a MenuGtk that uses |delegate| to create the menu as well as perform
+ // actions.
+ explicit MenuGtk(MenuGtk::Delegate* delegate);
~MenuGtk();
- // Displays the menu
+ // Displays the menu. |timestamp| is the time of activation.
+ void Popup(GtkWidget* widget, gint button_type, guint32 timestamp);
+
+ // Displays the menu using the button type and timestamp of |event|.
void Popup(GtkWidget* widget, GdkEvent* event);
private:
@@ -37,10 +55,23 @@ class MenuGtk {
// of GtkMenuItems.
void BuildMenuIn(GtkWidget* menu, const MenuCreateMaterial* menu_data);
- // Callback for when a menu item is clicked.
+ // A function that creates a GtkMenu from |delegate_|. This function is not
+ // recursive and does not support sub-menus.
+ void BuildMenuFromDelegate();
+
+ // Callback for when a menu item is clicked. Used when the menu is created
+ // via a MenuCreateMaterial.
static void OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu);
+ // Callback for when a menu item is clicked. Used when the menu is created
+ // via |delegate_|.
+ static void OnMenuItemActivatedById(GtkMenuItem* menuitem, MenuGtk* menu);
+
// Repositions the menu to be right under the button.
+ // Alignment is set as object data on |void_widget| with the tag "left_align".
+ // If "left_align" is true, it aligns the left side of the menu with the left
+ // side of the button. Otherwise it aligns the right side of the menu with the
+ // right side of the button.
static void MenuPositionFunc(GtkMenu* menu,
int* x,
int* y,
@@ -59,3 +90,4 @@ class MenuGtk {
};
#endif // CHROME_BROWSER_GTK_MENU_GTK_H_
+
diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc
index 360dc817..bf65185 100644
--- a/chrome/browser/views/toolbar_view.cc
+++ b/chrome/browser/views/toolbar_view.cc
@@ -83,9 +83,9 @@ BrowserToolbarView::BrowserToolbarView(Browser* browser)
browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
browser_->command_updater()->AddCommandObserver(IDC_STAR, this);
- back_menu_model_.reset(new BackForwardMenuModel(
+ back_menu_model_.reset(new BackForwardMenuModelWin(
browser, BackForwardMenuModel::BACKWARD_MENU_DELEGATE));
- forward_menu_model_.reset(new BackForwardMenuModel(
+ forward_menu_model_.reset(new BackForwardMenuModelWin(
browser, BackForwardMenuModel::FORWARD_MENU_DELEGATE));
if (browser->type() == Browser::TYPE_NORMAL)
display_mode_ = DISPLAYMODE_NORMAL;
diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h
index 77a28a7..ff77107 100644
--- a/chrome/browser/views/toolbar_view.h
+++ b/chrome/browser/views/toolbar_view.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H__
-#define CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H__
+#ifndef CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_
#include <vector>
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
-#include "chrome/browser/back_forward_menu_model.h"
+#include "chrome/browser/back_forward_menu_model_win.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/encoding_menu_controller_delegate.h"
#include "chrome/browser/user_data_manager.h"
@@ -168,8 +168,8 @@ class BrowserToolbarView : public views::View,
// accessibility focus.
virtual void ShowContextMenu(int x, int y, bool is_mouse_gesture);
- scoped_ptr<BackForwardMenuModel> back_menu_model_;
- scoped_ptr<BackForwardMenuModel> forward_menu_model_;
+ scoped_ptr<BackForwardMenuModelWin> back_menu_model_;
+ scoped_ptr<BackForwardMenuModelWin> forward_menu_model_;
// The model that contains the security level, text, icon to display...
ToolbarModel* model_;
@@ -209,4 +209,4 @@ class BrowserToolbarView : public views::View,
DisplayMode display_mode_;
};
-#endif // CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H__
+#endif // CHROME_BROWSER_VIEWS_TOOLBAR_VIEW_H_