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 27 matching lines...) Expand all Loading... |
38 | 38 |
39 AutocompleteEditController::~AutocompleteEditController() { | 39 AutocompleteEditController::~AutocompleteEditController() { |
40 } | 40 } |
41 | 41 |
42 /////////////////////////////////////////////////////////////////////////////// | 42 /////////////////////////////////////////////////////////////////////////////// |
43 // AutocompleteEditModel::State | 43 // AutocompleteEditModel::State |
44 | 44 |
45 AutocompleteEditModel::State::State(bool user_input_in_progress, | 45 AutocompleteEditModel::State::State(bool user_input_in_progress, |
46 const std::wstring& user_text, | 46 const std::wstring& user_text, |
47 const std::wstring& keyword, | 47 const std::wstring& keyword, |
48 bool is_keyword_hint, | 48 bool is_keyword_hint) |
49 KeywordUIState keyword_ui_state) | |
50 : user_input_in_progress(user_input_in_progress), | 49 : user_input_in_progress(user_input_in_progress), |
51 user_text(user_text), | 50 user_text(user_text), |
52 keyword(keyword), | 51 keyword(keyword), |
53 is_keyword_hint(is_keyword_hint), | 52 is_keyword_hint(is_keyword_hint) { |
54 keyword_ui_state(keyword_ui_state) { | |
55 } | 53 } |
56 | 54 |
57 AutocompleteEditModel::State::~State() { | 55 AutocompleteEditModel::State::~State() { |
58 } | 56 } |
59 | 57 |
60 /////////////////////////////////////////////////////////////////////////////// | 58 /////////////////////////////////////////////////////////////////////////////// |
61 // AutocompleteEditModel | 59 // AutocompleteEditModel |
62 | 60 |
63 AutocompleteEditModel::AutocompleteEditModel( | 61 AutocompleteEditModel::AutocompleteEditModel( |
64 AutocompleteEditView* view, | 62 AutocompleteEditView* view, |
65 AutocompleteEditController* controller, | 63 AutocompleteEditController* controller, |
66 Profile* profile) | 64 Profile* profile) |
67 : view_(view), | 65 : view_(view), |
68 popup_(NULL), | 66 popup_(NULL), |
69 controller_(controller), | 67 controller_(controller), |
70 has_focus_(false), | 68 has_focus_(false), |
71 user_input_in_progress_(false), | 69 user_input_in_progress_(false), |
72 just_deleted_text_(false), | 70 just_deleted_text_(false), |
73 has_temporary_text_(false), | 71 has_temporary_text_(false), |
74 original_keyword_ui_state_(NORMAL), | |
75 paste_state_(NONE), | 72 paste_state_(NONE), |
76 control_key_state_(UP), | 73 control_key_state_(UP), |
77 is_keyword_hint_(false), | 74 is_keyword_hint_(false), |
78 keyword_ui_state_(NORMAL), | |
79 paste_and_go_transition_(PageTransition::TYPED), | 75 paste_and_go_transition_(PageTransition::TYPED), |
80 profile_(profile) { | 76 profile_(profile) { |
81 } | 77 } |
82 | 78 |
83 AutocompleteEditModel::~AutocompleteEditModel() { | 79 AutocompleteEditModel::~AutocompleteEditModel() { |
84 } | 80 } |
85 | 81 |
86 void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) { | 82 void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) { |
87 popup_ = popup_model; | 83 popup_ = popup_model; |
88 registrar_.Add(this, | 84 registrar_.Add(this, |
(...skipping 18 matching lines...) Expand all Loading... |
107 // on switching back, typing will "just work"). | 103 // on switching back, typing will "just work"). |
108 const std::wstring user_text(UserTextFromDisplayText(view_->GetText())); | 104 const std::wstring user_text(UserTextFromDisplayText(view_->GetText())); |
109 if (user_text.empty()) { | 105 if (user_text.empty()) { |
110 view_->RevertAll(); | 106 view_->RevertAll(); |
111 view_->SelectAll(true); | 107 view_->SelectAll(true); |
112 } else { | 108 } else { |
113 InternalSetUserText(user_text); | 109 InternalSetUserText(user_text); |
114 } | 110 } |
115 } | 111 } |
116 | 112 |
117 return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_, | 113 return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_); |
118 keyword_ui_state_); | |
119 } | 114 } |
120 | 115 |
121 void AutocompleteEditModel::RestoreState(const State& state) { | 116 void AutocompleteEditModel::RestoreState(const State& state) { |
122 // Restore any user editing. | 117 // Restore any user editing. |
123 if (state.user_input_in_progress) { | 118 if (state.user_input_in_progress) { |
124 // NOTE: Be sure and set keyword-related state BEFORE invoking | 119 // NOTE: Be sure and set keyword-related state BEFORE invoking |
125 // DisplayTextFromUserText(), as its result depends upon this state. | 120 // DisplayTextFromUserText(), as its result depends upon this state. |
126 keyword_ = state.keyword; | 121 keyword_ = state.keyword; |
127 is_keyword_hint_ = state.is_keyword_hint; | 122 is_keyword_hint_ = state.is_keyword_hint; |
128 keyword_ui_state_ = state.keyword_ui_state; | |
129 view_->SetUserText(state.user_text, | 123 view_->SetUserText(state.user_text, |
130 DisplayTextFromUserText(state.user_text), false); | 124 DisplayTextFromUserText(state.user_text), false); |
131 } | 125 } |
132 } | 126 } |
133 | 127 |
134 AutocompleteMatch AutocompleteEditModel::CurrentMatch() { | 128 AutocompleteMatch AutocompleteEditModel::CurrentMatch() { |
135 AutocompleteMatch match; | 129 AutocompleteMatch match; |
136 GetInfoForCurrentText(&match, NULL); | 130 GetInfoForCurrentText(&match, NULL); |
137 return match; | 131 return match; |
138 } | 132 } |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 user_input_in_progress_ = in_progress; | 283 user_input_in_progress_ = in_progress; |
290 controller_->OnInputInProgress(in_progress); | 284 controller_->OnInputInProgress(in_progress); |
291 } | 285 } |
292 | 286 |
293 void AutocompleteEditModel::Revert() { | 287 void AutocompleteEditModel::Revert() { |
294 SetInputInProgress(false); | 288 SetInputInProgress(false); |
295 paste_state_ = NONE; | 289 paste_state_ = NONE; |
296 InternalSetUserText(std::wstring()); | 290 InternalSetUserText(std::wstring()); |
297 keyword_.clear(); | 291 keyword_.clear(); |
298 is_keyword_hint_ = false; | 292 is_keyword_hint_ = false; |
299 keyword_ui_state_ = NORMAL; | |
300 has_temporary_text_ = false; | 293 has_temporary_text_ = false; |
301 view_->SetWindowTextAndCaretPos(permanent_text_, | 294 view_->SetWindowTextAndCaretPos(permanent_text_, |
302 has_focus_ ? permanent_text_.length() : 0); | 295 has_focus_ ? permanent_text_.length() : 0); |
303 } | 296 } |
304 | 297 |
305 void AutocompleteEditModel::StartAutocomplete( | 298 void AutocompleteEditModel::StartAutocomplete( |
306 bool has_selected_text, | 299 bool has_selected_text, |
307 bool prevent_inline_autocomplete) const { | 300 bool prevent_inline_autocomplete) const { |
| 301 bool keyword_is_selected = KeywordIsSelected(); |
308 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), | 302 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), |
309 prevent_inline_autocomplete || just_deleted_text_ || | 303 prevent_inline_autocomplete || just_deleted_text_ || |
310 (has_selected_text && inline_autocomplete_text_.empty()) || | 304 (has_selected_text && inline_autocomplete_text_.empty()) || |
311 (paste_state_ != NONE), keyword_ui_state_ == KEYWORD, | 305 (paste_state_ != NONE), keyword_is_selected, keyword_is_selected); |
312 keyword_ui_state_ != NO_KEYWORD); | |
313 } | 306 } |
314 | 307 |
315 bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { | 308 bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { |
316 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) | 309 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) |
317 return false; | 310 return false; |
318 | 311 |
319 AutocompleteMatch match; | 312 AutocompleteMatch match; |
320 profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), false, | 313 profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), false, |
321 &match, &paste_and_go_alternate_nav_url_); | 314 &match, &paste_and_go_alternate_nav_url_); |
322 paste_and_go_url_ = match.destination_url; | 315 paste_and_go_url_ = match.destination_url; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 } | 424 } |
432 | 425 |
433 if (disposition != NEW_BACKGROUND_TAB) { | 426 if (disposition != NEW_BACKGROUND_TAB) { |
434 controller_->OnAutocompleteWillAccept(); | 427 controller_->OnAutocompleteWillAccept(); |
435 view_->RevertAll(); // Revert the box to its unedited state | 428 view_->RevertAll(); // Revert the box to its unedited state |
436 } | 429 } |
437 controller_->OnAutocompleteAccept(url, disposition, transition, | 430 controller_->OnAutocompleteAccept(url, disposition, transition, |
438 alternate_nav_url); | 431 alternate_nav_url); |
439 } | 432 } |
440 | 433 |
441 void AutocompleteEditModel::AcceptKeyword() { | 434 bool AutocompleteEditModel::AcceptKeyword() { |
| 435 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
| 436 |
442 view_->OnBeforePossibleChange(); | 437 view_->OnBeforePossibleChange(); |
443 view_->SetWindowTextAndCaretPos(std::wstring(), 0); | 438 view_->SetWindowTextAndCaretPos(std::wstring(), 0); |
444 is_keyword_hint_ = false; | 439 is_keyword_hint_ = false; |
445 keyword_ui_state_ = KEYWORD; | |
446 view_->OnAfterPossibleChange(); | 440 view_->OnAfterPossibleChange(); |
447 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 441 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this |
448 // since the edit contents have disappeared. It | 442 // since the edit contents have disappeared. It |
449 // doesn't really matter, but we clear it to be | 443 // doesn't really matter, but we clear it to be |
450 // consistent. | 444 // consistent. |
451 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); | 445 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); |
| 446 return true; |
452 } | 447 } |
453 | 448 |
454 void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) { | 449 void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) { |
455 view_->OnBeforePossibleChange(); | 450 view_->OnBeforePossibleChange(); |
456 const std::wstring window_text(keyword_ + visible_text); | 451 const std::wstring window_text(keyword_ + visible_text); |
457 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); | 452 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); |
458 keyword_.clear(); | 453 keyword_.clear(); |
459 keyword_ui_state_ = NORMAL; | 454 is_keyword_hint_ = false; |
460 view_->OnAfterPossibleChange(); | 455 view_->OnAfterPossibleChange(); |
461 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 456 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
462 // since the edit contents have actually grown | 457 // since the edit contents have actually grown |
463 // longer. | 458 // longer. |
464 } | 459 } |
465 | 460 |
466 bool AutocompleteEditModel::query_in_progress() const { | 461 bool AutocompleteEditModel::query_in_progress() const { |
467 return !popup_->autocomplete_controller()->done(); | 462 return !popup_->autocomplete_controller()->done(); |
468 } | 463 } |
469 | 464 |
(...skipping 25 matching lines...) Expand all Loading... |
495 bool AutocompleteEditModel::OnEscapeKeyPressed() { | 490 bool AutocompleteEditModel::OnEscapeKeyPressed() { |
496 if (has_temporary_text_) { | 491 if (has_temporary_text_) { |
497 AutocompleteMatch match; | 492 AutocompleteMatch match; |
498 popup_->InfoForCurrentSelection(&match, NULL); | 493 popup_->InfoForCurrentSelection(&match, NULL); |
499 if (match.destination_url != original_url_) { | 494 if (match.destination_url != original_url_) { |
500 // The user typed something, then selected a different item. Restore the | 495 // The user typed something, then selected a different item. Restore the |
501 // text they typed and change back to the default item. | 496 // text they typed and change back to the default item. |
502 // NOTE: This purposefully does not reset paste_state_. | 497 // NOTE: This purposefully does not reset paste_state_. |
503 just_deleted_text_ = false; | 498 just_deleted_text_ = false; |
504 has_temporary_text_ = false; | 499 has_temporary_text_ = false; |
505 keyword_ui_state_ = original_keyword_ui_state_; | |
506 popup_->ResetToDefaultMatch(); | 500 popup_->ResetToDefaultMatch(); |
507 view_->OnRevertTemporaryText(); | 501 view_->OnRevertTemporaryText(); |
508 return true; | 502 return true; |
509 } | 503 } |
510 } | 504 } |
511 | 505 |
512 // If the user wasn't editing, but merely had focus in the edit, allow <esc> | 506 // If the user wasn't editing, but merely had focus in the edit, allow <esc> |
513 // to be processed as an accelerator, so it can still be used to stop a load. | 507 // to be processed as an accelerator, so it can still be used to stop a load. |
514 // When the permanent text isn't all selected we still fall through to the | 508 // When the permanent text isn't all selected we still fall through to the |
515 // SelectAll() call below so users can arrow around in the text and then hit | 509 // SelectAll() call below so users can arrow around in the text and then hit |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 // normally. | 563 // normally. |
570 popup_->Move(count); | 564 popup_->Move(count); |
571 } | 565 } |
572 } | 566 } |
573 | 567 |
574 void AutocompleteEditModel::OnPopupDataChanged( | 568 void AutocompleteEditModel::OnPopupDataChanged( |
575 const std::wstring& text, | 569 const std::wstring& text, |
576 GURL* destination_for_temporary_text_change, | 570 GURL* destination_for_temporary_text_change, |
577 const std::wstring& keyword, | 571 const std::wstring& keyword, |
578 bool is_keyword_hint) { | 572 bool is_keyword_hint) { |
579 KeywordUIState old_keyword_ui_state = keyword_ui_state_; | |
580 | |
581 // Update keyword/hint-related local state. | 573 // Update keyword/hint-related local state. |
582 bool keyword_state_changed = (keyword_ != keyword) || | 574 bool keyword_state_changed = (keyword_ != keyword) || |
583 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); | 575 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); |
584 if (keyword_state_changed) { | 576 if (keyword_state_changed) { |
585 keyword_ = keyword; | 577 keyword_ = keyword; |
586 is_keyword_hint_ = is_keyword_hint; | 578 is_keyword_hint_ = is_keyword_hint; |
587 } | |
588 | 579 |
589 // Update |keyword_ui_state_| only when necessary. It may be changed even if | 580 // |is_keyword_hint_| should always be false if |keyword_| is empty. |
590 // |keyword_state_changed| is false. | 581 DCHECK(!keyword_.empty() || !is_keyword_hint_); |
591 if (keyword_ui_state_ != NO_KEYWORD) { | |
592 keyword_ui_state_ = (is_keyword_hint_ || keyword_.empty()) ? | |
593 NORMAL : KEYWORD; | |
594 } | 582 } |
595 | 583 |
596 // Handle changes to temporary text. | 584 // Handle changes to temporary text. |
597 if (destination_for_temporary_text_change != NULL) { | 585 if (destination_for_temporary_text_change != NULL) { |
598 const bool save_original_selection = !has_temporary_text_; | 586 const bool save_original_selection = !has_temporary_text_; |
599 if (save_original_selection) { | 587 if (save_original_selection) { |
600 // Save the original selection and URL so it can be reverted later. | 588 // Save the original selection and URL so it can be reverted later. |
601 has_temporary_text_ = true; | 589 has_temporary_text_ = true; |
602 original_url_ = *destination_for_temporary_text_change; | 590 original_url_ = *destination_for_temporary_text_change; |
603 original_keyword_ui_state_ = old_keyword_ui_state; | |
604 inline_autocomplete_text_.clear(); | 591 inline_autocomplete_text_.clear(); |
605 } | 592 } |
606 if (control_key_state_ == DOWN_WITHOUT_CHANGE) { | 593 if (control_key_state_ == DOWN_WITHOUT_CHANGE) { |
607 // Arrowing around the popup cancels control-enter. | 594 // Arrowing around the popup cancels control-enter. |
608 control_key_state_ = DOWN_WITH_CHANGE; | 595 control_key_state_ = DOWN_WITH_CHANGE; |
609 // Now things are a bit screwy: the desired_tld has changed, but if we | 596 // Now things are a bit screwy: the desired_tld has changed, but if we |
610 // update the popup, the new order of entries won't match the old, so the | 597 // update the popup, the new order of entries won't match the old, so the |
611 // user's selection gets screwy; and if we don't update the popup, and the | 598 // user's selection gets screwy; and if we don't update the popup, and the |
612 // user reverts, then the selected item will be as if control is still | 599 // user reverts, then the selected item will be as if control is still |
613 // pressed, even though maybe it isn't any more. There is no obvious | 600 // pressed, even though maybe it isn't any more. There is no obvious |
(...skipping 22 matching lines...) Expand all Loading... |
636 | 623 |
637 bool AutocompleteEditModel::OnAfterPossibleChange( | 624 bool AutocompleteEditModel::OnAfterPossibleChange( |
638 const std::wstring& new_text, | 625 const std::wstring& new_text, |
639 bool selection_differs, | 626 bool selection_differs, |
640 bool text_differs, | 627 bool text_differs, |
641 bool just_deleted_text, | 628 bool just_deleted_text, |
642 bool allow_keyword_ui_change) { | 629 bool allow_keyword_ui_change) { |
643 // Update the paste state as appropriate: if we're just finishing a paste | 630 // Update the paste state as appropriate: if we're just finishing a paste |
644 // that replaced all the text, preserve that information; otherwise, if we've | 631 // that replaced all the text, preserve that information; otherwise, if we've |
645 // made some other edit, clear paste tracking. | 632 // made some other edit, clear paste tracking. |
646 if (paste_state_ == REPLACING_ALL) | 633 if (paste_state_ == PASTING) |
647 paste_state_ = REPLACED_ALL; | 634 paste_state_ = PASTED; |
648 else if (text_differs) | 635 else if (text_differs) |
649 paste_state_ = NONE; | 636 paste_state_ = NONE; |
650 | 637 |
651 // Modifying the selection counts as accepting the autocompleted text. | 638 // Modifying the selection counts as accepting the autocompleted text. |
652 const bool user_text_changed = | 639 const bool user_text_changed = |
653 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); | 640 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); |
654 | 641 |
655 // If something has changed while the control key is down, prevent | 642 // If something has changed while the control key is down, prevent |
656 // "ctrl-enter" until the control key is released. When we do this, we need | 643 // "ctrl-enter" until the control key is released. When we do this, we need |
657 // to update the popup if it's open, since the desired_tld will have changed. | 644 // to update the popup if it's open, since the desired_tld will have changed. |
658 if ((text_differs || selection_differs) && | 645 if ((text_differs || selection_differs) && |
659 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { | 646 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { |
660 control_key_state_ = DOWN_WITH_CHANGE; | 647 control_key_state_ = DOWN_WITH_CHANGE; |
661 if (!text_differs && !popup_->IsOpen()) | 648 if (!text_differs && !popup_->IsOpen()) |
662 return false; // Don't open the popup for no reason. | 649 return false; // Don't open the popup for no reason. |
663 } else if (!user_text_changed) { | 650 } else if (!user_text_changed) { |
664 return false; | 651 return false; |
665 } | 652 } |
666 | 653 |
667 const bool had_keyword = KeywordIsSelected(); | |
668 | |
669 // If the user text has not changed, we do not want to change the model's | 654 // If the user text has not changed, we do not want to change the model's |
670 // state associated with the text. Otherwise, we can get surprising behavior | 655 // state associated with the text. Otherwise, we can get surprising behavior |
671 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 | 656 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 |
672 if (user_text_changed) { | 657 if (user_text_changed) { |
673 InternalSetUserText(UserTextFromDisplayText(new_text)); | 658 const std::wstring new_user_text = UserTextFromDisplayText(new_text); |
| 659 |
| 660 // Try to accept the current keyword if the user only typed a space at the |
| 661 // end of content. Model's state and popup will be updated when the keyword |
| 662 // is accepted. So we just need to return false here. |
| 663 if (allow_keyword_ui_change && !selection_differs && |
| 664 MaybeAcceptKeywordBySpace(new_user_text)) |
| 665 return false; |
| 666 |
| 667 InternalSetUserText(new_user_text); |
674 has_temporary_text_ = false; | 668 has_temporary_text_ = false; |
675 | 669 |
676 // Track when the user has deleted text so we won't allow inline | 670 // Track when the user has deleted text so we won't allow inline |
677 // autocomplete. | 671 // autocomplete. |
678 just_deleted_text_ = just_deleted_text; | 672 just_deleted_text_ = just_deleted_text; |
679 } | 673 } |
680 | 674 |
681 // Disable the fancy keyword UI if the user didn't already have a visible | |
682 // keyword and the view doesn't want us to change the keyword UI state. | |
683 // This prevents us from showing the fancy UI and interrupting the user's | |
684 // editing if, for example, the user happens to have a keyword for 'a', | |
685 // types 'ab' then puts a space between the 'a' and the 'b'. | |
686 // If |keyword_ui_state_| is set to NORMAL here, then it will be updated | |
687 // to a proper value in OnPopupDataChanged() method according to the new | |
688 // match result. | |
689 if (!had_keyword) | |
690 keyword_ui_state_ = allow_keyword_ui_change ? NORMAL : NO_KEYWORD; | |
691 | |
692 view_->UpdatePopup(); | 675 view_->UpdatePopup(); |
693 return true; | 676 return true; |
694 } | 677 } |
695 | 678 |
696 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { | 679 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { |
697 controller_->OnPopupBoundsChanged(bounds); | 680 controller_->OnPopupBoundsChanged(bounds); |
698 } | 681 } |
699 | 682 |
700 // Return true if the suggestion type warrants a TCP/IP preconnection. | 683 // Return true if the suggestion type warrants a TCP/IP preconnection. |
701 // i.e., it is now highly likely that the user will select the related domain. | 684 // i.e., it is now highly likely that the user will select the related domain. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint); | 734 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint); |
752 } | 735 } |
753 | 736 |
754 void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { | 737 void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { |
755 user_text_ = text; | 738 user_text_ = text; |
756 just_deleted_text_ = false; | 739 just_deleted_text_ = false; |
757 inline_autocomplete_text_.clear(); | 740 inline_autocomplete_text_.clear(); |
758 } | 741 } |
759 | 742 |
760 bool AutocompleteEditModel::KeywordIsSelected() const { | 743 bool AutocompleteEditModel::KeywordIsSelected() const { |
761 return keyword_ui_state_ == KEYWORD; | 744 return !is_keyword_hint_ && !keyword_.empty(); |
762 } | 745 } |
763 | 746 |
764 std::wstring AutocompleteEditModel::DisplayTextFromUserText( | 747 std::wstring AutocompleteEditModel::DisplayTextFromUserText( |
765 const std::wstring& text) const { | 748 const std::wstring& text) const { |
766 return KeywordIsSelected() ? | 749 return KeywordIsSelected() ? |
767 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 750 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
768 } | 751 } |
769 | 752 |
770 std::wstring AutocompleteEditModel::UserTextFromDisplayText( | 753 std::wstring AutocompleteEditModel::UserTextFromDisplayText( |
771 const std::wstring& text) const { | 754 const std::wstring& text) const { |
(...skipping 16 matching lines...) Expand all Loading... |
788 GURL* url) const { | 771 GURL* url) const { |
789 GURL parsed_url; | 772 GURL parsed_url; |
790 const AutocompleteInput::Type type = AutocompleteInput::Parse( | 773 const AutocompleteInput::Type type = AutocompleteInput::Parse( |
791 UserTextFromDisplayText(text), std::wstring(), NULL, NULL, &parsed_url); | 774 UserTextFromDisplayText(text), std::wstring(), NULL, NULL, &parsed_url); |
792 if (type != AutocompleteInput::URL) | 775 if (type != AutocompleteInput::URL) |
793 return false; | 776 return false; |
794 | 777 |
795 *url = parsed_url; | 778 *url = parsed_url; |
796 return true; | 779 return true; |
797 } | 780 } |
| 781 |
| 782 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( |
| 783 const std::wstring& new_user_text) { |
| 784 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
| 785 inline_autocomplete_text_.empty() && !user_text_.empty() && |
| 786 (new_user_text.length() == user_text_.length() + 1) && |
| 787 !new_user_text.compare(0, user_text_.length(), user_text_) && |
| 788 IsSpaceCharForAcceptingKeyword(new_user_text[user_text_.length()]) && |
| 789 !IsWhitespace(user_text_[user_text_.length() - 1]) && |
| 790 AcceptKeyword(); |
| 791 } |
| 792 |
| 793 // static |
| 794 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
| 795 switch (c) { |
| 796 case 0x0020: // Space |
| 797 case 0x3000: // Ideographic Space |
| 798 return true; |
| 799 default: |
| 800 return false; |
| 801 } |
| 802 } |
OLD | NEW |