From caa62f477849e63abfc28770f2d8173c166fa74b Mon Sep 17 00:00:00 2001 From: "oshima@chromium.org" Date: Fri, 7 Jan 2011 17:46:59 +0000 Subject: [PATCH] I'm working on autocomplete edit view which does not use native controls for Chromeos and Touch UI. The goal of this refactoring is to make it easy to swap AutocompleteEditView implementation between Gtk based impl and Views based one. This is 1st phrase and there will be more refacotring needed to implement AutocompleteEditViewViews. - Added factory method AutocompleteEditViewGtk::Create, which hides initialization details for gtk based impl. - Moved gtk specific accessibilty code to AutocompleteEditViewGtk. - Added TOOLKIT_VIWES only methods to AutocompleteEditView to hide platform specific implementation. (AddToView, CommitInstatntSuggestion/SetInstantSuggestion) BUG=none TEST=none no functional change. all tests should pass. Review URL: http://codereview.chromium.org/6036004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70746 0039d316-1c4b-4281-b951-d872f2087c98 --- .../autocomplete_edit_unittest.cc | 9 ++ .../autocomplete/autocomplete_edit_view.h | 24 ++- .../autocomplete_edit_view_gtk.cc | 140 +++++++++++++----- .../autocomplete/autocomplete_edit_view_gtk.h | 38 ++++- .../autocomplete_edit_view_win.cc | 33 ++++- .../autocomplete/autocomplete_edit_view_win.h | 14 +- .../views/location_bar/location_bar_view.cc | 41 ++--- .../ui/views/location_bar/location_bar_view.h | 13 +- 8 files changed, 212 insertions(+), 100 deletions(-) diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc index 7dedb984f0f331..73c8ae9ff7c31b 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc @@ -55,6 +55,15 @@ class TestingAutocompleteEditView : public AutocompleteEditView { virtual gfx::NativeView GetNativeView() const { return 0; } virtual CommandUpdater* GetCommandUpdater() { return NULL; } +#if defined(TOOLKIT_VIEWS) + virtual views::View* AddToView(views::View* parent) { return NULL; } + virtual int TextWidth() const { return 0; } + virtual bool CommitInstantSuggestion( + const std::wstring& typed_text, + const std::wstring& suggested_text) { return false;} + virtual void SetInstantSuggestion(const string16& input) {} +#endif + private: DISALLOW_COPY_AND_ASSIGN(TestingAutocompleteEditView); }; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h index 439b2edce7b6cb..12c42a239ac2dc 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view.h @@ -24,6 +24,12 @@ class CommandUpdater; class GURL; class TabContents; +#if defined(TOOLKIT_VIEWS) +namespace views { +class View; +} // namespace views +#endif + class AutocompleteEditView { public: // Used by the automation system for getting at the model from the view. @@ -152,7 +158,23 @@ class AutocompleteEditView { // Returns the command updater for this view. virtual CommandUpdater* GetCommandUpdater() = 0; - protected: +#if defined(TOOLKIT_VIEWS) + // Adds the autocomplete edit view to view hierarchy and + // returns the views::View of the edit view. + virtual views::View* AddToView(views::View* parent) = 0; + + // Commits the suggested text. + virtual bool CommitInstantSuggestion(const std::wstring& typed_text, + const std::wstring& suggested_text) = 0; + + // Shows the instant suggestion text. + virtual void SetInstantSuggestion(const string16& input) = 0; + + // Returns the width in pixels needed to display the current text. The + // returned value includes margins. + virtual int TextWidth() const = 0; +#endif + virtual ~AutocompleteEditView() {} }; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc index 3f435a326455fa..4de3d2ca03bd61 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -38,12 +38,14 @@ #include "ui/base/animation/multi_animation.h" #if defined(TOOLKIT_VIEWS) -#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" -#include "chrome/browser/views/location_bar/location_bar_view.h" +#include "chrome/browser/gtk/accessible_widget_helper_gtk.h" +#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" #else #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/location_bar_view_gtk.h" +#include "views/controls/native/native_view_host.h" #endif namespace { @@ -418,44 +420,6 @@ void AutocompleteEditViewGtk::SetFocus() { gtk_widget_grab_focus(text_view_); } -int AutocompleteEditViewGtk::TextWidth() { - int horizontal_border_size = - gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), - GTK_TEXT_WINDOW_LEFT) + - gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), - GTK_TEXT_WINDOW_RIGHT) + - gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) + - gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_)); - - GtkTextIter start, end; - GdkRectangle first_char_bounds, last_char_bounds; - gtk_text_buffer_get_start_iter(text_buffer_, &start); - - // Use the real end iterator here to take the width of instant suggestion - // text into account, so that location bar can layout its children correctly. - gtk_text_buffer_get_end_iter(text_buffer_, &end); - gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), - &start, &first_char_bounds); - gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), - &end, &last_char_bounds); - - gint first_char_start = first_char_bounds.x; - gint first_char_end = first_char_start + first_char_bounds.width; - gint last_char_start = last_char_bounds.x; - gint last_char_end = last_char_start + last_char_bounds.width; - - // bounds width could be negative for RTL text. - if (first_char_start > first_char_end) - std::swap(first_char_start, first_char_end); - if (last_char_start > last_char_end) - std::swap(last_char_start, last_char_end); - - gint text_width = first_char_start < last_char_start ? - last_char_end - first_char_start : first_char_end - last_char_start; - - return text_width + horizontal_border_size; -} - int AutocompleteEditViewGtk::WidthOfTextAfterCursor() { // Not used. return -1; @@ -790,6 +754,102 @@ CommandUpdater* AutocompleteEditViewGtk::GetCommandUpdater() { return command_updater_; } +#if defined(TOOLKIT_VIEWS) +views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) { + views::NativeViewHost* host = new views::NativeViewHost; + parent->AddChildView(host); + host->set_focus_view(parent); + host->Attach(GetNativeView()); + return host; +} + +bool AutocompleteEditViewGtk::CommitInstantSuggestion( + const std::wstring& typed_text, + const std::wstring& suggestion) { + return CommitInstantSuggestion(); +} + +void AutocompleteEditViewGtk::EnableAccessibility() { + accessible_widget_helper_.reset( + new AccessibleWidgetHelper(text_view(), model_->profile())); + accessible_widget_helper_->SetWidgetName( + text_view(), l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION)); +} + +void AutocompleteEditViewGtk::SetInstantSuggestion(const string16& suggestion) { + SetInstantSuggestion(UTF16ToUTF8(suggestion)); +} +#endif + +int AutocompleteEditViewGtk::TextWidth() const { + int horizontal_border_size = + gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), + GTK_TEXT_WINDOW_LEFT) + + gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), + GTK_TEXT_WINDOW_RIGHT) + + gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) + + gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_)); + + GtkTextIter start, end; + GdkRectangle first_char_bounds, last_char_bounds; + gtk_text_buffer_get_start_iter(text_buffer_, &start); + + // Use the real end iterator here to take the width of instant suggestion + // text into account, so that location bar can layout its children correctly. + gtk_text_buffer_get_end_iter(text_buffer_, &end); + gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), + &start, &first_char_bounds); + gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), + &end, &last_char_bounds); + + gint first_char_start = first_char_bounds.x; + gint first_char_end = first_char_start + first_char_bounds.width; + gint last_char_start = last_char_bounds.x; + gint last_char_end = last_char_start + last_char_bounds.width; + + // bounds width could be negative for RTL text. + if (first_char_start > first_char_end) + std::swap(first_char_start, first_char_end); + if (last_char_start > last_char_end) + std::swap(last_char_start, last_char_end); + + gint text_width = first_char_start < last_char_start ? + last_char_end - first_char_start : first_char_end - last_char_start; + + return text_width + horizontal_border_size; +} + +#if defined(TOOLKIT_VIEWS) +// static +AutocompleteEditView* AutocompleteEditViewGtk::Create( + AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater, + bool popup_window_mode, + const views::View* location_bar) { + AutocompleteEditViewGtk* autocomplete = + new AutocompleteEditViewGtk(controller, + toolbar_model, + profile, + command_updater, + popup_window_mode, + location_bar); + autocomplete->Init(); + + // Make all the children of the widget visible. NOTE: this won't display + // anything, it just toggles the visible flag. + gtk_widget_show_all(autocomplete->GetNativeView()); + // Hide the widget. NativeViewHostGtk will make it visible again as + // necessary. + gtk_widget_hide(autocomplete->GetNativeView()); + + autocomplete->EnableAccessibility(); + + return autocomplete; +} +#endif + void AutocompleteEditViewGtk::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h index 9e45db641ba91b..2397d2617b265c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -26,6 +26,7 @@ #include "ui/base/animation/animation_delegate.h" #include "webkit/glue/window_open_disposition.h" +class AccessibleWidgetHelper; class AutocompleteEditController; class AutocompleteEditModel; class AutocompletePopupView; @@ -74,19 +75,15 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, CommandUpdater* command_updater, bool popup_window_mode, #if defined(TOOLKIT_VIEWS) - const views::View* location_bar); + const views::View* location_bar #else - GtkWidget* location_bar); + GtkWidget* location_bar #endif - ~AutocompleteEditViewGtk(); + ); + virtual ~AutocompleteEditViewGtk(); // Initialize, create the underlying widgets, etc. void Init(); - - // Returns the width in pixels needed to display the current text. The - // returned value includes margins. - int TextWidth(); - // Returns the width in pixels needed to display the text from one character // before the caret to the end of the string. See comments in // LocationBarView::Layout as to why this uses -1. @@ -146,6 +143,27 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, virtual bool OnAfterPossibleChange(); virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); +#if defined(TOOLKIT_VIEWS) + virtual views::View* AddToView(views::View* parent); + virtual bool CommitInstantSuggestion(const std::wstring& typed_text, + const std::wstring& suggested_text); + virtual void SetInstantSuggestion(const string16& suggestion); + + // Enables accessibility on AutocompleteEditView. + void EnableAccessibility(); + + // A factory method to create an AutocompleteEditView instance initialized for + // linux_views. This currently returns an instance of + // AutocompleteEditViewGtk only, but AutocompleteEditViewViews will + // be added as an option when TextfieldViews is enabled. + static AutocompleteEditView* Create(AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater, + bool popup_window_mode, + const views::View* location_bar); +#endif + virtual int TextWidth() const; // Overridden from NotificationObserver: virtual void Observe(NotificationType type, @@ -517,6 +535,10 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, GtkSignalRegistrar signals_; +#if defined(TOOLKIT_VIEWS) + scoped_ptr accessible_widget_helper_; +#endif + DISALLOW_COPY_AND_ASSIGN(AutocompleteEditViewGtk); }; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index cc2a486e323997..df2a8ba4eba28d 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -498,10 +498,6 @@ AutocompleteEditViewWin::~AutocompleteEditViewWin() { g_paint_patcher.Pointer()->DerefPatch(); } -int AutocompleteEditViewWin::TextWidth() { - return WidthNeededToDisplay(GetText()); -} - int AutocompleteEditViewWin::WidthOfTextAfterCursor() { CHARRANGE selection; GetSelection(selection); @@ -913,6 +909,30 @@ CommandUpdater* AutocompleteEditViewWin::GetCommandUpdater() { return command_updater_; } +views::View* AutocompleteEditViewWin::AddToView(views::View* parent) { + views::NativeViewHost* host = new views::NativeViewHost; + parent->AddChildView(host); + host->set_focus_view(parent); + host->Attach(GetNativeView()); + return host; +} + +bool AutocompleteEditViewWin::CommitInstantSuggestion( + const std::wstring& typed_text, + const std::wstring& suggested_text) { + model_->FinalizeInstantQuery(typed_text, suggested_text); + return true; +} + +void AutocompleteEditViewWin::SetInstantSuggestion(const string16& suggestion) { + // Win shows the suggestion in LocationBarView. + NOTREACHED(); +} + +int AutocompleteEditViewWin::TextWidth() const { + return WidthNeededToDisplay(GetText()); +} + void AutocompleteEditViewWin::PasteAndGo(const std::wstring& text) { if (CanPasteAndGo(text)) model_->PasteAndGo(); @@ -2570,7 +2590,7 @@ void AutocompleteEditViewWin::TrackMousePosition(MouseButton button, } } -int AutocompleteEditViewWin::GetHorizontalMargin() { +int AutocompleteEditViewWin::GetHorizontalMargin() const { RECT rect; GetRect(&rect); RECT client_rect; @@ -2578,7 +2598,8 @@ int AutocompleteEditViewWin::GetHorizontalMargin() { return (rect.left - client_rect.left) + (client_rect.right - rect.right); } -int AutocompleteEditViewWin::WidthNeededToDisplay(const std::wstring& text) { +int AutocompleteEditViewWin::WidthNeededToDisplay( + const std::wstring& text) const { // Use font_.GetStringWidth() instead of // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h index 07738432eb1fb0..7fc56a9deccbe6 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h @@ -74,10 +74,6 @@ class AutocompleteEditViewWin views::View* parent_view() const { return parent_view_; } - // Returns the width in pixels needed to display the current text. The - // returned value includes margins. - int TextWidth(); - // Returns the width in pixels needed to display the text from one character // before the caret to the end of the string. See comments in // LocationBarView::Layout as to why this uses -1. @@ -137,6 +133,12 @@ class AutocompleteEditViewWin virtual bool OnAfterPossibleChange(); virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); + virtual views::View* AddToView(views::View* parent); + virtual bool CommitInstantSuggestion(const std::wstring& typed_text, + const std::wstring& suggested_text); + virtual void SetInstantSuggestion(const string16& suggestion); + virtual int TextWidth() const; + int GetPopupMaxYCoordinate(); // Exposes custom IAccessible implementation to the overall MSAA hierarchy. @@ -401,10 +403,10 @@ class AutocompleteEditViewWin void TrackMousePosition(MouseButton button, const CPoint& point); // Returns the sum of the left and right margins. - int GetHorizontalMargin(); + int GetHorizontalMargin() const; // Returns the width in pixels needed to display |text|. - int WidthNeededToDisplay(const std::wstring& text); + int WidthNeededToDisplay(const std::wstring& text) const; scoped_ptr model_; 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 0067c66194883f..b5dad74241f545 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -162,28 +162,14 @@ void LocationBarView::Init() { GetWidget()->GetNativeView(), profile_, command_updater_, mode_ == POPUP, this)); #else - location_entry_.reset(new AutocompleteEditViewGtk(this, model_, profile_, - command_updater_, mode_ == POPUP, this)); - location_entry_->Init(); - // Make all the children of the widget visible. NOTE: this won't display - // anything, it just toggles the visible flag. - gtk_widget_show_all(location_entry_->GetNativeView()); - // Hide the widget. NativeViewHostGtk will make it visible again as - // necessary. - gtk_widget_hide(location_entry_->GetNativeView()); - - // Associate an accessible name with the location entry. - accessible_widget_helper_.reset(new AccessibleWidgetHelper( - location_entry_->text_view(), profile_)); - accessible_widget_helper_->SetWidgetName( - location_entry_->text_view(), - l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION)); + location_entry_.reset( + AutocompleteEditViewGtk::Create( + this, model_, profile_, + command_updater_, mode_ == POPUP, this)); #endif - location_entry_view_ = new views::NativeViewHost; + + location_entry_view_ = location_entry_->AddToView(this); location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE); - AddChildView(location_entry_view_); - location_entry_view_->set_focus_view(this); - location_entry_view_->Attach(location_entry_->GetNativeView()); location_entry_view_->SetAccessibleName( UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION))); @@ -785,17 +771,13 @@ bool LocationBarView::OnCommitSuggestedText(const std::wstring& typed_text) { InstantController* instant = delegate_->GetInstant(); if (!instant) return false; - + std::wstring suggestion; #if defined(OS_WIN) if (!HasValidSuggestText()) return false; - location_entry_->model()->FinalizeInstantQuery( - typed_text, - suggested_text_view_->GetText()); - return true; -#else - return location_entry_->CommitInstantSuggestion(); + suggestion = suggested_text_view_->GetText(); #endif + return location_entry_->CommitInstantSuggestion(typed_text, suggestion); } bool LocationBarView::AcceptCurrentInstantPreview() { @@ -847,9 +829,8 @@ void LocationBarView::OnAutocompleteAccept( } if (delegate_->GetInstant() && - !location_entry_->model()->popup_model()->IsOpen()) { + !location_entry_->model()->popup_model()->IsOpen()) delegate_->GetInstant()->DestroyPreviewContents(); - } update_instant_ = true; } @@ -1172,7 +1153,7 @@ void LocationBarView::SetSuggestedText(const string16& input) { Layout(); SchedulePaint(); #else - location_entry_->SetInstantSuggestion(UTF16ToUTF8(input)); + location_entry_->SetInstantSuggestion(input); #endif } 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 317bd788dd3b00..1ffa5b19576e1e 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h @@ -25,9 +25,8 @@ #if defined(OS_WIN) #include "chrome/browser/autocomplete/autocomplete_edit_view_win.h" -#else +#elif defined(OS_LINUX) #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" -#include "chrome/browser/gtk/accessible_widget_helper_gtk.h" #endif class CommandUpdater; @@ -330,7 +329,7 @@ class LocationBarView : public LocationBar, #if defined(OS_WIN) scoped_ptr location_entry_; #else - scoped_ptr location_entry_; + scoped_ptr location_entry_; #endif // The CommandUpdater for the Browser object that corresponds to this View. @@ -364,8 +363,8 @@ class LocationBarView : public LocationBar, // A bubble displayed for EV HTTPS sites. EVBubbleView* ev_bubble_view_; - // Location_entry view wrapper - views::NativeViewHost* location_entry_view_; + // Location_entry view + views::View* location_entry_view_; // The following views are used to provide hints and remind the user as to // what is going in the edit. They are all added a children of the @@ -409,10 +408,6 @@ class LocationBarView : public LocationBar, // crash. TemplateURLModel* template_url_model_; -#if defined(OS_LINUX) - scoped_ptr accessible_widget_helper_; -#endif - // Should instant be updated? This is set to false in OnAutocompleteWillAccept // and true in OnAutocompleteAccept. This is needed as prior to accepting an // autocomplete suggestion the model is reverted which triggers resetting