diff options
author | stevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-10 19:28:50 +0000 |
---|---|---|
committer | stevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-10 19:28:50 +0000 |
commit | b584fb90f233ce696c9e1f26a306e4e13af78a56 (patch) | |
tree | b375031588f8ab04eca6707227774901bac33674 | |
parent | 08873a8668f8ec74d3f7ccb7f64971b11d57176c (diff) | |
download | chromium_src-b584fb90f233ce696c9e1f26a306e4e13af78a56.zip chromium_src-b584fb90f233ce696c9e1f26a306e4e13af78a56.tar.gz chromium_src-b584fb90f233ce696c9e1f26a306e4e13af78a56.tar.bz2 |
The initial prototype code for the compact navigation (cnav) prototype, currently only active in windows. This is well hidden behind a flag and a context menu option.
Loosely based off oshima's original prototype patch: http://codereview.chromium.org/165272
BUG=None
TEST=Activate the cnav prototype in about:flags. Right click a tab and select "Hide Toolbar" to go into cnav mode. Ensure that the compact location bar provides the same basic functionality as the toolbar (except browser actions).
Review URL: http://codereview.chromium.org/6913026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84831 0039d316-1c4b-4281-b951-d872f2087c98
67 files changed, 2454 insertions, 197 deletions
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index b269d83..a9cabbf 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h @@ -53,6 +53,7 @@ #define IDC_TOGGLE_VERTICAL_TABS 34034 #define IDC_SEARCH 34035 #define IDC_TABPOSE 34036 +#define IDC_COMPACT_NAVBAR 34037 // Page-related commands #define IDC_BOOKMARK_PAGE 35000 diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b946546..c636d04 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4198,6 +4198,15 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_FLAGS_DISABLE_INTERACTIVE_FORM_VALIDATION_DESCRIPTION" desc="Description of the 'Disable HTML5 interactive form validation' lab."> Disable showing validation messages and preventing form submission. </message> + <message name="IDS_FLAGS_ENABLE_COMPACT_NAVIGATION" desc="Name of the 'Compact Navigation' lab."> + Compact Navigation + </message> + <message name="IDS_FLAGS_ENABLE_COMPACT_NAVIGATION_DESCRIPTION" desc="Description of the 'Compact Navigation' lab."> + Adds a "Hide the toolbar" entry to the tabstrip's context menu. Use this to toggle between always displaying the toolbar (default) and only opening it as a drop down box as needed. + </message> + <message name="IDS_COMPACT_NAVIGATION_BAR" desc="The menu item on the app menu to toggle compact navigation bar"> + Compact Navigation Bar + </message> <message name="IDS_FLAGS_ENABLE_HISTORY_QUICK_PROVIDER" desc="Name of the 'Enable better visit history matching in the omnibox' lab."> Better omnibox history matching </message> @@ -5699,6 +5708,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_USE_VERTICAL_TABS" desc="Use the vertical tab strip"> Use side tabs </message> + <message name="IDS_TAB_CXMENU_USE_COMPACT_NAVIGATION_BAR" desc="Hide the toolbar so that we use the compact navigation bar instead"> + Hide the toolbar + </message> <message name="IDS_TAB_CXMENU_SELECT_BY_DOMAIN" desc="The label of the tab context menu item for selecting tabs with the same domain"> Select by domain </message> @@ -5746,6 +5758,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_USE_VERTICAL_TABS" desc="In Title Case: Use the vertical tab strip"> Use Side Tabs </message> + <message name="IDS_TAB_CXMENU_USE_COMPACT_NAVIGATION_BAR" desc="In Title Case: Hide the toolbar so that we use the compact navigation bar instead"> + Hide The Toolbar + </message> <message name="IDS_TAB_CXMENU_SELECT_BY_DOMAIN" desc="The label of the tab context menu item for selecting tabs with the same domain"> Select by Domain </message> diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 4696db8..cee7dec 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -38,6 +38,12 @@ <include name="IDR_BOOKMARK_BAR_FOLDER" file="bookmark_bar_folder_mac.png" type="BINDATA" /> </if> <include name="IDR_CLOSE_BUTTON_MASK" file="close_button_mask.png" type="BINDATA" /> + <include name="IDR_CNAV_DIALOG_LEFT" file="cnav_dialog_left.png" type="BINDATA" /> + <include name="IDR_CNAV_DIALOG_MIDDLE" file="cnav_dialog_middle.png" type="BINDATA" /> + <include name="IDR_CNAV_DIALOG_RIGHT" file="cnav_dialog_right.png" type="BINDATA" /> + <include name="IDR_COMPACTNAV_BACK" file="compactnav_back.png" type="BINDATA" /> + <include name="IDR_COMPACTNAV_FORWARD" file="compactnav_forward.png" type="BINDATA" /> + <include name="IDR_COMPACTNAV_SEPARATOR" file="compactnav_separator.png" type="BINDATA" /> <if expr="os.find('win') != -1"> <include name="IDR_CONFLICT_BADGE" file="conflict_badge.png" type="BINDATA" /> <include name="IDR_CONFLICT_MENU" file="conflict_menu.png" type="BINDATA" /> diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 7cd7eee..dce9ec2 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -249,6 +249,13 @@ const Experiment kExperiments[] = { SINGLE_VALUE_TYPE(switches::kFocusExistingTabOnOpen) }, { + "compact-navigation", + IDS_FLAGS_ENABLE_COMPACT_NAVIGATION, + IDS_FLAGS_ENABLE_COMPACT_NAVIGATION_DESCRIPTION, + kOsWin, // TODO(stevet): Add other platforms when ready. + SINGLE_VALUE_TYPE(switches::kEnableCompactNavigation) + }, + { "new-tab-page-4", IDS_FLAGS_NEW_TAB_PAGE_4_NAME, IDS_FLAGS_NEW_TAB_PAGE_4_DESCRIPTION, diff --git a/chrome/browser/tabs/default_tab_handler.cc b/chrome/browser/tabs/default_tab_handler.cc index b81f0a2..1524852 100644 --- a/chrome/browser/tabs/default_tab_handler.cc +++ b/chrome/browser/tabs/default_tab_handler.cc @@ -115,6 +115,10 @@ void DefaultTabHandler::ToggleUseVerticalTabs() { delegate_->AsBrowser()->ToggleUseVerticalTabs(); } +void DefaultTabHandler::ToggleUseCompactNavigationBar() { + delegate_->AsBrowser()->ToggleUseCompactNavigationBar(); +} + bool DefaultTabHandler::CanRestoreTab() { return delegate_->AsBrowser()->CanRestoreTab(); } @@ -131,6 +135,10 @@ bool DefaultTabHandler::UseVerticalTabs() const { return delegate_->AsBrowser()->UseVerticalTabs(); } +bool DefaultTabHandler::UseCompactNavigationBar() const { + return delegate_->AsBrowser()->UseCompactNavigationBar(); +} + //////////////////////////////////////////////////////////////////////////////// // DefaultTabHandler, TabStripModelObserver implementation: diff --git a/chrome/browser/tabs/default_tab_handler.h b/chrome/browser/tabs/default_tab_handler.h index 09f779a..f59dd25 100644 --- a/chrome/browser/tabs/default_tab_handler.h +++ b/chrome/browser/tabs/default_tab_handler.h @@ -52,10 +52,12 @@ class DefaultTabHandler : public TabHandler, virtual void BookmarkAllTabs(); virtual bool CanCloseTab() const; virtual void ToggleUseVerticalTabs(); + virtual void ToggleUseCompactNavigationBar(); virtual bool CanRestoreTab(); virtual void RestoreTab(); virtual bool LargeIconsPermitted() const; virtual bool UseVerticalTabs() const; + virtual bool UseCompactNavigationBar() const; // Overridden from TabStripModelObserver: virtual void TabInsertedAt(TabContentsWrapper* contents, diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc index fa632af..d1ded2f 100644 --- a/chrome/browser/tabs/tab_strip_model.cc +++ b/chrome/browser/tabs/tab_strip_model.cc @@ -711,6 +711,10 @@ void TabStripModel::MoveTabPrevious() { MoveTabContentsAt(active_index(), new_index, true); } +void TabStripModel::ActiveTabClicked(int index) { + FOR_EACH_OBSERVER(TabStripModelObserver, observers_, ActiveTabClicked(index)); +} + // Context menu functions. bool TabStripModel::IsContextMenuCommandEnabled( int context_index, ContextMenuCommand command_id) const { @@ -764,6 +768,7 @@ bool TabStripModel::IsContextMenuCommandEnabled( delegate_->CanBookmarkAllTabs(); case CommandUseVerticalTabs: + case CommandUseCompactNavigationBar: return true; case CommandSelectByDomain: @@ -782,6 +787,8 @@ bool TabStripModel::IsContextMenuCommandChecked( switch (command_id) { case CommandUseVerticalTabs: return delegate()->UseVerticalTabs(); + case CommandUseCompactNavigationBar: + return delegate()->UseCompactNavigationBar(); default: NOTREACHED(); break; @@ -904,6 +911,14 @@ void TabStripModel::ExecuteContextMenuCommand( break; } + case CommandUseCompactNavigationBar: { + UserMetrics::RecordAction( + UserMetricsAction("TabContextMenu_CompactNavigationBar")); + + delegate()->ToggleUseCompactNavigationBar(); + break; + } + case CommandSelectByDomain: case CommandSelectByOpener: { std::vector<int> indices; @@ -1029,6 +1044,9 @@ bool TabStripModel::ContextMenuCommandToBrowserCommand(int cmd_id, case CommandUseVerticalTabs: *browser_cmd = IDC_TOGGLE_VERTICAL_TABS; break; + case CommandUseCompactNavigationBar: + *browser_cmd = IDC_COMPACT_NAVBAR; + break; default: *browser_cmd = 0; return false; diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h index f236e5f..c0d1e0b 100644 --- a/chrome/browser/tabs/tab_strip_model.h +++ b/chrome/browser/tabs/tab_strip_model.h @@ -411,6 +411,10 @@ class TabStripModel : public NotificationObserver { void MoveTabNext(); void MoveTabPrevious(); + // Notifies the observers that the active/foreground tab at |index| was + // reselected (ie - it was already active and was clicked again). + void ActiveTabClicked(int index); + // View API ////////////////////////////////////////////////////////////////// // Context menu functions. @@ -426,6 +430,7 @@ class TabStripModel : public NotificationObserver { CommandTogglePinned, CommandBookmarkAllTabs, CommandUseVerticalTabs, + CommandUseCompactNavigationBar, CommandSelectByDomain, CommandSelectByOpener, CommandLast diff --git a/chrome/browser/tabs/tab_strip_model_delegate.h b/chrome/browser/tabs/tab_strip_model_delegate.h index bae327e..0279e84 100644 --- a/chrome/browser/tabs/tab_strip_model_delegate.h +++ b/chrome/browser/tabs/tab_strip_model_delegate.h @@ -118,6 +118,12 @@ class TabStripModelDelegate { // Toggles the use of the vertical tabstrip. virtual void ToggleUseVerticalTabs() = 0; + // Returns true if the compact navigation bar should be used. + virtual bool UseCompactNavigationBar() const = 0; + + // Toggles the use of the compact navigation bar. + virtual void ToggleUseCompactNavigationBar() = 0; + // Returns true if the tab strip can use large icons. virtual bool LargeIconsPermitted() const = 0; diff --git a/chrome/browser/tabs/tab_strip_model_observer.cc b/chrome/browser/tabs/tab_strip_model_observer.cc index f20746a..0f5395b 100644 --- a/chrome/browser/tabs/tab_strip_model_observer.cc +++ b/chrome/browser/tabs/tab_strip_model_observer.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -58,3 +58,5 @@ void TabStripModelObserver::TabBlockedStateChanged(TabContentsWrapper* contents, void TabStripModelObserver::TabStripEmpty() {} void TabStripModelObserver::TabStripModelDeleted() {} + +void TabStripModelObserver::ActiveTabClicked(int index) {} diff --git a/chrome/browser/tabs/tab_strip_model_observer.h b/chrome/browser/tabs/tab_strip_model_observer.h index af169ea..ba9df25 100644 --- a/chrome/browser/tabs/tab_strip_model_observer.h +++ b/chrome/browser/tabs/tab_strip_model_observer.h @@ -127,6 +127,10 @@ class TabStripModelObserver { // must be dropped. virtual void TabStripModelDeleted(); + // Invoked when an active/selected tab at |index| is selected again (ie - the + // active/foreground tab is clicked). + virtual void ActiveTabClicked(int index); + protected: virtual ~TabStripModelObserver() {} }; diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index 4876c81..fc1c941 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -130,6 +130,8 @@ class TabStripDummyDelegate : public TabStripModelDelegate { virtual bool CanCloseTab() const { return true; } virtual bool UseVerticalTabs() const { return false; } virtual void ToggleUseVerticalTabs() {} + virtual bool UseCompactNavigationBar() const { return false; } + virtual void ToggleUseCompactNavigationBar() {} virtual bool LargeIconsPermitted() const { return true; } private: diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 74acb11..ab07046 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -264,12 +264,22 @@ Browser::Browser(Type type, Profile* profile) encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector, profile_->GetPrefs(), NULL); use_vertical_tabs_.Init(prefs::kUseVerticalTabs, profile_->GetPrefs(), this); + use_compact_navigation_bar_.Init(prefs::kUseCompactNavigationBar, + 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); } + if (!TabMenuModel::IsCompactNavigationModeEnabled()) { + // If the compact navigation bar isn't enabled, explicitly turn it off. + // Otherwise we might show the compact navigation bar but not show an option + // to turn it off. + use_compact_navigation_bar_.SetValue(false); + } + UpdateTabStripModelInsertionPolicy(); tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile); @@ -328,6 +338,7 @@ Browser::~Browser() { encoding_auto_detect_.Destroy(); use_vertical_tabs_.Destroy(); + use_compact_navigation_bar_.Destroy(); if (profile_->IsOffTheRecord() && !BrowserList::IsOffTheRecordSessionActive()) { @@ -427,6 +438,11 @@ void Browser::InitBrowserWindow() { Source<Browser>(this), NotificationService::NoDetails()); + if (use_compact_navigation_bar_.GetValue()) { + // This enables the compact navigation bar host. + UseCompactNavigationBarChanged(); + } + // Show the First Run information bubble if we've been told to. PrefService* local_state = g_browser_process->local_state(); if (!local_state) @@ -1216,6 +1232,7 @@ void Browser::UpdateCommandsForFullscreenMode(bool is_fullscreen) { command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui); command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui); command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, show_main_ui); + command_updater_.UpdateCommandEnabled(IDC_COMPACT_NAVBAR, show_main_ui); #if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC) command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui); #endif @@ -1253,6 +1270,10 @@ void Browser::UseVerticalTabsChanged() { window()->ToggleTabStripMode(); } +void Browser::UseCompactNavigationBarChanged() { + window_->ToggleUseCompactNavigationBar(); +} + bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, bool check_fullscreen) const { // On Mac, fullscreen mode has most normal things (in a slide-down panel). On @@ -2150,6 +2171,9 @@ void Browser::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, false, PrefService::UNSYNCABLE_PREF); + prefs->RegisterBooleanPref(prefs::kUseCompactNavigationBar, + false, + PrefService::UNSYNCABLE_PREF); prefs->RegisterBooleanPref(prefs::kEnableTranslate, true, PrefService::SYNCABLE_PREF); @@ -2299,6 +2323,7 @@ void Browser::ExecuteCommandWithDisposition( case IDC_FULLSCREEN: ToggleFullscreenMode(); break; case IDC_EXIT: Exit(); break; case IDC_TOGGLE_VERTICAL_TABS: ToggleUseVerticalTabs(); break; + case IDC_COMPACT_NAVBAR: ToggleUseCompactNavigationBar(); break; #if defined(OS_CHROMEOS) case IDC_SEARCH: Search(); break; case IDC_SHOW_KEYBOARD_OVERLAY: ShowKeyboardOverlay(); break; @@ -2774,6 +2799,11 @@ void Browser::ToggleUseVerticalTabs() { UseVerticalTabsChanged(); } +void Browser::ToggleUseCompactNavigationBar() { + use_compact_navigation_bar_.SetValue(!UseCompactNavigationBar()); + UseCompactNavigationBarChanged(); +} + bool Browser::LargeIconsPermitted() const { // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because // for those windows, we already have a big icon in the top-left outside any @@ -3158,6 +3188,10 @@ bool Browser::UseVerticalTabs() const { return use_vertical_tabs_.GetValue(); } +bool Browser::UseCompactNavigationBar() const { + return use_compact_navigation_bar_.GetValue(); +} + void Browser::ContentsZoomChange(bool zoom_in) { ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS); } @@ -3555,6 +3589,8 @@ void Browser::Observe(NotificationType type, const std::string& pref_name = *Details<std::string>(details).ptr(); if (pref_name == prefs::kUseVerticalTabs) { UseVerticalTabsChanged(); + } else if (pref_name == prefs::kUseCompactNavigationBar) { + UseCompactNavigationBarChanged(); } else if (pref_name == prefs::kPrintingEnabled) { UpdatePrintingState(GetContentRestrictionsForSelectedTab()); } else if (pref_name == prefs::kInstantEnabled) { diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index a112030..79b1461d 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -485,7 +485,6 @@ class Browser : public TabHandlerDelegate, void ToggleFullscreenMode(); void Exit(); #if defined(OS_CHROMEOS) - void ToggleCompactNavigationBar(); void Search(); void ShowKeyboardOverlay(); #endif @@ -583,6 +582,7 @@ class Browser : public TabHandlerDelegate, // Overridden from TabStripModelDelegate: virtual bool UseVerticalTabs() const; + virtual bool UseCompactNavigationBar() const; ///////////////////////////////////////////////////////////////////////////// @@ -704,6 +704,7 @@ class Browser : public TabHandlerDelegate, virtual void BookmarkAllTabs(); virtual bool CanCloseTab() const; virtual void ToggleUseVerticalTabs(); + virtual void ToggleUseCompactNavigationBar(); virtual bool CanRestoreTab(); virtual void RestoreTab(); virtual bool LargeIconsPermitted() const; @@ -1029,6 +1030,10 @@ class Browser : public TabHandlerDelegate, // policy of the tab strip model and notifies the window. void UseVerticalTabsChanged(); + // Invoked when the use of the compact navigation bar preference changes. + // Notifies the window. + void UseCompactNavigationBarChanged(); + // Implementation of SupportsWindowFeature and CanSupportWindowFeature. If // |check_fullscreen| is true, the set of features reflect the actual state of // the browser, otherwise the set of features reflect the possible state of @@ -1192,6 +1197,9 @@ class Browser : public TabHandlerDelegate, // Tracks the display mode of the tabstrip. mutable BooleanPrefMember use_vertical_tabs_; + // Tracks the display mode of the navigation bar. + mutable BooleanPrefMember use_compact_navigation_bar_; + // The profile's tab restore service. The service is owned by the profile, // and we install ourselves as an observer. TabRestoreService* tab_restore_service_; diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index ec2f091..8bb212d 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h @@ -299,6 +299,9 @@ class BrowserWindow { virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, const Extension* app) = 0; + // Toggles compact navigation bar. + virtual void ToggleUseCompactNavigationBar() = 0; + // Clipboard commands applied to the whole browser window. virtual void Cut() = 0; virtual void Copy() = 0; diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index 50063c68..3d6a5f5 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -104,6 +104,7 @@ class BrowserWindowCocoa : public BrowserWindow, virtual void Copy(); virtual void Paste(); virtual void ToggleTabStripMode(); + virtual void ToggleUseCompactNavigationBar() {} virtual void OpenTabpose(); virtual void PrepareForInstant(); virtual void ShowInstant(TabContentsWrapper* preview); diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm index 59c7757..011a4f6 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm @@ -92,6 +92,10 @@ class TestTabStripDelegate : public TabStripModelDelegate { virtual void ToggleUseVerticalTabs() {} + virtual bool UseCompactNavigationBar() const { return false; } + + virtual void ToggleUseCompactNavigationBar() {} + virtual bool LargeIconsPermitted() const { return true; } }; diff --git a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm index 8d10b4c..959c4e6 100644 --- a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm +++ b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -72,7 +72,10 @@ class ViewIDTest : public InProcessBrowserTest { i == VIEW_ID_AUTOCOMPLETE || i == VIEW_ID_CONTENTS_SPLIT || i == VIEW_ID_SIDE_BAR_SPLIT || - i == VIEW_ID_FEEDBACK_BUTTON) { + i == VIEW_ID_FEEDBACK_BUTTON || + i == VIEW_ID_COMPACT_NAV_BAR || + i == VIEW_ID_COMPACT_OPT_BAR || + i == VIEW_ID_COMPACT_NAV_BAR_SPACER) { continue; } diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc index 36bc6fa..0e1d842 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.cc +++ b/chrome/browser/ui/gtk/browser_window_gtk.cc @@ -1088,6 +1088,12 @@ void BrowserWindowGtk::Paste() { gtk_util::DoPaste(this); } +void BrowserWindowGtk::ToggleTabStripMode() { +} + +void BrowserWindowGtk::ToggleUseCompactNavigationBar() { +} + void BrowserWindowGtk::PrepareForInstant() { TabContentsWrapper* contents = contents_container_->tab(); if (contents) diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h index 44ef7f0..537584b 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.h +++ b/chrome/browser/ui/gtk/browser_window_gtk.h @@ -127,7 +127,8 @@ class BrowserWindowGtk : public BrowserWindow, virtual void Cut(); virtual void Copy(); virtual void Paste(); - virtual void ToggleTabStripMode() {} + virtual void ToggleTabStripMode(); + virtual void ToggleUseCompactNavigationBar(); virtual void PrepareForInstant(); virtual void ShowInstant(TabContentsWrapper* preview); virtual void HideInstant(bool instant_is_active); diff --git a/chrome/browser/ui/gtk/view_id_util_browsertest.cc b/chrome/browser/ui/gtk/view_id_util_browsertest.cc index 64b9389..83ec15f 100644 --- a/chrome/browser/ui/gtk/view_id_util_browsertest.cc +++ b/chrome/browser/ui/gtk/view_id_util_browsertest.cc @@ -41,7 +41,10 @@ IN_PROC_BROWSER_TEST_F(ViewIDTest, Basic) { i == VIEW_ID_TAB || i == VIEW_ID_SIDE_BAR_CONTAINER || i == VIEW_ID_SIDE_BAR_SPLIT || - i == VIEW_ID_FEEDBACK_BUTTON) { + i == VIEW_ID_FEEDBACK_BUTTON || + i == VIEW_ID_COMPACT_NAV_BAR || + i == VIEW_ID_COMPACT_OPT_BAR || + i == VIEW_ID_COMPACT_NAV_BAR_SPACER) { continue; } diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc index b8b5897..9b433a3 100644 --- a/chrome/browser/ui/panels/panel.cc +++ b/chrome/browser/ui/panels/panel.cc @@ -307,6 +307,10 @@ void Panel::ShowCreateChromeAppShortcutsDialog(Profile* profile, NOTIMPLEMENTED(); } +void Panel::ToggleUseCompactNavigationBar() { + NOTIMPLEMENTED(); +} + void Panel::Cut() { NOTIMPLEMENTED(); } diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h index 1e997ca..4fe4480 100644 --- a/chrome/browser/ui/panels/panel.h +++ b/chrome/browser/ui/panels/panel.h @@ -111,6 +111,7 @@ class Panel : public BrowserWindow { TabContentsWrapper* tab_contents) OVERRIDE; virtual void ShowCreateChromeAppShortcutsDialog( Profile* profile, const Extension* app) OVERRIDE; + virtual void ToggleUseCompactNavigationBar(); virtual void Cut() OVERRIDE; virtual void Copy() OVERRIDE; virtual void Paste() OVERRIDE; diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.h b/chrome/browser/ui/panels/panel_browser_window_cocoa.h index e9e4484..3ccc106 100644 --- a/chrome/browser/ui/panels/panel_browser_window_cocoa.h +++ b/chrome/browser/ui/panels/panel_browser_window_cocoa.h @@ -97,6 +97,7 @@ class PanelBrowserWindowCocoa : public BrowserWindow { virtual void Copy() OVERRIDE; virtual void Paste() OVERRIDE; virtual void ToggleTabStripMode() OVERRIDE; + virtual void ToggleUseCompactNavigationBar() OVERRIDE; virtual void OpenTabpose() OVERRIDE; virtual void PrepareForInstant() OVERRIDE; virtual void ShowInstant(TabContentsWrapper* preview) OVERRIDE; diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm index fe8e7b8..58a019d 100644 --- a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm +++ b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm @@ -334,6 +334,10 @@ void PanelBrowserWindowCocoa::ToggleTabStripMode() { NOTIMPLEMENTED(); } +void PanelBrowserWindowCocoa::ToggleUseCompactNavigationBar() { + NOTIMPLEMENTED(); +} + #if defined(OS_MACOSX) void PanelBrowserWindowCocoa::OpenTabpose() { NOTIMPLEMENTED(); diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index 28b58f5..4e89731 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc @@ -32,6 +32,16 @@ bool TabMenuModel::AreVerticalTabsEnabled() { #endif } +bool TabMenuModel::IsCompactNavigationModeEnabled() { +#if defined(TOOLKIT_VIEWS) + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableCompactNavigation); +#else + return false; +#endif +} + + void TabMenuModel::Build(bool is_pinned) { AddItemWithStringId(TabStripModel::CommandNewTab, IDS_TAB_CXMENU_NEWTAB); AddSeparator(); @@ -52,10 +62,16 @@ void TabMenuModel::Build(bool is_pinned) { AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB); AddItemWithStringId(TabStripModel::CommandBookmarkAllTabs, IDS_TAB_CXMENU_BOOKMARK_ALL_TABS); - if (AreVerticalTabsEnabled()) { + if (AreVerticalTabsEnabled() || IsCompactNavigationModeEnabled()) { AddSeparator(); - AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs, - IDS_TAB_CXMENU_USE_VERTICAL_TABS); + if (AreVerticalTabsEnabled()) { + AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs, + IDS_TAB_CXMENU_USE_VERTICAL_TABS); + } + if (IsCompactNavigationModeEnabled()) { + AddCheckItemWithStringId(TabStripModel::CommandUseCompactNavigationBar, + IDS_TAB_CXMENU_USE_COMPACT_NAVIGATION_BAR); + } } } @@ -94,10 +110,16 @@ void TabMenuModel::Build(TabStripModel* tab_strip, int index) { AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB); AddItemWithStringId(TabStripModel::CommandBookmarkAllTabs, IDS_TAB_CXMENU_BOOKMARK_ALL_TABS); - if (AreVerticalTabsEnabled()) { + if (AreVerticalTabsEnabled() || IsCompactNavigationModeEnabled()) { AddSeparator(); - AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs, - IDS_TAB_CXMENU_USE_VERTICAL_TABS); + if (AreVerticalTabsEnabled()) { + AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs, + IDS_TAB_CXMENU_USE_VERTICAL_TABS); + } + if (IsCompactNavigationModeEnabled()) { + AddCheckItemWithStringId(TabStripModel::CommandUseCompactNavigationBar, + IDS_TAB_CXMENU_USE_COMPACT_NAVIGATION_BAR); + } } if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableTabGroupsContextMenu)) { diff --git a/chrome/browser/ui/tabs/tab_menu_model.h b/chrome/browser/ui/tabs/tab_menu_model.h index 7d4d952..234a201 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.h +++ b/chrome/browser/ui/tabs/tab_menu_model.h @@ -25,6 +25,9 @@ class TabMenuModel : public ui::SimpleMenuModel { // Returns true if vertical tabs are enabled. static bool AreVerticalTabsEnabled(); + // Returns true if compact navigation bar is enabled. + static bool IsCompactNavigationModeEnabled(); + private: // TODO: nuke this when first constructor is removed. void Build(bool is_pinned); diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h index 3df052d..e7199fe 100644 --- a/chrome/browser/ui/view_ids.h +++ b/chrome/browser/ui/view_ids.h @@ -78,6 +78,15 @@ enum ViewID { // The sidebar split. VIEW_ID_SIDE_BAR_SPLIT, + // The Compact Navigation bar. + VIEW_ID_COMPACT_NAV_BAR, + + // The Compact Options bar. + VIEW_ID_COMPACT_OPT_BAR, + + // The spacer for the compact navigation bar. + VIEW_ID_COMPACT_NAV_BAR_SPACER, + // Used in chrome/browser/ui/gtk/view_id_util_browsertests.cc // If you add new ids, make sure the above test passes. VIEW_ID_PREDEFINED_COUNT diff --git a/chrome/browser/ui/views/compact_nav/compact_location_bar_view.cc b/chrome/browser/ui/views/compact_nav/compact_location_bar_view.cc new file mode 100644 index 0000000..f4c0d18 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_location_bar_view.cc @@ -0,0 +1,332 @@ +// Copyright (c) 2011 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/ui/views/compact_nav/compact_location_bar_view.h" + +#if defined(TOOLKIT_USES_GTK) +#include <gtk/gtk.h> +#endif + +#include <algorithm> + +#include "chrome/app/chrome_command_ids.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/favicon/favicon_tab_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h" +#include "chrome/browser/ui/views/event_utils.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/browser/ui/views/reload_button.h" +#include "content/browser/user_metrics.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "grit/theme_resources_standard.h" +#include "ui/base/accessibility/accessible_view_state.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/theme_provider.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/point.h" +#include "views/background.h" +#include "views/controls/button/image_button.h" +#include "views/controls/native/native_view_host.h" +#include "views/widget/widget.h" +#include "views/window/window.h" + +namespace { + +const int kDefaultLocationEntryWidth = 375; +const int kCompactLocationLeftMargin = 7; +const int kCompactLocationRightMargin = 8; +const int kEntryPadding = 2; +// TODO(oshima): ToolbarView gets this from background image's height; +// Find out the right way, value for compact location bar. +const int kDefaultLocationBarHeight = 34; + +} // namespace + +CompactLocationBarView::CompactLocationBarView(CompactLocationBarViewHost* host) + : DropdownBarView(host), + reload_button_(NULL), + location_bar_view_(NULL), + initialized_(false) { + SetFocusable(true); +} + +CompactLocationBarView::~CompactLocationBarView() { +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarView public: + +void CompactLocationBarView::SetFocusAndSelection(bool select_all) { + location_bar_view_->FocusLocation(select_all); +} + +void CompactLocationBarView::Update(const TabContents* contents) { + location_bar_view_->Update(contents); +} + +//////////////////////////////////////////////////////////////////////////////// +// AccessiblePaneView overrides: + +bool CompactLocationBarView::SetPaneFocus( + int view_storage_id, views::View* initial_focus) { + if (!AccessiblePaneView::SetPaneFocus(view_storage_id, initial_focus)) + return false; + + location_bar_view_->SetShowFocusRect(true); + return true; +} + +void CompactLocationBarView::GetAccessibleState( + ui::AccessibleViewState* state) { + state->role = ui::AccessibilityTypes::ROLE_TOOLBAR; + state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_TOOLBAR); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarView private: + +Browser* CompactLocationBarView::browser() const { + return host()->browser_view()->browser(); +} + +void CompactLocationBarView::Init() { + DCHECK(!initialized_); + initialized_ = true; + + // Use a larger version of the system font. + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + font_ = rb.GetFont(ResourceBundle::MediumFont); + + // Location bar. + location_bar_view_ = new LocationBarView( + browser()->profile(), + browser()->command_updater(), + browser()->toolbar_model(), + clb_host(), + LocationBarView::NORMAL); + + // Reload button. + reload_button_ = new ReloadButton(location_bar_view_, browser()); + reload_button_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN | + ui::EF_MIDDLE_BUTTON_DOWN); + reload_button_->set_tag(IDC_RELOAD); + reload_button_->SetTooltipText( + UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_RELOAD))); + reload_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD)); + reload_button_->SetID(VIEW_ID_RELOAD_BUTTON); + + ThemeProvider* tp = GetThemeProvider(); + reload_button_->SetImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_RELOAD)); + reload_button_->SetImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_RELOAD_H)); + reload_button_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_RELOAD_P)); + reload_button_->SetToggledImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_STOP)); + reload_button_->SetToggledImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_STOP_H)); + reload_button_->SetToggledImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_STOP_P)); + reload_button_->SetToggledImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_STOP_D)); + + // Always add children in order from left to right, for accessibility. + AddChildView(reload_button_); + AddChildView(location_bar_view_); + location_bar_view_->Init(); + + SetDialogBorderBitmaps(rb.GetBitmapNamed(IDR_CNAV_DIALOG_LEFT), + rb.GetBitmapNamed(IDR_CNAV_DIALOG_MIDDLE), + rb.GetBitmapNamed(IDR_CNAV_DIALOG_RIGHT)); +} + +//////////////////////////////////////////////////////////////////////////////// +// views::View overrides: + +gfx::Size CompactLocationBarView::GetPreferredSize() { + if (!reload_button_) + return gfx::Size(); // Not initialized yet, do nothing. + + gfx::Size reload_size = reload_button_->GetPreferredSize(); + gfx::Size location_size = location_bar_view_->GetPreferredSize(); + int width = kCompactLocationLeftMargin + reload_size.width() + + std::max(kDefaultLocationEntryWidth, + location_bar_view_->GetPreferredSize().width()) + + kCompactLocationRightMargin; + return gfx::Size(width, kDefaultLocationBarHeight); +} + +void CompactLocationBarView::OnPaint(gfx::Canvas* canvas) { + // TODO(stevet): A lot of this method is copied almost directly from + // FindBarView. Perhaps we can share it in the common parent class. + SkPaint paint; + + gfx::Rect bounds = PaintOffsetToolbarBackground(canvas); + + // Now flip the canvas for the rest of the graphics if in RTL mode. + canvas->Save(); + if (base::i18n::IsRTL()) { + canvas->TranslateInt(width(), 0); + canvas->ScaleInt(-1, 1); + } + + PaintDialogBorder(canvas, bounds); + + PaintAnimatingEdges(canvas, bounds); + + canvas->Restore(); +} + +void CompactLocationBarView::Layout() { + if (!reload_button_) + return; // Not initialized yet, do nothing. + + int cur_x = kCompactLocationLeftMargin; + + // Vertically center all items, basing off the reload button. + gfx::Size reload_size = reload_button_->GetPreferredSize(); + int y = (height() - reload_size.height()) / 2; + reload_button_->SetBounds(cur_x, y, + reload_size.width(), reload_size.height()); + cur_x += reload_size.width() + kEntryPadding; + + int location_view_width = width() - cur_x - kCompactLocationRightMargin; + + // The location bar gets the rest of the space in the middle. We assume it has + // the same height as the reload button. + location_bar_view_->SetBounds(cur_x, y, location_view_width, + reload_size.height()); +} + +void CompactLocationBarView::Paint(gfx::Canvas* canvas) { + // This paints the background behind the reload button all the way across to + // the end of the CLB. Without this, everything comes up transparent. + gfx::Rect bounds = GetLocalBounds(); + ThemeProvider* tp = GetThemeProvider(); + // Now convert from screen to parent coordinates. + gfx::Point origin(bounds.origin()); + BrowserView* browser_view = host()->browser_view(); + ConvertPointToView(NULL, browser_view, &origin); + bounds.set_origin(origin); + // Finally, calculate the background image tiling offset. + origin = browser_view->OffsetPointForToolbarBackgroundImage(origin); + + canvas->TileImageInt(*tp->GetBitmapNamed(IDR_THEME_TOOLBAR), + origin.x(), origin.y(), 0, 0, + bounds.width(), bounds.height()); + View::Paint(canvas); +} + +void CompactLocationBarView::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (is_add && child == this && !initialized_) { + Init(); + } +} + +void CompactLocationBarView::Focus() { + location_bar_view_->SetFocusAndSelection(false); +} + +//////////////////////////////////////////////////////////////////////////////// +// views::ButtonListener overrides: + +void CompactLocationBarView::ButtonPressed(views::Button* sender, + const views::Event& event) { + int id = sender->tag(); + int flags = sender->mouse_event_flags(); + // Shift-clicking or ctrl-clicking the reload button means we should + // ignore any cached content. + // TODO(avayvod): eliminate duplication of this logic in + // CompactLocationBarView. + if (id == IDC_RELOAD && (event.IsShiftDown() || event.IsControlDown())) { + id = IDC_RELOAD_IGNORING_CACHE; + // Mask off shift/ctrl so they aren't interpreted as affecting the + // disposition below. + flags &= ~(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); + } + browser()->ExecuteCommandWithDisposition( + id, event_utils::DispositionFromEventFlags(flags)); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutocompleteEditController overrides: + +void CompactLocationBarView::OnAutocompleteAccept( + const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url) { + browser()->OpenURL(url, GURL(), disposition, transition); + clb_host()->StartAutoHideTimer(); +} + +void CompactLocationBarView::OnChanged() { + // TODO(stevet): Once we put in a location icon, we should resurrect this code + // to update the icon. + // location_icon_view_->SetImage( + // ResourceBundle::GetSharedInstance().GetBitmapNamed( + // location_entry_->GetIcon())); + // location_icon_view_->ShowTooltip(!location_entry()->IsEditingOrEmpty()); + + Layout(); + SchedulePaint(); +} + +void CompactLocationBarView::OnSelectionBoundsChanged() { + // TODO(stevet): LocationBarView, for OS_WIN, uses SuggestedTextView here. + // We should implement this usage eventually, if appropriate. +} + +void CompactLocationBarView::OnKillFocus() { + host()->UnregisterAccelerators(); +} + +void CompactLocationBarView::OnSetFocus() { + clb_host()->CancelAutoHideTimer(); + views::FocusManager* focus_manager = GetFocusManager(); + if (!focus_manager) { + NOTREACHED(); + return; + } + focus_manager->SetFocusedView(this); + host()->RegisterAccelerators(); +} + +void CompactLocationBarView::OnInputInProgress(bool in_progress) { +} + +SkBitmap CompactLocationBarView::GetFavicon() const { + TabContentsWrapper* wrapper = browser()->GetSelectedTabContentsWrapper(); + return wrapper ? wrapper->favicon_tab_helper()->GetFavicon() : SkBitmap(); +} + +string16 CompactLocationBarView::GetTitle() const { + const TabContentsWrapper* wrapper = + browser()->GetSelectedTabContentsWrapper(); + return wrapper ? wrapper->tab_contents()->GetTitle() : string16(); +} + +InstantController* CompactLocationBarView::GetInstant() { + // TODO(stevet): Re-enable instant for compact nav. + // return browser()->instant(); + return NULL; +} + +TabContentsWrapper* CompactLocationBarView::GetTabContentsWrapper() const { + return browser()->GetSelectedTabContentsWrapper(); +} diff --git a/chrome/browser/ui/views/compact_nav/compact_location_bar_view.h b/chrome/browser/ui/views/compact_nav/compact_location_bar_view.h new file mode 100644 index 0000000..01c30db --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_location_bar_view.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 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_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_H_ + +#include "base/basictypes.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h" +#include "chrome/browser/ui/views/dropdown_bar_view.h" +#include "views/controls/button/button.h" +#include "views/view.h" + +class Browser; +class BrowserView; +class CompactLocationBarViewHost; +class LocationBarView; +class ReloadButton; +class TabContents; + +namespace views { +class ImageButton; +class NativeViewHost; +} // namespace views + +// CompactLocationBarView is a version of location bar that is shown under a tab +// for short period of time when Chrome is in the compact navigation bar mode. +class CompactLocationBarView : public DropdownBarView, + public views::ButtonListener, + public AutocompleteEditController { + public: + explicit CompactLocationBarView(CompactLocationBarViewHost* host); + virtual ~CompactLocationBarView(); + + // Claims focus for the text field and optionally selects its contents. + virtual void SetFocusAndSelection(bool select_all); + + // Update the contained location bar to |contents|. + void Update(const TabContents* contents); + + // Overridden from AccessiblePaneView + virtual bool SetPaneFocus(int view_storage_id, View* initial_focus) OVERRIDE; + virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + + LocationBarView* location_bar_view() { return location_bar_view_; } + ReloadButton* reload_button() { return reload_button_; } + + private: + Browser* browser() const; + + // Called when the view is added to the tree to initialize the + // CompactLocationBarView. + void Init(); + + // Overridden from views::View. + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void OnPaint(gfx::Canvas* canvas); + virtual void Layout() OVERRIDE; + virtual void Paint(gfx::Canvas* canvas) OVERRIDE; + virtual void ViewHierarchyChanged(bool is_add, views::View* parent, + views::View* child) OVERRIDE; + + // No focus border for the location bar, the caret is enough. + virtual void Focus(); + virtual void PaintFocusBorder(gfx::Canvas* canvas) { } + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) OVERRIDE; + + // AutocompleteEditController implementation. + virtual void OnAutocompleteAccept(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url) OVERRIDE; + virtual void OnChanged() OVERRIDE; + virtual void OnSelectionBoundsChanged() OVERRIDE; + virtual void OnKillFocus() OVERRIDE; + virtual void OnSetFocus() OVERRIDE; + virtual SkBitmap GetFavicon() const OVERRIDE; + virtual void OnInputInProgress(bool in_progress) OVERRIDE; + virtual string16 GetTitle() const OVERRIDE; + virtual InstantController* GetInstant() OVERRIDE; + virtual TabContentsWrapper* GetTabContentsWrapper() const OVERRIDE; + + CompactLocationBarViewHost* clb_host() { + return static_cast<CompactLocationBarViewHost*>(host()); + } + + ReloadButton* reload_button_; + LocationBarView* location_bar_view_; + // TODO(stevet): Add the BrowserActionsContainer back. + + // Font used by edit and some of the hints. + gfx::Font font_; + + // True if we have already been initialized. + bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(CompactLocationBarView); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_H_ diff --git a/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.cc b/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.cc new file mode 100644 index 0000000..7a7a751 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.cc @@ -0,0 +1,517 @@ +// Copyright (c) 2011 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/ui/views/compact_nav/compact_location_bar_view_host.h" + +#if defined(TOOLKIT_USES_GTK) +#include <gtk/gtk.h> +#endif + +#include <algorithm> + +#include "base/i18n/rtl.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/platform_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/base_tab_strip.h" +#include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/browser/tab_contents/tab_contents_view.h" +#include "content/common/notification_source.h" +#include "ui/base/animation/slide_animation.h" +#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/gfx/rect.h" +#include "views/controls/scrollbar/native_scroll_bar.h" +#include "views/events/event.h" +#include "views/focus/external_focus_tracker.h" +#include "views/focus/view_storage.h" +#include "views/widget/root_view.h" +#include "views/widget/widget.h" + +namespace { + +const int kHideTimeoutInSeconds = 2; +// TODO(stevet): Share this with CompactLocationBarView. This is the actual +// height, without the overlap added. +const int kCompactNavbarSpacerHeight = 4; +const int kBookmarkBarLocationBarOverlap = 2; +const int kSpacerLocationbarOverlap = 1; + +} // namespace + +// An mouse event observer to detect a mouse click on +// BrowserView's content area and hide the location bar. +class MouseObserver : public MessageLoopForUI::Observer { + public: + MouseObserver(CompactLocationBarViewHost* host, BrowserView* view); + ~MouseObserver(); + + // MessageLoopForUI::Observer overrides. +#if defined(OS_WIN) + virtual void WillProcessMessage(const MSG& native_event) OVERRIDE; + virtual void DidProcessMessage(const MSG& native_event) OVERRIDE; +#elif defined(OS_LINUX) + virtual void WillProcessEvent(GdkEvent* native_event) OVERRIDE; + virtual void DidProcessEvent(GdkEvent* native_event) OVERRIDE; +#endif + + void Observe(MessageLoopForUI* loop); + void StopObserving(MessageLoopForUI* loop); + + private: + // TODO(mad): would be nice to have this on the views::Event class. + bool IsMouseEvent(const views::NativeEvent& native_event); + + bool IsSameTopLevelWindow(views::NativeEvent native_event); + + // Tests if the event occurred on the content area, using + // root window's coordinates. + bool HitContentArea(int x, int y); + + // Tests if |p| in the root window's coordinate is within the |view|'s bound. + bool HitOnScreen(const views::View* view, const gfx::Point& p); + + CompactLocationBarViewHost* host_; + BrowserView* browser_view_; + gfx::NativeView top_level_window_; + bool observing_; + + DISALLOW_COPY_AND_ASSIGN(MouseObserver); +}; + +MouseObserver::MouseObserver(CompactLocationBarViewHost* host, + BrowserView* view) + : host_(host), + browser_view_(view), + observing_(false) { + top_level_window_ = browser_view_->GetWidget()->GetNativeView(); +} + +MouseObserver::~MouseObserver() { + StopObserving(MessageLoopForUI::current()); +} + +#if defined(OS_WIN) +void MouseObserver::WillProcessMessage(const MSG& native_event) {} +void MouseObserver::DidProcessMessage(const MSG& native_event) { +#elif defined(OS_LINUX) +void MouseObserver::WillProcessEvent(GdkEvent* native_event) OVERRIDE {} +void MouseObserver::DidProcessEvent(GdkEvent* native_event) OVERRIDE { +#endif + // Hide the location bar iff the mouse is pressed on the + // BrowserView's content area. + if (!IsMouseEvent(native_event)) + return; + views::MouseEvent event(native_event); + if (event.type() == ui::ET_MOUSE_PRESSED && + IsSameTopLevelWindow(native_event) && + HitContentArea(event.x(), event.y())) { + host_->Hide(true); + } +} + +void MouseObserver::Observe(MessageLoopForUI* loop) { + if (!observing_) { + loop->AddObserver(this); + observing_ = true; + } +} + +void MouseObserver::StopObserving(MessageLoopForUI* loop) { + if (observing_) { + loop->RemoveObserver(this); + observing_ = false; + } +} + +bool MouseObserver::IsMouseEvent(const views::NativeEvent& native_event) { +#if defined(OS_WIN) + return views::IsClientMouseEvent(native_event) || + views::IsNonClientMouseEvent(native_event); +#elif defined(OS_LINUX) + return native_event->type == GDK_MOTION_NOTIFY || + native_event->type == GDK_BUTTON_PRESS || + native_event->type == GDK_2BUTTON_PRESS || + native_event->type == GDK_3BUTTON_PRESS || + native_event->type == GDK_BUTTON_RELEASE; +#endif +} + +// TODO(mad): Would be nice to have a NativeEvent -> NativeWindow mapping. +// Then, with a GetTopLevel receiving a NativeWindow, we could do this in a +// platform independent way. +bool MouseObserver::IsSameTopLevelWindow(views::NativeEvent native_event) { +#if defined(OS_WIN) + return platform_util::GetTopLevel(native_event.hwnd) == top_level_window_; +#elif defined(OS_LINUX) + return gdk_window_get_toplevel( + reinterpret_cast<GdkEventAny*>(native_event)->window) == + top_level_window_->window; +#endif +} + +bool MouseObserver::HitContentArea(int x, int y) { + gfx::Point p(x, y); + // First, exclude the location bar as it's shown on top of + // content area. + if (HitOnScreen(host_->view(), p)) { + return false; + } + // Treat the bookmark as a content area when it in detached mode. + if (browser_view_->GetBookmarkBarView()->IsDetached() && + browser_view_->IsBookmarkBarVisible() && + HitOnScreen(browser_view_->GetBookmarkBarView(), p)) { + return true; + } + if (HitOnScreen(browser_view_->GetContentsView(), p)) { + return true; + } + return false; +} + +bool MouseObserver::HitOnScreen(const views::View* view, const gfx::Point& p) { + gfx::Point origin(0, 0); + views::View::ConvertPointToScreen(view, &origin); + gfx::Rect new_bounds(origin, view->size()); + return new_bounds.Contains(p); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost, public: + +CompactLocationBarViewHost::CompactLocationBarViewHost( + BrowserView* browser_view) : DropdownBarHost(browser_view), + current_tab_model_index_(-1), + is_observing_(false) { + auto_hide_timer_.reset(new base::OneShotTimer<CompactLocationBarViewHost>()); + mouse_observer_.reset(new MouseObserver(this, browser_view)); + CompactLocationBarView* clbv = new CompactLocationBarView(this); + Init(clbv, clbv); +} + +CompactLocationBarViewHost::~CompactLocationBarViewHost() { + // This may happen if we are destroyed during cleanup. + if (browser_view() && browser_view()->browser() && + browser_view()->browser()->tabstrip_model()) { + browser_view()->browser()->tabstrip_model()->RemoveObserver(this); + } +} + +CompactLocationBarView* CompactLocationBarViewHost:: + GetCompactLocationBarView() { + return static_cast<CompactLocationBarView*>(view()); +} + +void CompactLocationBarViewHost::MoveWindowIfNecessary( + const gfx::Rect& selection_rect, + bool no_redraw) { + // We only move the window if one is currently shown. If we don't check + // this, then SetWidgetPosition below will end up making the Location Bar + // visible. + if (!IsVisible()) + return; + + gfx::Rect new_pos = GetDialogPosition(selection_rect); + SetDialogPosition(new_pos, no_redraw); + + // May need to redraw our frame to accommodate bookmark bar styles. + view()->SchedulePaint(); +} + +//////////////////////////////////////////////////////////////////////////////// +// LocationBarView::Delegate implementation: +TabContentsWrapper* CompactLocationBarViewHost::GetTabContentsWrapper() const { + return browser_view()->browser()->GetSelectedTabContentsWrapper(); +} + +InstantController* CompactLocationBarViewHost::GetInstant() { + // TODO(stevet): Re-enable instant for compact nav. + // return browser_view()->browser()->instant(); + return NULL; +} + +void CompactLocationBarViewHost::OnInputInProgress(bool in_progress) { +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost, views::AcceleratorTarget implementation: + +bool CompactLocationBarViewHost::AcceleratorPressed( + const views::Accelerator& accelerator) { + if (HasFocus()) { + DCHECK(view() != NULL); + views::FocusManager* focus_manager = view()->GetFocusManager(); + if (focus_manager) + focus_manager->ClearFocus(); + } + Hide(true); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost, views::DropdownBarHost implementation: + +gfx::Rect CompactLocationBarViewHost::GetDialogPosition( + gfx::Rect avoid_overlapping_rect) { + if (!browser_view() || !browser_view()->browser() || + !browser_view()->browser()->tabstrip_model()) { + return gfx::Rect(); + } + DCHECK_GE(current_tab_model_index_, 0); + if (!browser_view()->browser()->tabstrip_model()->ContainsIndex( + current_tab_model_index_)) { + return gfx::Rect(); + } + + gfx::Rect new_pos = GetBoundsUnderTab(current_tab_model_index_); + + if (animation_offset() > 0) + new_pos.Offset(0, std::min(0, -animation_offset())); + return new_pos; +} + +void CompactLocationBarViewHost::SetDialogPosition(const gfx::Rect& new_pos, + bool no_redraw) { + if (new_pos.IsEmpty()) + return; + + // Make sure the window edges are clipped to just the visible region. We need + // to do this before changing position, so that when we animate the closure + // of it it doesn't look like the window crumbles into the toolbar. + UpdateWindowEdges(new_pos); + + // TODO(oshima): Animate the window clipping like find-bar. + SetWidgetPositionNative(new_pos, no_redraw); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost, views::TabStripModelObserver implementation: + +void CompactLocationBarViewHost::TabClosingAt(TabStripModel* tab_strip_model, + TabContentsWrapper* contents, + int index) { + // TODO(stevet): We need to relocate the compact navigation bar if the + // removed tab is not the one we are currently under but the tabstrip does + // not have the ideal location yet because the tabs are animating at this + // time. Need to investigate the best way to handle this case. + Hide(false); +} + +void CompactLocationBarViewHost::TabSelectedAt(TabContentsWrapper* old_contents, + TabContentsWrapper* new_contents, + int index, + bool user_gesture) { + current_tab_model_index_ = index; + if (new_contents && new_contents->tab_contents()->is_loading()) { + Show(false); + } else { + Hide(false); + } +} + +void CompactLocationBarViewHost::TabMoved(TabContentsWrapper* contents, + int from_index, + int to_index) { + if (from_index == current_tab_model_index_) { + UpdateOnTabChange(to_index, false); + StartAutoHideTimer(); + } +} + +void CompactLocationBarViewHost::TabChangedAt(TabContentsWrapper* contents, + int index, + TabChangeType change_type) { + if (IsCurrentTabIndex(index) && change_type == + TabStripModelObserver::LOADING_ONLY) { + bool was_not_visible = !IsVisible(); + TabContents* tab_contents = contents->tab_contents(); + Update(tab_contents, false); + if (was_not_visible) { + if (tab_contents->is_loading()) { + // Register to NavigationController LOAD_STOP so that we can autohide + // when loading is done. + if (!registrar_.IsRegistered(this, NotificationType::LOAD_STOP, + Source<NavigationController>(&tab_contents->controller()))) { + registrar_.Add(this, NotificationType::LOAD_STOP, + Source<NavigationController>(&tab_contents->controller())); + } + } else { + StartAutoHideTimer(); + } + } + } +} + +void CompactLocationBarViewHost::ActiveTabClicked(int index) { + UpdateOnTabChange(index, true); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost, NotificationObserver implementation: + +void CompactLocationBarViewHost::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::LOAD_STOP: { + StartAutoHideTimer(); + // This is one shot deal... + registrar_.Remove(this, NotificationType::LOAD_STOP, source); + break; + } + default: + NOTREACHED(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost public: + +gfx::Rect CompactLocationBarViewHost::GetBoundsUnderTab(int model_index) const { + DCHECK(!browser_view()->UseVerticalTabs()); + + // Get the position of the left-bottom corner of the tab on the + // widget. The widget of the tab is same as the widget of the + // BrowserView which is the parent of the host. + BaseTabStrip* tabstrip = + static_cast<BaseTabStrip*>(browser_view()->tabstrip()); + gfx::Rect tab_bounds = + tabstrip->ideal_bounds(tabstrip->ModelIndexToTabIndex(model_index)); + gfx::Rect navbar_bounds(gfx::Point(tab_bounds.x(), tab_bounds.height()), + view()->GetPreferredSize()); + + // Convert our point to be relative to the widget, since the native code that + // draws the dropdown is not in the BrowserView coordinate system. + gfx::Point origin = navbar_bounds.origin(); + views::View::ConvertPointToWidget(browser_view(), &origin); + navbar_bounds.set_origin(origin); + + // For RTL case x() defines tab right corner. + if (base::i18n::IsRTL()) + navbar_bounds.Offset(tab_bounds.width(), 0); + navbar_bounds.Offset(tabstrip->x(), tabstrip->y()); + + // The compact location bar must be smaller than browser_width. + int width = std::min(browser_view()->width(), + view()->GetPreferredSize().width()); + + // Try to center around the tab. + navbar_bounds.set_x(browser_view()->GetMirroredXInView( + navbar_bounds.x()) - ((width - tab_bounds.width()) / 2)); + + // Adjust the location to create the illusion that the compact location bar + // is a part of the spacer or bookmark bar, depending on which is showing. + if (browser_view()->IsBookmarkBarVisible() && + !browser_view()->GetBookmarkBarView()->IsDetached()) { + // TODO(stevet): Compact location bar does not have right background image + // yet, so kBookmarkBarLocationBarOverlap is tentative. Fix this once UI is + // settled. This may be entirely replaced by a popup CLB, anyway. + navbar_bounds.Offset(0, + browser_view()->GetBookmarkBarView()->bounds().height() + + kCompactNavbarSpacerHeight - kBookmarkBarLocationBarOverlap); + } else { + // TODO(stevet): kSpacerLocationbarOverlap is tentative as well, as above. + navbar_bounds.Offset(0, kCompactNavbarSpacerHeight - + kSpacerLocationbarOverlap); + } + + // TODO(stevet): Adjust to the right if there is an info bar visible. + return navbar_bounds.AdjustToFit(browser_view()->bounds()); +} + +void CompactLocationBarViewHost::Update(TabContents* contents, bool animate) { + // Don't animate if the bar is already shown. + bool showing_in_same_tab = animation()->IsShowing() && IsCurrentTab(contents); + current_tab_model_index_ = browser_view()->browser()->active_index(); + Hide(false); + GetCompactLocationBarView()->Update(contents); + Show(animate && !showing_in_same_tab); + // If the tab is loading, we must wait for the notification that it is done. + if (contents && !contents->is_loading()) { + // This will be a NOOP if we have focus. + // We never want to stay up, unless we have focus. + StartAutoHideTimer(); + } +} + +void CompactLocationBarViewHost::UpdateOnTabChange(int model_index, + bool animate) { + DCHECK_GE(model_index, 0); + if (IsCurrentTabIndex(model_index) && animation()->IsShowing()) { + return; + } + current_tab_model_index_ = model_index; + Update(browser_view()->browser()->tabstrip_model()-> + GetTabContentsAt(model_index)->tab_contents(), animate); +} + +void CompactLocationBarViewHost::StartAutoHideTimer() { + if (!IsVisible() || HasFocus()) + return; + + if (auto_hide_timer_->IsRunning()) { + // Restart the timer. + auto_hide_timer_->Reset(); + } else { + auto_hide_timer_->Start(base::TimeDelta::FromSeconds(kHideTimeoutInSeconds), + this, &CompactLocationBarViewHost::HideCallback); + } +} + +void CompactLocationBarViewHost::CancelAutoHideTimer() { + auto_hide_timer_->Stop(); +} + +void CompactLocationBarViewHost::SetEnabled(bool enabled) { + if (enabled && !is_observing_) { + browser_view()->browser()->tabstrip_model()->AddObserver(this); + is_observing_ = true; + } else { + browser_view()->browser()->tabstrip_model()->RemoveObserver(this); + is_observing_ = false; + } +} + +void CompactLocationBarViewHost::Show(bool animate) { + CancelAutoHideTimer(); + mouse_observer_->Observe(MessageLoopForUI::current()); + DropdownBarHost::Show(animate); + host()->Show(); +} + +void CompactLocationBarViewHost::Hide(bool animate) { + CancelAutoHideTimer(); + mouse_observer_->StopObserving(MessageLoopForUI::current()); + host()->Hide(); + DropdownBarHost::Hide(animate); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactLocationBarViewHost private: +bool CompactLocationBarViewHost::HasFocus() { + DCHECK(view() != NULL); + views::FocusManager* focus_manager = view()->GetFocusManager(); + return focus_manager && view()->Contains(focus_manager->GetFocusedView()); +} + +void CompactLocationBarViewHost::HideCallback() { + if (IsVisible() && !HasFocus()) + Hide(true); +} + +bool CompactLocationBarViewHost::IsCurrentTabIndex(int index) { + return current_tab_model_index_ == index; +} + +bool CompactLocationBarViewHost::IsCurrentTab(TabContents* contents) { + TabStripModel* tab_strip_model = browser_view()->browser()->tabstrip_model(); + return tab_strip_model->ContainsIndex(current_tab_model_index_) && + tab_strip_model->GetTabContentsAt(current_tab_model_index_)-> + tab_contents() == contents; +} diff --git a/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h b/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h new file mode 100644 index 0000000..1037853 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h @@ -0,0 +1,138 @@ +// Copyright (c) 2011 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_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_HOST_H_ +#define CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_HOST_H_ + +#include "base/timer.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" + +class BrowserView; +class CompactLocationBarView; +class DropdownBarHost; +class MouseObserver; +class NotificationObserver; +class NotificationRegistrar; +class TabContents; + +namespace gfx { +class Rect; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// The CompactLocationBarViewHost implements the container window for the +// floating location bar. +// +// There is one CompactLocationBarViewHost per BrowserView, and its state +// is updated whenever the selected Tab is changed. The +// CompactLocationBarViewHost is created when the BrowserView is attached +// to the frame's Widget for the first time, and enabled/disabled +// when the compact navigation bar is toggled. +// +//////////////////////////////////////////////////////////////////////////////// +class CompactLocationBarViewHost : public DropdownBarHost, + public TabStripModelObserver, + public NotificationObserver, + public LocationBarView::Delegate { + public: + explicit CompactLocationBarViewHost(BrowserView* browser_view); + virtual ~CompactLocationBarViewHost(); + + // Returns the bounds to locate the compact location bar under the tab. The + // coordinate system is the browser frame for Windows, otherwise the browser + // view. + gfx::Rect GetBoundsUnderTab(int model_index) const; + + // Updates the content and the position of the compact location bar. + // |model_index| is the index of the tab the compact location bar + // will be attached to and |animate| specifies if the location bar + // should animate when shown. The second version gets the actual |contents| + // instead of the |model_index|. + void UpdateOnTabChange(int model_index, bool animate); + void Update(TabContents* contents, bool animate); + + // (Re)Starts the popup timer that hides the popup after X seconds. + void StartAutoHideTimer(); + + // Cancels the popup timer. + void CancelAutoHideTimer(); + + // Enable/disable the compact location bar. + void SetEnabled(bool enabled); + + CompactLocationBarView* GetCompactLocationBarView(); + + // Readjust the position of the host window while avoiding |selection_rect|. + // |selection_rect| is expected to have coordinates relative to the top of + // the web page area. If |no_redraw| is true, the window will be moved without + // redrawing siblings. + virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect, + bool no_redraw); + + // Overridden from DropdownBarhost. + virtual void Show(bool animate) OVERRIDE; + virtual void Hide(bool animate) OVERRIDE; + virtual gfx::Rect GetDialogPosition( + gfx::Rect avoid_overlapping_rect) OVERRIDE; + virtual void SetDialogPosition(const gfx::Rect& new_pos, + bool no_redraw) OVERRIDE; + + // Overridden from views::AcceleratorTarget in DropdownBarHost class. + virtual bool AcceleratorPressed( + const views::Accelerator& accelerator) OVERRIDE; + + // Overridden from TabStripModelObserver class. + virtual void TabClosingAt(TabStripModel* tab_strip_model, + TabContentsWrapper* contents, + int index) OVERRIDE; + virtual void TabSelectedAt(TabContentsWrapper* old_contents, + TabContentsWrapper* new_contents, + int index, + bool user_gesture) OVERRIDE; + virtual void TabMoved(TabContentsWrapper* contents, + int from_index, + int to_index) OVERRIDE; + virtual void TabChangedAt(TabContentsWrapper* contents, int index, + TabChangeType change_type) OVERRIDE; + virtual void ActiveTabClicked(int index) OVERRIDE; + + // Overridden from NotificationObserver. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; + + // LocationBarView::Delegate overrides + virtual TabContentsWrapper* GetTabContentsWrapper() const OVERRIDE; + virtual InstantController* GetInstant() OVERRIDE; + virtual void OnInputInProgress(bool in_progress) OVERRIDE; + + private: + friend class MouseObserver; + friend class CompactLocationBarViewHostTest; + + bool HasFocus(); + void HideCallback(); + bool IsCurrentTabIndex(int index); + bool IsCurrentTab(TabContents* contents); + + // We use this to be notified of the end of a page load so we can hide. + NotificationRegistrar registrar_; + + // The index of the tab, in terms of the model, that the compact location bar + // is attached to. + int current_tab_model_index_; + + scoped_ptr<base::OneShotTimer<CompactLocationBarViewHost> > auto_hide_timer_; + + scoped_ptr<MouseObserver> mouse_observer_; + + // Track if we are currently observing the tabstrip model. + bool is_observing_; + + DISALLOW_COPY_AND_ASSIGN(CompactLocationBarViewHost); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_LOCATION_BAR_VIEW_HOST_H_ diff --git a/chrome/browser/ui/views/compact_nav/compact_navigation_bar.cc b/chrome/browser/ui/views/compact_nav/compact_navigation_bar.cc new file mode 100644 index 0000000..64e3592 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_navigation_bar.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2011 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/ui/views/compact_nav/compact_navigation_bar.h" + +#include "base/logging.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/toolbar/back_forward_menu_model.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/event_utils.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/theme_background.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "grit/theme_resources_standard.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/theme_provider.h" +#include "ui/gfx/canvas.h" +#include "views/controls/button/button_dropdown.h" +#include "views/controls/button/image_button.h" +#include "views/controls/image_view.h" +#include "views/controls/native/native_view_host.h" + +// Padding inside each button around the image. +static const int kInnerPadding = 1; + +// Spacing between buttons (excluding left/right most margin) +static const int kHorizMargin = 3; + +// Left side margin of the back button to align with the main menu. +static const int kBackButtonLeftMargin = 10; + +// Right side margin of the forward button to align with the main menu. +static const int kForwardButtonRightMargin = 1; + +// Preferred height. +static const int kPreferredHeight = 25; + +//////////////////////////////////////////////////////////////////////////////// +// CompactNavigationBar public: + +CompactNavigationBar::CompactNavigationBar(BrowserView* browser_view) + : browser_view_(browser_view), + initialized_(false), + back_(NULL), + bf_separator_(NULL), + forward_(NULL) { + Browser* browser = browser_view_->browser(); + browser->command_updater()->AddCommandObserver(IDC_BACK, this); + browser->command_updater()->AddCommandObserver(IDC_FORWARD, this); +} + +CompactNavigationBar::~CompactNavigationBar() { + Browser* browser = browser_view_->browser(); + browser->command_updater()->RemoveCommandObserver(IDC_BACK, this); + browser->command_updater()->RemoveCommandObserver(IDC_FORWARD, this); +} + +void CompactNavigationBar::Init() { + DCHECK(!initialized_); + + Browser* browser = browser_view_->browser(); + + back_menu_model_.reset(new BackForwardMenuModel( + browser, BackForwardMenuModel::BACKWARD_MENU)); + forward_menu_model_.reset(new BackForwardMenuModel( + browser, BackForwardMenuModel::FORWARD_MENU)); + + ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); + + back_ = new views::ButtonDropDown(this, back_menu_model_.get()); + back_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN | + ui::EF_MIDDLE_BUTTON_DOWN); + back_->set_tag(IDC_BACK); + back_->SetTooltipText( + UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_BACK))); + back_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK)); + back_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); + AddChildView(back_); + + bf_separator_ = new views::ImageView; + bf_separator_->SetImage( + resource_bundle.GetBitmapNamed(IDR_COMPACTNAV_SEPARATOR)); + AddChildView(bf_separator_); + + forward_ = new views::ButtonDropDown(this, forward_menu_model_.get()); + forward_->set_triggerable_event_flags(ui::EF_LEFT_BUTTON_DOWN | + ui::EF_MIDDLE_BUTTON_DOWN); + forward_->set_tag(IDC_FORWARD); + forward_->SetTooltipText( + UTF16ToWide(l10n_util::GetStringUTF16(IDS_TOOLTIP_FORWARD))); + forward_->SetAccessibleName(l10n_util::GetStringUTF16((IDS_ACCNAME_FORWARD))); + forward_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); + AddChildView(forward_); + + LoadImages(); + + initialized_ = true; +} + +gfx::Size CompactNavigationBar::GetPreferredSize() { + int width = kBackButtonLeftMargin; + width += back_->GetPreferredSize().width() + kInnerPadding * 2; + width += kHorizMargin; + width += bf_separator_->GetPreferredSize().width(); + width += kHorizMargin; + width += forward_->GetPreferredSize().width() + kInnerPadding * 2; + width += kForwardButtonRightMargin; + return gfx::Size(width, kPreferredHeight); +} + +void CompactNavigationBar::Layout() { + if (!initialized_) + return; + + // Layout forward/back buttons after entry views as follows: + // [Back]|[Forward] + int curx = kBackButtonLeftMargin; + // "Back | Forward" section. + gfx::Size button_size = back_->GetPreferredSize(); + button_size.set_width(button_size.width() + kInnerPadding * 2); + back_->SetBounds(curx, 0, button_size.width(), height()); + curx += button_size.width() + kHorizMargin; + + button_size = bf_separator_->GetPreferredSize(); + bf_separator_->SetBounds(curx, 0, button_size.width(), height()); + curx += button_size.width() + kHorizMargin; + + button_size = forward_->GetPreferredSize(); + button_size.set_width(button_size.width() + kInnerPadding * 2); + forward_->SetBounds(curx, 0, button_size.width(), height()); +} + +//////////////////////////////////////////////////////////////////////////////// +// views::ButtonListener implementation. + +void CompactNavigationBar::ButtonPressed( + views::Button* sender, const views::Event& event) { + browser_view_->browser()->ExecuteCommandWithDisposition( + sender->tag(), + event_utils::DispositionFromEventFlags(sender->mouse_event_flags())); +} + +//////////////////////////////////////////////////////////////////////////////// +// CommandUpdater::CommandObserver implementation. +void CompactNavigationBar::EnabledStateChangedForCommand(int id, bool enabled) { + switch (id) { + case IDC_BACK: + back_->SetEnabled(enabled); + break; + case IDC_FORWARD: + forward_->SetEnabled(enabled); + break; + } +} + +void CompactNavigationBar::LoadImages() { + ui::ThemeProvider* tp = GetThemeProvider(); + + // TODO(stevet): Hook up other button image resources like + // IDR_COMPACTNAV_FORWARD for the different button states. + back_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_BACK)); + back_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_BACK_H)); + back_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_BACK_P)); + back_->SetImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_BACK_D)); + + forward_->SetImage(views::CustomButton::BS_NORMAL, + tp->GetBitmapNamed(IDR_FORWARD)); + forward_->SetImage(views::CustomButton::BS_HOT, + tp->GetBitmapNamed(IDR_FORWARD_H)); + forward_->SetImage(views::CustomButton::BS_PUSHED, + tp->GetBitmapNamed(IDR_FORWARD_P)); + forward_->SetImage(views::CustomButton::BS_DISABLED, + tp->GetBitmapNamed(IDR_FORWARD_D)); +} diff --git a/chrome/browser/ui/views/compact_nav/compact_navigation_bar.h b/chrome/browser/ui/views/compact_nav/compact_navigation_bar.h new file mode 100644 index 0000000..3e33098 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_navigation_bar.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 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_UI_VIEWS_COMPACT_NAV_COMPACT_NAVIGATION_BAR_H_ +#define CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_NAVIGATION_BAR_H_ + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/command_updater.h" +#include "views/controls/button/button.h" +#include "views/view.h" + +class BackForwardMenuModel; +class BrowserView; + +namespace views { +class ImageButton; +class ImageView; +} + +// This class provides a small navigation bar that includes back, forward, and +// a small text entry box. +class CompactNavigationBar : public views::View, + public views::ButtonListener, + public CommandUpdater::CommandObserver { + public: + explicit CompactNavigationBar(BrowserView* browser_view); + virtual ~CompactNavigationBar(); + + // Must be called before anything else, but after adding this view to the + // widget. + void Init(); + + // views::View overrides. + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void Layout() OVERRIDE; + + private: + // views::ButtonListener implementation. + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // CommandUpdater::CommandObserver implementation. + virtual void EnabledStateChangedForCommand(int id, bool enabled); + + // Load the images for the back and forward buttons. + void LoadImages(); + + BrowserView* browser_view_; + + bool initialized_; + + views::ImageButton* back_; + views::ImageView* bf_separator_; + views::ImageButton* forward_; + + // History menu for back and forward buttons. + scoped_ptr<BackForwardMenuModel> back_menu_model_; + scoped_ptr<BackForwardMenuModel> forward_menu_model_; + + DISALLOW_COPY_AND_ASSIGN(CompactNavigationBar); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_NAVIGATION_BAR_H_ diff --git a/chrome/browser/ui/views/compact_nav/compact_options_bar.cc b/chrome/browser/ui/views/compact_nav/compact_options_bar.cc new file mode 100644 index 0000000..677485f --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_options_bar.cc @@ -0,0 +1,151 @@ +// Copyright (c) 2011 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/ui/views/compact_nav/compact_options_bar.h" + +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/toolbar/wrench_menu_model.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/event_utils.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar_view.h" +#include "chrome/browser/ui/views/wrench_menu.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas.h" +#include "views/controls/button/menu_button.h" + +namespace { +const int kPreferredHeight = 25; +// Pad the left and right ends from other tabstrip region items. +const int kEndPadding = 3; +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactOptionsBar public: + +CompactOptionsBar::CompactOptionsBar(BrowserView* browser_view) + : browser_view_(browser_view), + initialized_(false), + app_menu_(NULL) { +} + +CompactOptionsBar::~CompactOptionsBar() { +} + +void CompactOptionsBar::Init() { + DCHECK(!initialized_); + initialized_ = true; + + wrench_menu_model_.reset(new WrenchMenuModel(this, browser_view_->browser())); + + app_menu_ = new views::MenuButton(NULL, std::wstring(), this, false); + app_menu_->set_border(NULL); + app_menu_->EnableCanvasFlippingForRTLUI(true); + app_menu_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_APP)); + app_menu_->SetTooltipText(UTF16ToWide(l10n_util::GetStringFUTF16( + IDS_APPMENU_TOOLTIP, + l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)))); + app_menu_->SetID(VIEW_ID_APP_MENU); + AddChildView(app_menu_); + + LoadImages(); +} + +void CompactOptionsBar::AddMenuListener(views::MenuListener* listener) { + menu_listeners_.push_back(listener); +} + +void CompactOptionsBar::RemoveMenuListener(views::MenuListener* listener) { + for (std::vector<views::MenuListener*>::iterator i(menu_listeners_.begin()); + i != menu_listeners_.end(); ++i) { + if (*i == listener) { + menu_listeners_.erase(i); + return; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactOptionsBar, views::View overrides: + +gfx::Size CompactOptionsBar::GetPreferredSize() { + int width = kEndPadding * 2 + app_menu_->GetPreferredSize().width(); + // TODO(stevet): Add the width of the browser actions container here when that + // is added to the bar. + return gfx::Size(width, kPreferredHeight); +} + +void CompactOptionsBar::Layout() { + if (!initialized_) + return; + + gfx::Size button_size = app_menu_->GetPreferredSize(); + app_menu_->SetBounds(kEndPadding, 0, button_size.width(), height()); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactOptionsBar, views::MenuDelegate implementation: + +void CompactOptionsBar::RunMenu(views::View* source, + const gfx::Point& /* pt */) { + DCHECK_EQ(VIEW_ID_APP_MENU, source->GetID()); + + wrench_menu_ = new WrenchMenu(browser_view_->browser()); + wrench_menu_->Init(wrench_menu_model_.get()); + + for (size_t i = 0; i < menu_listeners_.size(); ++i) + menu_listeners_[i]->OnMenuOpened(); + + // Note that this might be destroyed while the menu is running. + wrench_menu_->RunMenu(app_menu_); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactOptionsBar, ui::AcceleratorProvider implementation: + +bool CompactOptionsBar::GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) { + // TODO(stevet): Can we share ToolbarView's implementation? It's exactly the + // same so far. + // The standard Ctrl-X, Ctrl-V and Ctrl-C are not defined as accelerators + // anywhere so we need to check for them explicitly here. + // TODO(cpu) Bug 1109102. Query WebKit land for the actual bindings. + switch (command_id) { + case IDC_CUT: + *accelerator = views::Accelerator(ui::VKEY_X, false, true, false); + return true; + case IDC_COPY: + *accelerator = views::Accelerator(ui::VKEY_C, false, true, false); + return true; + case IDC_PASTE: + *accelerator = views::Accelerator(ui::VKEY_V, false, true, false); + return true; + } + // Else, we retrieve the accelerator information from the frame. + return GetWidget()->GetAccelerator(command_id, accelerator); +} + +//////////////////////////////////////////////////////////////////////////////// +// CompactOptionsBar, views::ButtonListener implementation. + +void CompactOptionsBar::ButtonPressed(views::Button* sender, + const views::Event& event) { + browser_view_->browser()->ExecuteCommandWithDisposition( + sender->tag(), + event_utils::DispositionFromEventFlags(sender->mouse_event_flags())); +} + +void CompactOptionsBar::LoadImages() { + // Reuse the resources loaded for the Toolbar's AppMenu. + DCHECK(browser_view_->toolbar()); + app_menu_->SetIcon(browser_view_->toolbar()->GetAppMenuIcon( + views::CustomButton::BS_NORMAL)); + app_menu_->SetHoverIcon(browser_view_->toolbar()->GetAppMenuIcon( + views::CustomButton::BS_HOT)); + app_menu_->SetPushedIcon(browser_view_->toolbar()->GetAppMenuIcon( + views::CustomButton::BS_PUSHED)); +} diff --git a/chrome/browser/ui/views/compact_nav/compact_options_bar.h b/chrome/browser/ui/views/compact_nav/compact_options_bar.h new file mode 100644 index 0000000..0d8cd20e6 --- /dev/null +++ b/chrome/browser/ui/views/compact_nav/compact_options_bar.h @@ -0,0 +1,81 @@ +// Copyright (c) 2011 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_UI_VIEWS_COMPACT_NAV_COMPACT_OPTIONS_BAR_H_ +#define CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_OPTIONS_BAR_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/command_updater.h" +#include "ui/base/models/simple_menu_model.h" +#include "views/controls/button/button.h" +#include "views/controls/menu/view_menu_delegate.h" +#include "views/view.h" + +class BrowserView; +class WrenchMenu; + +namespace views { +class MenuButton; +class MenuListener; +} // namespace views + +// This class provides a small options bar that includes browser actions and +// the wrench menu button. +class CompactOptionsBar : public views::View, + public views::ViewMenuDelegate, + public ui::AcceleratorProvider, + public views::ButtonListener { + public: + explicit CompactOptionsBar(BrowserView* browser_view); + virtual ~CompactOptionsBar(); + + // Must be called before anything else, but after adding this view to the + // widget. + void Init(); + + // Add a listener to receive a callback when the menu opens. + void AddMenuListener(views::MenuListener* listener); + + // Remove a menu listener. + void RemoveMenuListener(views::MenuListener* listener); + + // Overridden from views::View. + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void Layout() OVERRIDE; + + // Overridden from views::MenuDelegate: + virtual void RunMenu(views::View* source, const gfx::Point& pt) OVERRIDE; + + // Overridden from ui::AcceleratorProvider: + virtual bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) OVERRIDE; + + private: + // views::ButtonListener implementation. + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Load the images for the back and forward buttons. + void LoadImages(); + + BrowserView* browser_view_; + + bool initialized_; + + // Button and models for the wrench/app menu. + views::MenuButton* app_menu_; + scoped_ptr<ui::SimpleMenuModel> wrench_menu_model_; + scoped_refptr<WrenchMenu> wrench_menu_; + std::vector<views::MenuListener*> menu_listeners_; + + // TODO(stevet): Add the BrowserActionsContainer. + + DISALLOW_COPY_AND_ASSIGN(CompactOptionsBar); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COMPACT_NAV_COMPACT_OPTIONS_BAR_H_ diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc index 875e8a4..9675589 100644 --- a/chrome/browser/ui/views/dropdown_bar_host.cc +++ b/chrome/browser/ui/views/dropdown_bar_host.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/dropdown_bar_host_delegate.h" #include "chrome/browser/ui/views/dropdown_bar_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "ui/base/animation/slide_animation.h" @@ -44,14 +45,20 @@ bool DropdownBarHost::disable_animations_during_testing_ = false; DropdownBarHost::DropdownBarHost(BrowserView* browser_view) : browser_view_(browser_view), view_(NULL), + delegate_(NULL), animation_offset_(0), focus_manager_(NULL), esc_accel_target_registered_(false), is_visible_(false) { } -void DropdownBarHost::Init(DropdownBarView* view) { +void DropdownBarHost::Init(views::View* view, + DropdownBarHostDelegate* delegate) { + DCHECK(view); + DCHECK(delegate); + view_ = view; + delegate_ = delegate; // Initialize the host. host_.reset(views::Widget::CreateWidget()); @@ -102,7 +109,7 @@ void DropdownBarHost::Show(bool animate) { } void DropdownBarHost::SetFocusAndSelection() { - view_->SetFocusAndSelection(true); + delegate_->SetFocusAndSelection(true); } bool DropdownBarHost::IsAnimating() const { @@ -112,13 +119,23 @@ bool DropdownBarHost::IsAnimating() const { void DropdownBarHost::Hide(bool animate) { if (!IsVisible()) return; - if (animate && !disable_animations_during_testing_) { - animation_->Reset(1.0); + if (animate && !disable_animations_during_testing_ && + !animation_->IsClosing()) { animation_->Hide(); } else { - StopAnimation(); - is_visible_ = false; - host_->Hide(); + if (animation_->IsClosing()) { + // If we're in the middle of a close animation, skip immediately to the + // end of the animation. + StopAnimation(); + } else { + // Otherwise we need to set both the animation state to ended and the + // DropdownBarHost state to ended/hidden, otherwise the next time we try + // to show the bar, it might refuse to do so. Note that we call + // AnimationEnded ourselves as Reset does not call it if we are not + // animating here. + animation_->Reset(); + AnimationEnded(animation_.get()); + } } } @@ -171,7 +188,7 @@ void DropdownBarHost::AnimationProgressed(const ui::Animation* animation) { // Let the view know if we are animating, and at which offset to draw the // edges. - view_->set_animation_offset(animation_offset_); + delegate_->SetAnimationOffset(animation_offset_); view_->SchedulePaint(); } diff --git a/chrome/browser/ui/views/dropdown_bar_host.h b/chrome/browser/ui/views/dropdown_bar_host.h index c53f40c..914f240d 100644 --- a/chrome/browser/ui/views/dropdown_bar_host.h +++ b/chrome/browser/ui/views/dropdown_bar_host.h @@ -15,18 +15,19 @@ #include "views/focus/focus_manager.h" class BrowserView; +class DropdownBarHostDelegate; class DropdownBarView; class TabContents; namespace ui { class SlideAnimation; -} +} // namespace ui namespace views { class ExternalFocusTracker; class View; class Widget; -} +} // namespace views //////////////////////////////////////////////////////////////////////////////// // @@ -45,8 +46,7 @@ class DropdownBarHost : public views::AcceleratorTarget, explicit DropdownBarHost(BrowserView* browser_view); virtual ~DropdownBarHost(); - // Initializes the dropdown bar host with the give view. - void Init(DropdownBarView* view); + void Init(views::View* view, DropdownBarHostDelegate* delegate); // Whether we are animating the position of the dropdown widget. bool IsAnimating() const; @@ -101,7 +101,7 @@ class DropdownBarHost : public views::AcceleratorTarget, protected: // Returns the dropdown bar view. - DropdownBarView* view() const { return view_; } + views::View* view() const { return view_; } // Returns the focus tracker. views::ExternalFocusTracker* focus_tracker() const { @@ -154,7 +154,8 @@ class DropdownBarHost : public views::AcceleratorTarget, BrowserView* browser_view_; // Our view, which is responsible for drawing the UI. - DropdownBarView* view_; + views::View* view_; + DropdownBarHostDelegate* delegate_; // The y position pixel offset of the widget while animating the // dropdown widget. diff --git a/chrome/browser/ui/views/dropdown_bar_host_delegate.h b/chrome/browser/ui/views/dropdown_bar_host_delegate.h new file mode 100644 index 0000000..9b98b4b --- /dev/null +++ b/chrome/browser/ui/views/dropdown_bar_host_delegate.h @@ -0,0 +1,21 @@ +// Copyright (c) 2011 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_UI_VIEWS_DROPDOWN_BAR_HOST_DELEGATE_H_ +#define CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_DELEGATE_H_ + +class DropdownBarHostDelegate { + public: + // Claims focus for the text field and selects its contents. + virtual void SetFocusAndSelection(bool select_all) = 0; + + // Updates the view to let it know where the host is clipping the + // dropdown widget (while animating the opening or closing of the widget). + virtual void SetAnimationOffset(int offset) = 0; + + protected: + virtual ~DropdownBarHostDelegate() {} +}; + +#endif // CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_DELEGATE_H_ diff --git a/chrome/browser/ui/views/dropdown_bar_view.cc b/chrome/browser/ui/views/dropdown_bar_view.cc new file mode 100644 index 0000000..e1a58eb --- /dev/null +++ b/chrome/browser/ui/views/dropdown_bar_view.cc @@ -0,0 +1,107 @@ +// Copyright (c) 2011 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/ui/views/dropdown_bar_view.h" + +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources_standard.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas.h" +#include "views/background.h" +#include "views/widget/widget.h" + +namespace { + +// When we are animating, we draw only the top part of the left and right +// edges to give the illusion that the find dialog is attached to the +// window during this animation; this is the height of the items we draw. +const int kAnimatingEdgeHeight = 5; + +} // namespace + +DropdownBarView::DropdownBarView(DropdownBarHost* host) + : host_(host), + animation_offset_(0), + dialog_left_(NULL), + dialog_middle_(NULL), + dialog_right_(NULL) { +} + +DropdownBarView::~DropdownBarView() { +} + +//////////////////////////////////////////////////////////////////////////////// +// DropDownBarView, public: + +void DropdownBarView::SetAnimationOffset(int offset) { + animation_offset_ = offset; +} + +//////////////////////////////////////////////////////////////////////////////// +// DropDownBarView, protected: + +void DropdownBarView::SetDialogBorderBitmaps(const SkBitmap* dialog_left, + const SkBitmap* dialog_middle, + const SkBitmap* dialog_right) { + dialog_left_ = dialog_left; + dialog_middle_ = dialog_middle; + dialog_right_ = dialog_right; +} + +gfx::Rect DropdownBarView::PaintOffsetToolbarBackground(gfx::Canvas* canvas) { + // Determine the find bar size as well as the offset from which to tile the + // toolbar background image. First, get the widget bounds. + gfx::Rect bounds = GetWidget()->GetWindowScreenBounds(); + // Now convert from screen to parent coordinates. + gfx::Point origin(bounds.origin()); + BrowserView* browser_view = host()->browser_view(); + ConvertPointToView(NULL, browser_view, &origin); + bounds.set_origin(origin); + // Finally, calculate the background image tiling offset. + origin = browser_view->OffsetPointForToolbarBackgroundImage(origin); + + // First, we draw the background image for the whole dialog (3 images: left, + // middle and right). Note, that the window region has been set by the + // controller, so the whitespace in the left and right background images is + // actually outside the window region and is therefore not drawn. See + // FindInPageWidgetWin::CreateRoundedWindowEdges() for details. + ui::ThemeProvider* tp = GetThemeProvider(); + canvas->TileImageInt(*tp->GetBitmapNamed(IDR_THEME_TOOLBAR), origin.x(), + origin.y(), 0, 0, bounds.width(), bounds.height()); + return bounds; +} + +void DropdownBarView::PaintDialogBorder(gfx::Canvas* canvas, + const gfx::Rect& bounds) const { + DCHECK(dialog_left_); + DCHECK(dialog_middle_); + DCHECK(dialog_right_); + + canvas->DrawBitmapInt(*dialog_left_, 0, 0); + + // Stretch the middle background to cover all of the area between the two + // other images. + canvas->TileImageInt(*dialog_middle_, dialog_left_->width(), 0, + bounds.width() - dialog_left_->width() - dialog_right_->width(), + dialog_middle_->height()); + + canvas->DrawBitmapInt(*dialog_right_, bounds.width() - dialog_right_->width(), + 0); +} + +void DropdownBarView::PaintAnimatingEdges(gfx::Canvas* canvas, + const gfx::Rect& bounds) const { + if (animation_offset() > 0) { + // While animating we draw the curved edges at the point where the + // controller told us the top of the window is: |animation_offset()|. + canvas->TileImageInt(*dialog_left_, bounds.x(), animation_offset(), + dialog_left_->width(), kAnimatingEdgeHeight); + canvas->TileImageInt(*dialog_right_, + bounds.width() - dialog_right_->width(), animation_offset(), + dialog_right_->width(), kAnimatingEdgeHeight); + } +} diff --git a/chrome/browser/ui/views/dropdown_bar_view.h b/chrome/browser/ui/views/dropdown_bar_view.h index cfd3377..a92dd43 100644 --- a/chrome/browser/ui/views/dropdown_bar_view.h +++ b/chrome/browser/ui/views/dropdown_bar_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,9 +6,13 @@ #define CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_VIEW_H_ #pragma once -#include "views/view.h" +#include "chrome/browser/ui/views/dropdown_bar_host.h" +#include "chrome/browser/ui/views/dropdown_bar_host_delegate.h" +#include "chrome/browser/ui/views/accessible_pane_view.h" -class DropdownBarHost; +namespace gfx { +class Canvas; +} // namespace gfx //////////////////////////////////////////////////////////////////////////////// // @@ -16,20 +20,15 @@ class DropdownBarHost; // DropdownBarHost. // //////////////////////////////////////////////////////////////////////////////// -class DropdownBarView : public views::View { +class DropdownBarView : public AccessiblePaneView, + public DropdownBarHostDelegate { public: - explicit DropdownBarView(DropdownBarHost* host) - : host_(host), - animation_offset_(0) { - } - virtual ~DropdownBarView() {} - - // Claims focus for the text field and selects its contents. - virtual void SetFocusAndSelection(bool select_all) = 0; + explicit DropdownBarView(DropdownBarHost* host); + virtual ~DropdownBarView(); // Updates the view to let it know where the host is clipping the // dropdown widget (while animating the opening or closing of the widget). - void set_animation_offset(int offset) { animation_offset_ = offset; } + virtual void SetAnimationOffset(int offset) OVERRIDE; // Returns the offset used while animating. int animation_offset() const { return animation_offset_; } @@ -38,6 +37,22 @@ class DropdownBarView : public views::View { // Returns the DropdownBarHost that manages this view. DropdownBarHost* host() const { return host_; } + // Assign border bitmaps for this drop down instance. + void SetDialogBorderBitmaps(const SkBitmap* dialog_left, + const SkBitmap* dialog_middle, + const SkBitmap* dialog_right); + + // Paints the offset toolbar background over the widget area and returns the + // bounds of the widget. + gfx::Rect PaintOffsetToolbarBackground(gfx::Canvas* canvas); + + // Paint the border for the drop down dialog given the ends and middle + // bitmaps. + void PaintDialogBorder(gfx::Canvas* canvas, const gfx::Rect& bounds) const; + + // Special paint code for the edges when the drop down bar is animating. + void PaintAnimatingEdges(gfx::Canvas* canvas, const gfx::Rect& bounds) const; + private: // The dropdown bar host that controls this view. DropdownBarHost* host_; @@ -48,6 +63,11 @@ class DropdownBarView : public views::View { // in the right location. int animation_offset_; + // The dialog border bitmaps. + const SkBitmap* dialog_left_; + const SkBitmap* dialog_middle_; + const SkBitmap* dialog_right_; + DISALLOW_COPY_AND_ASSIGN(DropdownBarView); }; diff --git a/chrome/browser/ui/views/find_bar_host.cc b/chrome/browser/ui/views/find_bar_host.cc index 3b36f96..26bed98 100644 --- a/chrome/browser/ui/views/find_bar_host.cc +++ b/chrome/browser/ui/views/find_bar_host.cc @@ -36,7 +36,8 @@ FindBar* CreateFindBar(BrowserView* browser_view) { FindBarHost::FindBarHost(BrowserView* browser_view) : DropdownBarHost(browser_view), find_bar_controller_(NULL) { - Init(new FindBarView(this)); + FindBarView* find_bar_view = new FindBarView(this); + Init(find_bar_view, find_bar_view); } FindBarHost::~FindBarHost() { diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc index 8ecd4a1..957a028 100644 --- a/chrome/browser/ui/views/find_bar_view.cc +++ b/chrome/browser/ui/views/find_bar_view.cc @@ -67,11 +67,6 @@ static const SkBitmap* kDialog_left = NULL; static const SkBitmap* kDialog_middle = NULL; static const SkBitmap* kDialog_right = NULL; -// When we are animating, we draw only the top part of the left and right -// edges to give the illusion that the find dialog is attached to the -// window during this animation; this is the height of the items we draw. -static const int kAnimatingEdgeHeight = 5; - // The background image for the Find text box, which we draw behind the Find box // to provide the Chrome look to the edge of the text box. static const SkBitmap* kBackground = NULL; @@ -170,6 +165,7 @@ FindBarView::FindBarView(FindBarHost* host) kBackground = rb.GetBitmapNamed(IDR_FIND_BOX_BACKGROUND); kBackground_left = rb.GetBitmapNamed(IDR_FIND_BOX_BACKGROUND_LEFT); } + SetDialogBorderBitmaps(kDialog_left, kDialog_middle, kDialog_right); } FindBarView::~FindBarView() { @@ -246,25 +242,7 @@ void FindBarView::SetFocusAndSelection(bool select_all) { void FindBarView::OnPaint(gfx::Canvas* canvas) { SkPaint paint; - // Determine the find bar size as well as the offset from which to tile the - // toolbar background image. First, get the widget bounds. - gfx::Rect bounds = GetWidget()->GetWindowScreenBounds(); - // Now convert from screen to parent coordinates. - gfx::Point origin(bounds.origin()); - BrowserView* browser_view = host()->browser_view(); - ConvertPointToView(NULL, browser_view, &origin); - bounds.set_origin(origin); - // Finally, calculate the background image tiling offset. - origin = browser_view->OffsetPointForToolbarBackgroundImage(origin); - - // First, we draw the background image for the whole dialog (3 images: left, - // middle and right). Note, that the window region has been set by the - // controller, so the whitespace in the left and right background images is - // actually outside the window region and is therefore not drawn. See - // FindInPageWidgetWin::CreateRoundedWindowEdges() for details. - ui::ThemeProvider* tp = GetThemeProvider(); - canvas->TileImageInt(*tp->GetBitmapNamed(IDR_THEME_TOOLBAR), origin.x(), - origin.y(), 0, 0, bounds.width(), bounds.height()); + gfx::Rect bounds = PaintOffsetToolbarBackground(canvas); // Now flip the canvas for the rest of the graphics if in RTL mode. canvas->Save(); @@ -273,16 +251,7 @@ void FindBarView::OnPaint(gfx::Canvas* canvas) { canvas->ScaleInt(-1, 1); } - canvas->DrawBitmapInt(*kDialog_left, 0, 0); - - // Stretch the middle background to cover all of the area between the two - // other images. - canvas->TileImageInt(*kDialog_middle, kDialog_left->width(), 0, - bounds.width() - kDialog_left->width() - kDialog_right->width(), - kDialog_middle->height()); - - canvas->DrawBitmapInt(*kDialog_right, bounds.width() - kDialog_right->width(), - 0); + PaintDialogBorder(canvas, bounds); // Then we draw the background image for the Find Textfield. We start by // calculating the position of background images for the Find text box. @@ -300,15 +269,7 @@ void FindBarView::OnPaint(gfx::Canvas* canvas) { back_button_origin.x() - find_text_x, kBackground->height()); - if (animation_offset() > 0) { - // While animating we draw the curved edges at the point where the - // controller told us the top of the window is: |animation_offset()|. - canvas->TileImageInt(*kDialog_left, bounds.x(), animation_offset(), - kDialog_left->width(), kAnimatingEdgeHeight); - canvas->TileImageInt(*kDialog_right, - bounds.width() - kDialog_right->width(), animation_offset(), - kDialog_right->width(), kAnimatingEdgeHeight); - } + PaintAnimatingEdges(canvas, bounds); canvas->Restore(); } diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 46c5917..f983b42 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -41,10 +41,15 @@ #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/tabs/tab_menu_model.h" #include "chrome/browser/ui/toolbar/wrench_menu_model.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" #include "chrome/browser/ui/views/browser_dialogs.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h" +#include "chrome/browser/ui/views/compact_nav/compact_navigation_bar.h" +#include "chrome/browser/ui/views/compact_nav/compact_options_bar.h" #include "chrome/browser/ui/views/default_search_view.h" #include "chrome/browser/ui/views/download/download_in_progress_dialog_view.h" #include "chrome/browser/ui/views/download/download_shelf_view.h" @@ -78,6 +83,7 @@ #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" +#include "grit/theme_resources_standard.h" #include "grit/webkit_resources.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/l10n/l10n_util.h" @@ -304,6 +310,9 @@ BrowserView::BrowserView(Browser* browser) active_bookmark_bar_(NULL), tabstrip_(NULL), toolbar_(NULL), + compact_navigation_bar_(NULL), + compact_options_bar_(NULL), + compact_spacer_(NULL), infobar_container_(NULL), sidebar_container_(NULL), sidebar_split_(NULL), @@ -378,6 +387,11 @@ BrowserView* BrowserView::GetBrowserViewForNativeWindow( gfx::Rect BrowserView::GetToolbarBounds() const { gfx::Rect toolbar_bounds(toolbar_->bounds()); + // In compact navigation mode, the spacer essentially replaces the toolbar. + // We must provide it's height in order to have the client area divider paint + // properly. + if (UseCompactNavigationBar()) + toolbar_bounds = compact_spacer_->bounds(); if (toolbar_bounds.IsEmpty()) return toolbar_bounds; // When using vertical tabs, the toolbar appears to extend behind the tab @@ -401,6 +415,14 @@ gfx::Rect BrowserView::GetFindBarBoundingBox() const { return GetBrowserViewLayout()->GetFindBarBoundingBox(); } +gfx::Rect BrowserView::GetCompactNavigationBarBounds() const { + return compact_navigation_bar_->bounds(); +} + +gfx::Rect BrowserView::GetCompactOptionsBarBounds() const { + return compact_options_bar_->bounds(); +} + int BrowserView::GetTabStripHeight() const { // We want to return tabstrip_->height(), but we might be called in the midst // of layout, when that hasn't yet been updated to reflect the current state. @@ -432,6 +454,10 @@ bool BrowserView::UseVerticalTabs() const { return browser_->tabstrip_model()->delegate()->UseVerticalTabs(); } +bool BrowserView::UseCompactNavigationBar() const { + return browser_->tabstrip_model()->delegate()->UseCompactNavigationBar(); +} + bool BrowserView::IsOffTheRecord() const { return browser_->profile()->IsOffTheRecord(); } @@ -707,7 +733,7 @@ void BrowserView::UpdateLoadingAnimations(bool should_animate) { } void BrowserView::SetStarredState(bool is_starred) { - toolbar_->location_bar()->SetStarToggled(is_starred); + GetLocationBarView()->SetStarToggled(is_starred); } gfx::Rect BrowserView::GetRestoredBounds() const { @@ -754,11 +780,16 @@ void BrowserView::RestoreFocus() { } LocationBar* BrowserView::GetLocationBar() const { - return toolbar_->location_bar(); + return GetLocationBarView(); } void BrowserView::SetFocusToLocationBar(bool select_all) { - LocationBarView* location_bar = toolbar_->location_bar(); + if (UseCompactNavigationBar()) { + // If focus ever goes to the location bar, we should make sure it is shown + // in compact mode. This includes all accelerators that move focus there. + ShowCompactLocationBarUnderSelectedTab(); + } + LocationBarView* location_bar = GetLocationBarView(); if (location_bar->IsFocusableInRootView()) { // Location bar got focus. location_bar->FocusLocation(select_all); @@ -772,20 +803,42 @@ void BrowserView::SetFocusToLocationBar(bool select_all) { } void BrowserView::UpdateReloadStopState(bool is_loading, bool force) { - toolbar_->reload_button()->ChangeMode( + ReloadButton* reload_button = NULL; + if (UseCompactNavigationBar()) { + reload_button = compact_location_bar_view_host_-> + GetCompactLocationBarView()->reload_button(); + } else { + reload_button = toolbar_->reload_button(); + } + reload_button->ChangeMode( is_loading ? ReloadButton::MODE_STOP : ReloadButton::MODE_RELOAD, force); } void BrowserView::UpdateToolbar(TabContentsWrapper* contents, bool should_restore_state) { - toolbar_->Update(contents->tab_contents(), should_restore_state); + if (UseCompactNavigationBar()) { + if (compact_location_bar_view_host_->IsVisible()) { + compact_location_bar_view_host_->Update( + should_restore_state ? contents->tab_contents() : NULL, true); + } + } else { + toolbar_->Update(contents->tab_contents(), should_restore_state); + } } void BrowserView::FocusToolbar() { // Start the traversal within the main toolbar, passing it the storage id // of the view where focus should be returned if the user exits the toolbar. SaveFocusedView(); - toolbar_->SetPaneFocus(last_focused_view_storage_id_, NULL); + if (UseCompactNavigationBar()) { + if (!compact_location_bar_view_host_->IsVisible()) + compact_location_bar_view_host_->UpdateOnTabChange( + browser()->active_index(), true); + compact_location_bar_view_host_->GetCompactLocationBarView()->SetPaneFocus( + last_focused_view_storage_id_, NULL); + } else { + toolbar_->SetPaneFocus(last_focused_view_storage_id_, NULL); + } } void BrowserView::FocusBookmarksToolbar() { @@ -807,6 +860,7 @@ void BrowserView::FocusAppMenu() { RestoreFocus(); } else { SaveFocusedView(); + // TODO(mad): find out how to add this to compact nav view. toolbar_->SetPaneFocusAndFocusAppMenu(last_focused_view_storage_id_); } } @@ -906,8 +960,12 @@ bool BrowserView::IsTabStripEditable() const { } bool BrowserView::IsToolbarVisible() const { - return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) || - browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR); + if (UseCompactNavigationBar()) { + return false; + } else { + return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) || + browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR); + } } void BrowserView::DisableInactiveFrame() { @@ -951,6 +1009,13 @@ void BrowserView::ShowUpdateChromeDialog() { UpdateRecommendedMessageBox::ShowMessageBox(GetWindow()->GetNativeWindow()); } +void BrowserView::ShowCompactLocationBarUnderSelectedTab() { + if (!UseCompactNavigationBar()) + return; + compact_location_bar_view_host_->UpdateOnTabChange(browser()->active_index(), + true); +} + void BrowserView::ShowTaskManager() { browser::ShowTaskManager(); } @@ -960,7 +1025,7 @@ void BrowserView::ShowBackgroundPages() { } void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { - toolbar_->location_bar()->ShowStarBubble(url, !already_bookmarked); + GetLocationBarView()->ShowStarBubble(url, !already_bookmarked); } void BrowserView::SetDownloadShelfVisible(bool visible) { @@ -1061,6 +1126,7 @@ void BrowserView::ShowPageInfo(Profile* profile, } void BrowserView::ShowAppMenu() { + // TODO(mad): find out how to add this to compact nav view. toolbar_->app_menu()->Activate(); } @@ -1156,6 +1222,16 @@ void BrowserView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { #endif } +void BrowserView::ToggleUseCompactNavigationBar() { + bool use_compact_navigation_bar = UseCompactNavigationBar(); + // Compact Navigation Bar only works with horizontal tabs for now! + if (use_compact_navigation_bar && UseVerticalTabs()) + browser()->ExecuteCommand(IDC_TOGGLE_VERTICAL_TABS); + compact_location_bar_view_host_->SetEnabled(use_compact_navigation_bar); + compact_location_bar_view_host_->Hide(!use_compact_navigation_bar); + Layout(); +} + // TODO(devint): http://b/issue?id=1117225 Cut, Copy, and Paste are always // enabled in the page menu regardless of whether the command will do // anything. When someone selects the menu item, we just act as if they hit @@ -1179,6 +1255,10 @@ void BrowserView::Paste() { } void BrowserView::ToggleTabStripMode() { + // Compact Navigation Bar only works with horizontal tabs for now! + if (UseVerticalTabs() && UseCompactNavigationBar()) + browser()->ExecuteCommand(IDC_COMPACT_NAVBAR); + InitTabStrip(browser_->tabstrip_model()); frame_->TabStripDisplayModeChanged(); } @@ -1242,7 +1322,12 @@ BookmarkBarView* BrowserView::GetBookmarkBarView() const { } LocationBarView* BrowserView::GetLocationBarView() const { - return toolbar_->location_bar(); + if (UseCompactNavigationBar()) { + return compact_location_bar_view_host_->GetCompactLocationBarView()-> + location_bar_view(); + } else { + return toolbar_ ? toolbar_->location_bar() : NULL; + } } views::View* BrowserView::GetTabContentsContainerView() const { @@ -1563,8 +1648,9 @@ void BrowserView::OnWidgetMove() { browser::HideBookmarkBubbleView(); // Close the omnibox popup, if any. - if (toolbar_ && toolbar_->location_bar()) - toolbar_->location_bar()->location_entry()->ClosePopup(); + LocationBarView* location_bar_view = GetLocationBarView(); + if (location_bar_view) + location_bar_view->location_entry()->ClosePopup(); } /////////////////////////////////////////////////////////////////////////////// @@ -1843,6 +1929,27 @@ void BrowserView::Init() { browser_->tabstrip_model()->AddObserver(aeropeek_manager_.get()); } #endif + // Only create our compact navigation classes if the switch is enabled. Note + // that we directly check the switch and not the pref as the switch may be on + // and the pref could be off (currently not selected in the context menu). + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableCompactNavigation)) { + compact_location_bar_view_host_.reset(new CompactLocationBarViewHost(this)); + compact_navigation_bar_ = new CompactNavigationBar(this); + compact_navigation_bar_->SetID(VIEW_ID_COMPACT_NAV_BAR); + AddChildView(compact_navigation_bar_); + compact_navigation_bar_->Init(); + compact_options_bar_ = new CompactOptionsBar(this); + compact_options_bar_->SetID(VIEW_ID_COMPACT_OPT_BAR); + AddChildView(compact_options_bar_); + compact_options_bar_->Init(); + } + + // Use an empty view for the spacer since all it does is that it replaces the + // toolbar area in compact navigation mode. + compact_spacer_ = new views::View(); + compact_spacer_->SetID(VIEW_ID_COMPACT_NAV_BAR_SPACER); + AddChildView(compact_spacer_); // We're now initialized and ready to process Layout requests. ignore_layout_ = false; @@ -2111,7 +2218,7 @@ void BrowserView::ProcessFullscreen(bool fullscreen) { // * Ignoring all intervening Layout() calls, which resize the webpage and // thus are slow and look ugly ignore_layout_ = true; - LocationBarView* location_bar = toolbar_->location_bar(); + LocationBarView* location_bar = GetLocationBarView(); #if defined(OS_WIN) OmniboxViewWin* omnibox_view = static_cast<OmniboxViewWin*>(location_bar->location_entry()); diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index c80cee6..b15312f 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -16,6 +16,7 @@ #include "chrome/browser/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/views/compact_nav/compact_location_bar_view_host.h" #include "chrome/browser/ui/views/frame/browser_bubble_host.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/infobars/infobar_container.h" @@ -44,6 +45,9 @@ class Browser; class BrowserBubble; class BrowserViewLayout; class ContentsContainer; +class CompactLocationBar; +class CompactNavigationBar; +class CompactOptionsBar; class DownloadShelfView; class EncodingMenuModel; class FullscreenExitBubble; @@ -105,7 +109,9 @@ class BrowserView : public BrowserBubbleHost, // Returns the apparent bounds of the toolbar, in BrowserView coordinates. // These differ from |toolbar_.bounds()| in that they match where the toolbar // background image is drawn -- slightly outside the "true" bounds - // horizontally, and, when using vertical tabs, behind the tab column. + // horizontally, and, when using vertical tabs, behind the tab column. Note + // that this returns the bounds for the toolbar area, which could just be the + // spacer bounds if in compact navigation mode. virtual gfx::Rect GetToolbarBounds() const; // Returns the bounds of the content area, in the coordinates of the @@ -119,6 +125,14 @@ class BrowserView : public BrowserBubbleHost, // window. gfx::Rect GetFindBarBoundingBox() const; + // Returns the bounds of the compact navigation bar (back and forward + // buttons). + gfx::Rect GetCompactNavigationBarBounds() const; + + // Returns the bounds of the compact options bar (browser actions and app + // menu). + gfx::Rect GetCompactOptionsBarBounds() const; + // Returns the preferred height of the TabStrip. Used to position the OTR // avatar icon. virtual int GetTabStripHeight() const; @@ -144,6 +158,9 @@ class BrowserView : public BrowserBubbleHost, // Returns true if the vertical tabstrip is in use. bool UseVerticalTabs() const; + // Returns true if the compact navigation bar is in use. + bool UseCompactNavigationBar() const; + // Returns true if the profile associated with this Browser window is // incognito. bool IsOffTheRecord() const; @@ -226,6 +243,11 @@ class BrowserView : public BrowserBubbleHost, // when a new browser window is created. void RestoreFocus(); + // Access the CompactLocationBarHost. + CompactLocationBarViewHost* compact_location_bar_view_host() { + return compact_location_bar_view_host_.get(); + } + // Overridden from BrowserWindow: virtual void Show() OVERRIDE; virtual void ShowInactive() OVERRIDE; @@ -304,6 +326,7 @@ class BrowserView : public BrowserBubbleHost, OVERRIDE; virtual void ShowCreateChromeAppShortcutsDialog( Profile*, const Extension* app) OVERRIDE; + virtual void ToggleUseCompactNavigationBar() OVERRIDE; virtual void Cut() OVERRIDE; virtual void Copy() OVERRIDE; virtual void Paste() OVERRIDE; @@ -436,6 +459,7 @@ class BrowserView : public BrowserBubbleHost, private: friend class BrowserViewLayout; + friend class CompactLocationBarHostTest; FRIEND_TEST_ALL_PREFIXES(BrowserViewsAccessibilityTest, TestAboutChromeViewAccObj); @@ -526,7 +550,10 @@ class BrowserView : public BrowserBubbleHost, // Shows the about chrome modal dialog and returns the Window object. views::Window* DoShowAboutChromeDialog(); - // Set the value of |toolbar_| and hook it into the views hiearchy + // Shows the Compact Location Bar under the selected tab. + void ShowCompactLocationBarUnderSelectedTab(); + + // Set the value of |toolbar_| and hook it into the views hierarchy void SetToolbar(ToolbarView* toolbar); // Last focused view that issued a tab traversal. @@ -590,6 +617,19 @@ class BrowserView : public BrowserBubbleHost, // The Toolbar containing the navigation buttons, menus and the address bar. ToolbarView* toolbar_; + // CompactNavigationBar view. + CompactNavigationBar* compact_navigation_bar_; + + // CompactOptionsBar view. + CompactOptionsBar* compact_options_bar_; + + // CompactLocationBarHost. + scoped_ptr<CompactLocationBarViewHost> compact_location_bar_view_host_; + + // A spacer under the tap strip used when the compact navigation bar + // is active. + views::View* compact_spacer_; + // The Bookmark Bar View for this window. Lazily created. scoped_ptr<BookmarkBarView> bookmark_bar_view_; diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc index ff63aa9..1cde2ac 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout.cc @@ -34,6 +34,29 @@ namespace { const int kTabShadowSize = 2; // The vertical overlap between the TabStrip and the Toolbar. const int kToolbarTabStripVerticalOverlap = 3; +// The vertical size of the space between the content area and the tabstrip that +// is inserted in compact navigation mode. Note that we need to use a height +// that includes the overlap to get the visible height we want, in order to +// match how the toolbar overlaps the tabstrip. +const int kCompactNavbarSpacerVisibleHeight = 4; +const int kCompactNavbarSpacerHeight = + kCompactNavbarSpacerVisibleHeight + kToolbarTabStripVerticalOverlap; +// The size of the padding between the compact navigation bar and the tab strip. +const int kCompactNavbarHorizontalPadding = 2; +// The number of pixels the bookmark bar should overlap the spacer by if the +// spacer is visible. +const int kSpacerBookmarkBarOverlap = 1; + +// Combines View::ConvertPointToView and View::HitTest for a given |point|. +// Converts |point| from |src| to |dst| and hit tests it against |dst|. The +// converted |point| can then be retrieved and used for additional tests. +bool ConvertedHitTest(views::View* src, views::View* dst, gfx::Point* point) { + DCHECK(src); + DCHECK(dst); + DCHECK(point); + views::View::ConvertPointToView(src, dst, point); + return dst->HitTest(*point); +} } // namespace @@ -46,6 +69,9 @@ BrowserViewLayout::BrowserViewLayout() contents_split_(NULL), contents_container_(NULL), infobar_container_(NULL), + compact_navigation_bar_(NULL), + compact_options_bar_(NULL), + compact_spacer_(NULL), download_shelf_(NULL), active_bookmark_bar_(NULL), browser_view_(NULL), @@ -138,20 +164,29 @@ int BrowserViewLayout::NonClientHitTest( gfx::Point point_in_browser_view_coords(point); views::View::ConvertPointToView( parent, browser_view_, &point_in_browser_view_coords); + gfx::Point test_point(point); // Determine if the TabStrip exists and is capable of being clicked on. We // might be a popup window without a TabStrip. if (browser_view_->IsTabStripVisible()) { // See if the mouse pointer is within the bounds of the TabStrip. - gfx::Point point_in_tabstrip_coords(point); - views::View::ConvertPointToView(parent, tabstrip_, - &point_in_tabstrip_coords); - if (tabstrip_->HitTest(point_in_tabstrip_coords)) { - if (tabstrip_->IsPositionInWindowCaption(point_in_tabstrip_coords)) + if (ConvertedHitTest(parent, tabstrip_, &test_point)) { + if (tabstrip_->IsPositionInWindowCaption(test_point)) return HTCAPTION; return HTCLIENT; } + // If the tabstrip is visible and we are in compact navigation mode, test + // against the compact navigation and option bars. + if (browser_view_->UseCompactNavigationBar()) { + test_point = point; + if (ConvertedHitTest(parent, compact_navigation_bar_, &test_point)) + return HTCLIENT; + test_point = point; + if (ConvertedHitTest(parent, compact_options_bar_, &test_point)) + return HTCLIENT; + } + // The top few pixels of the TabStrip are a drop-shadow - as we're pretty // starved of dragable area, let's give it to window dragging (this also // makes sense visually). @@ -204,6 +239,9 @@ void BrowserViewLayout::Installed(views::View* host) { download_shelf_ = NULL; active_bookmark_bar_ = NULL; tabstrip_ = NULL; + compact_navigation_bar_ = NULL; + compact_options_bar_ = NULL; + compact_spacer_ = NULL; browser_view_ = static_cast<BrowserView*>(host); } @@ -234,6 +272,15 @@ void BrowserViewLayout::ViewAdded(views::View* host, views::View* view) { case VIEW_ID_TAB_STRIP: tabstrip_ = static_cast<AbstractTabStripView*>(view); break; + case VIEW_ID_COMPACT_NAV_BAR_SPACER: + compact_spacer_ = view; + break; + case VIEW_ID_COMPACT_NAV_BAR: + compact_navigation_bar_ = view; + break; + case VIEW_ID_COMPACT_OPT_BAR: + compact_options_bar_ = view; + break; } } @@ -247,7 +294,7 @@ void BrowserViewLayout::ViewRemoved(views::View* host, views::View* view) { void BrowserViewLayout::Layout(views::View* host) { vertical_layout_rect_ = browser_view_->GetLocalBounds(); - int top = LayoutTabStrip(); + int top = LayoutTabStripRegion(); if (browser_view_->IsTabStripVisible() && !browser_view_->UseVerticalTabs()) { tabstrip_->SetBackgroundOffset(gfx::Point( tabstrip_->GetMirroredX() + browser_view_->GetMirroredX(), @@ -268,6 +315,11 @@ void BrowserViewLayout::Layout(views::View* host) { browser()->GetFindBarController()->find_bar()->MoveWindowIfNecessary( gfx::Rect(), true); } + if (browser()->UseCompactNavigationBar()) { + DCHECK(browser_view_->compact_location_bar_view_host()); + browser_view_->compact_location_bar_view_host()->MoveWindowIfNecessary( + gfx::Rect(), true); + } } // Return the preferred size which is the size required to give each @@ -287,13 +339,19 @@ const Browser* BrowserViewLayout::browser() const { return browser_view_->browser(); } -int BrowserViewLayout::LayoutTabStrip() { +int BrowserViewLayout::LayoutTabStripRegion() { if (!browser_view_->IsTabStripVisible()) { + if (compact_navigation_bar_ && compact_options_bar_) { + compact_navigation_bar_->SetVisible(false); + compact_options_bar_->SetVisible(false); + } tabstrip_->SetVisible(false); tabstrip_->SetBounds(0, 0, 0, 0); return 0; } + // This retrieves the bounds for the tab strip based on whether or not we show + // anything to the left of it, like the incognito avatar. gfx::Rect tabstrip_bounds( browser_view_->frame()->GetBoundsForTabStrip(tabstrip_)); gfx::Point tabstrip_origin(tabstrip_bounds.origin()); @@ -301,6 +359,41 @@ int BrowserViewLayout::LayoutTabStrip() { &tabstrip_origin); tabstrip_bounds.set_origin(tabstrip_origin); + // If we are in compact nav mode, we want to reduce the tab strip bounds from + // both ends enough to lay out the compact navigation and options bars. We + // check the pointers to see if the mode is available, and then check the pref + // to see if the mode is enabled (and therefore if the additional bars should + // be made visible). + if (compact_navigation_bar_ && compact_options_bar_) { + compact_navigation_bar_->SetVisible( + browser_view_->UseCompactNavigationBar()); + compact_options_bar_->SetVisible(browser_view_->UseCompactNavigationBar()); + + if (compact_navigation_bar_->IsVisible()) { + gfx::Rect cnav_bar_bounds; + gfx::Size cnav_bar_size = compact_navigation_bar_->GetPreferredSize(); + cnav_bar_bounds.set_origin(tabstrip_bounds.origin()); + cnav_bar_bounds.set_size(cnav_bar_size); + compact_navigation_bar_->SetBoundsRect(cnav_bar_bounds); + + // The options bar is flush right of the tab strip region. + gfx::Rect copt_bar_bounds; + gfx::Size copt_bar_size = compact_options_bar_->GetPreferredSize(); + copt_bar_bounds.set_x(std::max(0, tabstrip_bounds.right() - + copt_bar_size.width())); + copt_bar_bounds.set_y(tabstrip_origin.y()); + copt_bar_bounds.set_size(copt_bar_size); + compact_options_bar_->SetBoundsRect(copt_bar_bounds); + + // Reduce the bounds of the tab strip accordingly. + tabstrip_bounds.set_x(tabstrip_bounds.x() + cnav_bar_size.width() + + kCompactNavbarHorizontalPadding); + tabstrip_bounds.set_width(std::max(0, tabstrip_bounds.width() - + cnav_bar_size.width() - copt_bar_size.width() - + kCompactNavbarHorizontalPadding * 2)); + } + } + if (browser_view_->UseVerticalTabs()) vertical_layout_rect_.Inset(tabstrip_bounds.width(), 0, 0, 0); @@ -312,16 +405,26 @@ int BrowserViewLayout::LayoutTabStrip() { int BrowserViewLayout::LayoutToolbar(int top) { int browser_view_width = vertical_layout_rect_.width(); - bool visible = browser_view_->IsToolbarVisible(); - toolbar_->location_bar()->SetFocusable(visible); + bool toolbar_visible = browser_view_->IsToolbarVisible(); + toolbar_->location_bar()->SetFocusable(toolbar_visible); int y = top; if (!browser_view_->UseVerticalTabs()) { - y -= ((visible && browser_view_->IsTabStripVisible()) ? - kToolbarTabStripVerticalOverlap : 0); + y -= ((toolbar_visible || browser_view_->UseCompactNavigationBar()) && + browser_view_->IsTabStripVisible()) ? + kToolbarTabStripVerticalOverlap : 0; } - int height = visible ? toolbar_->GetPreferredSize().height() : 0; - toolbar_->SetVisible(visible); + int height = toolbar_visible ? toolbar_->GetPreferredSize().height() : 0; + toolbar_->SetVisible(toolbar_visible); toolbar_->SetBounds(vertical_layout_rect_.x(), y, browser_view_width, height); + + // The spacer essentially replaces the toolbar when in compact mode. + if (browser_view_->UseCompactNavigationBar()) { + compact_spacer_->SetVisible(!toolbar_visible); + compact_spacer_->SetBounds(vertical_layout_rect_.x(), y, browser_view_width, + toolbar_visible ? 0 : kCompactNavbarSpacerHeight); + height = kCompactNavbarSpacerHeight; + } + return y + height; } @@ -351,8 +454,12 @@ int BrowserViewLayout::LayoutBookmarkBar(int top) { active_bookmark_bar_->set_infobar_visible(InfobarVisible()); int bookmark_bar_height = active_bookmark_bar_->GetPreferredSize().height(); - y -= views::NonClientFrameView::kClientEdgeThickness + - active_bookmark_bar_->GetToolbarOverlap(false); + if (!browser_view_->UseCompactNavigationBar()) { + y -= views::NonClientFrameView::kClientEdgeThickness + + active_bookmark_bar_->GetToolbarOverlap(false); + } else { + y -= kSpacerBookmarkBarOverlap; + } active_bookmark_bar_->SetVisible(true); active_bookmark_bar_->SetBounds(vertical_layout_rect_.x(), y, vertical_layout_rect_.width(), diff --git a/chrome/browser/ui/views/frame/browser_view_layout.h b/chrome/browser/ui/views/frame/browser_view_layout.h index 728b97c..e7a3742 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout.h +++ b/chrome/browser/ui/views/frame/browser_view_layout.h @@ -62,9 +62,11 @@ class BrowserViewLayout : public views::LayoutManager { Browser* browser(); const Browser* browser() const; - // Layout the TabStrip, returns the coordinate of the bottom of the TabStrip, - // for laying out subsequent controls. - virtual int LayoutTabStrip(); + // Layout the tab strip region, returns the coordinate of the bottom of the + // TabStrip, for laying out subsequent controls. This also lays out the + // compact navigation and options bars if the browser is in compact navigation + // mode. + virtual int LayoutTabStripRegion(); // Layout the following controls, starting at |top|, returns the coordinate // of the bottom of the control, for laying out the next control. @@ -112,6 +114,9 @@ class BrowserViewLayout : public views::LayoutManager { views::SingleSplitView* contents_split_; ContentsContainer* contents_container_; views::View* infobar_container_; + views::View* compact_navigation_bar_; + views::View* compact_options_bar_; + views::View* compact_spacer_; DownloadShelfView* download_shelf_; BookmarkBarView* active_bookmark_bar_; diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 69f3565..da4ca70 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc @@ -106,6 +106,19 @@ const int kMenuDisplayOffset = 7; const int kProfileTagYPosition = 1; // Offset y position of profile button and tag by this amount when maximized. const int kProfileElementMaximizedYOffset = 6; + +// Converts |bounds| from |src|'s coordinate system to |dst|, and checks if +// |pt| is contained within. +bool ConvertedContainsCheck(gfx::Rect bounds, const views::View* src, + const views::View* dst, const gfx::Point& pt) { + DCHECK(src); + DCHECK(dst); + gfx::Point origin(bounds.origin()); + views::View::ConvertPointToView(src, dst, &origin); + bounds.set_origin(origin); + return bounds.Contains(pt); +} + } /////////////////////////////////////////////////////////////////////////////// @@ -443,7 +456,8 @@ void OpaqueBrowserFrameView::OnPaint(gfx::Canvas* canvas) { else PaintRestoredFrameBorder(canvas); PaintTitleBar(canvas); - if (browser_view_->IsToolbarVisible()) + if (browser_view_->IsToolbarVisible() || + browser_view_->UseCompactNavigationBar()) PaintToolbarBackground(canvas); if (browser_view_->ShouldShowOffTheRecordAvatar()) PaintOTRAvatar(canvas); @@ -477,6 +491,22 @@ bool OpaqueBrowserFrameView::HitTest(const gfx::Point& l) const { return false; } + // Claim it only if we're also not in the compact navigation buttons. + if (browser_view_->UseCompactNavigationBar()) { + if (ConvertedContainsCheck(browser_view_->GetCompactNavigationBarBounds(), + frame_->GetWindow()->client_view(), + static_cast<const View*>(this), + l)) { + return false; + } + if (ConvertedContainsCheck(browser_view_->GetCompactOptionsBarBounds(), + frame_->GetWindow()->client_view(), + static_cast<const View*>(this), + l)) { + return false; + } + } + // We convert from our parent's coordinates since we assume we fill its bounds // completely. We need to do this since we're not a parent of the tabstrip, // meaning ConvertPointToView would otherwise return something bogus. @@ -962,9 +992,10 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); SkColor toolbar_color = tp->GetColor(ThemeService::COLOR_TOOLBAR); - if (browser_view_->IsToolbarVisible()) { + if (browser_view_->IsToolbarVisible() || + browser_view_->UseCompactNavigationBar()) { // The client edge images always start below the toolbar corner images. The - // client edge filled rects start there or at the bottom of the tooolbar, + // client edge filled rects start there or at the bottom of the toolbar, // whichever is shorter. gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds()); image_top += toolbar_bounds.y() + diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index d64fc59..05262f5 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -120,7 +120,8 @@ LocationBarView::LocationBarView(Profile* profile, mode_(mode), show_focus_rect_(false), bubble_type_(FirstRun::MINIMAL_BUBBLE), - template_url_model_(NULL) { + template_url_model_(NULL), + animation_offset_(0) { DCHECK(profile_); SetID(VIEW_ID_LOCATION_BAR); SetFocusable(true); @@ -269,6 +270,15 @@ SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level, } } +// DropdownBarHostDelegate +void LocationBarView::SetFocusAndSelection(bool select_all) { + FocusLocation(select_all); +} + +void LocationBarView::SetAnimationOffset(int offset) { + animation_offset_ = offset; +} + void LocationBarView::Update(const TabContents* tab_for_state_restoring) { bool star_enabled = star_view_ && !model_->input_in_progress() && edit_bookmarks_enabled_.GetValue(); diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index 4d6ac50..6947520 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h @@ -18,6 +18,8 @@ #include "chrome/browser/search_engines/template_url_model_observer.h" #include "chrome/browser/ui/omnibox/location_bar.h" #include "chrome/browser/ui/toolbar/toolbar_model.h" +#include "chrome/browser/ui/views/dropdown_bar_host.h" +#include "chrome/browser/ui/views/dropdown_bar_host_delegate.h" #include "chrome/browser/ui/views/extensions/extension_popup.h" #include "ui/gfx/font.h" #include "ui/gfx/rect.h" @@ -48,7 +50,7 @@ class TemplateURLModel; namespace views { class HorizontalPainter; class Label; -}; +} // namespace views #if defined(OS_WIN) class SuggestedTextView; @@ -67,12 +69,20 @@ class LocationBarView : public LocationBar, public views::View, public views::DragController, public AutocompleteEditController, + public DropdownBarHostDelegate, public TemplateURLModelObserver, public NotificationObserver { public: // The location bar view's class name. static const char kViewClassName[]; + // DropdownBarHostDelegate + virtual void SetFocusAndSelection(bool select_all) OVERRIDE; + virtual void SetAnimationOffset(int offset) OVERRIDE; + + // Returns the offset used while animating. + int animation_offset() const { return animation_offset_; } + class Delegate { public: // Should return the current tab contents. @@ -412,6 +422,12 @@ class LocationBarView : public LocationBar, // Tracks this preference to determine whether bookmark editing is allowed. BooleanPrefMember edit_bookmarks_enabled_; + // While animating, the host clips the widget and draws only the bottom + // part of it. The view needs to know the pixel offset at which we are drawing + // the widget so that we can draw the curved edges that attach to the toolbar + // in the right location. + int animation_offset_; + DISALLOW_IMPLICIT_CONSTRUCTORS(LocationBarView); }; diff --git a/chrome/browser/ui/views/tabs/base_tab.cc b/chrome/browser/ui/views/tabs/base_tab.cc index 9368313..79c0189 100644 --- a/chrome/browser/ui/views/tabs/base_tab.cc +++ b/chrome/browser/ui/views/tabs/base_tab.cc @@ -301,6 +301,8 @@ bool BaseTab::OnMousePressed(const views::MouseEvent& event) { } } else if (!IsSelected()) { controller()->SelectTab(this); + } else if (IsActive()) { + controller()->ClickActiveTab(this); } controller()->MaybeStartDrag(this, event); } diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.cc b/chrome/browser/ui/views/tabs/base_tab_strip.cc index 2a980df..8178edd 100644 --- a/chrome/browser/ui/views/tabs/base_tab_strip.cc +++ b/chrome/browser/ui/views/tabs/base_tab_strip.cc @@ -375,6 +375,13 @@ BaseTab* BaseTabStrip::GetTabAt(BaseTab* tab, return GetTabAtLocal(local_point); } +void BaseTabStrip::ClickActiveTab(const BaseTab* tab) const { + DCHECK(IsActiveTab(tab)); + int index = GetModelIndexOfBaseTab(tab); + if (controller() && IsValidModelIndex(index)) + controller()->ClickActiveTab(index); +} + void BaseTabStrip::Layout() { // Only do a layout if our size changed. if (last_layout_size_ == size()) diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.h b/chrome/browser/ui/views/tabs/base_tab_strip.h index 14254cb..ff82b58 100644 --- a/chrome/browser/ui/views/tabs/base_tab_strip.h +++ b/chrome/browser/ui/views/tabs/base_tab_strip.h @@ -133,6 +133,7 @@ class BaseTabStrip : public AbstractTabStripView, virtual bool EndDrag(bool canceled) OVERRIDE; virtual BaseTab* GetTabAt(BaseTab* tab, const gfx::Point& tab_in_tab_coordinates) OVERRIDE; + virtual void ClickActiveTab(const BaseTab* tab) const OVERRIDE; // View overrides: virtual void Layout() OVERRIDE; diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index b77e496..299dd7a 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc @@ -309,6 +309,11 @@ void BrowserTabStripController::CreateNewTab() { model_->delegate()->AddBlankTab(true); } +void BrowserTabStripController::ClickActiveTab(int index) { + DCHECK(model_->active_index() == index); + model_->ActiveTabClicked(index); +} + //////////////////////////////////////////////////////////////////////////////// // BrowserTabStripController, TabStripModelObserver implementation: diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 47fbad4..31e2af9 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h @@ -63,6 +63,7 @@ class BrowserTabStripController : public TabStripController, const GURL& url) OVERRIDE; virtual bool IsCompatibleWith(BaseTabStrip* other) const OVERRIDE; virtual void CreateNewTab() OVERRIDE; + virtual void ClickActiveTab(int index) OVERRIDE; // TabStripModelObserver implementation: virtual void TabInsertedAt(TabContentsWrapper* contents, diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index a95df6c..610e353 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h @@ -65,6 +65,10 @@ class TabController { virtual BaseTab* GetTabAt(BaseTab* tab, const gfx::Point& tab_in_tab_coordinates) = 0; + // Informs that an active tab is selected when already active (ie - clicked + // when already active/foreground). + virtual void ClickActiveTab(const BaseTab* tab) const = 0; + protected: virtual ~TabController() {} }; diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index 674431c..b97ca4a 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h @@ -81,6 +81,10 @@ class TabStripController { // Creates the new tab. virtual void CreateNewTab() = 0; + + // Informs that an active tab is selected when already active (ie - clicked + // when already active/foreground). + virtual void ClickActiveTab(int index) = 0; }; #endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_ diff --git a/chrome/browser/ui/views/toolbar_view.cc b/chrome/browser/ui/views/toolbar_view.cc index 3e62081..09c6d89 100644 --- a/chrome/browser/ui/views/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar_view.cc @@ -254,6 +254,61 @@ void ToolbarView::RemoveMenuListener(views::MenuListener* listener) { } } +SkBitmap ToolbarView::GetAppMenuIcon(views::CustomButton::ButtonState state) { + ui::ThemeProvider* tp = GetThemeProvider(); + + int id = 0; + switch (state) { + case views::CustomButton::BS_NORMAL: id = IDR_TOOLS; break; + case views::CustomButton::BS_HOT: id = IDR_TOOLS_H; break; + case views::CustomButton::BS_PUSHED: id = IDR_TOOLS_P; break; + default: NOTREACHED(); break; + } + SkBitmap icon = *tp->GetBitmapNamed(id); + +#if defined(OS_WIN) + // Keep track of whether we were showing the badge before, so we don't send + // multiple UMA events for example when multiple Chrome windows are open. + static bool incompatibility_badge_showing = false; + // Save the old value before resetting it. + bool was_showing = incompatibility_badge_showing; + incompatibility_badge_showing = false; +#endif + + bool add_badge = IsUpgradeRecommended() || ShouldShowIncompatibilityWarning(); + if (!add_badge) + return icon; + + // Draw the chrome app menu icon onto the canvas. + scoped_ptr<gfx::CanvasSkia> canvas( + new gfx::CanvasSkia(icon.width(), icon.height(), false)); + canvas->DrawBitmapInt(icon, 0, 0); + + SkBitmap badge; + // Only one badge can be active at any given time. The Upgrade notification + // is deemed most important, then the DLL conflict badge. + if (IsUpgradeRecommended()) { + badge = *tp->GetBitmapNamed( + UpgradeDetector::GetInstance()->GetIconResourceID( + UpgradeDetector::UPGRADE_ICON_TYPE_BADGE)); + } else if (ShouldShowIncompatibilityWarning()) { +#if defined(OS_WIN) + if (!was_showing) + UserMetrics::RecordAction(UserMetricsAction("ConflictBadge")); + badge = *tp->GetBitmapNamed(IDR_CONFLICT_BADGE); + incompatibility_badge_showing = true; +#else + NOTREACHED(); +#endif + } else { + NOTREACHED(); + } + + canvas->DrawBitmapInt(badge, icon.width() - badge.width(), kBadgeTopMargin); + + return canvas->ExtractBitmap(); +} + //////////////////////////////////////////////////////////////////////////////// // ToolbarView, AccessiblePaneView overrides: @@ -655,58 +710,3 @@ void ToolbarView::UpdateAppMenuBadge() { app_menu_->SetPushedIcon(GetAppMenuIcon(views::CustomButton::BS_PUSHED)); SchedulePaint(); } - -SkBitmap ToolbarView::GetAppMenuIcon(views::CustomButton::ButtonState state) { - ui::ThemeProvider* tp = GetThemeProvider(); - - int id = 0; - switch (state) { - case views::CustomButton::BS_NORMAL: id = IDR_TOOLS; break; - case views::CustomButton::BS_HOT: id = IDR_TOOLS_H; break; - case views::CustomButton::BS_PUSHED: id = IDR_TOOLS_P; break; - default: NOTREACHED(); break; - } - SkBitmap icon = *tp->GetBitmapNamed(id); - -#if defined(OS_WIN) - // Keep track of whether we were showing the badge before, so we don't send - // multiple UMA events for example when multiple Chrome windows are open. - static bool incompatibility_badge_showing = false; - // Save the old value before resetting it. - bool was_showing = incompatibility_badge_showing; - incompatibility_badge_showing = false; -#endif - - bool add_badge = IsUpgradeRecommended() || ShouldShowIncompatibilityWarning(); - if (!add_badge) - return icon; - - // Draw the chrome app menu icon onto the canvas. - scoped_ptr<gfx::CanvasSkia> canvas( - new gfx::CanvasSkia(icon.width(), icon.height(), false)); - canvas->DrawBitmapInt(icon, 0, 0); - - SkBitmap badge; - // Only one badge can be active at any given time. The Upgrade notification - // is deemed most important, then the DLL conflict badge. - if (IsUpgradeRecommended()) { - badge = *tp->GetBitmapNamed( - UpgradeDetector::GetInstance()->GetIconResourceID( - UpgradeDetector::UPGRADE_ICON_TYPE_BADGE)); - } else if (ShouldShowIncompatibilityWarning()) { -#if defined(OS_WIN) - if (!was_showing) - UserMetrics::RecordAction(UserMetricsAction("ConflictBadge")); - badge = *tp->GetBitmapNamed(IDR_CONFLICT_BADGE); - incompatibility_badge_showing = true; -#else - NOTREACHED(); -#endif - } else { - NOTREACHED(); - } - - canvas->DrawBitmapInt(badge, icon.width() - badge.width(), kBadgeTopMargin); - - return canvas->ExtractBitmap(); -} diff --git a/chrome/browser/ui/views/toolbar_view.h b/chrome/browser/ui/views/toolbar_view.h index 1a0dc8d..04a0a04 100644 --- a/chrome/browser/ui/views/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar_view.h @@ -79,6 +79,10 @@ class ToolbarView : public AccessiblePaneView, // Remove a menu listener. void RemoveMenuListener(views::MenuListener* listener); + // Gets a bitmap with the icon for the app menu and any overlaid notification + // badge. + SkBitmap GetAppMenuIcon(views::CustomButton::ButtonState state); + virtual bool GetAcceleratorInfo(int id, ui::Accelerator* accel); // Accessors... @@ -170,10 +174,6 @@ class ToolbarView : public AccessiblePaneView, // Updates the badge on the app menu (Wrench). void UpdateAppMenuBadge(); - // Gets a bitmap with the icon for the app menu and any overlaid notification - // badge. - SkBitmap GetAppMenuIcon(views::CustomButton::ButtonState state); - // Gets a badge for the wrench icon corresponding to the number of // unacknowledged background pages in the system. SkBitmap GetBackgroundPageBadge(); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index dec0729..e459178 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2913,6 +2913,14 @@ 'browser/ui/views/chrome_views_delegate.h', 'browser/ui/views/collected_cookies_win.cc', 'browser/ui/views/collected_cookies_win.h', + 'browser/ui/views/compact_nav/compact_location_bar_view.cc', + 'browser/ui/views/compact_nav/compact_location_bar_view.h', + 'browser/ui/views/compact_nav/compact_location_bar_view_host.cc', + 'browser/ui/views/compact_nav/compact_location_bar_view_host.h', + 'browser/ui/views/compact_nav/compact_navigation_bar.cc', + 'browser/ui/views/compact_nav/compact_navigation_bar.h', + 'browser/ui/views/compact_nav/compact_options_bar.cc', + 'browser/ui/views/compact_nav/compact_options_bar.h', 'browser/ui/views/constrained_html_delegate_gtk.cc', 'browser/ui/views/constrained_html_delegate_win.cc', 'browser/ui/views/constrained_window_views.cc', @@ -2943,8 +2951,10 @@ 'browser/ui/views/download/download_started_animation_win.cc', 'browser/ui/views/dropdown_bar_host.cc', 'browser/ui/views/dropdown_bar_host.h', + 'browser/ui/views/dropdown_bar_host_delegate.h', 'browser/ui/views/dropdown_bar_host_gtk.cc', 'browser/ui/views/dropdown_bar_host_win.cc', + 'browser/ui/views/dropdown_bar_view.cc', 'browser/ui/views/dropdown_bar_view.h', 'browser/ui/views/edit_search_engine_dialog.cc', 'browser/ui/views/edit_search_engine_dialog.h', @@ -3987,6 +3997,14 @@ ['include', '^browser/ui/views/bubble/bubble_border.cc'], ['include', '^browser/ui/views/bubble/bubble_border.h'], ['include', '^browser/ui/views/chrome_views_delegate.cc'], + ['include', '^browser/ui/views/compact_nav/compact_location_bar_view.cc'], + ['include', '^browser/ui/views/compact_nav/compact_location_bar_view.h'], + ['include', '^browser/ui/views/compact_nav/compact_location_bar_view_host.cc'], + ['include', '^browser/ui/views/compact_nav/compact_location_bar_view_host.h'], + ['include', '^browser/ui/views/compact_nav/compact_navigation_bar.cc'], + ['include', '^browser/ui/views/compact_nav/compact_navigation_bar.h'], + ['include', '^browser/ui/views/compact_nav/compact_options_bar.cc'], + ['include', '^browser/ui/views/compact_nav/compact_options_bar.h'], ['include', '^browser/ui/views/constrained_html_delegate_gtk.cc'], ['include', '^browser/ui/views/content_setting_bubble_contents.cc'], ['include', '^browser/ui/views/content_setting_bubble_contents.h'], @@ -4008,6 +4026,7 @@ ['include', '^browser/ui/views/dropdown_bar_host.cc'], ['include', '^browser/ui/views/dropdown_bar_host.h'], ['include', '^browser/ui/views/dropdown_bar_host_gtk.cc'], + ['include', '^browser/ui/views/dropdown_bar_view.cc'], ['include', '^browser/ui/views/dropdown_bar_view.h'], ['include', '^browser/ui/views/event_utils.cc'], ['include', '^browser/ui/views/event_utils.h'], diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 6325a44..0d0ec20 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -384,6 +384,10 @@ const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy"; // Enables the Cloud Print dialog hosting code. const char kEnableCloudPrint[] = "enable-cloud-print"; +// Enables compact navigation mode, which removes the toolbar and moves most of +// UI to the tab strip. +const char kEnableCompactNavigation[] = "enable-compact-navigation"; + // Enables compositing to texture instead of display. const char kEnableCompositeToTexture[] = "enable-composite-to-texture"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index e720ac1..625864f 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -117,6 +117,7 @@ extern const char kEnableClearServerData[]; extern const char kEnableClickToPlay[]; extern const char kEnableCloudPrintProxy[]; extern const char kEnableCloudPrint[]; +extern const char kEnableCompactNavigation[]; extern const char kEnableCompositeToTexture[]; extern const char kEnableConnectBackupJobs[]; extern const char kEnableCrxlessWebApps[]; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index baf048d..603ccf6 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -685,6 +685,9 @@ const char kEditBookmarksEnabled[] = "bookmarks.editing_enabled"; // side of the browser window. const char kUseVerticalTabs[] = "tabs.use_vertical_tabs"; +// Boolean that is true when the compact navigation bar is to be used. +const char kUseCompactNavigationBar[] = "tabs.use_compact_navigation_bar"; + // Boolean that is true when the translate feature is enabled. const char kEnableTranslate[] = "translate.enabled"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index bae339b..b2f4841 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -240,6 +240,7 @@ extern const char kAutofillPersonalDataManagerFirstRun[]; extern const char kEditBookmarksEnabled[]; extern const char kUseVerticalTabs[]; +extern const char kUseCompactNavigationBar[]; extern const char kEnableTranslate[]; extern const char kEnableBookmarkBar[]; extern const char kPinnedTabs[]; diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index 9048c40..7116897 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -59,9 +59,7 @@ class TestBrowserWindow : public BrowserWindow { TabContentsWrapper* tab_contents) {} virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, const Extension* app) {} -#if defined(TOOLKIT_VIEWS) - virtual void ToggleCompactNavigationBar() {} -#endif // defined(TOOLKIT_VIEWS) + virtual void ToggleUseCompactNavigationBar() {} virtual bool IsBookmarkBarVisible() const; virtual bool IsBookmarkBarAnimating() const; diff --git a/views/events/event.h b/views/events/event.h index 5ede973..924a350 100644 --- a/views/events/event.h +++ b/views/events/event.h @@ -27,6 +27,11 @@ namespace views { class RootView; class View; +#if defined(OS_WIN) +bool IsClientMouseEvent(const views::NativeEvent& native_event); +bool IsNonClientMouseEvent(const views::NativeEvent& native_event); +#endif + //////////////////////////////////////////////////////////////////////////////// // // Event class diff --git a/views/events/event_win.cc b/views/events/event_win.cc index 06c892c..9e063d3 100644 --- a/views/events/event_win.cc +++ b/views/events/event_win.cc @@ -74,20 +74,6 @@ ui::EventType EventTypeFromNative(NativeEvent native_event) { return ui::ET_UNKNOWN; } -bool IsClientMouseEvent(NativeEvent native_event) { - return native_event.message == WM_MOUSELEAVE || - native_event.message == WM_MOUSEHOVER || - (native_event.message >= WM_MOUSEFIRST && - native_event.message <= WM_MOUSELAST); -} - -bool IsNonClientMouseEvent(NativeEvent native_event) { - return native_event.message == WM_NCMOUSELEAVE || - native_event.message == WM_NCMOUSEHOVER || - (native_event.message >= WM_NCMOUSEMOVE && - native_event.message <= WM_NCXBUTTONDBLCLK); -} - // Get views::Event flags from a native Windows message int EventFlagsFromNative(NativeEvent native_event) { int flags = 0; @@ -172,6 +158,20 @@ int EventFlagsFromNative(NativeEvent native_event) { } // namespace +bool IsClientMouseEvent(const views::NativeEvent& native_event) { + return native_event.message == WM_MOUSELEAVE || + native_event.message == WM_MOUSEHOVER || + (native_event.message >= WM_MOUSEFIRST && + native_event.message <= WM_MOUSELAST); +} + +bool IsNonClientMouseEvent(const views::NativeEvent& native_event) { + return native_event.message == WM_NCMOUSELEAVE || + native_event.message == WM_NCMOUSEHOVER || + (native_event.message >= WM_NCMOUSEMOVE && + native_event.message <= WM_NCXBUTTONDBLCLK); +} + //////////////////////////////////////////////////////////////////////////////// // Event, public: |