/indra/newview/llsearchcombobox.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 263 lines · 184 code · 44 blank · 35 comment · 30 complexity · 68b6a8657533e8db63c8562ff052563b MD5 · raw file

  1. /**
  2. * @file llsearchcombobox.cpp
  3. * @brief Search Combobox implementation
  4. *
  5. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llsearchcombobox.h"
  28. #include "llkeyboard.h"
  29. #include "lltrans.h" // for LLTrans::getString()
  30. #include "lluictrlfactory.h"
  31. static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
  32. class LLSearchHistoryBuilder
  33. {
  34. public:
  35. LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter);
  36. virtual void buildSearchHistory();
  37. virtual ~LLSearchHistoryBuilder(){}
  38. protected:
  39. virtual bool filterSearchHistory();
  40. LLSearchComboBox* mComboBox;
  41. std::string mFilter;
  42. LLSearchHistory::search_history_list_t mFilteredSearchHistory;
  43. };
  44. LLSearchComboBox::Params::Params()
  45. : search_button("search_button"),
  46. dropdown_button_visible("dropdown_button_visible", false)
  47. {}
  48. LLSearchComboBox::LLSearchComboBox(const Params&p)
  49. : LLComboBox(p)
  50. {
  51. S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
  52. S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
  53. LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
  54. LLButton::Params button_params(p.search_button);
  55. button_params.name(std::string("search_btn"));
  56. button_params.rect(search_btn_rect) ;
  57. button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
  58. button_params.tab_stop(false);
  59. button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
  60. mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
  61. mTextEntry->addChild(mSearchButton);
  62. mTextEntry->setPassDelete(TRUE);
  63. setButtonVisible(p.dropdown_button_visible);
  64. mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2));
  65. mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL);
  66. setCommitCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
  67. setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2));
  68. mSearchButton->setCommitCallback(boost::bind(&LLSearchComboBox::onTextCommit, this, _2));
  69. }
  70. void LLSearchComboBox::rebuildSearchHistory(const std::string& filter)
  71. {
  72. LLSearchHistoryBuilder builder(this, filter);
  73. builder.buildSearchHistory();
  74. }
  75. void LLSearchComboBox::onSearchPrearrange(const LLSD& data)
  76. {
  77. std::string filter = data.asString();
  78. rebuildSearchHistory(filter);
  79. mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
  80. }
  81. void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor)
  82. {
  83. KEY key = gKeyboard->currentKey();
  84. if (line_editor->getText().empty())
  85. {
  86. prearrangeList(); // resets filter
  87. hideList();
  88. }
  89. // Typing? (moving cursor should not affect showing the list)
  90. else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
  91. {
  92. prearrangeList(line_editor->getText());
  93. if (mList->getItemCount() != 0)
  94. {
  95. showList();
  96. focusTextEntry();
  97. }
  98. else
  99. {
  100. // Hide the list if it's empty.
  101. hideList();
  102. }
  103. }
  104. LLComboBox::onTextEntry(line_editor);
  105. }
  106. void LLSearchComboBox::focusTextEntry()
  107. {
  108. // We can't use "mTextEntry->setFocus(TRUE)" instead because
  109. // if the "select_on_focus" parameter is true it places the cursor
  110. // at the beginning (after selecting text), thus screwing up updateSelection().
  111. if (mTextEntry)
  112. {
  113. gFocusMgr.setKeyboardFocus(mTextEntry);
  114. // Let the editor handle editing hotkeys (STORM-431).
  115. LLEditMenuHandler::gEditMenuHandler = mTextEntry;
  116. }
  117. }
  118. void LLSearchComboBox::hideList()
  119. {
  120. LLComboBox::hideList();
  121. if (mTextEntry && hasFocus())
  122. focusTextEntry();
  123. }
  124. LLSearchComboBox::~LLSearchComboBox()
  125. {
  126. }
  127. void LLSearchComboBox::onSelectionCommit()
  128. {
  129. std::string search_query = getSimple();
  130. LLStringUtil::trim(search_query);
  131. // Order of add() and mTextEntry->setText does matter because add() will select first item
  132. // in drop down list and its label will be copied to text box rewriting mTextEntry->setText() call
  133. if(!search_query.empty())
  134. {
  135. remove(search_query);
  136. add(search_query, ADD_TOP);
  137. }
  138. mTextEntry->setText(search_query);
  139. setControlValue(search_query);
  140. }
  141. BOOL LLSearchComboBox::remove(const std::string& name)
  142. {
  143. BOOL found = mList->selectItemByLabel(name, FALSE);
  144. if (found)
  145. {
  146. LLScrollListItem* item = mList->getFirstSelected();
  147. if (item)
  148. {
  149. LLComboBox::remove(mList->getItemIndex(item));
  150. }
  151. }
  152. return found;
  153. }
  154. void LLSearchComboBox::clearHistory()
  155. {
  156. removeall();
  157. setTextEntry(LLStringUtil::null);
  158. }
  159. BOOL LLSearchComboBox::handleKeyHere(KEY key,MASK mask )
  160. {
  161. if(mTextEntry->hasFocus() && MASK_NONE == mask && KEY_DOWN == key)
  162. {
  163. S32 first = 0;
  164. S32 size = 0;
  165. // get entered text (without auto-complete part)
  166. mTextEntry->getSelectionRange(&first, &size);
  167. std::string search_query = mTextEntry->getText();
  168. search_query.erase(first, size);
  169. onSearchPrearrange(search_query);
  170. }
  171. return LLComboBox::handleKeyHere(key, mask);
  172. }
  173. LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter)
  174. : mComboBox(combo_box)
  175. , mFilter(filter)
  176. {
  177. }
  178. bool LLSearchHistoryBuilder::filterSearchHistory()
  179. {
  180. // *TODO: an STL algorithm would look nicer
  181. mFilteredSearchHistory.clear();
  182. std::string filter_copy = mFilter;
  183. LLStringUtil::toLower(filter_copy);
  184. LLSearchHistory::search_history_list_t history =
  185. LLSearchHistory::getInstance()->getSearchHistoryList();
  186. LLSearchHistory::search_history_list_t::const_iterator it = history.begin();
  187. for ( ; it != history.end(); ++it)
  188. {
  189. std::string search_query = (*it).search_query;
  190. LLStringUtil::toLower(search_query);
  191. if (search_query.find(filter_copy) != std::string::npos)
  192. mFilteredSearchHistory.push_back(*it);
  193. }
  194. return mFilteredSearchHistory.size();
  195. }
  196. void LLSearchHistoryBuilder::buildSearchHistory()
  197. {
  198. mFilteredSearchHistory.clear();
  199. LLSearchHistory::search_history_list_t filtered_items;
  200. LLSearchHistory::search_history_list_t* itemsp = NULL;
  201. LLSearchHistory* sh = LLSearchHistory::getInstance();
  202. if (mFilter.empty())
  203. {
  204. itemsp = &sh->getSearchHistoryList();
  205. }
  206. else
  207. {
  208. filterSearchHistory();
  209. itemsp = &mFilteredSearchHistory;
  210. itemsp->sort();
  211. }
  212. mComboBox->removeall();
  213. LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin();
  214. for ( ; it != itemsp->end(); it++)
  215. {
  216. LLSearchHistory::LLSearchHistoryItem item = *it;
  217. mComboBox->add(item.search_query);
  218. }
  219. }