| 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 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 has_focus_ = false; | 479 has_focus_ = false; |
| 480 control_key_state_ = UP; | 480 control_key_state_ = UP; |
| 481 paste_state_ = NONE; | 481 paste_state_ = NONE; |
| 482 } | 482 } |
| 483 | 483 |
| 484 bool AutocompleteEditModel::OnEscapeKeyPressed() { | 484 bool AutocompleteEditModel::OnEscapeKeyPressed() { |
| 485 if (has_temporary_text_) { | 485 if (has_temporary_text_) { |
| 486 AutocompleteMatch match; | 486 AutocompleteMatch match; |
| 487 popup_->InfoForCurrentSelection(&match, NULL); | 487 popup_->InfoForCurrentSelection(&match, NULL); |
| 488 if (match.destination_url != original_url_) { | 488 if (match.destination_url != original_url_) { |
| 489 // The user typed something, then selected a different item. Restore the | 489 RevertTemporaryText(true); |
| 490 // text they typed and change back to the default item. | |
| 491 // NOTE: This purposefully does not reset paste_state_. | |
| 492 just_deleted_text_ = false; | |
| 493 has_temporary_text_ = false; | |
| 494 popup_->ResetToDefaultMatch(); | |
| 495 view_->OnRevertTemporaryText(); | |
| 496 return true; | 490 return true; |
| 497 } | 491 } |
| 498 } | 492 } |
| 499 | 493 |
| 500 // If the user wasn't editing, but merely had focus in the edit, allow <esc> | 494 // If the user wasn't editing, but merely had focus in the edit, allow <esc> |
| 501 // to be processed as an accelerator, so it can still be used to stop a load. | 495 // to be processed as an accelerator, so it can still be used to stop a load. |
| 502 // When the permanent text isn't all selected we still fall through to the | 496 // When the permanent text isn't all selected we still fall through to the |
| 503 // SelectAll() call below so users can arrow around in the text and then hit | 497 // SelectAll() call below so users can arrow around in the text and then hit |
| 504 // <esc> to quickly replace all the text; this matches IE. | 498 // <esc> to quickly replace all the text; this matches IE. |
| 505 if (!user_input_in_progress_ && view_->IsSelectAll()) | 499 if (!user_input_in_progress_ && view_->IsSelectAll()) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 // user's selection gets screwy; and if we don't update the popup, and the | 586 // user's selection gets screwy; and if we don't update the popup, and the |
| 593 // user reverts, then the selected item will be as if control is still | 587 // user reverts, then the selected item will be as if control is still |
| 594 // pressed, even though maybe it isn't any more. There is no obvious | 588 // pressed, even though maybe it isn't any more. There is no obvious |
| 595 // right answer here :( | 589 // right answer here :( |
| 596 } | 590 } |
| 597 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(text), | 591 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(text), |
| 598 save_original_selection); | 592 save_original_selection); |
| 599 return; | 593 return; |
| 600 } | 594 } |
| 601 | 595 |
| 602 // All cases that can result in |has_temporary_text_| being set should have | 596 bool call_controller_onchanged = true; |
| 603 // been handled by the conditional above. | |
| 604 DCHECK(!has_temporary_text_); | |
| 605 | |
| 606 inline_autocomplete_text_ = text; | 597 inline_autocomplete_text_ = text; |
| 607 if (view_->OnInlineAutocompleteTextMaybeChanged( | 598 if (view_->OnInlineAutocompleteTextMaybeChanged( |
| 608 DisplayTextFromUserText(user_text_ + inline_autocomplete_text_), | 599 DisplayTextFromUserText(user_text_ + inline_autocomplete_text_), |
| 609 DisplayTextFromUserText(user_text_).length())) | 600 DisplayTextFromUserText(user_text_).length())) |
| 610 return; | 601 call_controller_onchanged = false; |
| 611 | 602 |
| 612 // All other code paths that return invoke OnChanged. We need to invoke | 603 // If |has_temporary_text_| is true, then we previously had a manual selection |
| 613 // OnChanged in case the destination url changed (as could happen when control | 604 // but now don't (or |destination_for_temporary_text_change| would have been |
| 614 // is toggled). | 605 // non-NULL). This can happen when deleting the selected item in the popup. |
| 615 controller_->OnChanged(); | 606 // In this case, we've already reverted the popup to the default match, so we |
| 607 // need to revert ourselves as well. |
| 608 if (has_temporary_text_) { |
| 609 RevertTemporaryText(false); |
| 610 call_controller_onchanged = false; |
| 611 } |
| 612 |
| 613 // We need to invoke OnChanged in case the destination url changed (as could |
| 614 // happen when control is toggled). |
| 615 if (call_controller_onchanged) |
| 616 controller_->OnChanged(); |
| 616 } | 617 } |
| 617 | 618 |
| 618 bool AutocompleteEditModel::OnAfterPossibleChange( | 619 bool AutocompleteEditModel::OnAfterPossibleChange( |
| 619 const string16& new_text, | 620 const string16& new_text, |
| 620 bool selection_differs, | 621 bool selection_differs, |
| 621 bool text_differs, | 622 bool text_differs, |
| 622 bool just_deleted_text, | 623 bool just_deleted_text, |
| 623 bool allow_keyword_ui_change) { | 624 bool allow_keyword_ui_change) { |
| 624 // Update the paste state as appropriate: if we're just finishing a paste | 625 // Update the paste state as appropriate: if we're just finishing a paste |
| 625 // that replaced all the text, preserve that information; otherwise, if we've | 626 // that replaced all the text, preserve that information; otherwise, if we've |
| (...skipping 30 matching lines...) Expand all Loading... |
| 656 // Track when the user has deleted text so we won't allow inline | 657 // Track when the user has deleted text so we won't allow inline |
| 657 // autocomplete. | 658 // autocomplete. |
| 658 just_deleted_text_ = just_deleted_text; | 659 just_deleted_text_ = just_deleted_text; |
| 659 } | 660 } |
| 660 | 661 |
| 661 view_->UpdatePopup(); | 662 view_->UpdatePopup(); |
| 662 | 663 |
| 663 // Change to keyword mode if the user has typed a keyword name and is now | 664 // Change to keyword mode if the user has typed a keyword name and is now |
| 664 // pressing space after the name. Accepting the keyword will update our | 665 // pressing space after the name. Accepting the keyword will update our |
| 665 // state, so in that case there's no need to also return true here. | 666 // state, so in that case there's no need to also return true here. |
| 666 if (text_differs && allow_keyword_ui_change && !just_deleted_text && | 667 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && |
| 667 MaybeAcceptKeywordBySpace(old_user_text, user_text_)) | 668 MaybeAcceptKeywordBySpace(old_user_text, user_text_)); |
| 668 return false; | |
| 669 | |
| 670 return true; | |
| 671 } | 669 } |
| 672 | 670 |
| 673 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { | 671 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { |
| 674 controller_->OnPopupBoundsChanged(bounds); | 672 controller_->OnPopupBoundsChanged(bounds); |
| 675 } | 673 } |
| 676 | 674 |
| 677 void AutocompleteEditModel::OnPopupClosed() { | 675 void AutocompleteEditModel::OnPopupClosed() { |
| 678 // Accepts the temporary text as the user text, because it makes little | 676 // Accepts the temporary text as the user text, because it makes little |
| 679 // sense to have temporary text when the popup is closed. | 677 // sense to have temporary text when the popup is closed. |
| 680 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | 678 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 GURL parsed_url; | 772 GURL parsed_url; |
| 775 const AutocompleteInput::Type type = AutocompleteInput::Parse( | 773 const AutocompleteInput::Type type = AutocompleteInput::Parse( |
| 776 UserTextFromDisplayText(text), string16(), NULL, NULL, &parsed_url); | 774 UserTextFromDisplayText(text), string16(), NULL, NULL, &parsed_url); |
| 777 if (type != AutocompleteInput::URL) | 775 if (type != AutocompleteInput::URL) |
| 778 return false; | 776 return false; |
| 779 | 777 |
| 780 *url = parsed_url; | 778 *url = parsed_url; |
| 781 return true; | 779 return true; |
| 782 } | 780 } |
| 783 | 781 |
| 782 void AutocompleteEditModel::RevertTemporaryText(bool revert_popup) { |
| 783 // The user typed something, then selected a different item. Restore the |
| 784 // text they typed and change back to the default item. |
| 785 // NOTE: This purposefully does not reset paste_state_. |
| 786 just_deleted_text_ = false; |
| 787 has_temporary_text_ = false; |
| 788 if (revert_popup) |
| 789 popup_->ResetToDefaultMatch(); |
| 790 view_->OnRevertTemporaryText(); |
| 791 } |
| 792 |
| 784 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( | 793 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( |
| 785 const string16& old_user_text, | 794 const string16& old_user_text, |
| 786 const string16& new_user_text) { | 795 const string16& new_user_text) { |
| 787 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && | 796 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
| 788 inline_autocomplete_text_.empty() && new_user_text.length() >= 2 && | 797 inline_autocomplete_text_.empty() && new_user_text.length() >= 2 && |
| 789 IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) && | 798 IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) && |
| 790 !IsWhitespace(*(new_user_text.rbegin() + 1)) && | 799 !IsWhitespace(*(new_user_text.rbegin() + 1)) && |
| 791 (old_user_text.length() + 1 >= new_user_text.length()) && | 800 (old_user_text.length() + 1 >= new_user_text.length()) && |
| 792 !new_user_text.compare(0, new_user_text.length() - 1, old_user_text, | 801 !new_user_text.compare(0, new_user_text.length() - 1, old_user_text, |
| 793 0, new_user_text.length() - 1) && | 802 0, new_user_text.length() - 1) && |
| 794 AcceptKeyword(); | 803 AcceptKeyword(); |
| 795 } | 804 } |
| 796 | 805 |
| 797 // static | 806 // static |
| 798 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 807 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
| 799 switch (c) { | 808 switch (c) { |
| 800 case 0x0020: // Space | 809 case 0x0020: // Space |
| 801 case 0x3000: // Ideographic Space | 810 case 0x3000: // Ideographic Space |
| 802 return true; | 811 return true; |
| 803 default: | 812 default: |
| 804 return false; | 813 return false; |
| 805 } | 814 } |
| 806 } | 815 } |
| OLD | NEW |