Chromium Code Reviews| 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 |