diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-02 21:55:39 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-02 21:55:39 +0000 |
commit | d6c987134dcbb80e0624b580c37c363bc0c76eb7 (patch) | |
tree | eeab45f1b2b5ab428192fd910bea622517c6278e /chrome/browser/ui | |
parent | 185ec29c9f4d0daf853c2e3cf4f9df77a48915d7 (diff) | |
download | chromium_src-d6c987134dcbb80e0624b580c37c363bc0c76eb7.zip chromium_src-d6c987134dcbb80e0624b580c37c363bc0c76eb7.tar.gz chromium_src-d6c987134dcbb80e0624b580c37c363bc0c76eb7.tar.bz2 |
views: Move AutocompleteEditViewViews/autocomplete_edit_view_views.* to ui/views/omnibox directory.
- Rename AutocompleteEditViewViews to OmniboxViewViews.
- Move autocomplete_edit_view_views.* to omnibox_view_views.*
BUG=80186
TEST=None
R=pkasting@chromium.org
Review URL: http://codereview.chromium.org/6904130
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83801 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui')
-rw-r--r-- | chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc | 32 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h | 4 | ||||
-rw-r--r-- | chrome/browser/ui/views/omnibox/omnibox_view_views.cc | 639 | ||||
-rw-r--r-- | chrome/browser/ui/views/omnibox/omnibox_view_views.h | 193 |
4 files changed, 849 insertions, 19 deletions
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc index 7843277..89989f5 100644 --- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc +++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc @@ -40,9 +40,9 @@ #include "ui/gfx/skia_utils_gtk.h" #if defined(TOOLKIT_VIEWS) -#include "chrome/browser/autocomplete/autocomplete_edit_view_views.h" #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h" #include "views/controls/textfield/native_textfield_views.h" #include "views/events/event.h" #else @@ -885,33 +885,31 @@ AutocompleteEditView* OmniboxViewGtk::Create( bool popup_window_mode, views::View* location_bar) { if (views::NativeTextfieldViews::IsTextfieldViewsEnabled()) { - AutocompleteEditViewViews* autocomplete = - new AutocompleteEditViewViews(controller, - toolbar_model, - profile, - command_updater, - popup_window_mode, - location_bar); - autocomplete->Init(); - return autocomplete; + OmniboxViewViews* omnibox_view = new OmniboxViewViews(controller, + toolbar_model, + profile, + command_updater, + popup_window_mode, + location_bar); + omnibox_view->Init(); + return omnibox_view; } - OmniboxViewGtk* autocomplete = new OmniboxViewGtk(controller, + OmniboxViewGtk* omnibox_view = new OmniboxViewGtk(controller, toolbar_model, profile, command_updater, popup_window_mode, location_bar); - autocomplete->Init(); + omnibox_view->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()); + gtk_widget_show_all(omnibox_view->GetNativeView()); + // Hide the widget. NativeViewHostGtk will make it visible again as necessary. + gtk_widget_hide(omnibox_view->GetNativeView()); - return autocomplete; + return omnibox_view; } #endif diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h index cbda4c7..345e199 100644 --- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h +++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h @@ -151,8 +151,8 @@ class OmniboxViewGtk : public AutocompleteEditView, // A factory method to create an AutocompleteEditView instance initialized for // linux_views. This currently returns an instance of OmniboxViewGtk only, - // but AutocompleteEditViewViews will be added as an option when - // TextfieldViews is enabled. + // but OmniboxViewViews will be added as an option when TextfieldViews is + // enabled. static AutocompleteEditView* Create(AutocompleteEditController* controller, ToolbarModel* toolbar_model, Profile* profile, diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc new file mode 100644 index 0000000..5d0f4a1 --- /dev/null +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc @@ -0,0 +1,639 @@ +// 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/omnibox/omnibox_view_views.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/command_updater.h" +#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h" +#include "chrome/browser/ui/views/autocomplete/touch_autocomplete_popup_contents_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/common/notification_service.h" +#include "googleurl/src/gurl.h" +#include "grit/generated_resources.h" +#include "net/base/escape.h" +#include "ui/base/accessibility/accessible_view_state.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/font.h" +#include "views/border.h" +#include "views/controls/textfield/textfield.h" +#include "views/layout/fill_layout.h" + +namespace { + +// Textfield for autocomplete that intercepts events that are necessary +// for OmniboxViewViews. +class AutocompleteTextfield : public views::Textfield { + public: + explicit AutocompleteTextfield(OmniboxViewViews* omnibox_view) + : views::Textfield(views::Textfield::STYLE_DEFAULT), + omnibox_view_(omnibox_view) { + DCHECK(omnibox_view_); + RemoveBorder(); + } + + // views::View implementation + virtual void OnFocus() OVERRIDE { + views::Textfield::OnFocus(); + omnibox_view_->HandleFocusIn(); + } + + virtual void OnBlur() OVERRIDE { + views::Textfield::OnBlur(); + omnibox_view_->HandleFocusOut(); + } + + virtual bool OnKeyPressed(const views::KeyEvent& event) OVERRIDE { + bool handled = views::Textfield::OnKeyPressed(event); + return omnibox_view_->HandleAfterKeyEvent(event, handled) || handled; + } + + virtual bool OnKeyReleased(const views::KeyEvent& event) OVERRIDE { + return omnibox_view_->HandleKeyReleaseEvent(event); + } + + virtual bool IsFocusable() const OVERRIDE { + // Bypass Textfield::IsFocusable. The omnibox in popup window requires + // focus in order for text selection to work. + return views::View::IsFocusable(); + } + + private: + OmniboxViewViews* omnibox_view_; + + DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield); +}; + +// Stores omnibox state for each tab. +struct ViewState { + explicit ViewState(const ui::Range& selection_range) + : selection_range(selection_range) { + } + + // Range of selected text. + ui::Range selection_range; +}; + +struct AutocompleteEditState { + AutocompleteEditState(const AutocompleteEditModel::State& model_state, + const ViewState& view_state) + : model_state(model_state), + view_state(view_state) { + } + + const AutocompleteEditModel::State model_state; + const ViewState view_state; +}; + +// Returns a lazily initialized property bag accessor for saving our state in a +// TabContents. +PropertyAccessor<AutocompleteEditState>* GetStateAccessor() { + static PropertyAccessor<AutocompleteEditState> state; + return &state; +} + +const int kAutocompleteVerticalMargin = 4; + +} // namespace + +OmniboxViewViews::OmniboxViewViews(AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater, + bool popup_window_mode, + const views::View* location_bar) + : model_(new AutocompleteEditModel(this, controller, profile)), + popup_view_(CreatePopupView(profile, location_bar)), + controller_(controller), + toolbar_model_(toolbar_model), + command_updater_(command_updater), + popup_window_mode_(popup_window_mode), + security_level_(ToolbarModel::NONE), + ime_composing_before_change_(false), + delete_at_end_pressed_(false) { + set_border(views::Border::CreateEmptyBorder(kAutocompleteVerticalMargin, 0, + kAutocompleteVerticalMargin, 0)); +} + +OmniboxViewViews::~OmniboxViewViews() { + NotificationService::current()->Notify( + NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, + Source<OmniboxViewViews>(this), + NotificationService::NoDetails()); + // Explicitly teardown members which have a reference to us. Just to be safe + // we want them to be destroyed before destroying any other internal state. + popup_view_.reset(); + model_.reset(); +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews public: + +void OmniboxViewViews::Init() { + // The height of the text view is going to change based on the font used. We + // don't want to stretch the height, and we want it vertically centered. + // TODO(oshima): make sure the above happens with views. + textfield_ = new AutocompleteTextfield(this); + textfield_->SetController(this); + +#if defined(TOUCH_UI) + textfield_->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont( + ResourceBundle::LargeFont)); +#endif + + if (popup_window_mode_) + textfield_->SetReadOnly(true); + + // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe + // themes. + SetBaseColor(); +} + +void OmniboxViewViews::SetBaseColor() { + // TODO(oshima): Implment style change. + NOTIMPLEMENTED(); +} + +bool OmniboxViewViews::HandleAfterKeyEvent(const views::KeyEvent& event, + bool handled) { + if (event.key_code() == ui::VKEY_RETURN) { + bool alt_held = event.IsAltDown(); + model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); + handled = true; + } else if (!handled && event.key_code() == ui::VKEY_ESCAPE) { + // We can handle the Escape key if textfield did not handle it. + // If it's not handled by us, then we need to propagate it up to the parent + // widgets, so that Escape accelerator can still work. + handled = model_->OnEscapeKeyPressed(); + } else if (event.key_code() == ui::VKEY_CONTROL) { + // Omnibox2 can switch its contents while pressing a control key. To switch + // the contents of omnibox2, we notify the AutocompleteEditModel class when + // the control-key state is changed. + model_->OnControlKeyChanged(true); + } else if (!handled && event.key_code() == ui::VKEY_DELETE && + event.IsShiftDown()) { + // If shift+del didn't change the text, we let this delete an entry from + // the popup. We can't check to see if the IME handled it because even if + // nothing is selected, the IME or the TextView still report handling it. + if (model_->popup_model()->IsOpen()) + model_->popup_model()->TryDeletingCurrentItem(); + } else if (!handled && event.key_code() == ui::VKEY_UP) { + model_->OnUpOrDownKeyPressed(-1); + handled = true; + } else if (!handled && event.key_code() == ui::VKEY_DOWN) { + model_->OnUpOrDownKeyPressed(1); + handled = true; + } else if (!handled && + event.key_code() == ui::VKEY_TAB && + !event.IsShiftDown() && + !event.IsControlDown()) { + if (model_->is_keyword_hint()) { + handled = model_->AcceptKeyword(); + } else { + string16::size_type start = 0; + string16::size_type end = 0; + size_t length = GetTextLength(); + GetSelectionBounds(&start, &end); + if (start != end || start < length) { + OnBeforePossibleChange(); + SelectRange(length, length); + OnAfterPossibleChange(); + handled = true; + } + + // TODO(Oshima): handle instant + } + } + // TODO(oshima): page up & down + + return handled; +} + +bool OmniboxViewViews::HandleKeyReleaseEvent(const views::KeyEvent& event) { + // Omnibox2 can switch its contents while pressing a control key. To switch + // the contents of omnibox2, we notify the AutocompleteEditModel class when + // the control-key state is changed. + if (event.key_code() == ui::VKEY_CONTROL) { + // TODO(oshima): investigate if we need to support keyboard with two + // controls. See omnibox_view_gtk.cc. + model_->OnControlKeyChanged(false); + return true; + } + return false; +} + +void OmniboxViewViews::HandleFocusIn() { + // TODO(oshima): Get control key state. + model_->OnSetFocus(false); + // Don't call controller_->OnSetFocus as this view has already + // acquired the focus. +} + +void OmniboxViewViews::HandleFocusOut() { + // TODO(oshima): we don't have native view. This requires + // further refactoring. + model_->OnWillKillFocus(NULL); + // Close the popup. + ClosePopup(); + // Tell the model to reset itself. + model_->OnKillFocus(); + controller_->OnKillFocus(); +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews, views::View implementation: +void OmniboxViewViews::Layout() { + gfx::Insets insets = GetInsets(); + textfield_->SetBounds(insets.left(), insets.top(), + width() - insets.width(), + height() - insets.height()); +} + +void OmniboxViewViews::GetAccessibleState(ui::AccessibleViewState* state) { + state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION); +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews, AutocopmleteEditView implementation: + +AutocompleteEditModel* OmniboxViewViews::model() { + return model_.get(); +} + +const AutocompleteEditModel* OmniboxViewViews::model() const { + return model_.get(); +} + +void OmniboxViewViews::SaveStateToTab(TabContents* tab) { + DCHECK(tab); + + // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. + AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch(); + ui::Range selection; + textfield_->GetSelectedRange(&selection); + GetStateAccessor()->SetProperty( + tab->property_bag(), + AutocompleteEditState(model_state, ViewState(selection))); +} + +void OmniboxViewViews::Update(const TabContents* contents) { + // NOTE: We're getting the URL text here from the ToolbarModel. + bool visibly_changed_permanent_text = + model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText())); + + ToolbarModel::SecurityLevel security_level = + toolbar_model_->GetSecurityLevel(); + bool changed_security_level = (security_level != security_level_); + security_level_ = security_level; + + // TODO(oshima): Copied from gtk implementation which is + // slightly different from WIN impl. Find out the correct implementation + // for views-implementation. + if (contents) { + RevertAll(); + const AutocompleteEditState* state = + GetStateAccessor()->GetProperty(contents->property_bag()); + if (state) { + model_->RestoreState(state->model_state); + + // Move the marks for the cursor and the other end of the selection to + // the previously-saved offsets (but preserve PRIMARY). + textfield_->SelectRange(state->view_state.selection_range); + } + } else if (visibly_changed_permanent_text) { + RevertAll(); + } else if (changed_security_level) { + EmphasizeURLComponents(); + } +} + +void OmniboxViewViews::OpenURL(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url, + size_t selected_line, + const string16& keyword) { + if (!url.is_valid()) + return; + + model_->OpenURL(url, disposition, transition, alternate_nav_url, + selected_line, keyword); +} + +string16 OmniboxViewViews::GetText() const { + // TODO(oshima): IME support + return textfield_->text(); +} + +bool OmniboxViewViews::IsEditingOrEmpty() const { + return model_->user_input_in_progress() || (GetTextLength() == 0); +} + +int OmniboxViewViews::GetIcon() const { + return IsEditingOrEmpty() ? + AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : + toolbar_model_->GetIcon(); +} + +void OmniboxViewViews::SetUserText(const string16& text) { + SetUserText(text, text, true); +} + +void OmniboxViewViews::SetUserText(const string16& text, + const string16& display_text, + bool update_popup) { + model_->SetUserText(text); + SetWindowTextAndCaretPos(display_text, display_text.length()); + if (update_popup) + UpdatePopup(); + TextChanged(); +} + +void OmniboxViewViews::SetWindowTextAndCaretPos(const string16& text, + size_t caret_pos) { + const ui::Range range(caret_pos, caret_pos); + SetTextAndSelectedRange(text, range); +} + +void OmniboxViewViews::SetForcedQuery() { + const string16 current_text(GetText()); + const size_t start = current_text.find_first_not_of(kWhitespaceUTF16); + if (start == string16::npos || (current_text[start] != '?')) { + SetUserText(ASCIIToUTF16("?")); + } else { + SelectRange(current_text.size(), start + 1); + } +} + +bool OmniboxViewViews::IsSelectAll() { + // TODO(oshima): IME support. + return textfield_->text() == textfield_->GetSelectedText(); +} + +bool OmniboxViewViews::DeleteAtEndPressed() { + return delete_at_end_pressed_; +} + +void OmniboxViewViews::GetSelectionBounds(string16::size_type* start, + string16::size_type* end) { + ui::Range range; + textfield_->GetSelectedRange(&range); + *start = static_cast<size_t>(range.end()); + *end = static_cast<size_t>(range.start()); +} + +void OmniboxViewViews::SelectAll(bool reversed) { + if (reversed) + SelectRange(GetTextLength(), 0); + else + SelectRange(0, GetTextLength()); +} + +void OmniboxViewViews::RevertAll() { + ClosePopup(); + model_->Revert(); + TextChanged(); +} + +void OmniboxViewViews::UpdatePopup() { + model_->SetInputInProgress(true); + if (!model_->has_focus()) + return; + + // Don't inline autocomplete when the caret/selection isn't at the end of + // the text, or in the middle of composition. + ui::Range sel; + textfield_->GetSelectedRange(&sel); + bool no_inline_autocomplete = + sel.GetMax() < GetTextLength() || textfield_->IsIMEComposing(); + + model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete); +} + +void OmniboxViewViews::ClosePopup() { + model_->StopAutocomplete(); +} + +void OmniboxViewViews::SetFocus() { + // In views-implementation, the focus is on textfield rather than + // AutocompleteEditView. + textfield_->RequestFocus(); +} + +void OmniboxViewViews::OnTemporaryTextMaybeChanged( + const string16& display_text, + bool save_original_selection) { + if (save_original_selection) + textfield_->GetSelectedRange(&saved_temporary_selection_); + + SetWindowTextAndCaretPos(display_text, display_text.length()); + TextChanged(); +} + +bool OmniboxViewViews::OnInlineAutocompleteTextMaybeChanged( + const string16& display_text, + size_t user_text_length) { + if (display_text == GetText()) + return false; + ui::Range range(display_text.size(), user_text_length); + SetTextAndSelectedRange(display_text, range); + TextChanged(); + return true; +} + +void OmniboxViewViews::OnRevertTemporaryText() { + textfield_->SelectRange(saved_temporary_selection_); + TextChanged(); +} + +void OmniboxViewViews::OnBeforePossibleChange() { + // Record our state. + text_before_change_ = GetText(); + textfield_->GetSelectedRange(&sel_before_change_); + ime_composing_before_change_ = textfield_->IsIMEComposing(); +} + +bool OmniboxViewViews::OnAfterPossibleChange() { + ui::Range new_sel; + textfield_->GetSelectedRange(&new_sel); + + // See if the text or selection have changed since OnBeforePossibleChange(). + const string16 new_text = GetText(); + const bool text_changed = (new_text != text_before_change_) || + (ime_composing_before_change_ != textfield_->IsIMEComposing()); + const bool selection_differs = + !((sel_before_change_.is_empty() && new_sel.is_empty()) || + sel_before_change_.EqualsIgnoringDirection(new_sel)); + + // When the user has deleted text, we don't allow inline autocomplete. Make + // sure to not flag cases like selecting part of the text and then pasting + // (or typing) the prefix of that selection. (We detect these by making + // sure the caret, which should be after any insertion, hasn't moved + // forward of the old selection start.) + const bool just_deleted_text = + (text_before_change_.length() > new_text.length()) && + (new_sel.start() <= sel_before_change_.GetMin()); + + const bool something_changed = model_->OnAfterPossibleChange( + new_text, new_sel.start(), new_sel.end(), selection_differs, + text_changed, just_deleted_text, !textfield_->IsIMEComposing()); + + // If only selection was changed, we don't need to call |model_|'s + // OnChanged() method, which is called in TextChanged(). + // But we still need to call EmphasizeURLComponents() to make sure the text + // attributes are updated correctly. + if (something_changed && text_changed) + TextChanged(); + else if (selection_differs) + EmphasizeURLComponents(); + else if (delete_at_end_pressed_) + model_->OnChanged(); + + return something_changed; +} + +gfx::NativeView OmniboxViewViews::GetNativeView() const { + return GetWidget()->GetNativeView(); +} + +CommandUpdater* OmniboxViewViews::GetCommandUpdater() { + return command_updater_; +} + +void OmniboxViewViews::SetInstantSuggestion(const string16& input, + bool animate_to_complete) { + NOTIMPLEMENTED(); +} + +string16 OmniboxViewViews::GetInstantSuggestion() const { + NOTIMPLEMENTED(); + return string16(); +} + +int OmniboxViewViews::TextWidth() const { + // TODO(oshima): add horizontal margin. + return textfield_->font().GetStringWidth(textfield_->text()); +} + +bool OmniboxViewViews::IsImeComposing() const { + return false; +} + +views::View* OmniboxViewViews::AddToView(views::View* parent) { + parent->AddChildView(this); + AddChildView(textfield_); + return this; +} + +int OmniboxViewViews::OnPerformDrop(const views::DropTargetEvent& event) { + NOTIMPLEMENTED(); + return ui::DragDropTypes::DRAG_NONE; +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews, NotificationObserver implementation: + +void OmniboxViewViews::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); + SetBaseColor(); +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews, views::TextfieldController implementation: + +void OmniboxViewViews::ContentsChanged(views::Textfield* sender, + const string16& new_contents) { +} + +bool OmniboxViewViews::HandleKeyEvent(views::Textfield* textfield, + const views::KeyEvent& event) { + delete_at_end_pressed_ = false; + + if (event.key_code() == ui::VKEY_BACK) { + // Checks if it's currently in keyword search mode. + if (model_->is_keyword_hint() || model_->keyword().empty()) + return false; + // If there is selection, let textfield handle the backspace. + if (textfield_->HasSelection()) + return false; + // If not at the begining of the text, let textfield handle the backspace. + if (textfield_->GetCursorPosition()) + return false; + model_->ClearKeyword(GetText()); + return true; + } + + if (event.key_code() == ui::VKEY_DELETE && !event.IsAltDown()) { + delete_at_end_pressed_ = + (!textfield_->HasSelection() && + textfield_->GetCursorPosition() == textfield_->text().length()); + } + + return false; +} + +void OmniboxViewViews::OnBeforeUserAction(views::Textfield* sender) { + OnBeforePossibleChange(); +} + +void OmniboxViewViews::OnAfterUserAction(views::Textfield* sender) { + OnAfterPossibleChange(); +} + +//////////////////////////////////////////////////////////////////////////////// +// OmniboxViewViews, private: + +size_t OmniboxViewViews::GetTextLength() const { + // TODO(oshima): Support instant, IME. + return textfield_->text().length(); +} + +void OmniboxViewViews::EmphasizeURLComponents() { + // TODO(oshima): Update URL visual style + NOTIMPLEMENTED(); +} + +void OmniboxViewViews::TextChanged() { + EmphasizeURLComponents(); + model_->OnChanged(); +} + +void OmniboxViewViews::SetTextAndSelectedRange(const string16& text, + const ui::Range& range) { + if (text != GetText()) + textfield_->SetText(text); + textfield_->SelectRange(range); +} + +string16 OmniboxViewViews::GetSelectedText() const { + // TODO(oshima): Support instant, IME. + return textfield_->GetSelectedText(); +} + +void OmniboxViewViews::SelectRange(size_t caret, size_t end) { + const ui::Range range(caret, end); + textfield_->SelectRange(range); +} + +AutocompletePopupView* OmniboxViewViews::CreatePopupView( + Profile* profile, + const View* location_bar) { +#if defined(TOUCH_UI) + return new TouchAutocompletePopupContentsView( +#else + return new AutocompletePopupContentsView( +#endif + gfx::Font(), this, model_.get(), profile, location_bar); +} diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h new file mode 100644 index 0000000..7fdf5e0 --- /dev/null +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h @@ -0,0 +1,193 @@ +// 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_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_ +#define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/autocomplete/autocomplete_edit_view.h" +#include "chrome/browser/ui/toolbar/toolbar_model.h" +#include "content/common/notification_observer.h" +#include "content/common/page_transition_types.h" +#include "ui/base/range/range.h" +#include "views/controls/textfield/textfield_controller.h" +#include "views/view.h" +#include "webkit/glue/window_open_disposition.h" + +class AutocompleteEditController; +class AutocompleteEditModel; +class AutocompletePopupView; +class Profile; +class TabContents; + +// Views-implementation of AutocompleteEditView. This is based on +// gtk implementation. The following features are not yet supported. +// +// IME support. +// LTR support. +// Selection behavior. +// Cut,copy and paste behavior. +// Drag and drop behavior. +// URL styles (strikestrough insecure scheme, emphasize host). +// Custom context menu for omnibox. +// Instant. +class OmniboxViewViews : public views::View, + public AutocompleteEditView, + public NotificationObserver, + public views::TextfieldController { + public: + OmniboxViewViews(AutocompleteEditController* controller, + ToolbarModel* toolbar_model, + Profile* profile, + CommandUpdater* command_updater, + bool popup_window_mode, + const views::View* location_bar); + virtual ~OmniboxViewViews(); + + // Initialize, create the underlying views, etc; + void Init(); + + // Sets the colors of the text view according to the theme. + void SetBaseColor(); + + // Called after key even is handled either by HandleKeyEvent or by Textfield. + bool HandleAfterKeyEvent(const views::KeyEvent& event, bool handled); + + // Called when KeyRelease event is generated on textfield. + bool HandleKeyReleaseEvent(const views::KeyEvent& event); + + // Called when Focus is set/unset on textfield. + void HandleFocusIn(); + void HandleFocusOut(); + + // Implements views::View + virtual void Layout() OVERRIDE; + virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + + // Implement the AutocompleteEditView interface. + virtual AutocompleteEditModel* model() OVERRIDE; + virtual const AutocompleteEditModel* model() const OVERRIDE; + + virtual void SaveStateToTab(TabContents* tab) OVERRIDE; + + virtual void Update(const TabContents* tab_for_state_restoring) OVERRIDE; + + virtual void OpenURL(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url, + size_t selected_line, + const string16& keyword) OVERRIDE; + + virtual string16 GetText() const OVERRIDE; + + virtual bool IsEditingOrEmpty() const OVERRIDE; + virtual int GetIcon() const OVERRIDE; + virtual void SetUserText(const string16& text) OVERRIDE; + virtual void SetUserText(const string16& text, + const string16& display_text, + bool update_popup) OVERRIDE; + virtual void SetWindowTextAndCaretPos(const string16& text, + size_t caret_pos) OVERRIDE; + virtual void SetForcedQuery() OVERRIDE; + virtual bool IsSelectAll() OVERRIDE; + virtual bool DeleteAtEndPressed() OVERRIDE; + virtual void GetSelectionBounds(string16::size_type* start, + string16::size_type* end) OVERRIDE; + virtual void SelectAll(bool reversed) OVERRIDE; + virtual void RevertAll() OVERRIDE; + virtual void UpdatePopup() OVERRIDE; + virtual void ClosePopup() OVERRIDE; + virtual void SetFocus() OVERRIDE; + virtual void OnTemporaryTextMaybeChanged( + const string16& display_text, + bool save_original_selection) OVERRIDE; + virtual bool OnInlineAutocompleteTextMaybeChanged( + const string16& display_text, size_t user_text_length) OVERRIDE; + virtual void OnRevertTemporaryText() OVERRIDE; + virtual void OnBeforePossibleChange() OVERRIDE; + virtual bool OnAfterPossibleChange() OVERRIDE; + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual CommandUpdater* GetCommandUpdater() OVERRIDE; + virtual void SetInstantSuggestion(const string16& input, + bool animate_to_complete) OVERRIDE; + virtual string16 GetInstantSuggestion() const OVERRIDE; + virtual int TextWidth() const OVERRIDE; + virtual bool IsImeComposing() const OVERRIDE; + virtual views::View* AddToView(views::View* parent) OVERRIDE; + virtual int OnPerformDrop(const views::DropTargetEvent& event) OVERRIDE; + + // NotificationObserver: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; + + // views::TextfieldController: + virtual void ContentsChanged(views::Textfield* sender, + const string16& new_contents) OVERRIDE; + virtual bool HandleKeyEvent(views::Textfield* sender, + const views::KeyEvent& key_event) OVERRIDE; + virtual void OnBeforeUserAction(views::Textfield* sender) OVERRIDE; + virtual void OnAfterUserAction(views::Textfield* sender) OVERRIDE; + + private: + // Return the number of characers in the current buffer. + size_t GetTextLength() const; + + // Try to parse the current text as a URL and colorize the components. + void EmphasizeURLComponents(); + + // Internally invoked whenever the text changes in some way. + void TextChanged(); + + // Update the field with |text| and set the selection. + void SetTextAndSelectedRange(const string16& text, + const ui::Range& range); + + // Returns the selected text. + string16 GetSelectedText() const; + + // Selects the text given by |caret| and |end|. + void SelectRange(size_t caret, size_t end); + + AutocompletePopupView* CreatePopupView(Profile* profile, + const View* location_bar); + + views::Textfield* textfield_; + + scoped_ptr<AutocompleteEditModel> model_; + scoped_ptr<AutocompletePopupView> popup_view_; + AutocompleteEditController* controller_; + ToolbarModel* toolbar_model_; + + // The object that handles additional command functionality exposed on the + // edit, such as invoking the keyword editor. + CommandUpdater* command_updater_; + + // When true, the location bar view is read only and also is has a slightly + // different presentation (smaller font size). This is used for popups. + bool popup_window_mode_; + + ToolbarModel::SecurityLevel security_level_; + + // Selection at the point where the user started using the + // arrows to move around in the popup. + ui::Range saved_temporary_selection_; + + // Tracking state before and after a possible change. + string16 text_before_change_; + ui::Range sel_before_change_; + bool ime_composing_before_change_; + + // Was the delete key pressed with an empty selection at the end of the edit? + bool delete_at_end_pressed_; + + DISALLOW_COPY_AND_ASSIGN(OmniboxViewViews); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_ |