谷歌浏览器的源码分析(9)

系统 1631 0
 

为了处理字符消息实现自动完成的功能,这是怎么样实现的呢?其实是先记录字符消息响应前的字符串以及选中状态,接着再处理消息,最后才查询可能的输入,做出智能提示。

#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  

 

当自动完成框字符串发生变化,就需要更新 URL 重点显示。

#092     if (text_differs)

#093       TextChanged();

#094  

#095     return true;

#096   }

 

在这个函数里,先判断字符串是否发生变化,然后根据变化来决定是否更新编辑框的显示,同时还需要 UpdatePopup 更新智能提示菜单,最后判断是否有一个 URL 地址,如果有就重点显示出来。

 

其实这里最关键的问题就是智能菜单的数据从那里来的呢?怎么样根据用户的输入查找到最合适的提示呢?下一次我们再来分析这方面的问题。

谷歌浏览器的源码分析(9)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论