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 |