[XP Tools] Initial merge Cherry Pick Also modernize llfloaterauction internally, but leave the ui the same for now. Breaks out script_question_mute() in llviewermessage.cpp to better sync with upstream Adds support for UnknownScriptQuestion notification (translators need to translate this one~) RLVa note: Rewrote RLVa permissions handling block just a bit. Added 13 new capabilities from the XP Tools, I doubt all of them really exist. Minor update to LLComboBox, decided against implementing LLIconsComboBox for now. Modified LLExperienceLog::notify to lookup names and display them along with the slurls since our editors don't do that automatically. Experience tweak: Changed a few notify's to notifytips so that we can click the links to experience profiles from chat instead of via hacked in buttons Migrated LLFloaterCompileQueue to a proper Instance Tracker so we can call getKey Modernized LLSD, gives us reverse iterators and the new debugging impl. We needed the reverse iterators. Experience tweak: Added virtual destructors to responders. Updated llhandle.h to allow calling getDerivedHandle in public. Updated LLScrollContainer and LLScrollBar to be more modern. Added LLFlatListView/flat_list_view from upstream - these don't seem work though? Added some newer login/logout strings to strings.xml Thanks for the default timeout policies, Aleric~ To avoid needing to scroll through tabs, about land tabs now are as big as they need to be to display their labels, same on groups Group Members and Roles has been renamed to just Members because this allows the new Experiences tab enough room to display. Thanks to Henri Beauchamp (Cool VL Viewer) for the setupList augmentation. (without it, I'd still be stuck) Thanks to Shyotl for the helpsies~ Added the LSL constants, events, and functions that LL neglected to put in. Added click callbacks and name lookups for profile linky texts~ Merge is up to 22b4cdc Old TODO: Get the uis looking nice (profiles? Experiences... floater) - done Old TODO: Make sure flatlistviews look okay... - Not using Old TODO: Fix LLFloaterExperiencePicker, right now the panel does not show. - unsure Old TODO: Remove the llfloaterabout.cpp change. - done Merges llexperiencecache with upstream and unstable Introduces LLCoroResponder, TODO: Make everything use this. Updates Reporter floater to the latest, supports the new cap thingy Also adds these commits/changes: [XPTools] Double clicking experiences in namelists should open the profile Add List.CopyNames support for Experiences [XP Tools] Some UI work, I'll do more later [XPTools] More UI Stuff, Later is now! Allow getSLURL for experiences WIP Experience list menu Also make EXPERIENCE > OBJECT, because mainline started OBJECT already [XPTools] Add Experience support to Name UI [XPTools] Fix experience profile UI 9c3067e843265587e91c659200a8d783acf2d9b2 [XPTools] Fix experience location showing "last" and getting set to "last" [XPTools] Move Experiences floater from view menu to world menu [XPTools] Fix up more UI [XPTools] Fix experiences panels [XPTools] Hide pieces of the Experiences menu when they're not usable [XPTools] More UI work, mostly to get the menus working [XPTools] The events list is for events, not experiences, remove menu # Conflicts: # indra/llcommon/llsd.cpp - merge with unstable branch # indra/llmessage/message_prehash.cpp # indra/llmessage/message_prehash.h # indra/llui/llscrollbar.cpp # indra/llui/llscrollcontainer.cpp # indra/llui/llurlentry.cpp # indra/llui/llurlregistry.cpp # indra/newview/app_settings/keywords.ini # indra/newview/app_settings/settings.xml # indra/newview/llappviewer.cpp # indra/newview/llappviewer.h # indra/newview/llassetuploadresponders.cpp # indra/newview/llcompilequeue.* - merge stable # indra/newview/llfloaterabout.cpp # indra/newview/llfloaterland.* - merge unstable # indra/newview/llfloaterproperties.cpp # indra/newview/llfloaterregioninfo.* - merge unstable # indra/newview/llmenucommands.cpp - merge unstable # indra/newview/llpreviewscript.cpp - merge unstable # indra/newview/llviewermessage.cpp - merge unstable # indra/newview/llviewerregion.cpp - merge unstable # indra/newview/skins/default/textures/textures.xml - merge unstable # indra/newview/skins/default/xui/en-us/strings.xml - merge unstable
1270 lines
30 KiB
C++
1270 lines
30 KiB
C++
/**
|
|
* @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"
|
|
|
|
// Globals
|
|
S32 LLCOMBOBOX_HEIGHT = 0;
|
|
S32 LLCOMBOBOX_WIDTH = 0;
|
|
S32 MAX_COMBO_WIDTH = 500;
|
|
|
|
static LLRegisterWidget<LLComboBox> register_combo_box("combo_box");
|
|
|
|
LLComboBox::LLComboBox(const std::string& name, const LLRect& rect, const std::string& label, commit_callback_t commit_callback)
|
|
: LLUICtrl(name, rect, TRUE, commit_callback, FOLLOWS_LEFT | FOLLOWS_TOP),
|
|
mTextEntry(NULL),
|
|
mTextEntryTentative(TRUE),
|
|
mArrowImage(NULL),
|
|
mHasAutocompletedText(false),
|
|
mAllowTextEntry(false),
|
|
mAllowNewValues(false),
|
|
mMaxChars(20),
|
|
mPrearrangeCallback( NULL ),
|
|
mTextEntryCallback( NULL ),
|
|
mListPosition(BELOW),
|
|
mSuppressTentative( false ),
|
|
mSuppressAutoComplete( false ),
|
|
mListColor(LLUI::sColorsGroup->getColor("ComboBoxBg")),
|
|
mLastSelectedIndex(-1),
|
|
mLabel(label)
|
|
{
|
|
// Always use text box
|
|
// Text label button
|
|
mButton = new LLButton(mLabel, LLRect(), LLStringUtil::null);
|
|
mButton->setImageUnselected(LLUI::getUIImage("square_btn_32x128.tga"));
|
|
mButton->setImageSelected(LLUI::getUIImage("square_btn_selected_32x128.tga"));
|
|
mButton->setImageDisabled(LLUI::getUIImage("square_btn_32x128.tga"));
|
|
mButton->setImageDisabledSelected(LLUI::getUIImage("square_btn_selected_32x128.tga"));
|
|
mButton->setScaleImage(TRUE);
|
|
|
|
mButton->setMouseDownCallback(boost::bind(&LLComboBox::onButtonMouseDown,this));
|
|
mButton->setFont(LLFontGL::getFontSansSerifSmall());
|
|
mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
|
|
mButton->setHAlign( LLFontGL::LEFT );
|
|
mButton->setRightHPad(2);
|
|
|
|
addChild(mButton);
|
|
|
|
// disallow multiple selection
|
|
mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(),
|
|
boost::bind(&LLComboBox::onItemSelected, this, _2), FALSE);
|
|
mList->setVisible(false);
|
|
mList->setBgWriteableColor(mListColor);
|
|
mList->setCommitOnKeyboardMovement(false);
|
|
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));
|
|
|
|
mArrowImage = LLUI::getUIImage("combobox_arrow.tga");
|
|
mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT);
|
|
|
|
updateLayout();
|
|
|
|
mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this));
|
|
}
|
|
|
|
|
|
// virtual
|
|
LLXMLNodePtr LLComboBox::getXML(bool save_children) const
|
|
{
|
|
LLXMLNodePtr node = LLUICtrl::getXML();
|
|
|
|
node->setName(LL_COMBO_BOX_TAG);
|
|
|
|
// Attributes
|
|
node->createChild("allow_text_entry", TRUE)->setBoolValue(mAllowTextEntry);
|
|
node->createChild("max_chars", TRUE)->setIntValue(mMaxChars);
|
|
|
|
// Contents
|
|
std::vector<LLScrollListItem*> data_list = mList->getAllData();
|
|
for (std::vector<LLScrollListItem*>::iterator data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
|
|
{
|
|
LLScrollListItem* item = *data_itor;
|
|
LLScrollListCell* cell = item->getColumn(0);
|
|
if (cell)
|
|
{
|
|
LLXMLNodePtr item_node = node->createChild("combo_item", FALSE);
|
|
LLSD value = item->getValue();
|
|
item_node->createChild("value", TRUE)->setStringValue(value.asString());
|
|
item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled());
|
|
item_node->setStringValue(cell->getValue().asString());
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
// static
|
|
LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
|
{
|
|
std::string label("");
|
|
node->getAttributeString("label", label);
|
|
|
|
LLRect rect;
|
|
createRect(node, rect, parent, LLRect());
|
|
|
|
BOOL allow_text_entry = FALSE;
|
|
node->getAttributeBOOL("allow_text_entry", allow_text_entry);
|
|
|
|
S32 max_chars = 20;
|
|
node->getAttributeS32("max_chars", max_chars);
|
|
|
|
LLComboBox* combo_box = new LLComboBox("combo_box", rect, label);
|
|
combo_box->setAllowTextEntry(allow_text_entry, max_chars);
|
|
|
|
if (LLFontGL* font = selectFont(node))
|
|
combo_box->mButton->setFont(font);
|
|
|
|
const std::string& contents = node->getValue();
|
|
|
|
if (contents.find_first_not_of(" \n\t") != contents.npos)
|
|
{
|
|
LL_ERRS() << "Legacy combo box item format used! Please convert to <combo_item> tags!" << LL_ENDL;
|
|
}
|
|
else
|
|
{
|
|
LLXMLNodePtr child;
|
|
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
|
|
{
|
|
if (child->hasName("combo_item") || child->hasName("combo_box.item"))
|
|
{
|
|
std::string label = child->getTextContents();
|
|
child->getAttributeString("label", label);
|
|
|
|
std::string value = label;
|
|
child->getAttributeString("value", value);
|
|
|
|
LLScrollListItem * item=combo_box->add(label, LLSD(value) );
|
|
|
|
if(item && child->hasAttribute("tool_tip"))
|
|
{
|
|
std::string tool_tip = label;
|
|
child->getAttributeString("tool_tip", tool_tip);
|
|
item->getColumn(0)->setToolTip(tool_tip);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Do this AFTER combo_items are set up so setValue is actually able to select the correct initial entry.
|
|
combo_box->initFromXML(node, parent);
|
|
|
|
// if we haven't already gotten a value from our control_name and
|
|
// if providing user text entry or descriptive label
|
|
// don't select an item under the hood
|
|
if (combo_box->getControlName().empty())
|
|
{
|
|
const auto text = combo_box->acceptsTextInput();
|
|
std::string label;
|
|
if (node->getAttributeString("label", label))
|
|
text ? combo_box->setLabel(label) : (void)combo_box->mList->selectItemByLabel(label, FALSE);
|
|
else if (!text && combo_box->mLabel.empty())
|
|
combo_box->selectFirstItem();
|
|
}
|
|
|
|
return combo_box;
|
|
}
|
|
|
|
void LLComboBox::setEnabled(BOOL enabled)
|
|
{
|
|
LLView::setEnabled(enabled);
|
|
mButton->setEnabled(enabled);
|
|
}
|
|
|
|
|
|
LLComboBox::~LLComboBox()
|
|
{
|
|
// children automatically deleted, including mMenu, mButton
|
|
|
|
// explicitly disconect this signal, since base class destructor might fire top lost
|
|
mTopLostSignalConnection.disconnect();
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL LLComboBox::isTextDirty() const
|
|
{
|
|
BOOL grubby = FALSE;
|
|
if ( mTextEntry )
|
|
{
|
|
grubby = mTextEntry->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);
|
|
}
|
|
|
|
void LLComboBox::resetTextDirty()
|
|
{
|
|
if ( mTextEntry )
|
|
{
|
|
mTextEntry->resetDirty();
|
|
}
|
|
}
|
|
|
|
// 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())
|
|
{
|
|
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())
|
|
{
|
|
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())
|
|
{
|
|
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())
|
|
{
|
|
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
|
|
{
|
|
if (!mSuppressTentative) mTextEntry->setTentative(mTextEntryTentative);
|
|
}
|
|
mTextEntry->setCursor(0); // Be scrolled to the beginning!
|
|
}
|
|
|
|
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();
|
|
}
|
|
LLUICtrl::onFocusLost();
|
|
}
|
|
|
|
void LLComboBox::setButtonVisible(BOOL visible)
|
|
{
|
|
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
|
|
|
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 * drop_shadow_button;
|
|
}
|
|
//mTextEntry->setRect(text_entry_rect);
|
|
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
|
}
|
|
}
|
|
|
|
void LLComboBox::draw()
|
|
{
|
|
mButton->setEnabled(getEnabled() /*&& !mList->isEmpty()*/);
|
|
|
|
// Draw children normally
|
|
LLUICtrl::draw();
|
|
}
|
|
|
|
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::updateLayout()
|
|
{
|
|
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
|
LLRect rect = getLocalRect();
|
|
if (mAllowTextEntry)
|
|
{
|
|
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
|
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->setHAlign(LLFontGL::HCENTER);
|
|
|
|
if (!mTextEntry)
|
|
{
|
|
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
|
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
|
// clear label on button
|
|
std::string cur_label = mButton->getLabelSelected();
|
|
mTextEntry = new LLLineEditor(std::string("combo_text_entry"),
|
|
text_entry_rect,
|
|
LLStringUtil::null,
|
|
LLFontGL::getFontSansSerifSmall(),
|
|
mMaxChars,
|
|
boost::bind(&LLComboBox::onTextCommit, this, _2),
|
|
boost::bind(&LLComboBox::onTextEntry, this, _1));
|
|
mTextEntry->setSelectAllonFocusReceived(TRUE);
|
|
mTextEntry->setHandleEditKeysDirectly(TRUE);
|
|
mTextEntry->setCommitOnFocusLost(FALSE);
|
|
mTextEntry->setFollows(FOLLOWS_ALL);
|
|
mTextEntry->setText(cur_label);
|
|
mTextEntry->setIgnoreTab(TRUE);
|
|
addChild(mTextEntry);
|
|
}
|
|
else
|
|
{
|
|
mTextEntry->setVisible(TRUE);
|
|
mTextEntry->setMaxTextLength(mMaxChars);
|
|
}
|
|
|
|
// clear label on button
|
|
setLabel(LLStringUtil::null);
|
|
|
|
mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
|
|
}
|
|
else
|
|
{
|
|
mButton->setRect(rect);
|
|
mButton->setTabStop(TRUE);
|
|
mButton->setLabelUnselected(mLabel);
|
|
mButton->setLabelSelected(mLabel);
|
|
|
|
if (mTextEntry)
|
|
{
|
|
mTextEntry->setVisible(FALSE);
|
|
}
|
|
mButton->setFollows(FOLLOWS_ALL);
|
|
}
|
|
}
|
|
|
|
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
|
|
mList->updateColumnWidths();
|
|
S32 list_width = llclamp(mList->getMaxContentWidth(), 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, FALSE);
|
|
|
|
// 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);
|
|
|
|
// register ourselves as a "top" control
|
|
// effectively putting us into a special draw layer
|
|
// and not affecting the bounding rectangle calculation
|
|
gFocusMgr.setTopCtrl(this);
|
|
|
|
// Show the list and push the button down
|
|
mButton->setToggleState(TRUE);
|
|
mList->setVisible(TRUE);
|
|
|
|
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);
|
|
if( gFocusMgr.getTopCtrl() == this )
|
|
{
|
|
gFocusMgr.setTopCtrl(NULL);
|
|
}
|
|
// 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, std::string& msg, LLRect* sticky_rect_screen)
|
|
{
|
|
std::string tool_tip;
|
|
|
|
if(LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (LLUI::sShowXUINames)
|
|
{
|
|
tool_tip = getShowNamesToolTip();
|
|
}
|
|
else
|
|
{
|
|
tool_tip = getToolTip();
|
|
if (tool_tip.empty())
|
|
{
|
|
tool_tip = getSelectedItemLabel();
|
|
}
|
|
}
|
|
|
|
if( !tool_tip.empty() )
|
|
{
|
|
msg = tool_tip;
|
|
|
|
// Convert rect local to screen coordinates
|
|
localPointToScreen(
|
|
0, 0,
|
|
&(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
|
|
localPointToScreen(
|
|
getRect().getWidth(), getRect().getHeight(),
|
|
&(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
|
|
}
|
|
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)
|
|
{
|
|
// 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;
|
|
}
|
|
|
|
BOOL LLComboBox::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
|
{
|
|
if (mList->getVisible()) return mList->handleScrollWheel(x, y, clicks);
|
|
if (mAllowTextEntry) // We might be editable
|
|
if (!mList->getFirstSelected()) // We aren't in the list, don't kill their text
|
|
return false;
|
|
|
|
setCurrentByIndex(llclamp(getCurrentIndex() + clicks, 0, getItemCount() - 1));
|
|
prearrangeList();
|
|
onCommit();
|
|
return true;
|
|
}
|
|
|
|
void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
|
|
{
|
|
mAllowTextEntry = allow;
|
|
|
|
mTextEntryTentative = set_tentative;
|
|
mMaxChars = max_chars;
|
|
|
|
updateLayout();
|
|
}
|
|
|
|
void LLComboBox::setTextEntry(const LLStringExplicit& text)
|
|
{
|
|
if (mTextEntry)
|
|
{
|
|
mTextEntry->setText(text);
|
|
mTextEntry->setCursor(0); // Singu Note: Move the cursor over to the beginning
|
|
mHasAutocompletedText = FALSE;
|
|
updateSelection();
|
|
}
|
|
}
|
|
|
|
const std::string LLComboBox::getTextEntry() const
|
|
{
|
|
return mTextEntry->getText();
|
|
}
|
|
|
|
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
|
|
{
|
|
if (!mSuppressTentative)
|
|
line_editor->setTentative(mTextEntryTentative);
|
|
mList->deselectAllItems();
|
|
mLastSelectedIndex = -1;
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
void LLComboBox::updateSelection()
|
|
{
|
|
if(mSuppressAutoComplete) return;
|
|
|
|
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::setSuppressTentative(bool suppress)
|
|
{
|
|
mSuppressTentative = suppress;
|
|
if (mTextEntry && mSuppressTentative) mTextEntry->setTentative(FALSE);
|
|
}
|
|
|
|
void LLComboBox::setSuppressAutoComplete(bool suppress)
|
|
{
|
|
mSuppressAutoComplete = suppress;
|
|
}
|
|
|
|
|
|
void LLComboBox::setFocusText(BOOL b)
|
|
{
|
|
LLUICtrl::setFocus(b);
|
|
|
|
if (b && mTextEntry)
|
|
{
|
|
if (mTextEntry->getVisible())
|
|
{
|
|
mTextEntry->setFocus(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLComboBox::setFocus(BOOL b)
|
|
{
|
|
LLUICtrl::setFocus(b);
|
|
|
|
if (b)
|
|
{
|
|
mList->clearSearchString();
|
|
if (mList->getVisible())
|
|
{
|
|
mList->setFocus(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLComboBox::setPrevalidate( BOOL (*func)(const LLWString &) )
|
|
{
|
|
if (mTextEntry) mTextEntry->setPrevalidate(func);
|
|
}
|
|
|
|
void LLComboBox::prearrangeList(std::string filter)
|
|
{
|
|
if (mPrearrangeCallback)
|
|
{
|
|
mPrearrangeCallback(this, LLSD(filter));
|
|
}
|
|
}
|
|
|
|
//============================================================================
|
|
// 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);
|
|
}
|
|
|
|
|
|
/* Singu Note: This isn't very necessary for now, let's not bother.
|
|
static LLRegisterWidget<LLIconsComboBox> 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);
|
|
}
|
|
*/
|