From c285f59ce2a05703e3a1232fcaf3ee3aea714b3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 18 Feb 2024 12:52:19 +0100 Subject: Replace BOOL with bool in llwindow and dependent classes --- indra/llui/llcombobox.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llui/llcombobox.cpp') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 9ca05a16f3..81031508ec 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -782,13 +782,13 @@ void LLComboBox::onItemSelected(const LLSD& data) onCommit(); } -BOOL LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) +bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) { std::string tool_tip; if(LLUICtrl::handleToolTip(x, y, mask)) { - return TRUE; + return true; } tool_tip = getToolTip(); @@ -803,7 +803,7 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) .message(tool_tip) .sticky_rect(calcScreenRect())); } - return TRUE; + return true; } BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) @@ -852,9 +852,9 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) return result; } -BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) +bool LLComboBox::handleUnicodeCharHere(llwchar uni_char) { - BOOL result = FALSE; + bool result = false; if (gFocusMgr.childHasKeyboardFocus(this)) { // space bar just shows the list -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/llui/llcombobox.cpp | 140 +++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 70 deletions(-) (limited to 'indra/llui/llcombobox.cpp') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 81031508ec..07d1be3762 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -171,13 +171,13 @@ void LLComboBox::initFromParams(const LLComboBox::Params& p) } // virtual -BOOL LLComboBox::postBuild() +bool LLComboBox::postBuild() { if (mControlVariable) { setValue(mControlVariable->getValue()); // selects the appropriate item } - return TRUE; + return true; } @@ -210,16 +210,16 @@ void LLComboBox::onCommit() // we have selected an existing item, blitz the manual text entry with // the properly capitalized item mTextEntry->setValue(getSimple()); - mTextEntry->setTentative(FALSE); + mTextEntry->setTentative(false); } setControlValue(getValue()); LLUICtrl::onCommit(); } // virtual -BOOL LLComboBox::isDirty() const +bool LLComboBox::isDirty() const { - BOOL grubby = FALSE; + bool grubby = false; if ( mList ) { grubby = mList->isDirty(); @@ -242,7 +242,7 @@ bool LLComboBox::itemExists(const std::string& name) } // add item "name" to menu -LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOOL enabled) +LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, bool enabled) { LLScrollListItem* item = mList->addSimpleElement(name, pos); item->setEnabled(enabled); @@ -261,7 +261,7 @@ LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOO } // add item "name" with a unique id to menu -LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAddPosition pos, BOOL enabled ) +LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAddPosition pos, bool enabled ) { LLScrollListItem* item = mList->addSimpleElement(name, pos, id); item->setEnabled(enabled); @@ -280,7 +280,7 @@ LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAd } // add item "name" with attached userdata -LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddPosition pos, BOOL enabled ) +LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddPosition pos, bool enabled ) { LLScrollListItem* item = mList->addSimpleElement(name, pos); item->setEnabled(enabled); @@ -300,7 +300,7 @@ LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddP } // add item "name" with attached generic data -LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosition pos, BOOL enabled ) +LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosition pos, bool enabled ) { LLScrollListItem* item = mList->addSimpleElement(name, pos, value); item->setEnabled(enabled); @@ -323,17 +323,17 @@ LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos) return mList->addSeparator(pos); } -void LLComboBox::sortByName(BOOL ascending) +void LLComboBox::sortByName(bool ascending) { mList->sortOnce(0, ascending); } // Choose an item with a given name in the menu. -// Returns TRUE if the item was found. -BOOL LLComboBox::setSimple(const LLStringExplicit& name) +// Returns true if the item was found. +bool LLComboBox::setSimple(const LLStringExplicit& name) { - BOOL found = mList->selectItemByLabel(name, FALSE); + bool found = mList->selectItemByLabel(name, false); if (found) { @@ -347,7 +347,7 @@ BOOL LLComboBox::setSimple(const LLStringExplicit& name) // virtual void LLComboBox::setValue(const LLSD& value) { - BOOL found = mList->selectByValue(value); + bool found = mList->selectByValue(value); if (found) { LLScrollListItem* item = mList->getFirstSelected(); @@ -404,9 +404,9 @@ void LLComboBox::setLabel(const LLStringExplicit& name) if ( mTextEntry ) { mTextEntry->setText(name); - if (mList->selectItemByLabel(name, FALSE)) + if (mList->selectItemByLabel(name, false)) { - mTextEntry->setTentative(FALSE); + mTextEntry->setTentative(false); mLastSelectedIndex = mList->getFirstSelectedIndex(); } else @@ -428,7 +428,7 @@ void LLComboBox::updateLabel() if (mTextEntry) { mTextEntry->setText(getSelectedItemLabel()); - mTextEntry->setTentative(FALSE); + mTextEntry->setTentative(false); } // If combo box doesn't allow text entry update @@ -439,9 +439,9 @@ void LLComboBox::updateLabel() } } -BOOL LLComboBox::remove(const std::string& name) +bool LLComboBox::remove(const std::string& name) { - BOOL found = mList->selectItemByLabel(name); + bool found = mList->selectItemByLabel(name); if (found) { @@ -456,15 +456,15 @@ BOOL LLComboBox::remove(const std::string& name) return found; } -BOOL LLComboBox::remove(S32 index) +bool LLComboBox::remove(S32 index) { if (index < mList->getItemCount()) { mList->deleteSingleItem(index); setLabel(getSelectedItemLabel()); - return TRUE; + return true; } - return FALSE; + return false; } // Keyboard focus lost. @@ -480,7 +480,7 @@ void LLComboBox::onFocusLost() LLUICtrl::onFocusLost(); } -void LLComboBox::setButtonVisible(BOOL visible) +void LLComboBox::setButtonVisible(bool visible) { static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); @@ -494,13 +494,13 @@ void LLComboBox::setButtonVisible(BOOL visible) text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; } //mTextEntry->setRect(text_entry_rect); - mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); } } -BOOL LLComboBox::setCurrentByIndex( S32 index ) +bool LLComboBox::setCurrentByIndex( S32 index ) { - BOOL found = mList->selectNthItem( index ); + bool found = mList->selectNthItem( index ); if (found) { setLabel(getSelectedItemLabel()); @@ -519,7 +519,7 @@ S32 LLComboBox::getCurrentIndex() const return -1; } -void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled) +void LLComboBox::setEnabledByValue(const LLSD& value, bool enabled) { LLScrollListItem *found = mList->getItem(value); if (found) @@ -538,7 +538,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p) S32 shadow_size = drop_shadow_button; mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); - mButton->setTabStop(FALSE); + mButton->setTabStop(false); mButton->setHAlign(LLFontGL::HCENTER); LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); @@ -556,7 +556,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p) params.label(mLabel); mTextEntry = LLUICtrlFactory::create (params); mTextEntry->setText(cur_label); - mTextEntry->setIgnoreTab(TRUE); + mTextEntry->setIgnoreTab(true); addChild(mTextEntry); // clear label on button @@ -571,7 +571,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p) if (mTextEntry) { - mTextEntry->setVisible(FALSE); + mTextEntry->setVisible(false); } } } @@ -675,15 +675,15 @@ void LLComboBox::showList() // NB: this call will trigger the focuslost callback which will hide the list, so do it first // before finally showing the list - mList->setFocus(TRUE); + mList->setFocus(true); // Show the list and push the button down - mButton->setToggleState(TRUE); - mList->setVisible(TRUE); + mButton->setToggleState(true); + mList->setVisible(true); LLUI::getInstance()->addPopup(this); - setUseBoundingRect(TRUE); + setUseBoundingRect(true); // updateBoundingRect(); } @@ -702,11 +702,11 @@ void LLComboBox::hideList() else if(mLastSelectedIndex >= 0) mList->selectNthItem(mLastSelectedIndex); - mButton->setToggleState(FALSE); - mList->setVisible(FALSE); + mButton->setToggleState(false); + mList->setVisible(false); mList->mouseOverHighlightNthItem(-1); - setUseBoundingRect(FALSE); + setUseBoundingRect(false); LLUI::getInstance()->removePopup(this); // updateBoundingRect(); } @@ -732,7 +732,7 @@ void LLComboBox::onButtonMouseDown() showList(); } - setFocus( TRUE ); + setFocus( true ); // pass mouse capture on to list if button is depressed if (mButton->hasMouseCapture()) @@ -806,16 +806,16 @@ bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) return true; } -BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) +bool LLComboBox::handleKeyHere(KEY key, MASK mask) { - BOOL result = FALSE; + bool result = false; if (hasFocus()) { if (mList->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) { hideList(); - return TRUE; + return true; } //give list a chance to pop up and handle key LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); @@ -838,7 +838,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) // don't show list and don't eat key input when committing // free-form text entry with RETURN since user already knows // what they are trying to select - return FALSE; + return false; } // if selection has changed, pop open list else if (mList->getLastSelectedItem() != last_selected_item @@ -881,12 +881,12 @@ void LLComboBox::setTextEntry(const LLStringExplicit& text) if (mTextEntry) { mTextEntry->setText(text); - mHasAutocompletedText = FALSE; + mHasAutocompletedText = false; updateSelection(); } } -void LLComboBox::setKeystrokeOnEsc(BOOL enable) +void LLComboBox::setKeystrokeOnEsc(bool enable) { if (mTextEntry) { @@ -905,9 +905,9 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) if (key == KEY_BACKSPACE || key == KEY_DELETE) { - if (mList->selectItemByLabel(line_editor->getText(), FALSE)) + if (mList->selectItemByLabel(line_editor->getText(), false)) { - line_editor->setTentative(FALSE); + line_editor->setTentative(false); mLastSelectedIndex = mList->getFirstSelectedIndex(); } else @@ -942,7 +942,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) } } line_editor->selectAll(); - line_editor->setTentative(FALSE); + line_editor->setTentative(false); } else if (key == KEY_UP) { @@ -957,7 +957,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) } } line_editor->selectAll(); - line_editor->setTentative(FALSE); + line_editor->setTentative(false); } else { @@ -986,20 +986,20 @@ void LLComboBox::updateSelection() prearrangeList(mTextEntry->getText()); } - if (mList->selectItemByLabel(full_string, FALSE)) + if (mList->selectItemByLabel(full_string, false)) { - mTextEntry->setTentative(FALSE); + mTextEntry->setTentative(false); mLastSelectedIndex = mList->getFirstSelectedIndex(); } - else if (mList->selectItemByPrefix(left_wstring, FALSE)) + else if (mList->selectItemByPrefix(left_wstring, false)) { LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); mTextEntry->setText(wstring_to_utf8str(wtext)); mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); mTextEntry->endSelection(); - mTextEntry->setTentative(FALSE); - mHasAutocompletedText = TRUE; + mTextEntry->setTentative(false); + mHasAutocompletedText = true; mLastSelectedIndex = mList->getFirstSelectedIndex(); } else // no matching items found @@ -1007,7 +1007,7 @@ void LLComboBox::updateSelection() mList->deselectAllItems(); mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion mTextEntry->setTentative(mTextEntryTentative); - mHasAutocompletedText = FALSE; + mHasAutocompletedText = false; mLastSelectedIndex = -1; } } @@ -1020,7 +1020,7 @@ void LLComboBox::onTextCommit(const LLSD& data) mTextEntry->selectAll(); } -void LLComboBox::setFocus(BOOL b) +void LLComboBox::setFocus(bool b) { LLUICtrl::setFocus(b); @@ -1029,7 +1029,7 @@ void LLComboBox::setFocus(BOOL b) mList->clearSearchString(); if (mList->getVisible()) { - mList->setFocus(TRUE); + mList->setFocus(true); } } } @@ -1097,7 +1097,7 @@ void LLComboBox::imageLoaded() { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button; - mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); } } } @@ -1142,7 +1142,7 @@ void LLComboBox::clearRows() mList->clearRows(); } -void LLComboBox::sortByColumn(const std::string& name, BOOL ascending) +void LLComboBox::sortByColumn(const std::string& name, bool ascending) { mList->sortByColumn(name, ascending); } @@ -1150,9 +1150,9 @@ void LLComboBox::sortByColumn(const std::string& name, BOOL ascending) //============================================================================ //LLCtrlSelectionInterface functions -BOOL LLComboBox::setCurrentByID(const LLUUID& id) +bool LLComboBox::setCurrentByID(const LLUUID& id) { - BOOL found = mList->selectByID( id ); + bool found = mList->selectByID( id ); if (found) { @@ -1167,9 +1167,9 @@ LLUUID LLComboBox::getCurrentID() const { return mList->getStringUUIDSelectedItem(); } -BOOL LLComboBox::setSelectedByValue(const LLSD& value, BOOL selected) +bool LLComboBox::setSelectedByValue(const LLSD& value, bool selected) { - BOOL found = mList->setSelectedByValue(value, selected); + bool found = mList->setSelectedByValue(value, selected); if (found) { setLabel(getSelectedItemLabel()); @@ -1182,32 +1182,32 @@ LLSD LLComboBox::getSelectedValue() return mList->getSelectedValue(); } -BOOL LLComboBox::isSelected(const LLSD& value) const +bool LLComboBox::isSelected(const LLSD& value) const { return mList->isSelected(value); } -BOOL LLComboBox::operateOnSelection(EOperation op) +bool LLComboBox::operateOnSelection(EOperation op) { if (op == OP_DELETE) { mList->deleteSelectedItems(); - return TRUE; + return true; } - return FALSE; + return false; } -BOOL LLComboBox::operateOnAll(EOperation op) +bool LLComboBox::operateOnAll(EOperation op) { if (op == OP_DELETE) { clearRows(); - return TRUE; + return true; } - return FALSE; + return false; } -BOOL LLComboBox::selectItemRange( S32 first, S32 last ) +bool LLComboBox::selectItemRange( S32 first, S32 last ) { return mList->selectItemRange(first, last); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llui/llcombobox.cpp | 2462 ++++++++++++++++++++++----------------------- 1 file changed, 1231 insertions(+), 1231 deletions(-) (limited to 'indra/llui/llcombobox.cpp') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 305263e0cc..0d82f29dfb 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -1,1231 +1,1231 @@ -/** - * @file llcombobox.cpp - * @brief LLComboBox base class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// A control that displays the name of the chosen item, which when -// clicked shows a scrolling box of options. - -#include "linden_common.h" - -// file includes -#include "llcombobox.h" - -// common includes -#include "llstring.h" - -// newview includes -#include "llbutton.h" -#include "llkeyboard.h" -#include "llscrolllistctrl.h" -#include "llwindow.h" -#include "llfloater.h" -#include "llscrollbar.h" -#include "llscrolllistcell.h" -#include "llscrolllistitem.h" -#include "llcontrol.h" -#include "llfocusmgr.h" -#include "lllineeditor.h" -#include "v2math.h" -#include "lluictrlfactory.h" -#include "lltooltip.h" - -// Globals -S32 MAX_COMBO_WIDTH = 500; - -static LLDefaultChildRegistry::Register register_combo_box("combo_box"); - -void LLComboBox::PreferredPositionValues::declareValues() -{ - declare("above", ABOVE); - declare("below", BELOW); -} - -LLComboBox::ItemParams::ItemParams() -: label("label") -{ -} - - -LLComboBox::Params::Params() -: allow_text_entry("allow_text_entry", false), - allow_new_values("allow_new_values", false), - show_text_as_tentative("show_text_as_tentative", true), - max_chars("max_chars", 20), - list_position("list_position", BELOW), - items("item"), - combo_button("combo_button"), - combo_list("combo_list"), - combo_editor("combo_editor"), - drop_down_button("drop_down_button") -{ - addSynonym(items, "combo_item"); -} - - -LLComboBox::LLComboBox(const LLComboBox::Params& p) -: LLUICtrl(p), - mTextEntry(NULL), - mTextEntryTentative(p.show_text_as_tentative), - mHasAutocompletedText(false), - mAllowTextEntry(p.allow_text_entry), - mAllowNewValues(p.allow_new_values), - mMaxChars(p.max_chars), - mPrearrangeCallback(p.prearrange_callback()), - mTextEntryCallback(p.text_entry_callback()), - mTextChangedCallback(p.text_changed_callback()), - mListPosition(p.list_position), - mLastSelectedIndex(-1), - mLabel(p.label) -{ - // Text label button - - LLButton::Params button_params = (mAllowTextEntry ? p.combo_button : p.drop_down_button); - button_params.mouse_down_callback.function( - boost::bind(&LLComboBox::onButtonMouseDown, this)); - button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); - button_params.rect(p.rect); - - if(mAllowTextEntry) - { - button_params.pad_right(2); - } - - mArrowImage = button_params.image_unselected; - if (mArrowImage.notNull()) - { - mImageLoadedConnection = mArrowImage->addLoadedCallback(boost::bind(&LLComboBox::imageLoaded, this)); - } - - mButton = LLUICtrlFactory::create(button_params); - - - if(mAllowTextEntry) - { - //redo to compensate for button hack that leaves space for a character - //unless it is a "minimal combobox"(drop down) - mButton->setRightHPad(2); - } - addChild(mButton); - - LLScrollListCtrl::Params params = p.combo_list; - params.name("ComboBox"); - params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); - params.visible(false); - params.commit_on_keyboard_movement(false); - - mList = LLUICtrlFactory::create(params); - addChild(mList); - - // Mouse-down on button will transfer mouse focus to the list - // Grab the mouse-up event and make sure the button state is correct - mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this)); - - for (LLInitParam::ParamIterator::const_iterator it = p.items.begin(); - it != p.items.end(); - ++it) - { - LLScrollListItem::Params item_params = *it; - if (it->label.isProvided()) - { - item_params.columns.add().value(it->label()); - } - - mList->addRow(item_params); - } - - createLineEditor(p); - - mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); -} - -void LLComboBox::initFromParams(const LLComboBox::Params& p) -{ - LLUICtrl::initFromParams(p); - - if (!acceptsTextInput() && mLabel.empty()) - { - selectFirstItem(); - } -} - -// virtual -bool LLComboBox::postBuild() -{ - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - return true; -} - - -LLComboBox::~LLComboBox() -{ - // children automatically deleted, including mMenu, mButton - - // explicitly disconect this signal, since base class destructor might fire top lost - mTopLostSignalConnection.disconnect(); - mImageLoadedConnection.disconnect(); - - LLUI::getInstance()->removePopup(this); -} - - -void LLComboBox::clear() -{ - if (mTextEntry) - { - mTextEntry->setText(LLStringUtil::null); - } - mButton->setLabelSelected(LLStringUtil::null); - mButton->setLabelUnselected(LLStringUtil::null); - mList->deselectAllItems(); - mLastSelectedIndex = -1; -} - -void LLComboBox::onCommit() -{ - if (mAllowTextEntry && getCurrentIndex() != -1) - { - // we have selected an existing item, blitz the manual text entry with - // the properly capitalized item - mTextEntry->setValue(getSimple()); - mTextEntry->setTentative(false); - } - setControlValue(getValue()); - LLUICtrl::onCommit(); -} - -// virtual -bool LLComboBox::isDirty() const -{ - bool grubby = false; - if ( mList ) - { - grubby = mList->isDirty(); - } - return grubby; -} - -// virtual Clear dirty state -void LLComboBox::resetDirty() -{ - if ( mList ) - { - mList->resetDirty(); - } -} - -bool LLComboBox::itemExists(const std::string& name) -{ - return mList->getItemByLabel(name); -} - -// add item "name" to menu -LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, bool enabled) -{ - LLScrollListItem* item = mList->addSimpleElement(name, pos); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; -} - -// add item "name" with a unique id to menu -LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAddPosition pos, bool enabled ) -{ - LLScrollListItem* item = mList->addSimpleElement(name, pos, id); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; -} - -// add item "name" with attached userdata -LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddPosition pos, bool enabled ) -{ - LLScrollListItem* item = mList->addSimpleElement(name, pos); - item->setEnabled(enabled); - item->setUserdata( userdata ); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; -} - -// add item "name" with attached generic data -LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosition pos, bool enabled ) -{ - LLScrollListItem* item = mList->addSimpleElement(name, pos, value); - item->setEnabled(enabled); - if (!mAllowTextEntry && mLabel.empty()) - { - if (mControlVariable) - { - setValue(mControlVariable->getValue()); // selects the appropriate item - } - else - { - selectFirstItem(); - } - } - return item; -} - -LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos) -{ - return mList->addSeparator(pos); -} - -void LLComboBox::sortByName(bool ascending) -{ - mList->sortOnce(0, ascending); -} - - -// Choose an item with a given name in the menu. -// Returns true if the item was found. -bool LLComboBox::setSimple(const LLStringExplicit& name) -{ - bool found = mList->selectItemByLabel(name, false); - - if (found) - { - setLabel(name); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - - return found; -} - -// virtual -void LLComboBox::setValue(const LLSD& value) -{ - bool found = mList->selectByValue(value); - if (found) - { - LLScrollListItem* item = mList->getFirstSelected(); - if (item) - { - updateLabel(); - } - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - mLastSelectedIndex = -1; - } -} - -const std::string LLComboBox::getSimple() const -{ - const std::string res = getSelectedItemLabel(); - if (res.empty() && mAllowTextEntry) - { - return mTextEntry->getText(); - } - else - { - return res; - } -} - -const std::string LLComboBox::getSelectedItemLabel(S32 column) const -{ - return mList->getSelectedItemLabel(column); -} - -// virtual -LLSD LLComboBox::getValue() const -{ - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return item->getValue(); - } - else if (mAllowTextEntry) - { - return mTextEntry->getValue(); - } - else - { - return LLSD(); - } -} - -void LLComboBox::setLabel(const LLStringExplicit& name) -{ - if ( mTextEntry ) - { - mTextEntry->setText(name); - if (mList->selectItemByLabel(name, false)) - { - mTextEntry->setTentative(false); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - mTextEntry->setTentative(mTextEntryTentative); - } - } - - if (!mAllowTextEntry) - { - mButton->setLabel(name); - } -} - -void LLComboBox::updateLabel() -{ - // Update the combo editor with the selected - // item label. - if (mTextEntry) - { - mTextEntry->setText(getSelectedItemLabel()); - mTextEntry->setTentative(false); - } - - // If combo box doesn't allow text entry update - // the combo button label. - if (!mAllowTextEntry) - { - mButton->setLabel(getSelectedItemLabel()); - } -} - -bool LLComboBox::remove(const std::string& name) -{ - bool found = mList->selectItemByLabel(name); - - if (found) - { - LLScrollListItem* item = mList->getFirstSelected(); - if (item) - { - mList->deleteSingleItem(mList->getItemIndex(item)); - } - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - - return found; -} - -bool LLComboBox::remove(S32 index) -{ - if (index < mList->getItemCount()) - { - mList->deleteSingleItem(index); - setLabel(getSelectedItemLabel()); - return true; - } - return false; -} - -// Keyboard focus lost. -void LLComboBox::onFocusLost() -{ - hideList(); - // if valid selection - if (mAllowTextEntry && getCurrentIndex() != -1) - { - mTextEntry->selectAll(); - } - mButton->setForcePressedState(false); - LLUICtrl::onFocusLost(); -} - -void LLComboBox::setButtonVisible(bool visible) -{ - mButton->setVisible(visible); - if (mTextEntry) - { - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - if (visible) - { - S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; - } - //mTextEntry->setRect(text_entry_rect); - mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); - } -} - -bool LLComboBox::setCurrentByIndex( S32 index ) -{ - bool found = mList->selectNthItem( index ); - if (found) - { - setLabel(getSelectedItemLabel()); - mLastSelectedIndex = index; - } - return found; -} - -S32 LLComboBox::getCurrentIndex() const -{ - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return mList->getItemIndex( item ); - } - return -1; -} - -void LLComboBox::setEnabledByValue(const LLSD& value, bool enabled) -{ - LLScrollListItem *found = mList->getItem(value); - if (found) - { - found->setEnabled(enabled); - } -} - -void LLComboBox::createLineEditor(const LLComboBox::Params& p) -{ - LLRect rect = getLocalRect(); - if (mAllowTextEntry) - { - S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = BTN_DROP_SHADOW; - mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, - rect.mTop, rect.mRight, rect.mBottom)); - mButton->setTabStop(false); - mButton->setHAlign(LLFontGL::HCENTER); - - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; - // clear label on button - std::string cur_label = mButton->getLabelSelected(); - LLLineEditor::Params params = p.combo_editor; - params.rect(text_entry_rect); - params.default_text(LLStringUtil::null); - params.max_length.bytes(mMaxChars); - params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); - params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); - params.commit_on_focus_lost(false); - params.follows.flags(FOLLOWS_ALL); - params.label(mLabel); - mTextEntry = LLUICtrlFactory::create (params); - mTextEntry->setText(cur_label); - mTextEntry->setIgnoreTab(true); - addChild(mTextEntry); - - // clear label on button - setLabel(LLStringUtil::null); - - mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); - } - else - { - mButton->setRect(rect); - mButton->setLabel(mLabel.getString()); - - if (mTextEntry) - { - mTextEntry->setVisible(false); - } - } -} - -void LLComboBox::setLeftTextPadding(S32 pad) -{ - S32 left_pad, right_pad; - mTextEntry->getTextPadding(&left_pad, &right_pad); - mTextEntry->setTextPadding(pad, right_pad); -} - -void* LLComboBox::getCurrentUserdata() -{ - LLScrollListItem* item = mList->getFirstSelected(); - if( item ) - { - return item->getUserdata(); - } - return NULL; -} - - -void LLComboBox::showList() -{ - // Make sure we don't go off top of screen. - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - //HACK: shouldn't have to know about scale here - mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); - - // Make sure that we can see the whole list - LLRect root_view_local; - LLView* root_view = getRootView(); - root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); - - LLRect rect = mList->getRect(); - - S32 min_width = getRect().getWidth(); - S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); - // make sure we have up to date content width metrics - S32 list_width = llclamp(mList->calcMaxContentWidth(), min_width, max_width); - - if (mListPosition == BELOW) - { - if (rect.getHeight() <= -root_view_local.mBottom) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); - } - else - { - // stack on top or bottom, depending on which has more room - if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); - } - else - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - } - } - else // ABOVE - { - if (rect.getHeight() <= root_view_local.mTop - getRect().getHeight()) - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - else - { - // stack on top or bottom, depending on which has more room - if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) - { - // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); - } - else - { - // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); - } - } - - } - mList->setOrigin(rect.mLeft, rect.mBottom); - mList->reshape(rect.getWidth(), rect.getHeight()); - mList->translateIntoRect(root_view_local); - - // Make sure we didn't go off bottom of screen - S32 x, y; - mList->localPointToScreen(0, 0, &x, &y); - - if (y < 0) - { - mList->translate(0, -y); - } - - // NB: this call will trigger the focuslost callback which will hide the list, so do it first - // before finally showing the list - - mList->setFocus(true); - - // Show the list and push the button down - mButton->setToggleState(true); - mList->setVisible(true); - - LLUI::getInstance()->addPopup(this); - - setUseBoundingRect(true); -// updateBoundingRect(); -} - -void LLComboBox::hideList() -{ - if (mList->getVisible()) - { - // assert selection in list - if(mAllowNewValues) - { - // mLastSelectedIndex = -1 means that we entered a new value, don't select - // any of existing items in this case. - if(mLastSelectedIndex >= 0) - mList->selectNthItem(mLastSelectedIndex); - } - else if(mLastSelectedIndex >= 0) - mList->selectNthItem(mLastSelectedIndex); - - mButton->setToggleState(false); - mList->setVisible(false); - mList->mouseOverHighlightNthItem(-1); - - setUseBoundingRect(false); - LLUI::getInstance()->removePopup(this); -// updateBoundingRect(); - } -} - -void LLComboBox::onButtonMouseDown() -{ - if (!mList->getVisible()) - { - // this might change selection, so do it first - prearrangeList(); - - // highlight the last selected item from the original selection before potentially selecting a new item - // as visual cue to original value of combo box - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } - - if (mList->getItemCount() != 0) - { - showList(); - } - - setFocus( true ); - - // pass mouse capture on to list if button is depressed - if (mButton->hasMouseCapture()) - { - gFocusMgr.setMouseCapture(mList); - - // But keep the "pressed" look, which buttons normally lose when they - // lose focus - mButton->setForcePressedState(true); - } - } - else - { - hideList(); - } - -} - -void LLComboBox::onListMouseUp() -{ - // In some cases this is the termination of a mouse click that started on - // the button, so clear its pressed state - mButton->setForcePressedState(false); -} - -//------------------------------------------------------------------ -// static functions -//------------------------------------------------------------------ - -void LLComboBox::onItemSelected(const LLSD& data) -{ - mLastSelectedIndex = getCurrentIndex(); - if (mLastSelectedIndex != -1) - { - updateLabel(); - - if (mAllowTextEntry) - { - gFocusMgr.setKeyboardFocus(mTextEntry); - mTextEntry->selectAll(); - } - } - // hiding the list reasserts the old value stored in the text editor/dropdown button - hideList(); - - // commit does the reverse, asserting the value in the list - onCommit(); -} - -bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) -{ - std::string tool_tip; - - if(LLUICtrl::handleToolTip(x, y, mask)) - { - return true; - } - - tool_tip = getToolTip(); - if (tool_tip.empty()) - { - tool_tip = getSelectedItemLabel(); - } - - if( !tool_tip.empty() ) - { - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tool_tip) - .sticky_rect(calcScreenRect())); - } - return true; -} - -bool LLComboBox::handleKeyHere(KEY key, MASK mask) -{ - bool result = false; - if (hasFocus()) - { - if (mList->getVisible() - && key == KEY_ESCAPE && mask == MASK_NONE) - { - hideList(); - return true; - } - //give list a chance to pop up and handle key - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - // highlight the original selection before potentially selecting a new item - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } - result = mList->handleKeyHere(key, mask); - - // will only see return key if it is originating from line editor - // since the dropdown button eats the key - if (key == KEY_RETURN) - { - if (mask == MASK_NONE) - { - mOnReturnSignal(this, getValue()); - } - - // don't show list and don't eat key input when committing - // free-form text entry with RETURN since user already knows - // what they are trying to select - return false; - } - // if selection has changed, pop open list - else if (mList->getLastSelectedItem() != last_selected_item - || ((key == KEY_DOWN || key == KEY_UP) - && mList->getCanSelect() - && !mList->isEmpty())) - { - showList(); - } - } - return result; -} - -bool LLComboBox::handleUnicodeCharHere(llwchar uni_char) -{ - bool result = false; - if (gFocusMgr.childHasKeyboardFocus(this)) - { - // space bar just shows the list - if (' ' != uni_char ) - { - LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); - if (last_selected_item) - { - // highlight the original selection before potentially selecting a new item - mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); - } - result = mList->handleUnicodeCharHere(uni_char); - if (mList->getLastSelectedItem() != last_selected_item) - { - showList(); - } - } - } - return result; -} - -void LLComboBox::setTextEntry(const LLStringExplicit& text) -{ - if (mTextEntry) - { - mTextEntry->setText(text); - mHasAutocompletedText = false; - updateSelection(); - } -} - -void LLComboBox::setKeystrokeOnEsc(bool enable) -{ - if (mTextEntry) - { - mTextEntry->setKeystrokeOnEsc(enable); - } -} - -void LLComboBox::onTextEntry(LLLineEditor* line_editor) -{ - if (mTextEntryCallback != NULL) - { - (mTextEntryCallback)(line_editor, LLSD()); - } - - KEY key = gKeyboard->currentKey(); - if (key == KEY_BACKSPACE || - key == KEY_DELETE) - { - if (mList->selectItemByLabel(line_editor->getText(), false)) - { - line_editor->setTentative(false); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else - { - line_editor->setTentative(mTextEntryTentative); - mList->deselectAllItems(); - mLastSelectedIndex = -1; - } - if (mTextChangedCallback != NULL) - { - (mTextChangedCallback)(line_editor, LLSD()); - } - return; - } - - if (key == KEY_LEFT || - key == KEY_RIGHT) - { - return; - } - - if (key == KEY_DOWN) - { - setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); - if (!mList->getVisible()) - { - prearrangeList(); - - if (mList->getItemCount() != 0) - { - showList(); - } - } - line_editor->selectAll(); - line_editor->setTentative(false); - } - else if (key == KEY_UP) - { - setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); - if (!mList->getVisible()) - { - prearrangeList(); - - if (mList->getItemCount() != 0) - { - showList(); - } - } - line_editor->selectAll(); - line_editor->setTentative(false); - } - else - { - // RN: presumably text entry - updateSelection(); - } - if (mTextChangedCallback != NULL) - { - (mTextChangedCallback)(line_editor, LLSD()); - } -} - -void LLComboBox::updateSelection() -{ - LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); - // user-entered portion of string, based on assumption that any selected - // text was a result of auto-completion - LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText(); - std::string full_string = mTextEntry->getText(); - - // go ahead and arrange drop down list on first typed character, even - // though we aren't showing it... some code relies on prearrange - // callback to populate content - if( mTextEntry->getWText().size() == 1 ) - { - prearrangeList(mTextEntry->getText()); - } - - if (mList->selectItemByLabel(full_string, false)) - { - mTextEntry->setTentative(false); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else if (mList->selectItemByPrefix(left_wstring, false)) - { - LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); - LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); - mTextEntry->setText(wstring_to_utf8str(wtext)); - mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); - mTextEntry->endSelection(); - mTextEntry->setTentative(false); - mHasAutocompletedText = true; - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - else // no matching items found - { - mList->deselectAllItems(); - mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion - mTextEntry->setTentative(mTextEntryTentative); - mHasAutocompletedText = false; - mLastSelectedIndex = -1; - } -} - -void LLComboBox::onTextCommit(const LLSD& data) -{ - std::string text = mTextEntry->getText(); - setSimple(text); - onCommit(); - mTextEntry->selectAll(); -} - -void LLComboBox::setFocus(bool b) -{ - LLUICtrl::setFocus(b); - - if (b) - { - mList->clearSearchString(); - if (mList->getVisible()) - { - mList->setFocus(true); - } - } -} - -void LLComboBox::prearrangeList(std::string filter) -{ - if (mPrearrangeCallback) - { - mPrearrangeCallback(this, LLSD(filter)); - } -} - - -//============================================================================ -// ll::ui::SearchableControl functions - -//virtual -std::string LLComboBox::_getSearchText() const -{ - std::string res; - if (mList) - { - // getAllData returns a full copy of content, might be a - // better option to implement an mList->getSearchText(column) - std::vector data = mList->getAllData(); - std::vector::iterator iter = data.begin(); - while (iter != data.end()) - { - LLScrollListCell* cell = (*iter)->getColumn(0); - if (cell) - { - std::string whitelist_url = cell->getValue().asString(); - res += cell->getValue().asString(); - } - iter++; - } - } - return res + getToolTip(); -} - -//virtual -void LLComboBox::onSetHighlight() const -{ - if (mButton) - { - mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted()); - } -} - -void LLComboBox::imageLoaded() -{ - if (mAllowTextEntry) - { - LLRect rect = getLocalRect(); - S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = BTN_DROP_SHADOW; - mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size, - rect.mTop, rect.mRight, rect.mBottom)); - if (mButton->getVisible()) - { - // recalculate field size - if (mTextEntry) - { - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW; - mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); - } - } - } -} - -//============================================================================ -// LLCtrlListInterface functions - -S32 LLComboBox::getItemCount() const -{ - return mList->getItemCount(); -} - -void LLComboBox::addColumn(const LLSD& column, EAddPosition pos) -{ - mList->clearColumns(); - mList->addColumn(column, pos); -} - -void LLComboBox::clearColumns() -{ - mList->clearColumns(); -} - -void LLComboBox::setColumnLabel(const std::string& column, const std::string& label) -{ - mList->setColumnLabel(column, label); -} - -LLScrollListItem* LLComboBox::addElement(const LLSD& value, EAddPosition pos, void* userdata) -{ - return mList->addElement(value, pos, userdata); -} - -LLScrollListItem* LLComboBox::addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) -{ - return mList->addSimpleElement(value, pos, id); -} - -void LLComboBox::clearRows() -{ - mList->clearRows(); -} - -void LLComboBox::sortByColumn(const std::string& name, bool ascending) -{ - mList->sortByColumn(name, ascending); -} - -//============================================================================ -//LLCtrlSelectionInterface functions - -bool LLComboBox::setCurrentByID(const LLUUID& id) -{ - bool found = mList->selectByID( id ); - - if (found) - { - setLabel(getSelectedItemLabel()); - mLastSelectedIndex = mList->getFirstSelectedIndex(); - } - - return found; -} - -LLUUID LLComboBox::getCurrentID() const -{ - return mList->getStringUUIDSelectedItem(); -} -bool LLComboBox::setSelectedByValue(const LLSD& value, bool selected) -{ - bool found = mList->setSelectedByValue(value, selected); - if (found) - { - setLabel(getSelectedItemLabel()); - } - return found; -} - -LLSD LLComboBox::getSelectedValue() -{ - return mList->getSelectedValue(); -} - -bool LLComboBox::isSelected(const LLSD& value) const -{ - return mList->isSelected(value); -} - -bool LLComboBox::operateOnSelection(EOperation op) -{ - if (op == OP_DELETE) - { - mList->deleteSelectedItems(); - return true; - } - return false; -} - -bool LLComboBox::operateOnAll(EOperation op) -{ - if (op == OP_DELETE) - { - clearRows(); - return true; - } - return false; -} - -bool LLComboBox::selectItemRange( S32 first, S32 last ) -{ - return mList->selectItemRange(first, last); -} - - -static LLDefaultChildRegistry::Register register_icons_combo_box("icons_combo_box"); - -LLIconsComboBox::Params::Params() -: icon_column("icon_column", ICON_COLUMN), - label_column("label_column", LABEL_COLUMN) -{} - -LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p) -: LLComboBox(p), - mIconColumnIndex(p.icon_column), - mLabelColumnIndex(p.label_column) -{} - -const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const -{ - mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); - - return LLComboBox::getSelectedItemLabel(mLabelColumnIndex); -} +/** + * @file llcombobox.cpp + * @brief LLComboBox base class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// A control that displays the name of the chosen item, which when +// clicked shows a scrolling box of options. + +#include "linden_common.h" + +// file includes +#include "llcombobox.h" + +// common includes +#include "llstring.h" + +// newview includes +#include "llbutton.h" +#include "llkeyboard.h" +#include "llscrolllistctrl.h" +#include "llwindow.h" +#include "llfloater.h" +#include "llscrollbar.h" +#include "llscrolllistcell.h" +#include "llscrolllistitem.h" +#include "llcontrol.h" +#include "llfocusmgr.h" +#include "lllineeditor.h" +#include "v2math.h" +#include "lluictrlfactory.h" +#include "lltooltip.h" + +// Globals +S32 MAX_COMBO_WIDTH = 500; + +static LLDefaultChildRegistry::Register register_combo_box("combo_box"); + +void LLComboBox::PreferredPositionValues::declareValues() +{ + declare("above", ABOVE); + declare("below", BELOW); +} + +LLComboBox::ItemParams::ItemParams() +: label("label") +{ +} + + +LLComboBox::Params::Params() +: allow_text_entry("allow_text_entry", false), + allow_new_values("allow_new_values", false), + show_text_as_tentative("show_text_as_tentative", true), + max_chars("max_chars", 20), + list_position("list_position", BELOW), + items("item"), + combo_button("combo_button"), + combo_list("combo_list"), + combo_editor("combo_editor"), + drop_down_button("drop_down_button") +{ + addSynonym(items, "combo_item"); +} + + +LLComboBox::LLComboBox(const LLComboBox::Params& p) +: LLUICtrl(p), + mTextEntry(NULL), + mTextEntryTentative(p.show_text_as_tentative), + mHasAutocompletedText(false), + mAllowTextEntry(p.allow_text_entry), + mAllowNewValues(p.allow_new_values), + mMaxChars(p.max_chars), + mPrearrangeCallback(p.prearrange_callback()), + mTextEntryCallback(p.text_entry_callback()), + mTextChangedCallback(p.text_changed_callback()), + mListPosition(p.list_position), + mLastSelectedIndex(-1), + mLabel(p.label) +{ + // Text label button + + LLButton::Params button_params = (mAllowTextEntry ? p.combo_button : p.drop_down_button); + button_params.mouse_down_callback.function( + boost::bind(&LLComboBox::onButtonMouseDown, this)); + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + button_params.rect(p.rect); + + if(mAllowTextEntry) + { + button_params.pad_right(2); + } + + mArrowImage = button_params.image_unselected; + if (mArrowImage.notNull()) + { + mImageLoadedConnection = mArrowImage->addLoadedCallback(boost::bind(&LLComboBox::imageLoaded, this)); + } + + mButton = LLUICtrlFactory::create(button_params); + + + if(mAllowTextEntry) + { + //redo to compensate for button hack that leaves space for a character + //unless it is a "minimal combobox"(drop down) + mButton->setRightHPad(2); + } + addChild(mButton); + + LLScrollListCtrl::Params params = p.combo_list; + params.name("ComboBox"); + params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); + + mList = LLUICtrlFactory::create(params); + addChild(mList); + + // Mouse-down on button will transfer mouse focus to the list + // Grab the mouse-up event and make sure the button state is correct + mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this)); + + for (LLInitParam::ParamIterator::const_iterator it = p.items.begin(); + it != p.items.end(); + ++it) + { + LLScrollListItem::Params item_params = *it; + if (it->label.isProvided()) + { + item_params.columns.add().value(it->label()); + } + + mList->addRow(item_params); + } + + createLineEditor(p); + + mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); +} + +void LLComboBox::initFromParams(const LLComboBox::Params& p) +{ + LLUICtrl::initFromParams(p); + + if (!acceptsTextInput() && mLabel.empty()) + { + selectFirstItem(); + } +} + +// virtual +bool LLComboBox::postBuild() +{ + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + return true; +} + + +LLComboBox::~LLComboBox() +{ + // children automatically deleted, including mMenu, mButton + + // explicitly disconect this signal, since base class destructor might fire top lost + mTopLostSignalConnection.disconnect(); + mImageLoadedConnection.disconnect(); + + LLUI::getInstance()->removePopup(this); +} + + +void LLComboBox::clear() +{ + if (mTextEntry) + { + mTextEntry->setText(LLStringUtil::null); + } + mButton->setLabelSelected(LLStringUtil::null); + mButton->setLabelUnselected(LLStringUtil::null); + mList->deselectAllItems(); + mLastSelectedIndex = -1; +} + +void LLComboBox::onCommit() +{ + if (mAllowTextEntry && getCurrentIndex() != -1) + { + // we have selected an existing item, blitz the manual text entry with + // the properly capitalized item + mTextEntry->setValue(getSimple()); + mTextEntry->setTentative(false); + } + setControlValue(getValue()); + LLUICtrl::onCommit(); +} + +// virtual +bool LLComboBox::isDirty() const +{ + bool grubby = false; + if ( mList ) + { + grubby = mList->isDirty(); + } + return grubby; +} + +// virtual Clear dirty state +void LLComboBox::resetDirty() +{ + if ( mList ) + { + mList->resetDirty(); + } +} + +bool LLComboBox::itemExists(const std::string& name) +{ + return mList->getItemByLabel(name); +} + +// add item "name" to menu +LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, bool enabled) +{ + LLScrollListItem* item = mList->addSimpleElement(name, pos); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; +} + +// add item "name" with a unique id to menu +LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAddPosition pos, bool enabled ) +{ + LLScrollListItem* item = mList->addSimpleElement(name, pos, id); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; +} + +// add item "name" with attached userdata +LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddPosition pos, bool enabled ) +{ + LLScrollListItem* item = mList->addSimpleElement(name, pos); + item->setEnabled(enabled); + item->setUserdata( userdata ); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; +} + +// add item "name" with attached generic data +LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosition pos, bool enabled ) +{ + LLScrollListItem* item = mList->addSimpleElement(name, pos, value); + item->setEnabled(enabled); + if (!mAllowTextEntry && mLabel.empty()) + { + if (mControlVariable) + { + setValue(mControlVariable->getValue()); // selects the appropriate item + } + else + { + selectFirstItem(); + } + } + return item; +} + +LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos) +{ + return mList->addSeparator(pos); +} + +void LLComboBox::sortByName(bool ascending) +{ + mList->sortOnce(0, ascending); +} + + +// Choose an item with a given name in the menu. +// Returns true if the item was found. +bool LLComboBox::setSimple(const LLStringExplicit& name) +{ + bool found = mList->selectItemByLabel(name, false); + + if (found) + { + setLabel(name); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + + return found; +} + +// virtual +void LLComboBox::setValue(const LLSD& value) +{ + bool found = mList->selectByValue(value); + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + updateLabel(); + } + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + mLastSelectedIndex = -1; + } +} + +const std::string LLComboBox::getSimple() const +{ + const std::string res = getSelectedItemLabel(); + if (res.empty() && mAllowTextEntry) + { + return mTextEntry->getText(); + } + else + { + return res; + } +} + +const std::string LLComboBox::getSelectedItemLabel(S32 column) const +{ + return mList->getSelectedItemLabel(column); +} + +// virtual +LLSD LLComboBox::getValue() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getValue(); + } + else if (mAllowTextEntry) + { + return mTextEntry->getValue(); + } + else + { + return LLSD(); + } +} + +void LLComboBox::setLabel(const LLStringExplicit& name) +{ + if ( mTextEntry ) + { + mTextEntry->setText(name); + if (mList->selectItemByLabel(name, false)) + { + mTextEntry->setTentative(false); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + mTextEntry->setTentative(mTextEntryTentative); + } + } + + if (!mAllowTextEntry) + { + mButton->setLabel(name); + } +} + +void LLComboBox::updateLabel() +{ + // Update the combo editor with the selected + // item label. + if (mTextEntry) + { + mTextEntry->setText(getSelectedItemLabel()); + mTextEntry->setTentative(false); + } + + // If combo box doesn't allow text entry update + // the combo button label. + if (!mAllowTextEntry) + { + mButton->setLabel(getSelectedItemLabel()); + } +} + +bool LLComboBox::remove(const std::string& name) +{ + bool found = mList->selectItemByLabel(name); + + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + mList->deleteSingleItem(mList->getItemIndex(item)); + } + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + + return found; +} + +bool LLComboBox::remove(S32 index) +{ + if (index < mList->getItemCount()) + { + mList->deleteSingleItem(index); + setLabel(getSelectedItemLabel()); + return true; + } + return false; +} + +// Keyboard focus lost. +void LLComboBox::onFocusLost() +{ + hideList(); + // if valid selection + if (mAllowTextEntry && getCurrentIndex() != -1) + { + mTextEntry->selectAll(); + } + mButton->setForcePressedState(false); + LLUICtrl::onFocusLost(); +} + +void LLComboBox::setButtonVisible(bool visible) +{ + mButton->setVisible(visible); + if (mTextEntry) + { + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + if (visible) + { + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; + } + //mTextEntry->setRect(text_entry_rect); + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); + } +} + +bool LLComboBox::setCurrentByIndex( S32 index ) +{ + bool found = mList->selectNthItem( index ); + if (found) + { + setLabel(getSelectedItemLabel()); + mLastSelectedIndex = index; + } + return found; +} + +S32 LLComboBox::getCurrentIndex() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return mList->getItemIndex( item ); + } + return -1; +} + +void LLComboBox::setEnabledByValue(const LLSD& value, bool enabled) +{ + LLScrollListItem *found = mList->getItem(value); + if (found) + { + found->setEnabled(enabled); + } +} + +void LLComboBox::createLineEditor(const LLComboBox::Params& p) +{ + LLRect rect = getLocalRect(); + if (mAllowTextEntry) + { + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + S32 shadow_size = BTN_DROP_SHADOW; + mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, + rect.mTop, rect.mRight, rect.mBottom)); + mButton->setTabStop(false); + mButton->setHAlign(LLFontGL::HCENTER); + + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; + // clear label on button + std::string cur_label = mButton->getLabelSelected(); + LLLineEditor::Params params = p.combo_editor; + params.rect(text_entry_rect); + params.default_text(LLStringUtil::null); + params.max_length.bytes(mMaxChars); + params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); + params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); + params.commit_on_focus_lost(false); + params.follows.flags(FOLLOWS_ALL); + params.label(mLabel); + mTextEntry = LLUICtrlFactory::create (params); + mTextEntry->setText(cur_label); + mTextEntry->setIgnoreTab(true); + addChild(mTextEntry); + + // clear label on button + setLabel(LLStringUtil::null); + + mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); + } + else + { + mButton->setRect(rect); + mButton->setLabel(mLabel.getString()); + + if (mTextEntry) + { + mTextEntry->setVisible(false); + } + } +} + +void LLComboBox::setLeftTextPadding(S32 pad) +{ + S32 left_pad, right_pad; + mTextEntry->getTextPadding(&left_pad, &right_pad); + mTextEntry->setTextPadding(pad, right_pad); +} + +void* LLComboBox::getCurrentUserdata() +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getUserdata(); + } + return NULL; +} + + +void LLComboBox::showList() +{ + // Make sure we don't go off top of screen. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + //HACK: shouldn't have to know about scale here + mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); + + // Make sure that we can see the whole list + LLRect root_view_local; + LLView* root_view = getRootView(); + root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); + + LLRect rect = mList->getRect(); + + S32 min_width = getRect().getWidth(); + S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); + // make sure we have up to date content width metrics + S32 list_width = llclamp(mList->calcMaxContentWidth(), min_width, max_width); + + if (mListPosition == BELOW) + { + if (rect.getHeight() <= -root_view_local.mBottom) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); + } + else + { + // stack on top or bottom, depending on which has more room + if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); + } + else + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + } + } + else // ABOVE + { + if (rect.getHeight() <= root_view_local.mTop - getRect().getHeight()) + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + else + { + // stack on top or bottom, depending on which has more room + if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) + { + // Move rect so it hangs off the bottom of this view + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); + } + else + { + // move rect so it stacks on top of this view (clipped to size of screen) + rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); + } + } + + } + mList->setOrigin(rect.mLeft, rect.mBottom); + mList->reshape(rect.getWidth(), rect.getHeight()); + mList->translateIntoRect(root_view_local); + + // Make sure we didn't go off bottom of screen + S32 x, y; + mList->localPointToScreen(0, 0, &x, &y); + + if (y < 0) + { + mList->translate(0, -y); + } + + // NB: this call will trigger the focuslost callback which will hide the list, so do it first + // before finally showing the list + + mList->setFocus(true); + + // Show the list and push the button down + mButton->setToggleState(true); + mList->setVisible(true); + + LLUI::getInstance()->addPopup(this); + + setUseBoundingRect(true); +// updateBoundingRect(); +} + +void LLComboBox::hideList() +{ + if (mList->getVisible()) + { + // assert selection in list + if(mAllowNewValues) + { + // mLastSelectedIndex = -1 means that we entered a new value, don't select + // any of existing items in this case. + if(mLastSelectedIndex >= 0) + mList->selectNthItem(mLastSelectedIndex); + } + else if(mLastSelectedIndex >= 0) + mList->selectNthItem(mLastSelectedIndex); + + mButton->setToggleState(false); + mList->setVisible(false); + mList->mouseOverHighlightNthItem(-1); + + setUseBoundingRect(false); + LLUI::getInstance()->removePopup(this); +// updateBoundingRect(); + } +} + +void LLComboBox::onButtonMouseDown() +{ + if (!mList->getVisible()) + { + // this might change selection, so do it first + prearrangeList(); + + // highlight the last selected item from the original selection before potentially selecting a new item + // as visual cue to original value of combo box + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + + if (mList->getItemCount() != 0) + { + showList(); + } + + setFocus( true ); + + // pass mouse capture on to list if button is depressed + if (mButton->hasMouseCapture()) + { + gFocusMgr.setMouseCapture(mList); + + // But keep the "pressed" look, which buttons normally lose when they + // lose focus + mButton->setForcePressedState(true); + } + } + else + { + hideList(); + } + +} + +void LLComboBox::onListMouseUp() +{ + // In some cases this is the termination of a mouse click that started on + // the button, so clear its pressed state + mButton->setForcePressedState(false); +} + +//------------------------------------------------------------------ +// static functions +//------------------------------------------------------------------ + +void LLComboBox::onItemSelected(const LLSD& data) +{ + mLastSelectedIndex = getCurrentIndex(); + if (mLastSelectedIndex != -1) + { + updateLabel(); + + if (mAllowTextEntry) + { + gFocusMgr.setKeyboardFocus(mTextEntry); + mTextEntry->selectAll(); + } + } + // hiding the list reasserts the old value stored in the text editor/dropdown button + hideList(); + + // commit does the reverse, asserting the value in the list + onCommit(); +} + +bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) +{ + std::string tool_tip; + + if(LLUICtrl::handleToolTip(x, y, mask)) + { + return true; + } + + tool_tip = getToolTip(); + if (tool_tip.empty()) + { + tool_tip = getSelectedItemLabel(); + } + + if( !tool_tip.empty() ) + { + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(tool_tip) + .sticky_rect(calcScreenRect())); + } + return true; +} + +bool LLComboBox::handleKeyHere(KEY key, MASK mask) +{ + bool result = false; + if (hasFocus()) + { + if (mList->getVisible() + && key == KEY_ESCAPE && mask == MASK_NONE) + { + hideList(); + return true; + } + //give list a chance to pop up and handle key + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + // highlight the original selection before potentially selecting a new item + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + result = mList->handleKeyHere(key, mask); + + // will only see return key if it is originating from line editor + // since the dropdown button eats the key + if (key == KEY_RETURN) + { + if (mask == MASK_NONE) + { + mOnReturnSignal(this, getValue()); + } + + // don't show list and don't eat key input when committing + // free-form text entry with RETURN since user already knows + // what they are trying to select + return false; + } + // if selection has changed, pop open list + else if (mList->getLastSelectedItem() != last_selected_item + || ((key == KEY_DOWN || key == KEY_UP) + && mList->getCanSelect() + && !mList->isEmpty())) + { + showList(); + } + } + return result; +} + +bool LLComboBox::handleUnicodeCharHere(llwchar uni_char) +{ + bool result = false; + if (gFocusMgr.childHasKeyboardFocus(this)) + { + // space bar just shows the list + if (' ' != uni_char ) + { + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + // highlight the original selection before potentially selecting a new item + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + result = mList->handleUnicodeCharHere(uni_char); + if (mList->getLastSelectedItem() != last_selected_item) + { + showList(); + } + } + } + return result; +} + +void LLComboBox::setTextEntry(const LLStringExplicit& text) +{ + if (mTextEntry) + { + mTextEntry->setText(text); + mHasAutocompletedText = false; + updateSelection(); + } +} + +void LLComboBox::setKeystrokeOnEsc(bool enable) +{ + if (mTextEntry) + { + mTextEntry->setKeystrokeOnEsc(enable); + } +} + +void LLComboBox::onTextEntry(LLLineEditor* line_editor) +{ + if (mTextEntryCallback != NULL) + { + (mTextEntryCallback)(line_editor, LLSD()); + } + + KEY key = gKeyboard->currentKey(); + if (key == KEY_BACKSPACE || + key == KEY_DELETE) + { + if (mList->selectItemByLabel(line_editor->getText(), false)) + { + line_editor->setTentative(false); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else + { + line_editor->setTentative(mTextEntryTentative); + mList->deselectAllItems(); + mLastSelectedIndex = -1; + } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } + return; + } + + if (key == KEY_LEFT || + key == KEY_RIGHT) + { + return; + } + + if (key == KEY_DOWN) + { + setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); + if (!mList->getVisible()) + { + prearrangeList(); + + if (mList->getItemCount() != 0) + { + showList(); + } + } + line_editor->selectAll(); + line_editor->setTentative(false); + } + else if (key == KEY_UP) + { + setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); + if (!mList->getVisible()) + { + prearrangeList(); + + if (mList->getItemCount() != 0) + { + showList(); + } + } + line_editor->selectAll(); + line_editor->setTentative(false); + } + else + { + // RN: presumably text entry + updateSelection(); + } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } +} + +void LLComboBox::updateSelection() +{ + LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); + // user-entered portion of string, based on assumption that any selected + // text was a result of auto-completion + LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText(); + std::string full_string = mTextEntry->getText(); + + // go ahead and arrange drop down list on first typed character, even + // though we aren't showing it... some code relies on prearrange + // callback to populate content + if( mTextEntry->getWText().size() == 1 ) + { + prearrangeList(mTextEntry->getText()); + } + + if (mList->selectItemByLabel(full_string, false)) + { + mTextEntry->setTentative(false); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else if (mList->selectItemByPrefix(left_wstring, false)) + { + LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); + LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); + mTextEntry->setText(wstring_to_utf8str(wtext)); + mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); + mTextEntry->endSelection(); + mTextEntry->setTentative(false); + mHasAutocompletedText = true; + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + else // no matching items found + { + mList->deselectAllItems(); + mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion + mTextEntry->setTentative(mTextEntryTentative); + mHasAutocompletedText = false; + mLastSelectedIndex = -1; + } +} + +void LLComboBox::onTextCommit(const LLSD& data) +{ + std::string text = mTextEntry->getText(); + setSimple(text); + onCommit(); + mTextEntry->selectAll(); +} + +void LLComboBox::setFocus(bool b) +{ + LLUICtrl::setFocus(b); + + if (b) + { + mList->clearSearchString(); + if (mList->getVisible()) + { + mList->setFocus(true); + } + } +} + +void LLComboBox::prearrangeList(std::string filter) +{ + if (mPrearrangeCallback) + { + mPrearrangeCallback(this, LLSD(filter)); + } +} + + +//============================================================================ +// ll::ui::SearchableControl functions + +//virtual +std::string LLComboBox::_getSearchText() const +{ + std::string res; + if (mList) + { + // getAllData returns a full copy of content, might be a + // better option to implement an mList->getSearchText(column) + std::vector data = mList->getAllData(); + std::vector::iterator iter = data.begin(); + while (iter != data.end()) + { + LLScrollListCell* cell = (*iter)->getColumn(0); + if (cell) + { + std::string whitelist_url = cell->getValue().asString(); + res += cell->getValue().asString(); + } + iter++; + } + } + return res + getToolTip(); +} + +//virtual +void LLComboBox::onSetHighlight() const +{ + if (mButton) + { + mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted()); + } +} + +void LLComboBox::imageLoaded() +{ + if (mAllowTextEntry) + { + LLRect rect = getLocalRect(); + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + S32 shadow_size = BTN_DROP_SHADOW; + mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size, + rect.mTop, rect.mRight, rect.mBottom)); + if (mButton->getVisible()) + { + // recalculate field size + if (mTextEntry) + { + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW; + mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), true); + } + } + } +} + +//============================================================================ +// LLCtrlListInterface functions + +S32 LLComboBox::getItemCount() const +{ + return mList->getItemCount(); +} + +void LLComboBox::addColumn(const LLSD& column, EAddPosition pos) +{ + mList->clearColumns(); + mList->addColumn(column, pos); +} + +void LLComboBox::clearColumns() +{ + mList->clearColumns(); +} + +void LLComboBox::setColumnLabel(const std::string& column, const std::string& label) +{ + mList->setColumnLabel(column, label); +} + +LLScrollListItem* LLComboBox::addElement(const LLSD& value, EAddPosition pos, void* userdata) +{ + return mList->addElement(value, pos, userdata); +} + +LLScrollListItem* LLComboBox::addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) +{ + return mList->addSimpleElement(value, pos, id); +} + +void LLComboBox::clearRows() +{ + mList->clearRows(); +} + +void LLComboBox::sortByColumn(const std::string& name, bool ascending) +{ + mList->sortByColumn(name, ascending); +} + +//============================================================================ +//LLCtrlSelectionInterface functions + +bool LLComboBox::setCurrentByID(const LLUUID& id) +{ + bool found = mList->selectByID( id ); + + if (found) + { + setLabel(getSelectedItemLabel()); + mLastSelectedIndex = mList->getFirstSelectedIndex(); + } + + return found; +} + +LLUUID LLComboBox::getCurrentID() const +{ + return mList->getStringUUIDSelectedItem(); +} +bool LLComboBox::setSelectedByValue(const LLSD& value, bool selected) +{ + bool found = mList->setSelectedByValue(value, selected); + if (found) + { + setLabel(getSelectedItemLabel()); + } + return found; +} + +LLSD LLComboBox::getSelectedValue() +{ + return mList->getSelectedValue(); +} + +bool LLComboBox::isSelected(const LLSD& value) const +{ + return mList->isSelected(value); +} + +bool LLComboBox::operateOnSelection(EOperation op) +{ + if (op == OP_DELETE) + { + mList->deleteSelectedItems(); + return true; + } + return false; +} + +bool LLComboBox::operateOnAll(EOperation op) +{ + if (op == OP_DELETE) + { + clearRows(); + return true; + } + return false; +} + +bool LLComboBox::selectItemRange( S32 first, S32 last ) +{ + return mList->selectItemRange(first, last); +} + + +static LLDefaultChildRegistry::Register register_icons_combo_box("icons_combo_box"); + +LLIconsComboBox::Params::Params() +: icon_column("icon_column", ICON_COLUMN), + label_column("label_column", LABEL_COLUMN) +{} + +LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p) +: LLComboBox(p), + mIconColumnIndex(p.icon_column), + mLabelColumnIndex(p.label_column) +{} + +const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const +{ + mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign()); + + return LLComboBox::getSelectedItemLabel(mLabelColumnIndex); +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llui/llcombobox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui/llcombobox.cpp') diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 0d82f29dfb..79dce1c714 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -995,7 +995,7 @@ void LLComboBox::updateSelection() LLWString selected_item = utf8str_to_wstring(getSelectedItemLabel()); LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); mTextEntry->setText(wstring_to_utf8str(wtext)); - mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); + mTextEntry->setSelection(static_cast(left_wstring.size()), static_cast(mTextEntry->getWText().size())); mTextEntry->endSelection(); mTextEntry->setTentative(false); mHasAutocompletedText = true; -- cgit v1.2.3