PageRenderTime 57ms CodeModel.GetById 1ms app.highlight 42ms RepoModel.GetById 9ms app.codeStats 0ms

/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
 27#include "llviewerprecompiledheaders.h"
 28#include "llsearchcombobox.h"
 29
 30#include "llkeyboard.h"
 31#include "lltrans.h"  // for LLTrans::getString()
 32#include "lluictrlfactory.h"
 33
 34static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
 35
 36class LLSearchHistoryBuilder
 37{
 38public:
 39	LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter);
 40
 41	virtual void buildSearchHistory();
 42
 43	virtual ~LLSearchHistoryBuilder(){}
 44
 45protected:
 46
 47	virtual bool filterSearchHistory();
 48
 49	LLSearchComboBox* mComboBox;
 50	std::string mFilter;
 51	LLSearchHistory::search_history_list_t mFilteredSearchHistory;
 52};
 53
 54LLSearchComboBox::Params::Params()
 55:	search_button("search_button"),
 56	dropdown_button_visible("dropdown_button_visible", false)
 57{}
 58
 59LLSearchComboBox::LLSearchComboBox(const Params&p)
 60: LLComboBox(p)
 61{
 62	S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
 63	S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
 64	LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
 65
 66	LLButton::Params button_params(p.search_button);
 67	button_params.name(std::string("search_btn"));
 68	button_params.rect(search_btn_rect) ;
 69	button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
 70	button_params.tab_stop(false);
 71	button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
 72	mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
 73	mTextEntry->addChild(mSearchButton);
 74	mTextEntry->setPassDelete(TRUE);
 75
 76	setButtonVisible(p.dropdown_button_visible);
 77	mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2));
 78	mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL);
 79	setCommitCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
 80	setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2));
 81	mSearchButton->setCommitCallback(boost::bind(&LLSearchComboBox::onTextCommit, this, _2));
 82}
 83
 84void LLSearchComboBox::rebuildSearchHistory(const std::string& filter)
 85{
 86	LLSearchHistoryBuilder builder(this, filter);
 87	builder.buildSearchHistory();
 88}
 89
 90void LLSearchComboBox::onSearchPrearrange(const LLSD& data)
 91{
 92	std::string filter = data.asString();
 93	rebuildSearchHistory(filter);
 94
 95	mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
 96}
 97
 98void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor)
 99{
100	KEY key = gKeyboard->currentKey();
101
102	if (line_editor->getText().empty())
103	{
104		prearrangeList(); // resets filter
105		hideList();
106	}
107	// Typing? (moving cursor should not affect showing the list)
108	else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
109	{
110		prearrangeList(line_editor->getText());
111		if (mList->getItemCount() != 0)
112		{
113			showList();
114			focusTextEntry();
115		}
116		else
117		{
118			// Hide the list if it's empty.
119			hideList();
120		}
121	}
122	LLComboBox::onTextEntry(line_editor);
123}
124
125void LLSearchComboBox::focusTextEntry()
126{
127	// We can't use "mTextEntry->setFocus(TRUE)" instead because
128	// if the "select_on_focus" parameter is true it places the cursor
129	// at the beginning (after selecting text), thus screwing up updateSelection().
130	if (mTextEntry)
131	{
132		gFocusMgr.setKeyboardFocus(mTextEntry);
133
134		// Let the editor handle editing hotkeys (STORM-431).
135		LLEditMenuHandler::gEditMenuHandler = mTextEntry;
136	}
137}
138
139void LLSearchComboBox::hideList()
140{
141	LLComboBox::hideList();
142	if (mTextEntry && hasFocus())
143		focusTextEntry();
144}
145
146LLSearchComboBox::~LLSearchComboBox()
147{
148}
149
150void LLSearchComboBox::onSelectionCommit()
151{
152	std::string search_query = getSimple();
153	LLStringUtil::trim(search_query);
154
155	// Order of add() and mTextEntry->setText does matter because add() will select first item 
156	// in drop down list and its label will be copied to text box rewriting mTextEntry->setText() call
157	if(!search_query.empty())
158	{
159		remove(search_query);
160		add(search_query, ADD_TOP);
161	}
162
163	mTextEntry->setText(search_query);
164	setControlValue(search_query);
165}
166
167BOOL LLSearchComboBox::remove(const std::string& name)
168{
169	BOOL found = mList->selectItemByLabel(name, FALSE);
170
171	if (found)
172	{
173		LLScrollListItem* item = mList->getFirstSelected();
174		if (item)
175		{
176			LLComboBox::remove(mList->getItemIndex(item));
177		}
178	}
179
180	return found;
181}
182
183void LLSearchComboBox::clearHistory()
184{
185	removeall();
186	setTextEntry(LLStringUtil::null);
187}
188
189BOOL LLSearchComboBox::handleKeyHere(KEY key,MASK mask )
190{
191	if(mTextEntry->hasFocus() && MASK_NONE == mask && KEY_DOWN == key)
192	{
193		S32 first = 0;
194		S32 size = 0;
195
196		// get entered text (without auto-complete part)
197		mTextEntry->getSelectionRange(&first, &size);
198		std::string search_query = mTextEntry->getText();
199		search_query.erase(first, size);
200
201		onSearchPrearrange(search_query);
202	}
203	return LLComboBox::handleKeyHere(key, mask);
204}
205
206LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter)
207: mComboBox(combo_box)
208, mFilter(filter)
209{
210}
211
212bool LLSearchHistoryBuilder::filterSearchHistory()
213{
214	// *TODO: an STL algorithm would look nicer
215	mFilteredSearchHistory.clear();
216
217	std::string filter_copy = mFilter;
218	LLStringUtil::toLower(filter_copy);
219
220	LLSearchHistory::search_history_list_t history = 
221		LLSearchHistory::getInstance()->getSearchHistoryList();
222
223	LLSearchHistory::search_history_list_t::const_iterator it = history.begin();
224	for ( ; it != history.end(); ++it)
225	{
226		std::string search_query = (*it).search_query;
227		LLStringUtil::toLower(search_query);
228
229		if (search_query.find(filter_copy) != std::string::npos)
230			mFilteredSearchHistory.push_back(*it);
231	}
232
233	return mFilteredSearchHistory.size();
234}
235
236void LLSearchHistoryBuilder::buildSearchHistory()
237{
238	mFilteredSearchHistory.clear();
239
240	LLSearchHistory::search_history_list_t filtered_items;
241	LLSearchHistory::search_history_list_t* itemsp = NULL;
242	LLSearchHistory* sh = LLSearchHistory::getInstance();
243
244	if (mFilter.empty())
245	{
246		itemsp = &sh->getSearchHistoryList();
247	}
248	else
249	{
250		filterSearchHistory();
251		itemsp = &mFilteredSearchHistory;
252		itemsp->sort();
253	}
254
255	mComboBox->removeall();
256
257	LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin();
258	for ( ; it != itemsp->end(); it++)
259	{
260		LLSearchHistory::LLSearchHistoryItem item = *it;
261		mComboBox->add(item.search_query);
262	}
263}