diff options
author | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-12 17:03:37 +0000 |
---|---|---|
committer | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-12 17:03:37 +0000 |
commit | 92e175a8152b4a7226cf8715aed8501ed7d83187 (patch) | |
tree | 67ca4faf8de98eef08cbc592f4b16b8d08d739be /chrome | |
parent | 7985f9159ec6ba70fcdc4c76b6bc8787c074cb50 (diff) | |
download | chromium_src-92e175a8152b4a7226cf8715aed8501ed7d83187.zip chromium_src-92e175a8152b4a7226cf8715aed8501ed7d83187.tar.gz chromium_src-92e175a8152b4a7226cf8715aed8501ed7d83187.tar.bz2 |
Some work in refactoring FindBarWin/FindBarView so
we can share code across platforms.
See http://code.google.com/p/chromium/wiki/FindBarRefactoring for
more information about the design.
Review URL: http://codereview.chromium.org/42057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11544 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.scons | 3 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 12 | ||||
-rw-r--r-- | chrome/browser/find_bar.h | 72 | ||||
-rw-r--r-- | chrome/browser/find_bar_controller.cc | 136 | ||||
-rw-r--r-- | chrome/browser/find_bar_controller.h | 51 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 22 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 4 | ||||
-rw-r--r-- | chrome/browser/gtk/find_bar_gtk.cc | 52 | ||||
-rw-r--r-- | chrome/browser/gtk/find_bar_gtk.h | 41 | ||||
-rw-r--r-- | chrome/browser/views/find_bar_view.cc | 25 | ||||
-rw-r--r-- | chrome/browser/views/find_bar_win.cc | 151 | ||||
-rw-r--r-- | chrome/browser/views/find_bar_win.h | 78 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 32 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.h | 4 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 |
15 files changed, 470 insertions, 216 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index fd164282..a572a0b 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -189,6 +189,9 @@ input_files = ChromeFileList([ 'controller.h', 'dock_info.cc', 'dock_info.h', + 'find_bar.h', + 'find_bar_controller.cc', + 'find_bar_controller.h', 'find_notification_details.h', 'js_before_unload_handler.h', 'js_before_unload_handler_win.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index c7827fa..da8341a 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -702,6 +702,18 @@ > </File> <File + RelativePath=".\find_bar_controller.cc" + > + </File> + <File + RelativePath=".\find_bar_controller.h" + > + </File> + <File + RelativePath=".\find_bar.h" + > + </File> + <File RelativePath=".\find_notification_details.h" > </File> diff --git a/chrome/browser/find_bar.h b/chrome/browser/find_bar.h new file mode 100644 index 0000000..5ebb188 --- /dev/null +++ b/chrome/browser/find_bar.h @@ -0,0 +1,72 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This is an interface for the platform specific FindBar. It is responsible +// for drawing the FindBar bar on the platform and is owned by the +// FindBarController. + +#ifndef CHROME_BROWSER_FIND_BAR_H_ +#define CHROME_BROWSER_FIND_BAR_H_ + +#include "base/gfx/rect.h" + +class FindNotificationDetails; +class WebContents; + +class FindBar { + public: + virtual ~FindBar() { } + + // Shows the find bar. Any previous search string will again be visible. + virtual void Show() = 0; + + // Hide the find bar. If |animate| is true, we try to slide the find bar + // away. + virtual void Hide(bool animate) = 0; + + // Restore the selected text in the find box and focus it. + virtual void SetFocusAndSelection() = 0; + + // Clear the text in the find box. + virtual void ClearResults(const FindNotificationDetails& results) = 0; + + // Stop the animation. + virtual void StopAnimation() = 0; + + // Set the text in the find box. + virtual void SetFindText(const std::wstring& find_text) = 0; + + // Updates the FindBar with the find result details contained within the + // specified |result|. + virtual void UpdateUIForFindResult(const FindNotificationDetails& result, + const std::wstring& find_text) = 0; + + // Returns the rectangle representing where to position the find bar. It uses + // GetDialogBounds and positions itself within that, either to the left (if an + // InfoBar is present) or to the right (no InfoBar). If + // |avoid_overlapping_rect| is specified, the return value will be a rectangle + // located immediately to the left of |avoid_overlapping_rect|, as long as + // there is enough room for the dialog to draw within the bounds. If not, the + // dialog position returned will overlap |avoid_overlapping_rect|. + // Note: |avoid_overlapping_rect| is expected to use coordinates relative to + // the top of the page area, (it will be converted to coordinates relative to + // the top of the browser window, when comparing against the dialog + // coordinates). The returned value is relative to the browser window. + virtual gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect) = 0; + + // Moves the dialog window to the provided location, moves it to top in the + // z-order (HWND_TOP, not HWND_TOPMOST) and shows the window (if hidden). + // It then calls UpdateWindowEdges to make sure we don't overwrite the Chrome + // window border. If |no_redraw| is set, the window is getting moved but not + // sized, and should not be redrawn to reduce update flicker. + virtual void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) = 0; + + virtual bool IsFindBarVisible() = 0; + + // Upon dismissing the window, restore focus to the last focused view which is + // not FindBarView or any of its children. + virtual void RestoreSavedFocus() = 0; +}; + +#endif // CHROME_BROWSER_FIND_BAR_H_ diff --git a/chrome/browser/find_bar_controller.cc b/chrome/browser/find_bar_controller.cc new file mode 100644 index 0000000..81e759b --- /dev/null +++ b/chrome/browser/find_bar_controller.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/find_bar_controller.h" + +#include "build/build_config.h" +#include "chrome/browser/find_bar.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/common/notification_service.h" +#include "chrome/browser/tab_contents/web_contents.h" + +FindBarController::FindBarController(FindBar* find_bar) + : find_bar_(find_bar), web_contents_(NULL) { +} + +FindBarController::~FindBarController() { + // Web contents should have been NULLed out. If not, then we're leaking + // notification observers. + DCHECK(!web_contents_); +} + +void FindBarController::Show() { + // Only show the animation if we're not already showing a find bar for the + // selected WebContents. + if (!web_contents_->find_ui_active()) { + web_contents_->set_find_ui_active(true); + find_bar_->Show(); + } + find_bar_->SetFocusAndSelection(); +} + +void FindBarController::EndFindSession() { + find_bar_->Hide(true); + + // |web_contents_| can be NULL for a number of reasons, for example when the + // tab is closing. We must guard against that case. See issue 8030. + if (web_contents_) { + // When we hide the window, we need to notify the renderer that we are done + // for now, so that we can abort the scoping effort and clear all the + // tickmarks and highlighting. + web_contents_->StopFinding(false); // false = don't clear selection on + // page. + find_bar_->ClearResults(web_contents_->find_result()); + + // When we get dismissed we restore the focus to where it belongs. + find_bar_->RestoreSavedFocus(); + } +} + +void FindBarController::ChangeWebContents(WebContents* contents) { + if (web_contents_) { + NotificationService::current()->RemoveObserver( + this, NotificationType::FIND_RESULT_AVAILABLE, + Source<TabContents>(web_contents_)); + NotificationService::current()->RemoveObserver( + this, NotificationType::NAV_ENTRY_COMMITTED, + Source<NavigationController>(web_contents_->controller())); + find_bar_->StopAnimation(); + } + + web_contents_ = contents; + + // Hide any visible find window from the previous tab if NULL |web_contents| + // is passed in or if the find UI is not active in the new tab. + if (find_bar_->IsFindBarVisible() && + (!web_contents_ || !web_contents_->find_ui_active())) { + find_bar_->Hide(false); + } + + if (web_contents_) { + NotificationService::current()->AddObserver( + this, NotificationType::FIND_RESULT_AVAILABLE, + Source<TabContents>(web_contents_)); + NotificationService::current()->AddObserver( + this, NotificationType::NAV_ENTRY_COMMITTED, + Source<NavigationController>(web_contents_->controller())); + + // Update the find bar with existing results and search text, regardless of + // whether or not the find bar is visible, so that if it's subsequently + // shown it is showing the right state for this tab. We update the find text + // _first_ since the FindBarView checks its emptiness to see if it should + // clear the result count display when there's nothing in the box. + find_bar_->SetFindText(web_contents_->find_text()); + + if (web_contents_->find_ui_active()) { + // A tab with a visible find bar just got selected and we need to show the + // find bar but without animation since it was already animated into its + // visible state. We also want to reset the window location so that + // we don't surprise the user by popping up to the left for no apparent + // reason. + gfx::Rect new_pos = find_bar_->GetDialogPosition(gfx::Rect()); + find_bar_->SetDialogPosition(new_pos, false); + + // Only modify focus and selection if Find is active, otherwise the Find + // Bar will interfere with user input. + find_bar_->SetFocusAndSelection(); + } + + find_bar_->UpdateUIForFindResult(web_contents_->find_result(), + web_contents_->find_text()); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FindBarWin, NotificationObserver implementation: + +void FindBarController::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::FIND_RESULT_AVAILABLE) { + // Don't update for notifications from TabContentses other than the one we + // are actively tracking. + if (Source<TabContents>(source).ptr() == web_contents_) { + find_bar_->UpdateUIForFindResult(web_contents_->find_result(), + web_contents_->find_text()); + FindNotificationDetails details = web_contents_->find_result(); + } + } else if (type == NotificationType::NAV_ENTRY_COMMITTED) { + NavigationController* source_controller = + Source<NavigationController>(source).ptr(); + if (source_controller == web_contents_->controller()) { + NavigationController::LoadCommittedDetails* commit_details = + Details<NavigationController::LoadCommittedDetails>(details).ptr(); + PageTransition::Type transition_type = + commit_details->entry->transition_type(); + // We hide the FindInPage window when the user navigates away, except on + // reload. + if (find_bar_->IsFindBarVisible() && + PageTransition::StripQualifier(transition_type) != + PageTransition::RELOAD) { + EndFindSession(); + } + } + } +} diff --git a/chrome/browser/find_bar_controller.h b/chrome/browser/find_bar_controller.h new file mode 100644 index 0000000..7551239 --- /dev/null +++ b/chrome/browser/find_bar_controller.h @@ -0,0 +1,51 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_FIND_BAR_CONTROLLER_H_ +#define CHROME_BROWSER_FIND_BAR_CONTROLLER_H_ + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/common/notification_observer.h" + +class FindBar; +class WebContents; + +class FindBarController : public NotificationObserver { + public: + // FindBar takes ownership of |find_bar_view|. + FindBarController(FindBar* find_bar); + + virtual ~FindBarController(); + + // Shows the find bar. Any previous search string will again be visible. + void Show(); + + // Ends the current session. + void EndFindSession(); + + // Accessor for the attached WebContents. + WebContents* web_contents() const { return web_contents_; } + + // Changes the WebContents that this FindBar is attached to. This occurs when + // the user switches tabs in the Browser window. |contents| can be NULL. + void ChangeWebContents(WebContents* contents); + + // Overridden from NotificationObserver: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + FindBar* get_find_bar() const { return find_bar_.get(); } + + private: + scoped_ptr<FindBar> find_bar_; + + // The WebContents we are currently associated with. Can be NULL. + WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(FindBarController); +}; + +#endif // CHROME_BROWSER_FIND_BAR_CONTROLLER_H_ diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 484b5ff..6a58b4b 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -8,6 +8,7 @@ #include "base/base_paths_linux.h" #include "base/path_service.h" #include "chrome/browser/browser.h" +#include "chrome/browser/find_bar_controller.h" #include "chrome/browser/gtk/browser_toolbar_gtk.h" #include "chrome/browser/gtk/find_bar_gtk.h" #include "chrome/browser/gtk/nine_box.h" @@ -169,10 +170,12 @@ void BrowserWindowGtk::Init() { toolbar_->Init(browser_->profile(), accel_group); toolbar_->AddToolbarToBox(vbox_); - find_bar_.reset(new FindBarGtk()); + FindBarGtk* find_bar_gtk = new FindBarGtk(); + find_bar_controller_.reset(new FindBarController(find_bar_gtk)); + find_bar_gtk->set_find_bar_controller(find_bar_controller_.get()); contents_container_.reset(new TabContentsContainerGtk( - find_bar_->gtk_widget())); + find_bar_gtk->gtk_widget())); contents_container_->AddContainerToBox(vbox_); @@ -205,6 +208,11 @@ void BrowserWindowGtk::Close() { if (!window_) return; + // TODO(tc): Once the tab strip model is hooked up, this call can be removed. + // It should get called by TabDetachedAt when the window is being closed, but + // we don't have a TabStripModel yet. + find_bar_controller_->ChangeWebContents(NULL); + gtk_widget_destroy(GTK_WIDGET(window_)); window_ = NULL; } @@ -311,7 +319,7 @@ void BrowserWindowGtk::ToggleBookmarkBar() { } void BrowserWindowGtk::ShowFindBar() { - find_bar_->Show(); + find_bar_controller_->Show(); } void BrowserWindowGtk::ShowAboutChromeDialog() { @@ -368,6 +376,11 @@ void BrowserWindowGtk::TabDetachedAt(TabContents* contents, int index) { // TODO(port): Uncoment this line when we get infobars. // infobar_container_->ChangeTabContents(NULL); contents_container_->SetTabContents(NULL); + + // When dragging the last TabContents out of a window there is no selection + // notification that causes the find bar for that window to be un-registered + // for notifications from this TabContents. + find_bar_controller_->ChangeWebContents(NULL); } } @@ -390,7 +403,8 @@ void BrowserWindowGtk::TabSelectedAt(TabContents* old_contents, toolbar_->SetProfile(new_contents->profile()); UpdateToolbar(new_contents, true); - find_bar_->ChangeWebContents(new_contents->AsWebContents()); + if (find_bar_controller_.get()) + find_bar_controller_->ChangeWebContents(new_contents->AsWebContents()); } void BrowserWindowGtk::TabStripEmpty() { diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index df1fbdd..7d86175 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -13,7 +13,7 @@ #include "chrome/browser/tabs/tab_strip_model.h" class BrowserToolbarGtk; -class FindBarGtk; +class FindBarController; class LocationBar; class NineBox; class StatusBubbleGtk; @@ -124,7 +124,7 @@ class BrowserWindowGtk : public BrowserWindow, // The Find Bar. This may be NULL if there is no Find Bar, and if it is // non-NULL, it may or may not be visible. It is possible for the Find Bar // to move among windows as tabs are dragged around. - scoped_ptr<FindBarGtk> find_bar_; + scoped_ptr<FindBarController> find_bar_controller_; }; #endif // CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc index 5bfe1c6..2398770 100644 --- a/chrome/browser/gtk/find_bar_gtk.cc +++ b/chrome/browser/gtk/find_bar_gtk.cc @@ -7,6 +7,7 @@ #include <gdk/gdkkeysyms.h> #include "base/string_util.h" +#include "chrome/browser/find_bar_controller.h" #include "chrome/browser/gtk/tab_contents_container_gtk.h" #include "chrome/browser/tab_contents/web_contents.h" @@ -20,13 +21,13 @@ gboolean EntryContentsChanged(GtkWindow* window, FindBarGtk* find_bar) { gboolean KeyPressEvent(GtkWindow* window, GdkEventKey* event, FindBarGtk* find_bar) { if (GDK_Escape == event->keyval) - find_bar->Hide(); + find_bar->EscapePressed(); return FALSE; } } -FindBarGtk::FindBarGtk() : web_contents_(NULL) { +FindBarGtk::FindBarGtk() { find_text_ = gtk_entry_new(); gtk_widget_show(find_text_); @@ -45,26 +46,57 @@ void FindBarGtk::Show() { gtk_widget_grab_focus(find_text_); } -void FindBarGtk::Hide() { +void FindBarGtk::Hide(bool animate) { + // TODO(tc): Animated slide away. gtk_widget_hide(container_); - if (web_contents_) - web_contents_->StopFinding(true); +} + +void FindBarGtk::SetFocusAndSelection() { +} + +void FindBarGtk::ClearResults(const FindNotificationDetails& results) { +} + +void FindBarGtk::StopAnimation() { + // No animation yet, so do nothing. +} + +void FindBarGtk::SetFindText(const std::wstring& find_text) { +} + +void FindBarGtk::UpdateUIForFindResult(const FindNotificationDetails& result, + const std::wstring& find_text) { +} + +gfx::Rect FindBarGtk::GetDialogPosition(gfx::Rect avoid_overlapping_rect) { + return gfx::Rect(); +} + +void FindBarGtk::SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) { +} + +bool FindBarGtk::IsFindBarVisible() { + return true; +} + +void FindBarGtk::RestoreSavedFocus() { } void FindBarGtk::ContentsChanged() { - if (!web_contents_) + WebContents* web_contents = find_bar_controller_->web_contents(); + if (!web_contents) return; std::string new_contents(gtk_entry_get_text(GTK_ENTRY(find_text_))); if (new_contents.length() > 0) { - web_contents_->StartFinding(UTF8ToWide(new_contents), true); + web_contents->StartFinding(UTF8ToWide(new_contents), true); } else { // The textbox is empty so we reset. - web_contents_->StopFinding(true); // true = clear selection on page. + web_contents->StopFinding(true); // true = clear selection on page. } } -void FindBarGtk::ChangeWebContents(WebContents* contents) { - web_contents_ = contents; +void FindBarGtk::EscapePressed() { + find_bar_controller_->EndFindSession(); } diff --git a/chrome/browser/gtk/find_bar_gtk.h b/chrome/browser/gtk/find_bar_gtk.h index 9a38ce9..6ac3c41 100644 --- a/chrome/browser/gtk/find_bar_gtk.h +++ b/chrome/browser/gtk/find_bar_gtk.h @@ -5,33 +5,49 @@ #ifndef CHROME_BROWSER_GTK_FIND_BAR_GTK_H_ #define CHROME_BROWSER_GTK_FIND_BAR_GTK_H_ -#include <string> +#include "chrome/browser/find_bar.h" #include <gtk/gtk.h> +#include <string> + +class FindBarController; class TabContentsContainerGtk; class WebContents; // Currently this class contains both a model and a view. We may want to // eventually pull out the model specific bits and share with Windows. -class FindBarGtk { +class FindBarGtk : public FindBar { public: FindBarGtk(); - ~FindBarGtk() { } + virtual ~FindBarGtk() { } - // Show the find dialog if it's not already showing. The Find dialog is - // positioned above the web contents area (TabContentsContainerGtk). - void Show(); - void Hide(); + void set_find_bar_controller(FindBarController* find_bar_controller) { + find_bar_controller_ = find_bar_controller; + } // Callback when the text in the find box changes. void ContentsChanged(); - // Callback from BrowserWindowGtk when the web contents changes. - void ChangeWebContents(WebContents* contents); + // Callback when Escape is pressed. + void EscapePressed(); GtkWidget* gtk_widget() const { return container_; } + // Methods from FindBar. + virtual void Show(); + virtual void Hide(bool animate); + virtual void SetFocusAndSelection(); + virtual void ClearResults(const FindNotificationDetails& results); + virtual void StopAnimation(); + virtual void SetFindText(const std::wstring& find_text); + virtual void UpdateUIForFindResult(const FindNotificationDetails& result, + const std::wstring& find_text); + virtual gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect); + virtual void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw); + virtual bool IsFindBarVisible(); + virtual void RestoreSavedFocus(); + private: // GtkHBox containing the find bar widgets. GtkWidget* container_; @@ -39,9 +55,10 @@ class FindBarGtk { // The widget where text is entered. GtkWidget* find_text_; - // A non-owning pointer to the web contents associated with the find bar. - // This can be NULL. - WebContents* web_contents_; + // Pointer back to the owning controller. + FindBarController* find_bar_controller_; + + DISALLOW_COPY_AND_ASSIGN(FindBarGtk); }; #endif // CHROME_BROWSER_GTK_FIND_BAR_GTK_H_ diff --git a/chrome/browser/views/find_bar_view.cc b/chrome/browser/views/find_bar_view.cc index 45616b1..1cb9481 100644 --- a/chrome/browser/views/find_bar_view.cc +++ b/chrome/browser/views/find_bar_view.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/string_util.h" +#include "chrome/browser/find_bar_controller.h" #include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/views/find_bar_win.h" #include "chrome/browser/view_ids.h" @@ -398,9 +399,7 @@ void FindBarView::Layout() { find_previous_button_->height()); } -void FindBarView::ViewHierarchyChanged(bool is_add, - View *parent, - View *child) { +void FindBarView::ViewHierarchyChanged(bool is_add, View *parent, View *child) { if (is_add && child == this) { find_text_->SetHorizontalMargins(3, 3); // Left and Right margins. find_text_->RemoveBorder(); // We draw our own border (a background image). @@ -429,13 +428,13 @@ void FindBarView::ButtonPressed(views::BaseButton* sender) { case FIND_PREVIOUS_TAG: case FIND_NEXT_TAG: if (find_text_->GetText().length() > 0) { - container_->web_contents()->StartFinding( + container_->find_bar_controller()->web_contents()->StartFinding( find_text_->GetText(), sender->GetTag() == FIND_NEXT_TAG); } break; case CLOSE_TAG: - container_->EndFindSession(); + container_->find_bar_controller()->EndFindSession(); break; default: NOTREACHED() << L"Unknown button"; @@ -448,23 +447,23 @@ void FindBarView::ButtonPressed(views::BaseButton* sender) { void FindBarView::ContentsChanged(views::TextField* sender, const std::wstring& new_contents) { + FindBarController* controller = container_->find_bar_controller(); + DCHECK(controller); // We must guard against a NULL web_contents, which can happen if the text // in the Find box is changed right after the tab is destroyed. Otherwise, it // can lead to crashes, as exposed by automation testing in issue 8048. - if (!container_->web_contents()) + if (!controller->web_contents()) return; // When the user changes something in the text box we check the contents and // if the textbox contains something we set it as the new search string and // initiate search (even though old searches might be in progress). if (new_contents.length() > 0) { - container_->web_contents()->StartFinding(new_contents, true); + controller->web_contents()->StartFinding(new_contents, true); } else { - // The textbox is empty so we reset. - container_->web_contents()->StopFinding(true); // true = clear selection on - // page. - UpdateForResult(container_->web_contents()->find_result(), - std::wstring()); + // The textbox is empty so we reset. true = clear selection on page. + controller->web_contents()->StopFinding(true); + UpdateForResult(controller->web_contents()->find_result(), std::wstring()); } } @@ -480,7 +479,7 @@ void FindBarView::HandleKeystroke(views::TextField* sender, UINT message, std::wstring find_string = find_text_->GetText(); if (find_string.length() > 0) { // Search forwards for enter, backwards for shift-enter. - container_->web_contents()->StartFinding( + container_->find_bar_controller()->web_contents()->StartFinding( find_string, GetKeyState(VK_SHIFT) >= 0); } diff --git a/chrome/browser/views/find_bar_win.cc b/chrome/browser/views/find_bar_win.cc index dd9056c..5eae72d 100644 --- a/chrome/browser/views/find_bar_win.cc +++ b/chrome/browser/views/find_bar_win.cc @@ -6,15 +6,14 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/find_bar_controller.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/find_bar_view.h" #include "chrome/browser/views/frame/browser_view.h" -#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/tab_contents/web_contents_view.h" -#include "chrome/common/notification_service.h" #include "chrome/views/external_focus_tracker.h" #include "chrome/views/native_scroll_bar.h" #include "chrome/views/root_view.h" @@ -28,11 +27,11 @@ static const int kMinFindWndDistanceFromSelection = 5; // FindBarWin, public: FindBarWin::FindBarWin(BrowserView* browser_view) - : web_contents_(NULL), - browser_view_(browser_view), + : browser_view_(browser_view), find_dialog_animation_offset_(0), focus_manager_(NULL), - old_accel_target_for_esc_(NULL) { + old_accel_target_for_esc_(NULL), + find_bar_controller_(NULL) { HWND parent_hwnd = browser_view->GetWidget()->GetHWND(); // Start listening to focus changes, so we can register and unregister our @@ -178,13 +177,11 @@ void FindBarWin::UpdateWindowEdges(const gfx::Rect& new_pos) { } void FindBarWin::Show() { - // Only show the animation if we're not already showing a find bar for the - // selected WebContents. - if (!web_contents_->find_ui_active()) { - web_contents_->set_find_ui_active(true); - animation_->Reset(); - animation_->Show(); - } + animation_->Reset(); + animation_->Show(); +} + +void FindBarWin::SetFocusAndSelection() { view_->SetFocusAndSelection(); } @@ -192,76 +189,30 @@ bool FindBarWin::IsAnimating() { return animation_->IsAnimating(); } -void FindBarWin::EndFindSession() { - animation_->Reset(1.0); - animation_->Hide(); - - // |web_contents_| can be NULL for a number of reasons, for example when the - // tab is closing. We must guard against that case. See issue 8030. - if (web_contents_) { - // When we hide the window, we need to notify the renderer that we are done - // for now, so that we can abort the scoping effort and clear all the - // tickmarks and highlighting. - web_contents_->StopFinding(false); // false = don't clear selection on - // page. - view_->UpdateForResult(web_contents_->find_result(), std::wstring()); - - // When we get dismissed we restore the focus to where it belongs. - RestoreSavedFocus(); +void FindBarWin::Hide(bool animate) { + if (animate) { + animation_->Reset(1.0); + animation_->Hide(); + } else { + ShowWindow(SW_HIDE); } } -void FindBarWin::ChangeWebContents(WebContents* contents) { - if (web_contents_) { - NotificationService::current()->RemoveObserver( - this, NotificationType::FIND_RESULT_AVAILABLE, - Source<TabContents>(web_contents_)); - NotificationService::current()->RemoveObserver( - this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(web_contents_->controller())); - if (animation_->IsAnimating()) - animation_->End(); - } - - web_contents_ = contents; +void FindBarWin::ClearResults(const FindNotificationDetails& results) { + view_->UpdateForResult(results, std::wstring()); +} - // Hide any visible find window from the previous tab if NULL |web_contents| - // is passed in or if the find UI is not active in the new tab. - if (IsVisible() && (!web_contents_ || !web_contents_->find_ui_active())) - ShowWindow(SW_HIDE); +void FindBarWin::StopAnimation() { + if (animation_->IsAnimating()) + animation_->End(); +} - if (web_contents_) { - NotificationService::current()->AddObserver( - this, NotificationType::FIND_RESULT_AVAILABLE, - Source<TabContents>(web_contents_)); - NotificationService::current()->AddObserver( - this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(web_contents_->controller())); - - // Update the find bar with existing results and search text, regardless of - // whether or not the find bar is visible, so that if it's subsequently - // shown it is showing the right state for this tab. We update the find text - // _first_ since the FindBarView checks its emptiness to see if it should - // clear the result count display when there's nothing in the box. - view_->SetFindText(web_contents_->find_text()); - - if (web_contents_->find_ui_active()) { - // A tab with a visible find bar just got selected and we need to show the - // find bar but without animation since it was already animated into its - // visible state. We also want to reset the window location so that - // we don't surprise the user by popping up to the left for no apparent - // reason. - gfx::Rect new_pos = GetDialogPosition(gfx::Rect()); - SetDialogPosition(new_pos, false); - - // Only modify focus and selection if Find is active, otherwise the Find - // Bar will interfere with user input. - view_->SetFocusAndSelection(); - } +void FindBarWin::SetFindText(const std::wstring& find_text) { + view_->SetFindText(find_text); +} - UpdateUIForFindResult(web_contents_->find_result(), - web_contents_->find_text()); - } +bool FindBarWin::IsFindBarVisible() { + return IsVisible(); } void FindBarWin::MoveWindowIfNecessary(const gfx::Rect& selection_rect, @@ -269,8 +220,10 @@ void FindBarWin::MoveWindowIfNecessary(const gfx::Rect& selection_rect, // We only move the window if one is active for the current WebContents. If we // don't check this, then SetDialogPosition below will end up making the Find // Bar visible. - if (!web_contents_ || !web_contents_->find_ui_active()) + if (!find_bar_controller()->web_contents() || + !find_bar_controller()->web_contents()->find_ui_active()) { return; + } gfx::Rect new_pos = GetDialogPosition(selection_rect); SetDialogPosition(new_pos, no_redraw); @@ -280,38 +233,6 @@ void FindBarWin::MoveWindowIfNecessary(const gfx::Rect& selection_rect, } //////////////////////////////////////////////////////////////////////////////// -// FindBarWin, NotificationObserver implementation: - -void FindBarWin::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::FIND_RESULT_AVAILABLE) { - // Don't update for notifications from TabContentses other than the one we - // are actively tracking. - if (Source<TabContents>(source).ptr() == web_contents_) { - UpdateUIForFindResult(web_contents_->find_result(), - web_contents_->find_text()); - FindNotificationDetails details = web_contents_->find_result(); - } - } else if (type == NotificationType::NAV_ENTRY_COMMITTED) { - NavigationController* source_controller = - Source<NavigationController>(source).ptr(); - if (source_controller == web_contents_->controller()) { - NavigationController::LoadCommittedDetails* commit_details = - Details<NavigationController::LoadCommittedDetails>(details).ptr(); - PageTransition::Type transition_type = - commit_details->entry->transition_type(); - // We hide the FindInPage window when the user navigates away, except on - // reload. - if (IsVisible() && PageTransition::StripQualifier(transition_type) != - PageTransition::RELOAD) { - EndFindSession(); - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// // FindBarWin, views::WidgetWin implementation: void FindBarWin::OnFinalMessage(HWND window) { @@ -362,7 +283,7 @@ bool FindBarWin::AcceleratorPressed(const views::Accelerator& accelerator) { // This will end the Find session and hide the window, causing it to loose // focus and in the process unregister us as the handler for the Escape // accelerator through the FocusWillChange event. - EndFindSession(); + find_bar_controller_->EndFindSession(); return true; } @@ -389,9 +310,11 @@ void FindBarWin::AnimationProgressed(const Animation* animation) { } void FindBarWin::AnimationEnded(const Animation* animation) { + // Place the find bar in its fully opened state. + find_dialog_animation_offset_ = 0; + if (!animation_->IsShowing()) { // Animation has finished closing. - find_dialog_animation_offset_ = 0; ShowWindow(SW_HIDE); } else { // Animation has finished opening. @@ -445,7 +368,9 @@ gfx::Rect FindBarWin::GetDialogPosition(gfx::Rect avoid_overlapping_rect) { // whereas the selection rect is relative to the page. RECT frame_rect = {0}, webcontents_rect = {0}; ::GetWindowRect(GetParent(), &frame_rect); - ::GetWindowRect(web_contents_->view()->GetNativeView(), &webcontents_rect); + ::GetWindowRect( + find_bar_controller()->web_contents()->view()->GetNativeView(), + &webcontents_rect); avoid_overlapping_rect.Offset(0, webcontents_rect.top - frame_rect.top); } @@ -522,7 +447,7 @@ void FindBarWin::SetFocusChangeListener(HWND parent_hwnd) { void FindBarWin::RestoreSavedFocus() { if (focus_tracker_.get() == NULL) { // TODO(brettw) Focus() should be on WebContentsView. - web_contents_->Focus(); + find_bar_controller()->web_contents()->Focus(); } else { focus_tracker_->FocusLastFocusedExternalView(); } diff --git a/chrome/browser/views/find_bar_win.h b/chrome/browser/views/find_bar_win.h index c226ea9..b06a033 100644 --- a/chrome/browser/views/find_bar_win.h +++ b/chrome/browser/views/find_bar_win.h @@ -6,14 +6,15 @@ #define CHROME_BROWSER_VIEWS_FIND_BAR_WIN_H_ #include "base/gfx/rect.h" -#include "chrome/browser/find_notification_details.h" +#include "chrome/browser/find_bar.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/common/animation.h" -#include "chrome/common/notification_service.h" #include "chrome/views/widget_win.h" class BrowserView; +class FindBarController; class FindBarView; +class FindNotificationDetails; class RenderViewHost; class SlideAnimation; @@ -39,23 +40,19 @@ class View; class FindBarWin : public views::FocusChangeListener, public views::WidgetWin, public AnimationDelegate, - public NotificationObserver { + public FindBar { public: explicit FindBarWin(BrowserView* browser_view); virtual ~FindBarWin(); - // Accessor for the attached WebContents. - WebContents* web_contents() const { return web_contents_; } - - // Shows the find bar. Any previous search string will again be visible. - void Show(); - - // Ends the current session. - void EndFindSession(); - - // Changes the WebContents that this FindBar is attached to. This occurs when - // the user switches tabs in the Browser window. |contents| can be NULL. - void ChangeWebContents(WebContents* contents); + // Accessor for find_bar_controller so FindBarView can get back to + // FindBarController. + FindBarController* find_bar_controller() const { + return find_bar_controller_; + } + void set_find_bar_controller(FindBarController* find_bar_controller) { + find_bar_controller_ = find_bar_controller; + } // If the find bar obscures the search results we need to move the window. To // do that we need to know what is selected on the page. We simply calculate @@ -79,10 +76,19 @@ class FindBarWin : public views::FocusChangeListener, // new |parent_hwnd|. void SetFocusChangeListener(HWND parent_hwnd); - // Overridden from NotificationObserver: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + // FindBar implementation: + virtual void Show(); + virtual void Hide(bool animate); + virtual void SetFocusAndSelection(); + virtual void ClearResults(const FindNotificationDetails& results); + virtual void StopAnimation(); + virtual void SetFindText(const std::wstring& find_text); + virtual void UpdateUIForFindResult(const FindNotificationDetails& result, + const std::wstring& find_text); + virtual gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect); + virtual void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw); + virtual bool IsFindBarVisible(); + virtual void RestoreSavedFocus(); // Overridden from views::WidgetWin: virtual void OnFinalMessage(HWND window); @@ -111,26 +117,6 @@ class FindBarWin : public views::FocusChangeListener, // be an empty rectangle. void GetDialogBounds(gfx::Rect* bounds); - // Returns the rectangle representing where to position the find bar. It uses - // GetDialogBounds and positions itself within that, either to the left (if an - // InfoBar is present) or to the right (no InfoBar). If - // |avoid_overlapping_rect| is specified, the return value will be a rectangle - // located immediately to the left of |avoid_overlapping_rect|, as long as - // there is enough room for the dialog to draw within the bounds. If not, the - // dialog position returned will overlap |avoid_overlapping_rect|. - // Note: |avoid_overlapping_rect| is expected to use coordinates relative to - // the top of the page area, (it will be converted to coordinates relative to - // the top of the browser window, when comparing against the dialog - // coordinates). The returned value is relative to the browser window. - gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect); - - // Moves the dialog window to the provided location, moves it to top in the - // z-order (HWND_TOP, not HWND_TOPMOST) and shows the window (if hidden). - // It then calls UpdateWindowEdges to make sure we don't overwrite the Chrome - // window border. If |no_redraw| is set, the window is getting moved but not - // sized, and should not be redrawn to reduce update flicker. - void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw); - // The dialog needs rounded edges, so we create a polygon that corresponds to // the background images for this window (and make the polygon only contain // the pixels that we want to draw). The polygon is then given to SetWindowRgn @@ -139,9 +125,6 @@ class FindBarWin : public views::FocusChangeListener, // to prevent from drawing onto Chrome's window border. void UpdateWindowEdges(const gfx::Rect& new_pos); - // Upon dismissing the window, restore focus to the last focused view which is - // not FindBarView or any of its children. - void RestoreSavedFocus(); // Registers this class as the handler for when Escape is pressed. We will // unregister once we loose focus. See also: SetFocusChangeListener(). @@ -151,14 +134,6 @@ class FindBarWin : public views::FocusChangeListener, // also: SetFocusChangeListener(). void UnregisterEscAccelerator(); - // Updates the FindBarView with the find result details contained within the - // specified |result|. - void UpdateUIForFindResult(const FindNotificationDetails& result, - const std::wstring& find_text); - - // The WebContents we are currently associated with. - WebContents* web_contents_; - // The BrowserView that created us. BrowserView* browser_view_; @@ -183,6 +158,9 @@ class FindBarWin : public views::FocusChangeListener, // closed. scoped_ptr<views::ExternalFocusTracker> focus_tracker_; + // A pointer back to the owning controller. + FindBarController* find_bar_controller_; + DISALLOW_COPY_AND_ASSIGN(FindBarWin); }; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index e8c2a54..27ddcac 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -12,6 +12,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/encoding_menu_controller_delegate.h" +#include "chrome/browser/find_bar_controller.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/about_chrome_view.h" #include "chrome/browser/views/bookmark_bar_view.h" @@ -462,7 +463,10 @@ void BrowserView::Init() { infobar_container_ = new InfoBarContainer(this); AddChildView(infobar_container_); - find_bar_.reset(new FindBarWin(this)); + FindBarWin* find_bar_win = new FindBarWin(this); + + find_bar_controller_.reset(new FindBarController(find_bar_win)); + find_bar_win->set_find_bar_controller(find_bar_controller_.get()); contents_container_ = new TabContentsContainerView; set_contents_view(contents_container_); @@ -754,7 +758,7 @@ void BrowserView::ToggleBookmarkBar() { } void BrowserView::ShowFindBar() { - find_bar_->Show(); + find_bar_controller_->Show(); } void BrowserView::ShowAboutChromeDialog() { @@ -865,17 +869,24 @@ LocationBarView* BrowserView::GetLocationBarView() const { bool BrowserView::GetFindBarWindowInfo(gfx::Point* position, bool* fully_visible) const { + FindBarWin* find_bar_win = NULL; + if (find_bar_controller_.get()) { + find_bar_win = static_cast<FindBarWin*>( + find_bar_controller_->get_find_bar()); + DCHECK(find_bar_win); + } + CRect window_rect; - if (!find_bar_.get() || - !::IsWindow(find_bar_->GetHWND()) || - !::GetWindowRect(find_bar_->GetHWND(), &window_rect)) { + if (!find_bar_controller_.get() || + !::IsWindow(find_bar_win->GetHWND()) || + !::GetWindowRect(find_bar_win->GetHWND(), &window_rect)) { *position = gfx::Point(0, 0); *fully_visible = false; return false; } *position = gfx::Point(window_rect.TopLeft().x, window_rect.TopLeft().y); - *fully_visible = find_bar_->IsVisible() && !find_bar_->IsAnimating(); + *fully_visible = find_bar_win->IsVisible() && !find_bar_win->IsAnimating(); return true; } @@ -910,7 +921,7 @@ void BrowserView::TabDetachedAt(TabContents* contents, int index) { // When dragging the last TabContents out of a window there is no selection // notification that causes the find bar for that window to be un-registered // for notifications from this TabContents. - find_bar_->ChangeWebContents(NULL); + find_bar_controller_->ChangeWebContents(NULL); } } @@ -948,8 +959,8 @@ void BrowserView::TabSelectedAt(TabContents* old_contents, UpdateToolbar(new_contents, true); UpdateUIForContents(new_contents); - if (find_bar_.get()) - find_bar_->ChangeWebContents(new_contents->AsWebContents()); + if (find_bar_controller_.get()) + find_bar_controller_->ChangeWebContents(new_contents->AsWebContents()); } void BrowserView::TabStripEmpty() { @@ -1210,7 +1221,8 @@ void BrowserView::Layout() { // back into us to find the bounding box the find bar must be laid out within, // and that code depends on the TabContentsContainer's bounds being up to // date. - find_bar_->MoveWindowIfNecessary(gfx::Rect(), true); + static_cast<FindBarWin*>(find_bar_controller_->get_find_bar())-> + MoveWindowIfNecessary(gfx::Rect(), true); LayoutStatusBubble(bottom); #ifdef CHROME_PERSONALIZATION if (IsPersonalizationEnabled()) { diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 8b9173c..a222819 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -24,7 +24,7 @@ class BookmarkBarView; class Browser; class BrowserToolbarView; class EncodingMenuControllerDelegate; -class FindBarWin; +class FindBarController; class FullscreenExitBubble; class InfoBarContainer; class Menu; @@ -395,7 +395,7 @@ class BrowserView : public BrowserWindow, // The Find Bar. This may be NULL if there is no Find Bar, and if it is // non-NULL, it may or may not be visible. - scoped_ptr<FindBarWin> find_bar_; + scoped_ptr<FindBarController> find_bar_controller_; // The distance the FindBar is from the top of the window, in pixels. int find_bar_y_; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 83772a1..afdc600 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -606,6 +606,9 @@ 'browser/external_tab_container.h', 'browser/fav_icon_helper.cc', 'browser/fav_icon_helper.h', + 'browser/find_bar.h", + 'browser/find_bar_controller.cc", + 'browser/find_bar_controller.h", 'browser/find_notification_details.h', 'browser/first_run.cc', 'browser/first_run.h', |