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..ea854c16da32df9775744ffc10cceb0174c133a3 |
--- /dev/null |
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc |
@@ -0,0 +1,636 @@ |
+// 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, |
Peter Kasting
2011/01/20 19:44:37
Nit: Just put the zeros on the ends of the other t
oshima
2011/01/20 21:35:48
Done.
|
+ 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. |
Peter Kasting
2011/01/20 19:44:37
Nit: pass -> Pass
oshima
2011/01/20 21:35:48
Done.
|
+ return false; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// 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); |
+ // TODO(oshima): |
+ // gtk imlp uses bounds (end) as start and caret (start) as end and |
Peter Kasting
2011/01/20 19:44:37
Nit: This comment can go away now, right?
oshima
2011/01/20 21:35:48
Done.
|
+ // win's behavior seem to be the same. Figure out why and fix if necessary. |
+ *start = static_cast<size_t>(range.end()); |
+ *end = static_cast<size_t>(range.start()); |
+} |
+ |
+void AutocompleteEditViewViews::SelectAll(bool reversed) { |
+ if (reversed) { |
Peter Kasting
2011/01/20 19:44:37
Nit: No {}
oshima
2011/01/20 21:35:48
Done.
|
+ 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_); |
+ SetLayoutManager(new views::FillLayout(true /* exlucde insets*/)); |
+ 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()) |
Peter Kasting
2011/01/20 19:44:37
Nit: Could simplify all this to
if (!model_->is
|
+ 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()) { |
Peter Kasting
2011/01/20 19:44:37
Nit: No {}
oshima
2011/01/20 21:35:48
Done.
|
+ 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); |
+} |