diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-29 03:20:27 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-29 03:20:27 +0000 |
commit | ad3d7273dff93e5107a947c05c6a47c35ea7eea7 (patch) | |
tree | dd34fa6e3aaa7080885f5d28e046c76751f7d25f | |
parent | 21bd81995a2dbeb92833ee6b55612ec30ce6122f (diff) | |
download | chromium_src-ad3d7273dff93e5107a947c05c6a47c35ea7eea7.zip chromium_src-ad3d7273dff93e5107a947c05c6a47c35ea7eea7.tar.gz chromium_src-ad3d7273dff93e5107a947c05c6a47c35ea7eea7.tar.bz2 |
Relands your patch to have an option for enabling vertical tabs. I've
added the following additions:
. made the layout work for opaque_browser_frame.
. Only show the menu if the user supplied --enable-vertical-tabs.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/1708014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45906 0039d316-1c4b-4281-b951-d872f2087c98
35 files changed, 389 insertions, 85 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 401ddde..1ebb1a3 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4602,6 +4602,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_BOOKMARK_ALL_TABS" desc="In Title Case: The label of the tab context menu item for creating a bookmark folder containing an entry for each open tab."> Bookmark all tabs... </message> + <message name="IDS_TAB_CXMENU_USE_VERTICAL_TABS" desc="Use the vertical tab strip"> + Use side tabs + </message> </if> <if expr="pp_ifdef('use_titlecase')"> <message name="IDS_TAB_CXMENU_NEWTAB" desc="In Title Case: The label of the 'New Tab' Tab context menu item."> @@ -4634,6 +4637,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_BOOKMARK_ALL_TABS" desc="In Title Case: The label of the tab context menu item for creating a bookmark folder containing an entry for each open tab."> Bookmark All Tabs... </message> + <message name="IDS_TAB_CXMENU_USE_VERTICAL_TABS" desc="Use the vertical tab strip"> + Use Side Tabs + </message> </if> <!-- Bookmarks bar --> diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index efb6f1a..f810c7e 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -67,6 +67,7 @@ #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/tab_menu_model.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_constants.h" @@ -195,6 +196,12 @@ Browser::Browser(Type type, Profile* profile) encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector, profile_->GetPrefs(), NULL); + use_vertical_tabs_.Init(prefs::kUseVerticalTabs, profile_->GetPrefs(), this); + if (!TabMenuModel::AreVerticalTabsEnabled()) { + // If vertical tabs aren't enabled, explicitly turn them off. Otherwise we + // might show vertical tabs but not show an option to turn them off. + use_vertical_tabs_.SetValue(false); + } } Browser::~Browser() { @@ -1667,7 +1674,7 @@ void Browser::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kWebAppCreateOnDesktop, true); prefs->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true); prefs->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true); - prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, true); + prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, false); prefs->RegisterBooleanPref(prefs::kEnableTranslate, true); } @@ -2096,6 +2103,15 @@ void Browser::BookmarkAllTabs() { BookmarkEditor::SHOW_TREE); } +bool Browser::UseVerticalTabs() const { + return use_vertical_tabs_.GetValue(); +} + +void Browser::ToggleUseVerticalTabs() { + use_vertical_tabs_.SetValue(!UseVerticalTabs()); + window()->ToggleTabStripMode(); +} + /////////////////////////////////////////////////////////////////////////////// // Browser, TabStripModelObserver implementation: @@ -2752,6 +2768,14 @@ void Browser::Observe(NotificationType type, break; } + case NotificationType::PREF_CHANGED: { + if (*(Details<std::wstring>(details).ptr()) == prefs::kUseVerticalTabs) + window()->ToggleTabStripMode(); + else + NOTREACHED(); + break; + } + default: NOTREACHED() << "Got a notification we didn't register for."; } diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index 15123da..6527d2c 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -622,6 +622,8 @@ class Browser : public TabStripModelDelegate, virtual bool CanCloseContentsAt(int index); virtual bool CanBookmarkAllTabs() const; virtual void BookmarkAllTabs(); + virtual bool UseVerticalTabs() const; + virtual void ToggleUseVerticalTabs(); // Overridden from TabStripModelObserver: virtual void TabInsertedAt(TabContents* contents, @@ -968,6 +970,9 @@ class Browser : public TabStripModelDelegate, // The extension app associated with this window, if any. Extension* extension_app_; + // Tracks the display mode of the tabstrip. + mutable BooleanPrefMember use_vertical_tabs_; + DISALLOW_COPY_AND_ASSIGN(Browser); }; diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h index 4d2b461..fa7b22b 100644 --- a/chrome/browser/browser_window.h +++ b/chrome/browser/browser_window.h @@ -304,6 +304,9 @@ class BrowserWindow { virtual void Copy() = 0; virtual void Paste() = 0; + // Switches between available tabstrip display modes. + virtual void ToggleTabStripMode() = 0; + // Construct a BrowserWindow implementation for the specified |browser|. static BrowserWindow* CreateBrowserWindow(Browser* browser); diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index b79712a..dc760f8 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -102,6 +102,7 @@ class BrowserWindowCocoa : public BrowserWindow, virtual void Cut(); virtual void Copy(); virtual void Paste(); + virtual void ToggleTabStripMode() {} // Overridden from NotificationObserver virtual void Observe(NotificationType type, diff --git a/chrome/browser/cocoa/tab_strip_controller_unittest.mm b/chrome/browser/cocoa/tab_strip_controller_unittest.mm index 82cea8e..2a161ab 100644 --- a/chrome/browser/cocoa/tab_strip_controller_unittest.mm +++ b/chrome/browser/cocoa/tab_strip_controller_unittest.mm @@ -63,6 +63,10 @@ class TestTabStripDelegate : public TabStripModelDelegate { virtual bool CanBookmarkAllTabs() const { return false; } virtual void BookmarkAllTabs() {} + + virtual bool UseVerticalTabs() const { return false; } + + virtual void ToggleUseVerticalTabs() {} }; class TabStripControllerTest : public CocoaTest { diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 3f10f57..d193d13 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -120,6 +120,7 @@ class BrowserWindowGtk : public BrowserWindow, virtual void Cut(); virtual void Copy(); virtual void Paste(); + virtual void ToggleTabStripMode() {} // Overridden from NotificationObserver: virtual void Observe(NotificationType type, diff --git a/chrome/browser/tab_menu_model.cc b/chrome/browser/tab_menu_model.cc index bb0ba34..f955837 100644 --- a/chrome/browser/tab_menu_model.cc +++ b/chrome/browser/tab_menu_model.cc @@ -4,7 +4,9 @@ #include "chrome/browser/tab_menu_model.h" +#include "base/command_line.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" #include "grit/generated_resources.h" TabMenuModel::TabMenuModel(menus::SimpleMenuModel::Delegate* delegate, @@ -13,6 +15,16 @@ TabMenuModel::TabMenuModel(menus::SimpleMenuModel::Delegate* delegate, Build(is_pinned); } +// static +bool TabMenuModel::AreVerticalTabsEnabled() { +#if defined(TOOLKIT_VIEWS) + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableVerticalTabs); +#else + return false; +#endif +} + void TabMenuModel::Build(bool is_pinned) { AddItemWithStringId(TabStripModel::CommandNewTab, IDS_TAB_CXMENU_NEWTAB); AddSeparator(); @@ -35,4 +47,9 @@ void TabMenuModel::Build(bool is_pinned) { AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB); AddItemWithStringId(TabStripModel::CommandBookmarkAllTabs, IDS_TAB_CXMENU_BOOKMARK_ALL_TABS); + if (AreVerticalTabsEnabled()) { + AddSeparator(); + AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs, + IDS_TAB_CXMENU_USE_VERTICAL_TABS); + } } diff --git a/chrome/browser/tab_menu_model.h b/chrome/browser/tab_menu_model.h index dca49af..189fefe 100644 --- a/chrome/browser/tab_menu_model.h +++ b/chrome/browser/tab_menu_model.h @@ -18,6 +18,9 @@ class TabMenuModel : public menus::SimpleMenuModel { TabMenuModel(menus::SimpleMenuModel::Delegate* delegate, bool is_pinned); virtual ~TabMenuModel() {} + // Returns true if vertical tabs are enabled. + static bool AreVerticalTabsEnabled(); + private: void Build(bool is_pinned); diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc index b5095a2..a1b1355 100644 --- a/chrome/browser/tabs/tab_strip_model.cc +++ b/chrome/browser/tabs/tab_strip_model.cc @@ -574,11 +574,24 @@ bool TabStripModel::IsContextMenuCommandEnabled( return delegate_->CanRestoreTab(); case CommandTogglePinned: return true; - case CommandBookmarkAllTabs: { + case CommandBookmarkAllTabs: return delegate_->CanBookmarkAllTabs(); - } + case CommandUseVerticalTabs: + return true; + default: + NOTREACHED(); + } + return false; +} + +bool TabStripModel::IsContextMenuCommandChecked(int context_index, + ContextMenuCommand command_id) const { + switch (command_id) { + case CommandUseVerticalTabs: + return delegate()->UseVerticalTabs(); default: NOTREACHED(); + break; } return false; } @@ -655,6 +668,14 @@ void TabStripModel::ExecuteContextMenuCommand( delegate_->BookmarkAllTabs(); break; } + case CommandUseVerticalTabs: { + UserMetrics::RecordAction( + UserMetricsAction("TabContextMenu_UseVerticalTabs"), + profile_); + + delegate()->ToggleUseVerticalTabs(); + break; + } default: NOTREACHED(); } diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h index 427fb6e..90b4419 100644 --- a/chrome/browser/tabs/tab_strip_model.h +++ b/chrome/browser/tabs/tab_strip_model.h @@ -223,6 +223,12 @@ class TabStripModelDelegate { // Creates a bookmark folder containing a bookmark for all open tabs. virtual void BookmarkAllTabs() = 0; + + // Returns true if the vertical tabstrip presentation should be used. + virtual bool UseVerticalTabs() const = 0; + + // Toggles the use of the vertical tabstrip. + virtual void ToggleUseVerticalTabs() = 0; }; //////////////////////////////////////////////////////////////////////////////// @@ -547,6 +553,7 @@ class TabStripModel : public NotificationObserver { CommandRestoreTab, CommandTogglePinned, CommandBookmarkAllTabs, + CommandUseVerticalTabs, CommandLast }; @@ -554,6 +561,10 @@ class TabStripModel : public NotificationObserver { bool IsContextMenuCommandEnabled(int context_index, ContextMenuCommand command_id) const; + // Returns true if the specified command is checked. + bool IsContextMenuCommandChecked(int context_index, + ContextMenuCommand command_id) const; + // Performs the action associated with the specified command for the given // TabStripModel index |context_index|. void ExecuteContextMenuCommand(int context_index, diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index 451cc81..44c56e6 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -71,6 +71,8 @@ class TabStripDummyDelegate : public TabStripModelDelegate { virtual bool CanCloseContentsAt(int index) { return can_close_ ; } virtual bool CanBookmarkAllTabs() const { return false; } virtual void BookmarkAllTabs() {} + virtual bool UseVerticalTabs() const { return false; } + virtual void ToggleUseVerticalTabs() {} private: // A dummy TabContents we give to callers that expect us to actually build a diff --git a/chrome/browser/views/frame/browser_frame.h b/chrome/browser/views/frame/browser_frame.h index fd94d51..392200d 100644 --- a/chrome/browser/views/frame/browser_frame.h +++ b/chrome/browser/views/frame/browser_frame.h @@ -41,10 +41,6 @@ class BrowserFrame { // construction. virtual views::Window* GetWindow() = 0; - // Notification that the tab strip has been created. This should let the - // BrowserRootView know about it so it can enable drag and drop. - virtual void TabStripCreated(BaseTabStrip* tabstrip) = 0; - // Determine the distance of the left edge of the minimize button from the // left edge of the window. Used in our Non-Client View's Layout. virtual int GetMinimizeButtonOffset() const = 0; @@ -74,6 +70,10 @@ class BrowserFrame { // calls this method _after_ the TabStrip has painted itself so the shadow is // rendered above the tabs. virtual void PaintTabStripShadow(gfx::Canvas* canvas) = 0; + + // Notifies the frame that the tab strip display mode changed so it can update + // its frame treatment if necessary. + virtual void TabStripDisplayModeChanged() = 0; }; #endif // CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_H_ diff --git a/chrome/browser/views/frame/browser_frame_gtk.cc b/chrome/browser/views/frame/browser_frame_gtk.cc index ef6f5a1..cb67b3b 100644 --- a/chrome/browser/views/frame/browser_frame_gtk.cc +++ b/chrome/browser/views/frame/browser_frame_gtk.cc @@ -102,9 +102,6 @@ views::Window* BrowserFrameGtk::GetWindow() { return this; } -void BrowserFrameGtk::TabStripCreated(BaseTabStrip* tabstrip) { -} - int BrowserFrameGtk::GetMinimizeButtonOffset() const { NOTIMPLEMENTED(); return 0; @@ -139,6 +136,10 @@ views::View* BrowserFrameGtk::GetFrameView() const { void BrowserFrameGtk::PaintTabStripShadow(gfx::Canvas* canvas) { } +void BrowserFrameGtk::TabStripDisplayModeChanged() { + GetRootView()->Layout(); +} + ThemeProvider* BrowserFrameGtk::GetThemeProvider() const { return profile_->GetThemeProvider(); } diff --git a/chrome/browser/views/frame/browser_frame_gtk.h b/chrome/browser/views/frame/browser_frame_gtk.h index 93330c1..f8e8f2a 100644 --- a/chrome/browser/views/frame/browser_frame_gtk.h +++ b/chrome/browser/views/frame/browser_frame_gtk.h @@ -28,7 +28,6 @@ class BrowserFrameGtk : public BrowserFrame, // Overridden from BrowserFrame: virtual views::Window* GetWindow(); - virtual void TabStripCreated(BaseTabStrip* tabstrip); virtual int GetMinimizeButtonOffset() const; virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const; virtual void UpdateThrobber(bool running); @@ -37,6 +36,7 @@ class BrowserFrameGtk : public BrowserFrame, virtual bool AlwaysUseNativeFrame() const; virtual views::View* GetFrameView() const; virtual void PaintTabStripShadow(gfx::Canvas* canvas); + virtual void TabStripDisplayModeChanged(); // Overridden from views::Widget: virtual ThemeProvider* GetThemeProvider() const; diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc index 7239b53..e0b420e 100644 --- a/chrome/browser/views/frame/browser_frame_win.cc +++ b/chrome/browser/views/frame/browser_frame_win.cc @@ -72,9 +72,6 @@ views::Window* BrowserFrameWin::GetWindow() { return this; } -void BrowserFrameWin::TabStripCreated(BaseTabStrip* tabstrip) { -} - int BrowserFrameWin::GetMinimizeButtonOffset() const { TITLEBARINFOEX titlebar_info; titlebar_info.cbSize = sizeof(TITLEBARINFOEX); @@ -133,6 +130,12 @@ void BrowserFrameWin::PaintTabStripShadow(gfx::Canvas* canvas) { browser_frame_view_->PaintTabStripShadow(canvas); } +void BrowserFrameWin::TabStripDisplayModeChanged() { + GetRootView()->Layout(); + UpdateDWMFrame(); + GetRootView()->Layout(); +} + /////////////////////////////////////////////////////////////////////////////// // BrowserFrame, views::WindowWin overrides: @@ -303,7 +306,7 @@ void BrowserFrameWin::UpdateDWMFrame() { // In maximized mode, we only have a titlebar strip of glass, no side/bottom // borders. if (!browser_view_->IsFullscreen()) { - if (browser_view_->UsingSideTabs()) { + if (browser_view_->UseVerticalTabs()) { margins.cxLeftWidth += GetBoundsForTabStrip(browser_view_->tabstrip()).right(); margins.cyTopHeight += GetSystemMetrics(SM_CYSIZEFRAME); @@ -319,7 +322,7 @@ void BrowserFrameWin::UpdateDWMFrame() { DwmExtendFrameIntoClientArea(GetNativeView(), &margins); DWORD window_style = GetWindowLong(GWL_STYLE); - if (browser_view_->UsingSideTabs()) { + if (browser_view_->UseVerticalTabs()) { if (window_style & WS_CAPTION) SetWindowLong(GWL_STYLE, window_style & ~WS_CAPTION); } else { diff --git a/chrome/browser/views/frame/browser_frame_win.h b/chrome/browser/views/frame/browser_frame_win.h index d928f93..42e8974 100644 --- a/chrome/browser/views/frame/browser_frame_win.h +++ b/chrome/browser/views/frame/browser_frame_win.h @@ -37,7 +37,6 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin { // BrowserFrame implementation. virtual views::Window* GetWindow(); - virtual void TabStripCreated(BaseTabStrip* tabstrip); virtual int GetMinimizeButtonOffset() const; virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const; virtual void UpdateThrobber(bool running); @@ -46,6 +45,7 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin { virtual bool AlwaysUseNativeFrame() const; virtual views::View* GetFrameView() const; virtual void PaintTabStripShadow(gfx::Canvas* canvas); + virtual void TabStripDisplayModeChanged(); protected: // Overridden from views::WindowWin: diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index e8ee1d9..70fcc10 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -530,8 +530,8 @@ bool BrowserView::IsTabStripVisible() const { return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP); } -bool BrowserView::UsingSideTabs() const { - return SideTabStrip::Visible(browser_->profile()); +bool BrowserView::UseVerticalTabs() const { + return browser_->tabstrip_model()->delegate()->UseVerticalTabs(); } bool BrowserView::IsOffTheRecord() const { @@ -1206,6 +1206,11 @@ void BrowserView::Paste() { false, false); } +void BrowserView::ToggleTabStripMode() { + InitTabStrip(browser_->tabstrip_model()); + frame_->TabStripDisplayModeChanged(); +} + /////////////////////////////////////////////////////////////////////////////// // BrowserView, BrowserWindowTesting implementation: @@ -1609,13 +1614,34 @@ views::LayoutManager* BrowserView::CreateLayoutManager() const { return new BrowserViewLayout; } -BaseTabStrip* BrowserView::CreateTabStrip(TabStripModel* model) { - if (UsingSideTabs()) { +void BrowserView::InitTabStrip(TabStripModel* model) { +// Throw away the existing tabstrip if we're switching display modes. + if (tabstrip_) { + tabstrip_->GetParent()->RemoveChildView(tabstrip_); + delete tabstrip_; + } + + TabStrip* tabstrip_as_tabstrip = NULL; + BrowserTabStripController* tabstrip_controller = NULL; + + if (UseVerticalTabs()) { SideTabStrip* tabstrip = new SideTabStrip; - tabstrip->SetModel(new BrowserTabStripController(model, tabstrip)); - return tabstrip; + tabstrip_controller = new BrowserTabStripController(model, tabstrip); + tabstrip->SetModel(tabstrip_controller); + tabstrip_ = tabstrip; + } else { + tabstrip_as_tabstrip = new TabStrip(model); + tabstrip_ = tabstrip_as_tabstrip; } - return new TabStrip(model); + tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP)); + if (browser_->extension_app() && tabstrip_->AsTabStrip()) + tabstrip_->AsTabStrip()->set_new_tab_button_enabled(false); + AddChildView(tabstrip_); + + if (tabstrip_controller) + tabstrip_controller->InitFromModel(); + else + tabstrip_as_tabstrip->InitFromModel(); } /////////////////////////////////////////////////////////////////////////////// @@ -1674,12 +1700,7 @@ void BrowserView::Init() { } } - tabstrip_ = CreateTabStrip(browser_->tabstrip_model()); - tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP)); - if (browser_->extension_app() && tabstrip_->AsTabStrip()) - tabstrip_->AsTabStrip()->set_new_tab_button_enabled(false); - AddChildView(tabstrip_); - frame_->TabStripCreated(tabstrip_); + InitTabStrip(browser_->tabstrip_model()); toolbar_ = new ToolbarView(browser_.get()); AddChildView(toolbar_); diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 7e52404..4e13040 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -167,7 +167,7 @@ class BrowserView : public BrowserBubbleHost, bool IsTabStripVisible() const; // Returns true if the vertical tabstrip is in use. - bool UsingSideTabs() const; + bool UseVerticalTabs() const; // Returns true if the profile associated with this Browser window is // off the record. @@ -336,6 +336,7 @@ class BrowserView : public BrowserBubbleHost, virtual void Cut(); virtual void Copy(); virtual void Paste(); + virtual void ToggleTabStripMode(); // Overridden from BrowserWindowTesting: virtual BookmarkBarView* GetBookmarkBarView() const; @@ -409,9 +410,10 @@ class BrowserView : public BrowserBubbleHost, // override to implemnet different layout pocily. virtual views::LayoutManager* CreateLayoutManager() const; - // Returns a new TabStrip for the browser view. A subclass may - // override to return a different TabStrip implementation. - virtual BaseTabStrip* CreateTabStrip(TabStripModel* tab_strip_model); + // Initializes a new TabStrip for the browser view. This can be performed + // multiple times over the life of the browser, and is run when the display + // mode for the tabstrip changes from horizontal to vertical. + void InitTabStrip(TabStripModel* tab_strip_model); // Browser window related initializations. virtual void Init(); diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc index 505a913..8f2588d 100644 --- a/chrome/browser/views/frame/browser_view_layout.cc +++ b/chrome/browser/views/frame/browser_view_layout.cc @@ -321,7 +321,7 @@ int BrowserViewLayout::LayoutTabStrip() { gfx::Rect layout_bounds = browser_view_->frame()->GetBoundsForTabStrip(tabstrip_); - if (browser_view_->UsingSideTabs()) { + if (browser_view_->UseVerticalTabs()) { vertical_layout_rect_.Inset( layout_bounds.right() - kBrowserViewTabStripHorizontalOverlap, 0, 0, 0); } else { @@ -337,18 +337,18 @@ int BrowserViewLayout::LayoutTabStrip() { layout_bounds.set_origin(tabstrip_origin); tabstrip_->SetVisible(true); tabstrip_->SetBounds(layout_bounds); - return browser_view_->UsingSideTabs() ? 0 : layout_bounds.bottom(); + return browser_view_->UseVerticalTabs() ? + layout_bounds.y() : layout_bounds.bottom(); } int BrowserViewLayout::LayoutToolbar(int top) { int browser_view_width = vertical_layout_rect_.width(); bool visible = browser_view_->IsToolbarVisible(); toolbar_->location_bar()->SetFocusable(visible); - int y = 0; - if (!browser_view_->UsingSideTabs()) { - y = top - - ((visible && browser_view_->IsTabStripVisible()) - ? kToolbarTabStripVerticalOverlap : 0); + int y = top; + if (!browser_view_->UseVerticalTabs()) { + y -= ((visible && browser_view_->IsTabStripVisible()) ? + kToolbarTabStripVerticalOverlap : 0); } int height = 0; if (visible) { diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc index 9a665f7..0026e60 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/views/frame/glass_browser_frame_view.cc @@ -77,7 +77,7 @@ GlassBrowserFrameView::~GlassBrowserFrameView() { gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( BaseTabStrip* tabstrip) const { - if (browser_view_->UsingSideTabs()) { + if (browser_view_->UseVerticalTabs()) { gfx::Size ps = tabstrip->GetPreferredSize(); return gfx::Rect(0, NonClientTopBorderHeight(), ps.width(), browser_view_->height()); @@ -114,8 +114,10 @@ void GlassBrowserFrameView::UpdateThrobber(bool running) { } void GlassBrowserFrameView::PaintTabStripShadow(gfx::Canvas* canvas) { - if (!browser_view_->UILayoutIsRightToLeft()) + if (!browser_view_->UILayoutIsRightToLeft() || + !browser_view_->UseVerticalTabs()) { return; + } ThemeProvider* tp = GetThemeProvider(); SkBitmap* shadow_top = tp->GetBitmapNamed(IDR_SIDETABS_SHADOW_TOP); @@ -237,7 +239,7 @@ int GlassBrowserFrameView::NonClientTopBorderHeight() const { // We'd like to use FrameBorderThickness() here, but the maximized Aero glass // frame has a 0 frame border around most edges and a CXSIZEFRAME-thick border // at the top (see AeroGlassFrame::OnGetMinMaxInfo()). - const int kRestoredHeight = browser_view_->UsingSideTabs() ? + const int kRestoredHeight = browser_view_->UseVerticalTabs() ? -2 : kNonClientRestoredExtraThickness; return GetSystemMetrics(SM_CXSIZEFRAME) + (browser_view_->IsMaximized() ? -kTabstripTopShadowThickness : kRestoredHeight); @@ -256,7 +258,7 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) { // Draw the toolbar background, setting src_y of the paint to the tab // strip height as the toolbar background begins at the top of the tabs. - int src_y = browser_view_->UsingSideTabs() + int src_y = browser_view_->UseVerticalTabs() ? TabRenderer::GetMinimumUnselectedSize().height() : browser_view_->GetTabStripHeight() - 1; canvas->TileImageInt(*theme_toolbar, 0, src_y, @@ -333,7 +335,7 @@ void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(); gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); - if (browser_view_->UsingSideTabs()) { + if (browser_view_->UseVerticalTabs()) { client_area_bounds.Inset( GetBoundsForTabStrip(browser_view_->tabstrip()).width() - 4, 0, 0, 0); } diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index 5014ef42..3b92e3b 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -194,9 +194,14 @@ OpaqueBrowserFrameView::~OpaqueBrowserFrameView() { gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( BaseTabStrip* tabstrip) const { - int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? - (otr_avatar_icon_->bounds().right() + kOTRSideSpacing) : - NonClientBorderThickness() + kTabStripIndent; + if (browser_view_->UseVerticalTabs()) { + // Position the tab strip slightly below the caption buttons. + // TODO(sky): adjust the 2. + int y = CaptionButtonY() + minimize_button_->GetPreferredSize().height() + + 2; + gfx::Size ps = tabstrip->GetPreferredSize(); + return gfx::Rect(0, y, ps.width(), browser_view_->height()); + } int tabstrip_y = NonClientTopBorderHeight(); if (!frame_->GetWindow()->IsMaximized() && @@ -204,6 +209,10 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( tabstrip_y += kNonClientRestoredExtraThickness; } + int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? + (otr_avatar_icon_->bounds().right() + kOTRSideSpacing) : + NonClientBorderThickness() + kTabStripIndent; + int tabstrip_width = minimize_button_->x() - tabstrip_x - (frame_->GetWindow()->IsMaximized() ? kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); @@ -247,7 +256,7 @@ gfx::Size OpaqueBrowserFrameView::GetMinimumSize() { } void OpaqueBrowserFrameView::PaintTabStripShadow(gfx::Canvas* canvas) { - // TODO(beng): SIDE tabs. + // TODO(sky): SIDE tabs. } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/views/tabs/browser_tab_strip_controller.cc index 343ee09..e828326 100644 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/views/tabs/browser_tab_strip_controller.cc @@ -5,7 +5,69 @@ #include "chrome/browser/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_menu_model.h" #include "chrome/browser/views/tabs/side_tab_strip.h" +#include "views/controls/menu/menu_2.h" +#include "views/widget/widget.h" + +class BrowserTabStripController::TabContextMenuContents + : public menus::SimpleMenuModel::Delegate { + public: + TabContextMenuContents(int tab_index, BrowserTabStripController* controller) + : ALLOW_THIS_IN_INITIALIZER_LIST( + model_(this, controller->IsTabPinned(tab_index))), + tab_index_(tab_index), + controller_(controller) { + Build(); + } + virtual ~TabContextMenuContents() { + menu_->CancelMenu(); + } + + void RunMenuAt(const gfx::Point& point) { + menu_->RunMenuAt(point, views::Menu2::ALIGN_TOPLEFT); + } + + // Overridden from menus::SimpleMenuModel::Delegate: + virtual bool IsCommandIdChecked(int command_id) const { + return controller_->IsCommandCheckedForTab( + static_cast<TabStripModel::ContextMenuCommand>(command_id), + tab_index_); + } + virtual bool IsCommandIdEnabled(int command_id) const { + return controller_->IsCommandEnabledForTab( + static_cast<TabStripModel::ContextMenuCommand>(command_id), + tab_index_); + } + virtual bool GetAcceleratorForCommandId( + int command_id, + menus::Accelerator* accelerator) { + return controller_->tabstrip_->GetWidget()->GetAccelerator(command_id, + accelerator); + } + virtual void ExecuteCommand(int command_id) { + controller_->ExecuteCommandForTab( + static_cast<TabStripModel::ContextMenuCommand>(command_id), + tab_index_); + } + + private: + void Build() { + menu_.reset(new views::Menu2(&model_)); + } + + TabMenuModel model_; + scoped_ptr<views::Menu2> menu_; + + // The index of the tab we are showing the context menu for. + int tab_index_; + + // A pointer back to our hosting controller, for command state information. + BrowserTabStripController* controller_; + + DISALLOW_COPY_AND_ASSIGN(TabContextMenuContents); +}; + //////////////////////////////////////////////////////////////////////////////// // BrowserTabStripController, public: @@ -18,6 +80,45 @@ BrowserTabStripController::BrowserTabStripController(TabStripModel* model, } BrowserTabStripController::~BrowserTabStripController() { + model_->RemoveObserver(this); +} + +void BrowserTabStripController::InitFromModel() { + // Walk the model, calling our insertion observer method for each item within + // it. + for (int i = 0; i < model_->count(); ++i) { + TabInsertedAt(model_->GetTabContentsAt(i), i, + i == model_->selected_index()); + } +} + +bool BrowserTabStripController::IsCommandEnabledForTab( + TabStripModel::ContextMenuCommand command_id, int tab_index) const { + if (model_->ContainsIndex(tab_index)) + return model_->IsContextMenuCommandEnabled(tab_index, command_id); + return false; +} + +bool BrowserTabStripController::IsCommandCheckedForTab( + TabStripModel::ContextMenuCommand command_id, int tab_index) const { + // TODO(beng): move to TabStripModel, see note in IsTabPinned. + if (command_id == TabStripModel::CommandTogglePinned) + return false; + + if (model_->ContainsIndex(tab_index)) + return model_->IsContextMenuCommandChecked(tab_index, command_id); + return false; +} + +void BrowserTabStripController::ExecuteCommandForTab( + TabStripModel::ContextMenuCommand command_id, int tab_index) { + if (model_->ContainsIndex(tab_index)) + model_->ExecuteContextMenuCommand(tab_index, command_id); +} + +bool BrowserTabStripController::IsTabPinned(int tab_index) { + return model_->ContainsIndex(tab_index) ? + model_->IsTabPinned(tab_index) : false; } //////////////////////////////////////////////////////////////////////////////// @@ -53,6 +154,12 @@ void BrowserTabStripController::CloseTab(int index) { model_->CloseTabContentsAt(index); } +void BrowserTabStripController::ShowContextMenu(int index, + const gfx::Point& p) { + context_menu_contents_.reset(new TabContextMenuContents(index, this)); + context_menu_contents_->RunMenuAt(p); +} + //////////////////////////////////////////////////////////////////////////////// // BrowserTabStripController, TabStripModelObserver implementation: diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h index e127659..f4a0295 100644 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/views/tabs/browser_tab_strip_controller.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_ #define CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_ +#include "base/scoped_ptr.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/tabs/side_tab_strip_model.h" @@ -18,6 +19,16 @@ class BrowserTabStripController : public SideTabStripModel, BrowserTabStripController(TabStripModel* model, SideTabStrip* tabstrip); virtual ~BrowserTabStripController(); + void InitFromModel(); + + bool IsCommandEnabledForTab(TabStripModel::ContextMenuCommand command_id, + int tab_index) const; + bool IsCommandCheckedForTab(TabStripModel::ContextMenuCommand command_id, + int tab_index) const; + void ExecuteCommandForTab(TabStripModel::ContextMenuCommand command_id, + int tab_index); + bool IsTabPinned(int tab_index); + // SideTabStripModel implementation: virtual SkBitmap GetIcon(int index) const; virtual string16 GetTitle(int index) const; @@ -25,6 +36,7 @@ class BrowserTabStripController : public SideTabStripModel, virtual NetworkState GetNetworkState(int index) const; virtual void SelectTab(int index); virtual void CloseTab(int index); + virtual void ShowContextMenu(int index, const gfx::Point& p); // TabStripModelObserver implementation: virtual void TabInsertedAt(TabContents* contents, int index, @@ -43,9 +55,14 @@ class BrowserTabStripController : public SideTabStripModel, virtual void TabBlockedStateChanged(TabContents* contents, int index); private: + class TabContextMenuContents; + TabStripModel* model_; SideTabStrip* tabstrip_; + // If non-NULL it means we're showing a menu for the tab. + scoped_ptr<TabContextMenuContents> context_menu_contents_; + DISALLOW_COPY_AND_ASSIGN(BrowserTabStripController); }; diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc index 9c45dd2..dfa18e1 100644 --- a/chrome/browser/views/tabs/side_tab.cc +++ b/chrome/browser/views/tabs/side_tab.cc @@ -57,6 +57,8 @@ SideTab::SideTab(SideTabModel* model) hover_animation_.reset(new SlideAnimation(this)); hover_animation_->SetSlideDuration(kHoverDurationMs); + + SetContextMenuController(this); } SideTab::~SideTab() { @@ -111,6 +113,15 @@ void SideTab::ButtonPressed(views::Button* sender, const views::Event& event) { } //////////////////////////////////////////////////////////////////////////////// +// SideTab, views::ContextMenuController implementation: + +void SideTab::ShowContextMenu(views::View* source, + const gfx::Point& p, + bool is_mouse_gesture) { + model_->ShowContextMenu(this, p); +} + +//////////////////////////////////////////////////////////////////////////////// // SideTab, views::View overrides: void SideTab::Layout() { @@ -120,14 +131,19 @@ void SideTab::Layout() { gfx::Size ps = close_button_->GetPreferredSize(); int close_y = (height() - ps.height()) / 2; - close_button_->SetBounds(width() - ps.width() - close_y, close_y, ps.width(), - ps.height()); + close_button_->SetBounds( + std::max(0, width() - ps.width() - close_y), + close_y, + ps.width(), + ps.height()); int title_y = (height() - font_->height()) / 2; int title_x = icon_bounds_.right() + kIconTitleSpacing; - title_bounds_.SetRect(title_x, title_y, - close_button_->x() - kTitleCloseSpacing - title_x, - font_->height()); + title_bounds_.SetRect( + title_x, + title_y, + std::max(0, close_button_->x() - kTitleCloseSpacing - title_x), + font_->height()); } void SideTab::Paint(gfx::Canvas* canvas) { diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h index b267d5a..7c0e9d6 100644 --- a/chrome/browser/views/tabs/side_tab.h +++ b/chrome/browser/views/tabs/side_tab.h @@ -26,9 +26,13 @@ class SideTabModel { // Closes the tab. virtual void CloseTab(SideTab* tab) = 0; + + // Shows a context menu for the tab at the specified point in screen coords. + virtual void ShowContextMenu(SideTab* tab, const gfx::Point& p) = 0; }; class SideTab : public views::View, + public views::ContextMenuController, public views::ButtonListener, public AnimationDelegate { public: @@ -48,6 +52,11 @@ class SideTab : public views::View, // views::ButtonListener implementation: virtual void ButtonPressed(views::Button* sender, const views::Event& event); + // views::ContextMenuController implementation: + virtual void ShowContextMenu(views::View* source, + const gfx::Point& p, + bool is_mouse_gesture); + // views::View Overrides: virtual void Layout(); virtual void Paint(gfx::Canvas* canvas); diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc index 7ef38d6..c7a343c 100644 --- a/chrome/browser/views/tabs/side_tab_strip.cc +++ b/chrome/browser/views/tabs/side_tab_strip.cc @@ -4,13 +4,7 @@ #include "chrome/browser/views/tabs/side_tab_strip.h" -#include "base/command_line.h" -#include "chrome/browser/pref_service.h" -#include "chrome/browser/profile.h" #include "chrome/browser/view_ids.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "gfx/canvas.h" namespace { const int kVerticalTabSpacing = 2; @@ -32,18 +26,6 @@ void SideTabStrip::SetModel(SideTabStripModel* model) { model_.reset(model); } -// static -bool SideTabStrip::Available() { - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableVerticalTabs); -} - -// static -bool SideTabStrip::Visible(Profile* profile) { - return Available() && - profile->GetPrefs()->GetBoolean(prefs::kUseVerticalTabs); -} - void SideTabStrip::AddTabAt(int index) { SideTab* tab = new SideTab(this); AddChildView(tab); @@ -88,6 +70,10 @@ void SideTabStrip::CloseTab(SideTab* tab) { model_->CloseTab(GetIndexOfSideTab(tab)); } +void SideTabStrip::ShowContextMenu(SideTab* tab, const gfx::Point& p) { + model_->ShowContextMenu(GetIndexOfSideTab(tab), p); +} + //////////////////////////////////////////////////////////////////////////////// // SideTabStrip, BaseTabStrip implementation: diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h index 71b704a..558d1a1 100644 --- a/chrome/browser/views/tabs/side_tab_strip.h +++ b/chrome/browser/views/tabs/side_tab_strip.h @@ -21,14 +21,6 @@ class SideTabStrip : public BaseTabStrip, // Associate a model with this SideTabStrip. The SideTabStrip owns its model. void SetModel(SideTabStripModel* model); - // Whether or not the browser has been run with the "enable-vertical-tabs" - // command line flag that allows the SideTabStrip to be optionally shown. - static bool Available(); - - // Whether or not the vertical tabstrip is shown. Only valid if Available() - // returns true. - static bool Visible(Profile* profile); - // Notifies the SideTabStrip that a tab was added in the model at |index|. void AddTabAt(int index); @@ -48,6 +40,7 @@ class SideTabStrip : public BaseTabStrip, virtual bool IsSelected(SideTab* tab) const; virtual void SelectTab(SideTab* tab); virtual void CloseTab(SideTab* tab); + virtual void ShowContextMenu(SideTab* tab, const gfx::Point& p); // BaseTabStrip implementation: virtual int GetPreferredHeight(); diff --git a/chrome/browser/views/tabs/side_tab_strip_model.h b/chrome/browser/views/tabs/side_tab_strip_model.h index a456c36..835e5ba 100644 --- a/chrome/browser/views/tabs/side_tab_strip_model.h +++ b/chrome/browser/views/tabs/side_tab_strip_model.h @@ -7,12 +7,17 @@ #include "base/string16.h" +namespace gfx { +class Point; +} class SkBitmap; // A model interface implemented by an object that can provide information // about SideTabs in a SideTabStrip. class SideTabStripModel { public: + virtual ~SideTabStripModel() {} + // Returns metadata about the tab at the specified index. virtual SkBitmap GetIcon(int index) const = 0; virtual string16 GetTitle(int index) const = 0; @@ -35,6 +40,10 @@ class SideTabStripModel { // Closes the tab at the specified index in the model. virtual void CloseTab(int index) = 0; + + // Shows a context menu for the tab at the specified index at the specified + // point in screen coords. + virtual void ShowContextMenu(int index, const gfx::Point& p) = 0; }; #endif // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_MODEL_H_ diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc index eb80e89..4f3989c 100644 --- a/chrome/browser/views/tabs/tab.cc +++ b/chrome/browser/views/tabs/tab.cc @@ -52,7 +52,9 @@ class Tab::TabContextMenuContents : public menus::SimpleMenuModel::Delegate { // Overridden from menus::SimpleMenuModel::Delegate: virtual bool IsCommandIdChecked(int command_id) const { - return false; + return tab_ && tab_->delegate()->IsCommandCheckedForTab( + static_cast<TabStripModel::ContextMenuCommand>(command_id), + tab_); } virtual bool IsCommandIdEnabled(int command_id) const { return tab_ && tab_->delegate()->IsCommandEnabledForTab( diff --git a/chrome/browser/views/tabs/tab.h b/chrome/browser/views/tabs/tab.h index 79b08f2..2276239 100644 --- a/chrome/browser/views/tabs/tab.h +++ b/chrome/browser/views/tabs/tab.h @@ -46,6 +46,10 @@ class Tab : public TabRenderer, virtual bool IsCommandEnabledForTab( TabStripModel::ContextMenuCommand command_id, const Tab* tab) const = 0; + // Returns true if the specified command is checked for the specified Tab. + virtual bool IsCommandCheckedForTab( + TabStripModel::ContextMenuCommand command_id, const Tab* tab) const = 0; + // Executes the specified command for the specified Tab. virtual void ExecuteCommandForTab( TabStripModel::ContextMenuCommand command_id, Tab* tab) = 0; diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index 7f31722..a6e11d3 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -265,8 +265,7 @@ TabStrip::~TabStrip() { // delete the tabs. StopAnimating(false); - // TODO(beng): (1031854) Restore this line once XPFrame/VistaFrame are dead. - // model_->RemoveObserver(this); + model_->RemoveObserver(this); // TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug. drag_controller_.reset(NULL); @@ -341,6 +340,15 @@ gfx::Rect TabStrip::GetNewTabButtonBounds() { return newtab_button_->bounds(); } +void TabStrip::InitFromModel() { + // Walk the model, calling our insertion observer method for each item within + // it. + for (int i = 0; i < model_->count(); ++i) { + TabInsertedAt(model_->GetTabContentsAt(i), i, + i == model_->selected_index()); + } +} + //////////////////////////////////////////////////////////////////////////////// // TabStrip, BaseTabStrip implementation: @@ -866,6 +874,14 @@ bool TabStrip::IsCommandEnabledForTab( return false; } +bool TabStrip::IsCommandCheckedForTab( + TabStripModel::ContextMenuCommand command_id, const Tab* tab) const { + int model_index = GetModelIndexOfTab(tab); + if (model_->ContainsIndex(model_index)) + return model_->IsContextMenuCommandChecked(model_index, command_id); + return false; +} + void TabStrip::ExecuteCommandForTab( TabStripModel::ContextMenuCommand command_id, Tab* tab) { int model_index = GetModelIndexOfTab(tab); diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index 95ccfdb..8752bf1 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -95,6 +95,11 @@ class TabStrip : public BaseTabStrip, // Returns the bounds of the new tab button. gfx::Rect GetNewTabButtonBounds(); + // Populates the BaseTabStrip implementation from its model. This is primarily + // useful when switching between display types and there are existing tabs. + // Upon initial creation the TabStrip is empty. + void InitFromModel(); + // BaseTabStrip implementation: virtual int GetPreferredHeight(); virtual void SetBackgroundOffset(const gfx::Point& offset); @@ -161,6 +166,8 @@ class TabStrip : public BaseTabStrip, virtual void CloseTab(Tab* tab); virtual bool IsCommandEnabledForTab( TabStripModel::ContextMenuCommand command_id, const Tab* tab) const; + virtual bool IsCommandCheckedForTab( + TabStripModel::ContextMenuCommand command_id, const Tab* tab) const; virtual void ExecuteCommandForTab( TabStripModel::ContextMenuCommand command_id, Tab* tab); virtual void StartHighlightTabsForCommand( diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index eb9c51aa..d2463a5 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -629,7 +629,8 @@ class NotificationType { // the profile. No details are provided. WEB_APP_INSTALL_CHANGED, - // This is sent to a pref observer when a pref is changed. + // This is sent to a pref observer when a pref is changed. The source is the + // PrefService and the details a std::wstring of the changed path. PREF_CHANGED, // Sent when a default request context has been created, so calling diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index 9f384f6..701ccf0 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -100,6 +100,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void Cut() { } virtual void Copy() { } virtual void Paste() { } + virtual void ToggleTabStripMode() {} protected: virtual void DestroyBrowser() {} |