点击这里给我发消息 点击这里给我发消息

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

添加时间:2013-12-7
    相关阅读: 谷歌
副标题#e#
  为了处理字符消息实现自动完成的功能,这是怎么样实现的呢?其实是先记录字符消息响应前的字符串以及选中状态,接着再处理消息,最后才查询可能的输入,做出智能提示。
 
 #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 


  下面开始设置新的显示字符串。

#p#副标题#e#

 #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地址,如果有就重点显示出来。其实这里最关键的问题就是智能菜单的数据从那里来的呢?怎么样根据用户的输入查找到最合适的提示呢?下一次我们再来分析这方面的问题。

相关谷歌浏览器的源码分析(7)

咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册