| 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 |