diff options
Diffstat (limited to 'indra/newview/llsearchcombobox.cpp')
-rw-r--r-- | indra/newview/llsearchcombobox.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp new file mode 100644 index 0000000000..c903f40f3f --- /dev/null +++ b/indra/newview/llsearchcombobox.cpp @@ -0,0 +1,250 @@ +/** + * @file llsearchcombobox.cpp + * @brief Search Combobox implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llsearchcombobox.h" + +#include "llkeyboard.h" +#include "lluictrlfactory.h" + +static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box"); + +class LLSearchHistoryBuilder +{ +public: + LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter); + + virtual void buildSearchHistory(); + + virtual ~LLSearchHistoryBuilder(){} + +protected: + + virtual bool filterSearchHistory(); + + LLSearchComboBox* mComboBox; + std::string mFilter; + LLSearchHistory::search_history_list_t mFilteredSearchHistory; +}; + +LLSearchComboBox::Params::Params() +: search_button("search_button") +, dropdown_button_visible("dropdown_button_visible", false) +{ +} + +LLSearchComboBox::LLSearchComboBox(const Params&p) +: LLComboBox(p) +{ + S32 btn_top = p.search_button.top_pad + p.search_button.rect.height; + S32 btn_right = p.search_button.rect.width + p.search_button.left_pad; + LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad); + + LLButton::Params button_params(p.search_button); + button_params.name(std::string("search_btn")); + button_params.rect(search_btn_rect) ; + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP); + button_params.tab_stop(false); + button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this)); + mSearchButton = LLUICtrlFactory::create<LLButton>(button_params); + mTextEntry->addChild(mSearchButton); + + setButtonVisible(p.dropdown_button_visible); + mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2)); + mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL); + setSelectionCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this)); + setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2)); +} + +void LLSearchComboBox::rebuildSearchHistory(const std::string& filter) +{ + LLSearchHistoryBuilder builder(this, filter); + builder.buildSearchHistory(); +} + +void LLSearchComboBox::onSearchPrearrange(const LLSD& data) +{ + std::string filter = data.asString(); + rebuildSearchHistory(filter); + + mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item. +} + +void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor) +{ + KEY key = gKeyboard->currentKey(); + + if (line_editor->getText().empty()) + { + prearrangeList(); // resets filter + hideList(); + } + // Typing? (moving cursor should not affect showing the list) + else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + { + prearrangeList(line_editor->getText()); + if (mList->getItemCount() != 0) + { + showList(); + focusTextEntry(); + } + else + { + // Hide the list if it's empty. + hideList(); + } + } + LLComboBox::onTextEntry(line_editor); +} + +void LLSearchComboBox::focusTextEntry() +{ + // We can't use "mTextEntry->setFocus(TRUE)" instead because + // if the "select_on_focus" parameter is true it places the cursor + // at the beginning (after selecting text), thus screwing up updateSelection(). + if (mTextEntry) + { + gFocusMgr.setKeyboardFocus(mTextEntry); + } +} + +void LLSearchComboBox::hideList() +{ + LLComboBox::hideList(); + if (mTextEntry && hasFocus()) + focusTextEntry(); +} + +LLSearchComboBox::~LLSearchComboBox() +{ +} + +void LLSearchComboBox::onSelectionCommit() +{ + std::string search_query = getSimple(); + LLStringUtil::trim(search_query); + if(search_query.empty()) + { + mTextEntry->setText(search_query); + setControlValue(search_query); + + return; + } + + remove(search_query); + add(search_query, ADD_TOP); + mTextEntry->setText(search_query); + setControlValue(search_query); + + LLUICtrl::onCommit(); +} + +BOOL LLSearchComboBox::remove(const std::string& name) +{ + BOOL found = mList->selectItemByLabel(name, FALSE); + + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + LLComboBox::remove(mList->getItemIndex(item)); + } + } + + return found; +} + +void LLSearchComboBox::clearHistory() +{ + removeall(); + setTextEntry(LLStringUtil::null); +} + +LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter) +: mComboBox(combo_box) +, mFilter(filter) +{ +} + +bool LLSearchHistoryBuilder::filterSearchHistory() +{ + // *TODO: an STL algorithm would look nicer + mFilteredSearchHistory.clear(); + + std::string filter_copy = mFilter; + LLStringUtil::toLower(filter_copy); + + LLSearchHistory::search_history_list_t history = + LLSearchHistory::getInstance()->getSearchHistoryList(); + + LLSearchHistory::search_history_list_t::const_iterator it = history.begin(); + for ( ; it != history.end(); ++it) + { + std::string search_query = (*it).search_query; + LLStringUtil::toLower(search_query); + + if (search_query.find(filter_copy) != std::string::npos) + mFilteredSearchHistory.push_back(*it); + } + + return mFilteredSearchHistory.size(); +} + +void LLSearchHistoryBuilder::buildSearchHistory() +{ + mFilteredSearchHistory.clear(); + + LLSearchHistory::search_history_list_t filtered_items; + LLSearchHistory::search_history_list_t* itemsp = NULL; + LLSearchHistory* sh = LLSearchHistory::getInstance(); + + if (mFilter.empty()) + { + itemsp = &sh->getSearchHistoryList(); + } + else + { + filterSearchHistory(); + itemsp = &mFilteredSearchHistory; + itemsp->sort(); + } + + mComboBox->removeall(); + + LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin(); + for ( ; it != itemsp->end(); it++) + { + LLSearchHistory::LLSearchHistoryItem item = *it; + mComboBox->add(item.search_query); + } +} |