OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 view_(view), | 70 view_(view), |
71 popup_(NULL), | 71 popup_(NULL), |
72 controller_(controller), | 72 controller_(controller), |
73 has_focus_(false), | 73 has_focus_(false), |
74 user_input_in_progress_(false), | 74 user_input_in_progress_(false), |
75 just_deleted_text_(false), | 75 just_deleted_text_(false), |
76 has_temporary_text_(false), | 76 has_temporary_text_(false), |
77 paste_state_(NONE), | 77 paste_state_(NONE), |
78 control_key_state_(UP), | 78 control_key_state_(UP), |
79 is_keyword_hint_(false), | 79 is_keyword_hint_(false), |
80 result_frozen_(false), | |
80 paste_and_go_transition_(PageTransition::TYPED), | 81 paste_and_go_transition_(PageTransition::TYPED), |
81 profile_(profile), | 82 profile_(profile), |
82 update_instant_(true), | 83 update_instant_(true), |
83 instant_complete_behavior_(INSTANT_COMPLETE_DELAYED) { | 84 instant_complete_behavior_(INSTANT_COMPLETE_DELAYED) { |
84 } | 85 } |
85 | 86 |
86 AutocompleteEditModel::~AutocompleteEditModel() { | 87 AutocompleteEditModel::~AutocompleteEditModel() { |
87 } | 88 } |
88 | 89 |
89 void AutocompleteEditModel::SetProfile(Profile* profile) { | 90 void AutocompleteEditModel::SetProfile(Profile* profile) { |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 } | 536 } |
536 controller_->OnAutocompleteAccept(url, disposition, transition, | 537 controller_->OnAutocompleteAccept(url, disposition, transition, |
537 alternate_nav_url); | 538 alternate_nav_url); |
538 | 539 |
539 InstantController* instant = controller_->GetInstant(); | 540 InstantController* instant = controller_->GetInstant(); |
540 if (instant && !popup_->IsOpen()) | 541 if (instant && !popup_->IsOpen()) |
541 instant->DestroyPreviewContents(); | 542 instant->DestroyPreviewContents(); |
542 update_instant_ = true; | 543 update_instant_ = true; |
543 } | 544 } |
544 | 545 |
545 bool AutocompleteEditModel::AcceptKeyword() { | 546 bool AutocompleteEditModel::AcceptKeyword(bool update_result) { |
546 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 547 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
547 | 548 |
548 view_->OnBeforePossibleChange(); | 549 view_->OnBeforePossibleChange(); |
550 result_frozen_ = !update_result; | |
549 view_->SetWindowTextAndCaretPos(string16(), 0); | 551 view_->SetWindowTextAndCaretPos(string16(), 0); |
550 is_keyword_hint_ = false; | 552 is_keyword_hint_ = false; |
551 view_->OnAfterPossibleChange(); | 553 view_->OnAfterPossibleChange(); |
554 result_frozen_ = false; | |
552 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 555 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this |
553 // since the edit contents have disappeared. It | 556 // since the edit contents have disappeared. It |
554 // doesn't really matter, but we clear it to be | 557 // doesn't really matter, but we clear it to be |
555 // consistent. | 558 // consistent. |
556 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); | 559 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); |
557 return true; | 560 return true; |
558 } | 561 } |
559 | 562 |
560 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { | 563 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { |
561 view_->OnBeforePossibleChange(); | 564 view_->OnBeforePossibleChange(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
624 // Don't change anything unless the key state is actually toggling. | 627 // Don't change anything unless the key state is actually toggling. |
625 if (pressed == (control_key_state_ == UP)) { | 628 if (pressed == (control_key_state_ == UP)) { |
626 ControlKeyState old_state = control_key_state_; | 629 ControlKeyState old_state = control_key_state_; |
627 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP; | 630 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP; |
628 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) { | 631 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) { |
629 // Arrowing down and then hitting control accepts the temporary text as | 632 // Arrowing down and then hitting control accepts the temporary text as |
630 // the input text. | 633 // the input text. |
631 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | 634 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); |
632 has_temporary_text_ = false; | 635 has_temporary_text_ = false; |
633 if (KeywordIsSelected()) | 636 if (KeywordIsSelected()) |
634 AcceptKeyword(); | 637 AcceptKeyword(true); |
635 } | 638 } |
636 if ((old_state != DOWN_WITH_CHANGE) && popup_->IsOpen()) { | 639 if ((old_state != DOWN_WITH_CHANGE) && popup_->IsOpen()) { |
637 // Autocomplete history provider results may change, so refresh the | 640 // Autocomplete history provider results may change, so refresh the |
638 // popup. This will force user_input_in_progress_ to true, but if the | 641 // popup. This will force user_input_in_progress_ to true, but if the |
639 // popup is open, that should have already been the case. | 642 // popup is open, that should have already been the case. |
640 view_->UpdatePopup(); | 643 view_->UpdatePopup(); |
641 } | 644 } |
642 } | 645 } |
643 } | 646 } |
644 | 647 |
(...skipping 22 matching lines...) Expand all Loading... | |
667 // normally. | 670 // normally. |
668 popup_->Move(count); | 671 popup_->Move(count); |
669 } | 672 } |
670 } | 673 } |
671 | 674 |
672 void AutocompleteEditModel::OnPopupDataChanged( | 675 void AutocompleteEditModel::OnPopupDataChanged( |
673 const string16& text, | 676 const string16& text, |
674 GURL* destination_for_temporary_text_change, | 677 GURL* destination_for_temporary_text_change, |
675 const string16& keyword, | 678 const string16& keyword, |
676 bool is_keyword_hint) { | 679 bool is_keyword_hint) { |
680 | |
Peter Kasting
2011/04/01 00:09:09
Nit: Don't add a blank line
| |
677 // Update keyword/hint-related local state. | 681 // Update keyword/hint-related local state. |
678 bool keyword_state_changed = (keyword_ != keyword) || | 682 bool keyword_state_changed = (keyword_ != keyword) || |
679 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); | 683 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); |
680 if (keyword_state_changed) { | 684 if (keyword_state_changed) { |
681 keyword_ = keyword; | 685 keyword_ = keyword; |
682 is_keyword_hint_ = is_keyword_hint; | 686 is_keyword_hint_ = is_keyword_hint; |
683 | 687 |
688 // If the current result has a duplicate keyword with a | |
689 // more relevant result, don't show a hint. | |
690 if (is_keyword_hint && popup_->selected_line() >= 1) { | |
691 const AutocompleteResult& result = this->result(); | |
692 const AutocompleteResult::const_iterator match(result.begin() + | |
693 popup_->selected_line()); | |
694 const AutocompleteResult::const_iterator found = | |
Peter Kasting
2011/04/01 00:09:09
Nit: It's probably simpler overall to eliminate th
| |
695 std::search(result.begin(), match, match, match + 1, | |
696 AutocompleteMatch::KeywordsEqual); | |
697 if (found != match) { | |
698 is_keyword_hint_ = false; | |
699 keyword_.clear(); | |
700 } | |
701 } | |
702 | |
684 // |is_keyword_hint_| should always be false if |keyword_| is empty. | 703 // |is_keyword_hint_| should always be false if |keyword_| is empty. |
685 DCHECK(!keyword_.empty() || !is_keyword_hint_); | 704 DCHECK(!keyword_.empty() || !is_keyword_hint_); |
686 } | 705 } |
687 | 706 |
688 // Handle changes to temporary text. | 707 // Handle changes to temporary text. |
689 if (destination_for_temporary_text_change != NULL) { | 708 if (destination_for_temporary_text_change != NULL) { |
690 const bool save_original_selection = !has_temporary_text_; | 709 const bool save_original_selection = !has_temporary_text_; |
691 if (save_original_selection) { | 710 if (save_original_selection) { |
692 // Save the original selection and URL so it can be reverted later. | 711 // Save the original selection and URL so it can be reverted later. |
693 has_temporary_text_ = true; | 712 has_temporary_text_ = true; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
768 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 | 787 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 |
769 if (user_text_changed) { | 788 if (user_text_changed) { |
770 InternalSetUserText(UserTextFromDisplayText(new_text)); | 789 InternalSetUserText(UserTextFromDisplayText(new_text)); |
771 has_temporary_text_ = false; | 790 has_temporary_text_ = false; |
772 | 791 |
773 // Track when the user has deleted text so we won't allow inline | 792 // Track when the user has deleted text so we won't allow inline |
774 // autocomplete. | 793 // autocomplete. |
775 just_deleted_text_ = just_deleted_text; | 794 just_deleted_text_ = just_deleted_text; |
776 } | 795 } |
777 | 796 |
778 view_->UpdatePopup(); | 797 if (!result_frozen_) |
798 view_->UpdatePopup(); | |
779 | 799 |
780 // Change to keyword mode if the user has typed a keyword name and is now | 800 // Change to keyword mode if the user has typed a keyword name and is now |
781 // pressing space after the name. Accepting the keyword will update our | 801 // pressing space after the name. Accepting the keyword will update our |
782 // state, so in that case there's no need to also return true here. | 802 // state, so in that case there's no need to also return true here. |
783 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && | 803 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && |
784 MaybeAcceptKeywordBySpace(old_user_text, user_text_)); | 804 MaybeAcceptKeywordBySpace(old_user_text, user_text_)); |
785 } | 805 } |
786 | 806 |
787 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { | 807 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { |
788 InstantController* instant = controller_->GetInstant(); | 808 InstantController* instant = controller_->GetInstant(); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
945 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( | 965 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( |
946 const string16& old_user_text, | 966 const string16& old_user_text, |
947 const string16& new_user_text) { | 967 const string16& new_user_text) { |
948 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && | 968 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
949 inline_autocomplete_text_.empty() && new_user_text.length() >= 2 && | 969 inline_autocomplete_text_.empty() && new_user_text.length() >= 2 && |
950 IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) && | 970 IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) && |
951 !IsWhitespace(*(new_user_text.rbegin() + 1)) && | 971 !IsWhitespace(*(new_user_text.rbegin() + 1)) && |
952 (old_user_text.length() + 1 >= new_user_text.length()) && | 972 (old_user_text.length() + 1 >= new_user_text.length()) && |
953 !new_user_text.compare(0, new_user_text.length() - 1, old_user_text, | 973 !new_user_text.compare(0, new_user_text.length() - 1, old_user_text, |
954 0, new_user_text.length() - 1) && | 974 0, new_user_text.length() - 1) && |
955 AcceptKeyword(); | 975 AcceptKeyword(true); |
956 } | 976 } |
957 | 977 |
958 // static | 978 // static |
959 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 979 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
960 switch (c) { | 980 switch (c) { |
961 case 0x0020: // Space | 981 case 0x0020: // Space |
962 case 0x3000: // Ideographic Space | 982 case 0x3000: // Ideographic Space |
963 return true; | 983 return true; |
964 default: | 984 default: |
965 return false; | 985 return false; |
966 } | 986 } |
967 } | 987 } |
OLD | NEW |