| Index: chrome/browser/autocomplete/autocomplete_edit_view_views.cc
|
| diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_views.cc b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..357c7a21578594ee8f4bbf6729f3e005987f262a
|
| --- /dev/null
|
| +++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc
|
| @@ -0,0 +1,635 @@
|
| +// 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/autocomplete/autocomplete_edit_view_views.h"
|
| +
|
| +#include "app/l10n_util.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/tab_contents/tab_contents.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/common/notification_service.h"
|
| +#include "gfx/font.h"
|
| +#include "googleurl/src/gurl.h"
|
| +#include "grit/generated_resources.h"
|
| +#include "net/base/escape.h"
|
| +#include "views/border.h"
|
| +#include "views/fill_layout.h"
|
| +
|
| +namespace {
|
| +
|
| +// Textfield for autocomplete that intercepts events that are necessary
|
| +// for AutocompleteEditViewViews.
|
| +class AutocompleteTextfield : public views::Textfield {
|
| + public:
|
| + explicit AutocompleteTextfield(
|
| + AutocompleteEditViewViews* autocomplete_edit_view)
|
| + : views::Textfield(views::Textfield::STYLE_DEFAULT),
|
| + autocomplete_edit_view_(autocomplete_edit_view) {
|
| + DCHECK(autocomplete_edit_view_);
|
| + RemoveBorder();
|
| + }
|
| +
|
| + // views::View implementation
|
| + virtual void DidGainFocus() {
|
| + views::Textfield::DidGainFocus();
|
| + autocomplete_edit_view_->HandleFocusIn();
|
| + }
|
| +
|
| + virtual void WillLoseFocus() {
|
| + views::Textfield::WillLoseFocus();
|
| + autocomplete_edit_view_->HandleFocusOut();
|
| + }
|
| +
|
| + virtual bool OnKeyPressed(const views::KeyEvent& e) {
|
| + bool handled = views::Textfield::OnKeyPressed(e);
|
| + return autocomplete_edit_view_->HandleAfterKeyEvent(e, handled) || handled;
|
| + }
|
| +
|
| + virtual bool OnKeyReleased(const views::KeyEvent& e) {
|
| + return autocomplete_edit_view_->HandleKeyReleaseEvent(e);
|
| + }
|
| +
|
| + virtual bool IsFocusable() const {
|
| + // Bypass Textfield::IsFocusable. The omnibox in popup window requires
|
| + // focus in order for text selection to work.
|
| + return views::View::IsFocusable();
|
| + }
|
| +
|
| + private:
|
| + AutocompleteEditViewViews* autocomplete_edit_view_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield);
|
| +};
|
| +
|
| +// Stores omnibox state for each tab.
|
| +struct ViewState {
|
| + explicit ViewState(const views::TextRange& selection_range)
|
| + : selection_range(selection_range) {
|
| + }
|
| +
|
| + // Range of selected text.
|
| + views::TextRange 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
|
| +
|
| +AutocompleteEditViewViews::AutocompleteEditViewViews(
|
| + 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_(new AutocompletePopupContentsView(
|
| + gfx::Font(), this, model_.get(), profile, location_bar)),
|
| + controller_(controller),
|
| + toolbar_model_(toolbar_model),
|
| + command_updater_(command_updater),
|
| + popup_window_mode_(popup_window_mode),
|
| + security_level_(ToolbarModel::NONE),
|
| + delete_was_pressed_(false),
|
| + delete_at_end_pressed_(false) {
|
| + model_->SetPopupModel(popup_view_->GetModel());
|
| + set_border(views::Border::CreateEmptyBorder(kAutocompleteVerticalMargin, 0,
|
| + kAutocompleteVerticalMargin, 0));
|
| +}
|
| +
|
| +AutocompleteEditViewViews::~AutocompleteEditViewViews() {
|
| + NotificationService::current()->Notify(
|
| + NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
|
| + Source<AutocompleteEditViewViews>(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();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews public:
|
| +
|
| +void AutocompleteEditViewViews::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 (popup_window_mode_)
|
| + textfield_->SetReadOnly(true);
|
| +
|
| + // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe
|
| + // themes.
|
| + SetBaseColor();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetBaseColor() {
|
| + // TODO(oshima): Implment style change.
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::HandleAfterKeyEvent(
|
| + const views::KeyEvent& event,
|
| + bool handled) {
|
| + handling_key_press_ = false;
|
| + if (content_maybe_changed_by_key_press_)
|
| + OnAfterPossibleChange();
|
| +
|
| + if (event.GetKeyCode() == ui::VKEY_RETURN) {
|
| + bool alt_held = event.IsAltDown();
|
| + model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
|
| + handled = true;
|
| + } else if (!handled && event.GetKeyCode() == 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.GetKeyCode() == 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 (!text_changed_ && event.GetKeyCode() == 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.
|
| + AutocompletePopupModel* popup_model = popup_view_->GetModel();
|
| + if (popup_model->IsOpen())
|
| + popup_model->TryDeletingCurrentItem();
|
| + } else if (!handled && event.GetKeyCode() == ui::VKEY_UP) {
|
| + model_->OnUpOrDownKeyPressed(-1);
|
| + handled = true;
|
| + } else if (!handled && event.GetKeyCode() == ui::VKEY_DOWN) {
|
| + model_->OnUpOrDownKeyPressed(1);
|
| + handled = true;
|
| + } else if (!handled &&
|
| + event.GetKeyCode() == ui::VKEY_TAB &&
|
| + !event.IsShiftDown() &&
|
| + !event.IsControlDown()) {
|
| + if (model_->is_keyword_hint() && !model_->keyword().empty()) {
|
| + model_->AcceptKeyword();
|
| + handled = true;
|
| + } else {
|
| + // TODO(Oshima): handle instant
|
| + }
|
| + }
|
| + // TODO(oshima): page up & down
|
| +
|
| + return handled;
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::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.GetKeyCode() == ui::VKEY_CONTROL) {
|
| + // TODO(oshima): investigate if we need to support keyboard with two
|
| + // controls. See autocomplete_edit_view_gtk.cc.
|
| + model_->OnControlKeyChanged(false);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::HandleFocusIn() {
|
| + // TODO(oshima): Get control key state.
|
| + model_->OnSetFocus(false);
|
| + // Don't call controller_->OnSetFocus as this view has already
|
| + // acquired the focus.
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::HandleFocusOut() {
|
| + // TODO(oshima): we don't have native view. This requires
|
| + // further refactoring.
|
| + controller_->OnAutocompleteLosingFocus(NULL);
|
| + // Close the popup.
|
| + ClosePopup();
|
| + // Tell the model to reset itself.
|
| + model_->OnKillFocus();
|
| + controller_->OnKillFocus();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews, views::View implementation:
|
| +
|
| +bool AutocompleteEditViewViews::OnMousePressed(
|
| + const views::MouseEvent& event) {
|
| + if (event.IsLeftMouseButton()) {
|
| + // Button press event may change the selection, we need to record the change
|
| + // and report it to |model_| later when button is released.
|
| + OnBeforePossibleChange();
|
| + }
|
| + // Pass the event through to TextfieldViews.
|
| + return false;
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::Layout() {
|
| + gfx::Insets insets = GetInsets();
|
| + textfield_->SetBounds(insets.left(), insets.top(),
|
| + width() - insets.width(),
|
| + height() - insets.height());
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews, AutocopmleteEditView implementation:
|
| +
|
| +AutocompleteEditModel* AutocompleteEditViewViews::model() {
|
| + return model_.get();
|
| +}
|
| +
|
| +const AutocompleteEditModel* AutocompleteEditViewViews::model() const {
|
| + return model_.get();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SaveStateToTab(TabContents* tab) {
|
| + DCHECK(tab);
|
| +
|
| + // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
|
| + AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch();
|
| + views::TextRange selection;
|
| + textfield_->GetSelectedRange(&selection);
|
| + GetStateAccessor()->SetProperty(
|
| + tab->property_bag(),
|
| + AutocompleteEditState(model_state, ViewState(selection)));
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::Update(const TabContents* contents) {
|
| + // NOTE: We're getting the URL text here from the ToolbarModel.
|
| + bool visibly_changed_permanent_text =
|
| + model_->UpdatePermanentText(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 AutocompleteEditViewViews::OpenURL(const GURL& url,
|
| + WindowOpenDisposition disposition,
|
| + PageTransition::Type transition,
|
| + const GURL& alternate_nav_url,
|
| + size_t selected_line,
|
| + const std::wstring& keyword) {
|
| + if (!url.is_valid())
|
| + return;
|
| +
|
| + model_->OpenURL(url, disposition, transition, alternate_nav_url,
|
| + selected_line, keyword);
|
| +}
|
| +
|
| +std::wstring AutocompleteEditViewViews::GetText() const {
|
| + // TODO(oshima): IME support
|
| + return UTF16ToWide(textfield_->text());
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::IsEditingOrEmpty() const {
|
| + return model_->user_input_in_progress() || (GetTextLength() == 0);
|
| +}
|
| +
|
| +int AutocompleteEditViewViews::GetIcon() const {
|
| + return IsEditingOrEmpty() ?
|
| + AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
|
| + toolbar_model_->GetIcon();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetUserText(const std::wstring& text) {
|
| + SetUserText(text, text, true);
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetUserText(const std::wstring& text,
|
| + const std::wstring& display_text,
|
| + bool update_popup) {
|
| + model_->SetUserText(text);
|
| + SetWindowTextAndCaretPos(display_text, display_text.length());
|
| + if (update_popup)
|
| + UpdatePopup();
|
| + TextChanged();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetWindowTextAndCaretPos(
|
| + const std::wstring& text,
|
| + size_t caret_pos) {
|
| + const views::TextRange range(caret_pos, caret_pos);
|
| + SetTextAndSelectedRange(text, range);
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetForcedQuery() {
|
| + const std::wstring current_text(GetText());
|
| + const size_t start = current_text.find_first_not_of(kWhitespaceWide);
|
| + if (start == std::wstring::npos || (current_text[start] != '?')) {
|
| + SetUserText(L"?");
|
| + } else {
|
| + SelectRange(current_text.size(), start + 1);
|
| + }
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::IsSelectAll() {
|
| + // TODO(oshima): IME support.
|
| + return textfield_->text() == textfield_->GetSelectedText();
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::DeleteAtEndPressed() {
|
| + return delete_at_end_pressed_;
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::GetSelectionBounds(
|
| + std::wstring::size_type* start,
|
| + std::wstring::size_type* end) {
|
| + views::TextRange range;
|
| + textfield_->GetSelectedRange(&range);
|
| + *start = static_cast<size_t>(range.end());
|
| + *end = static_cast<size_t>(range.start());
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SelectAll(bool reversed) {
|
| + if (reversed)
|
| + SelectRange(GetTextLength(), 0);
|
| + else
|
| + SelectRange(0, GetTextLength());
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::RevertAll() {
|
| + ClosePopup();
|
| + model_->Revert();
|
| + TextChanged();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::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.
|
| + views::TextRange sel;
|
| + textfield_->GetSelectedRange(&sel);
|
| + bool no_inline_autocomplete = sel.GetMax() < GetTextLength();
|
| +
|
| + // TODO(oshima): Support IME. Don't show autocomplete if IME has some text.
|
| + model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete);
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::ClosePopup() {
|
| + if (popup_view_->GetModel()->IsOpen())
|
| + controller_->OnAutocompleteWillClosePopup();
|
| +
|
| + popup_view_->GetModel()->StopAutocomplete();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetFocus() {
|
| + // In views-implementation, the focus is on textfield rather than
|
| + // AutocompleteEditView.
|
| + textfield_->RequestFocus();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::OnTemporaryTextMaybeChanged(
|
| + const std::wstring& display_text,
|
| + bool save_original_selection) {
|
| + if (save_original_selection)
|
| + textfield_->GetSelectedRange(&saved_temporary_selection_);
|
| +
|
| + SetWindowTextAndCaretPos(display_text, display_text.length());
|
| + TextChanged();
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::OnInlineAutocompleteTextMaybeChanged(
|
| + const std::wstring& display_text,
|
| + size_t user_text_length) {
|
| + if (display_text == GetText())
|
| + return false;
|
| + views::TextRange range(display_text.size(), user_text_length);
|
| + SetTextAndSelectedRange(display_text, range);
|
| + TextChanged();
|
| + return true;
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::OnRevertTemporaryText() {
|
| + textfield_->SelectRange(saved_temporary_selection_);
|
| + TextChanged();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::OnBeforePossibleChange() {
|
| + // Record our state.
|
| + text_before_change_ = GetText();
|
| + textfield_->GetSelectedRange(&sel_before_change_);
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::OnAfterPossibleChange() {
|
| + // OnAfterPossibleChange should be called once per modification,
|
| + // and we should ignore if this is called while a key event is being handled
|
| + // because OnAfterPossibleChagne will be called after the key event is
|
| + // actually handled.
|
| + if (handling_key_press_) {
|
| + content_maybe_changed_by_key_press_ = true;
|
| + return false;
|
| + }
|
| + views::TextRange new_sel;
|
| + textfield_->GetSelectedRange(&new_sel);
|
| +
|
| + size_t length = GetTextLength();
|
| + bool at_end_of_edit = (new_sel.start() == length && new_sel.end() == length);
|
| +
|
| + // See if the text or selection have changed since OnBeforePossibleChange().
|
| + std::wstring new_text = GetText();
|
| + text_changed_ = (new_text != text_before_change_);
|
| + bool selection_differs = !sel_before_change_.Equals(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.)
|
| + bool just_deleted_text =
|
| + (text_before_change_.length() > new_text.length()) &&
|
| + (new_sel.start() <= sel_before_change_.GetMin());
|
| +
|
| + delete_at_end_pressed_ = false;
|
| +
|
| + bool something_changed = model_->OnAfterPossibleChange(new_text,
|
| + selection_differs, text_changed_, just_deleted_text, at_end_of_edit);
|
| +
|
| + // If only selection was changed, we don't need to call |controller_|'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_was_pressed_ && at_end_of_edit) {
|
| + delete_at_end_pressed_ = true;
|
| + controller_->OnChanged();
|
| + }
|
| + delete_was_pressed_ = false;
|
| +
|
| + return something_changed;
|
| +}
|
| +
|
| +gfx::NativeView AutocompleteEditViewViews::GetNativeView() const {
|
| + return GetWidget()->GetNativeView();
|
| +}
|
| +
|
| +CommandUpdater* AutocompleteEditViewViews::GetCommandUpdater() {
|
| + return command_updater_;
|
| +}
|
| +
|
| +views::View* AutocompleteEditViewViews::AddToView(views::View* parent) {
|
| + parent->AddChildView(this);
|
| + AddChildView(textfield_);
|
| + return this;
|
| +}
|
| +
|
| +int AutocompleteEditViewViews::TextWidth() const {
|
| + // TODO(oshima): add horizontal margin.
|
| + return textfield_->font().GetStringWidth(textfield_->text());
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::IsImeComposing() const {
|
| + return false;
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::CommitInstantSuggestion(
|
| + const std::wstring& typed_text,
|
| + const std::wstring& suggested_text) {
|
| + model_->FinalizeInstantQuery(typed_text, suggested_text);
|
| + return true;
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input) {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews, NotificationObserver implementation:
|
| +
|
| +void AutocompleteEditViewViews::Observe(NotificationType type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
|
| + SetBaseColor();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews, Textfield::Controller implementation:
|
| +
|
| +void AutocompleteEditViewViews::ContentsChanged(views::Textfield* sender,
|
| + const string16& new_contents) {
|
| + if (handling_key_press_)
|
| + content_maybe_changed_by_key_press_ = true;
|
| +}
|
| +
|
| +bool AutocompleteEditViewViews::HandleKeyEvent(
|
| + views::Textfield* textfield,
|
| + const views::KeyEvent& event) {
|
| + delete_was_pressed_ = event.GetKeyCode() == ui::VKEY_DELETE;
|
| +
|
| + // Reset |text_changed_| before passing the key event on to the text view.
|
| + text_changed_ = false;
|
| + OnBeforePossibleChange();
|
| + handling_key_press_ = true;
|
| + content_maybe_changed_by_key_press_ = false;
|
| +
|
| + if (event.GetKeyCode() == 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_->GetSelectedText().empty())
|
| + 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;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// AutocompleteEditViewViews, private:
|
| +
|
| +size_t AutocompleteEditViewViews::GetTextLength() const {
|
| + // TODO(oshima): Support instant, IME.
|
| + return textfield_->text().length();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::EmphasizeURLComponents() {
|
| + // TODO(oshima): Update URL visual style
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::TextChanged() {
|
| + EmphasizeURLComponents();
|
| + controller_->OnChanged();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SetTextAndSelectedRange(
|
| + const std::wstring& text,
|
| + const views::TextRange& range) {
|
| + if (text != GetText())
|
| + textfield_->SetText(WideToUTF16(text));
|
| + textfield_->SelectRange(range);
|
| +}
|
| +
|
| +string16 AutocompleteEditViewViews::GetSelectedText() const {
|
| + // TODO(oshima): Support instant, IME.
|
| + return textfield_->GetSelectedText();
|
| +}
|
| +
|
| +void AutocompleteEditViewViews::SelectRange(size_t caret, size_t end) {
|
| + const views::TextRange range(caret, end);
|
| + textfield_->SelectRange(range);
|
| +}
|
|
|