#001 void AutocompleteEdit::OnBeforePossibleChange() { #002 // Record our state. |
#003 text_before_change_ = GetText(); |
#004 GetSelection(sel_before_change_); #005 select_all_before_change_ = IsSelectAll(sel_before_change_); #006 } |
#001 bool AutocompleteEdit::OnAfterPossibleChange() { #002 // Prevent the user from selecting the "phantom newline" at the end of the #003 // edit. If they try, we just silently move the end of the selection back to #004 // the end of the real text. |
#005 CHARRANGE new_sel; #006 GetSelection(new_sel); #007 const int length = GetTextLength(); #008 if ((new_sel.cpMin > length) || (new_sel.cpMax > length)) { #009 if (new_sel.cpMin > length) #010 new_sel.cpMin = length; #011 if (new_sel.cpMax > length) #012 new_sel.cpMax = length; #013 SetSelectionRange(new_sel); #014 } |
#015 const bool selection_differs = (new_sel.cpMin != sel_before_change_.cpMin) || #016 (new_sel.cpMax != sel_before_change_.cpMax); #017 #018 // See if the text or selection have changed since OnBeforePossibleChange(). #019 const std::wstring new_text(GetText()); #020 const bool text_differs = (new_text != text_before_change_); #021 #022 // Update the paste state as appropriate: if we're just finishing a paste #023 // that replaced all the text, preserve that information; otherwise, if we've #024 // made some other edit, clear paste tracking. #025 if (paste_state_ == REPLACING_ALL) #026 paste_state_ = REPLACED_ALL; #027 else if (text_differs) #028 paste_state_ = NONE; #029 |
#030 // If something has changed while the control key is down, prevent #031 // "ctrl-enter" until the control key is released. When we do this, we need #032 // to update the popup if it's open, since the desired_tld will have changed. #033 if ((text_differs || selection_differs) && #034 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { #035 control_key_state_ = DOWN_WITH_CHANGE; #036 if (!text_differs && !popup_->is_open()) #037 return false; // Don't open the popup for no reason. #038 } else if (!text_differs && #039 (inline_autocomplete_text_.empty() || !selection_differs)) { #040 return false; #041 } #042 #043 const bool had_keyword = !is_keyword_hint_ && !keyword_.empty(); #044 |
下面开始设置新的显示字符串。
#045 // Modifying the selection counts as accepting the autocompleted text. #046 InternalSetUserText(UserTextFromDisplayText(new_text)); #047 has_temporary_text_ = false; #048 #049 if (text_differs) { #050 // When the user has deleted text, don't allow inline autocomplete. Make #051 // sure to not flag cases like selecting part of the text and then pasting #052 // (or typing) the prefix of that selection. (We detect these by making #053 // sure the caret, which should be after any insertion, hasn't moved #054 // forward of the old selection start.) #055 just_deleted_text_ = (text_before_change_.length() > new_text.length()) && #056 (new_sel.cpMin <= std::min(sel_before_change_.cpMin, #057 sel_before_change_.cpMax)); #058 #059 // When the user doesn't have a selected keyword, deleting text or replacing #060 // all of it with something else should reset the provider affinity. The #061 // typical use case for deleting is that the user starts typing, sees that #062 // some entry is close to what he wants, arrows to it, and then deletes some #063 // unnecessary bit from the end of the string. In this case the user didn't #064 // actually want "provider X", he wanted the string from that entry for #065 // editing purposes, and he's no longer looking at the popup to notice that, #066 // despite deleting some text, the action we'll take on enter hasn't changed #067 // at all. |
#068 if (!had_keyword && (just_deleted_text_ || select_all_before_change_)) { #069 popup_->manually_selected_match_.Clear(); #070 } #071 } #072 #073 // Disable the fancy keyword UI if the user didn't already have a visible #074 // keyword and is not at the end of the edit. This prevents us from showing #075 // the fancy UI (and interrupting the user's editing) if the user happens to #076 // have a keyword for 'a', types 'ab' then puts a space between the 'a' and #077 // the 'b'. #078 disable_keyword_ui_ = (is_keyword_hint_ || keyword_.empty()) && #079 ((new_sel.cpMax != length) || (new_sel.cpMin != length)); #080 |
#081 UpdatePopup(); #082 #083 if (!had_keyword && !is_keyword_hint_ && !keyword_.empty()) { #084 // Went from no selected keyword to a selected keyword. Set the affinity to #085 // the keyword provider. This forces the selected keyword to persist even #086 // if the user deletes all the text. #087 popup_->manually_selected_match_.Clear(); #088 popup_->manually_selected_match_.provider_affinity = #089 popup_->autocomplete_controller()->keyword_provider(); #090 } #091 |
#092 if (text_differs) #093 TextChanged(); #094 #095 return true; #096 } |