diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-18 22:30:16 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-18 22:30:16 +0000 |
commit | 70b45efc15674aa7241bbb95dc81b3019eac294b (patch) | |
tree | b4b8cae88b43ffb0a669cc7b50aabafa93506a02 /chrome | |
parent | cb71491f6fd9eb062ecbce3df5ca543c77652d91 (diff) | |
download | chromium_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.cc | 318 | ||||
-rw-r--r-- | chrome/browser/back_forward_menu_model.h | 93 | ||||
-rw-r--r-- | chrome/browser/back_forward_menu_model_unittest.cc | 16 | ||||
-rw-r--r-- | chrome/browser/back_forward_menu_model_win.cc | 64 | ||||
-rw-r--r-- | chrome/browser/back_forward_menu_model_win.h | 35 | ||||
-rw-r--r-- | chrome/browser/browser.scons | 7 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/gtk/back_forward_menu_model_gtk.cc | 47 | ||||
-rw-r--r-- | chrome/browser/gtk/back_forward_menu_model_gtk.h | 34 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_view_gtk.cc | 92 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_view_gtk.h | 43 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.cc | 68 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.h | 40 | ||||
-rw-r--r-- | chrome/browser/views/toolbar_view.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/toolbar_view.h | 12 |
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_ |