794 lines
22 KiB
C++
794 lines
22 KiB
C++
/**
|
|
* @file llfloateravatarpicker.cpp
|
|
*
|
|
* $LicenseInfo:firstyear=2003&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$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llfloateravatarpicker.h"
|
|
|
|
// Viewer includes
|
|
#include "llagent.h"
|
|
#include "llcallingcard.h"
|
|
#include "llfocusmgr.h"
|
|
#include "llimview.h" // for gIMMgr
|
|
#include "lltooldraganddrop.h" // for LLToolDragAndDrop
|
|
#include "llviewercontrol.h"
|
|
#include "llviewerregion.h" // getCapability()
|
|
#include "llworld.h"
|
|
|
|
// Linden libraries
|
|
#include "llavatarnamecache.h" // IDEVO
|
|
#include "llbutton.h"
|
|
#include "llcachename.h"
|
|
#include "lllineeditor.h"
|
|
#include "llscrolllistctrl.h"
|
|
#include "lltabcontainer.h"
|
|
#include "lluictrlfactory.h"
|
|
#include "message.h"
|
|
|
|
// [RLVa:KB]
|
|
#include "rlvhandler.h"
|
|
// [/RLVa:KB]
|
|
|
|
//put it back as a member once the legacy path is out?
|
|
static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
|
|
|
|
LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
|
|
BOOL allow_multiple,
|
|
BOOL closeOnSelect)
|
|
{
|
|
// *TODO: Use a key to allow this not to be an effective singleton
|
|
|
|
LLFloaterAvatarPicker* floater = getInstance();
|
|
floater->open();
|
|
|
|
floater->mSelectionCallback = callback;
|
|
floater->setAllowMultiple(allow_multiple);
|
|
floater->mNearMeListComplete = FALSE;
|
|
floater->mCloseOnSelect = closeOnSelect;
|
|
|
|
if (!closeOnSelect)
|
|
{
|
|
// Use Select/Close
|
|
std::string select_string = floater->getString("Select");
|
|
std::string close_string = floater->getString("Close");
|
|
floater->getChild<LLButton>("ok_btn")->setLabel(select_string);
|
|
floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
|
|
}
|
|
|
|
return floater;
|
|
}
|
|
|
|
// Default constructor
|
|
LLFloaterAvatarPicker::LLFloaterAvatarPicker() :
|
|
LLFloater(),
|
|
mNumResultsReturned(0),
|
|
mNearMeListComplete(FALSE),
|
|
mCloseOnSelect(FALSE)
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL);
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::postBuild()
|
|
{
|
|
childSetKeystrokeCallback("Edit", &LLFloaterAvatarPicker::editKeystroke, (void*)this);
|
|
childSetKeystrokeCallback("EditUUID", &LLFloaterAvatarPicker::editKeystroke, (void*)this);
|
|
|
|
childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this));
|
|
getChildView("Find")->setEnabled(FALSE);
|
|
childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this));
|
|
getChild<LLUICtrl>("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this));
|
|
|
|
LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>("SearchResults");
|
|
searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
getChildView("SearchResults")->setEnabled(FALSE);
|
|
|
|
LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
|
|
nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
|
|
LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
|
|
friends->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
childSetAction("RefreshFriends", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
|
|
getChild<LLUICtrl>("Friends")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
|
|
childSetAction("ok_btn", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
childSetAction("cancel_btn", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this));
|
|
|
|
getChild<LLUICtrl>("Edit")->setFocus(TRUE);
|
|
|
|
LLPanel* search_panel = getChild<LLPanel>("SearchPanel");
|
|
if (search_panel)
|
|
{
|
|
// Start searching when Return is pressed in the line editor.
|
|
search_panel->setDefaultBtn("Find");
|
|
}
|
|
|
|
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("no_results"));
|
|
|
|
getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(
|
|
boost::bind(&LLFloaterAvatarPicker::onTabChanged,this));
|
|
|
|
setAllowMultiple(FALSE);
|
|
|
|
center();
|
|
|
|
populateFriend();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::setOkBtnEnableCb(validate_callback_t cb)
|
|
{
|
|
mOkButtonValidateSignal.connect(cb);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onTabChanged()
|
|
{
|
|
getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
|
|
}
|
|
|
|
// Destroys the object
|
|
LLFloaterAvatarPicker::~LLFloaterAvatarPicker()
|
|
{
|
|
gFocusMgr.releaseFocusIfNeeded( this );
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnFind()
|
|
{
|
|
find();
|
|
}
|
|
|
|
static void addAvatarUUID(const LLUUID av_id, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
|
|
{
|
|
if (av_id.notNull())
|
|
{
|
|
avatar_ids.push_back(av_id);
|
|
|
|
std::map<LLUUID, LLAvatarName>::iterator iter = sAvatarNameMap.find(av_id);
|
|
if (iter != sAvatarNameMap.end())
|
|
{
|
|
avatar_names.push_back(iter->second);
|
|
}
|
|
else
|
|
{
|
|
// the only case where it isn't in the name map is friends
|
|
// but it should be in the name cache
|
|
LLAvatarName av_name;
|
|
LLAvatarNameCache::get(av_id, &av_name);
|
|
avatar_names.push_back(av_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void getSelectedAvatarData(const LLUICtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
|
|
{
|
|
const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from);
|
|
if(list)
|
|
{
|
|
std::vector<LLScrollListItem*> items = list->getAllSelected();
|
|
for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
|
|
{
|
|
addAvatarUUID((*iter)->getUUID(), avatar_ids, avatar_names);
|
|
}
|
|
}
|
|
else
|
|
addAvatarUUID(from->getValue().asUUID(), avatar_ids, avatar_names);
|
|
}
|
|
|
|
|
|
void LLFloaterAvatarPicker::onBtnSelect()
|
|
{
|
|
|
|
// If select btn not enabled then do not callback
|
|
if (!isSelectBtnEnabled())
|
|
return;
|
|
|
|
if(mSelectionCallback)
|
|
{
|
|
std::string active_panel_name;
|
|
LLUICtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
if(active_panel)
|
|
{
|
|
active_panel_name = active_panel->getName();
|
|
}
|
|
if(active_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(active_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (active_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
else if(active_panel_name == "KeyPanel")
|
|
{
|
|
list = getChild<LLLineEditor>("EditUUID");
|
|
}
|
|
|
|
if(list)
|
|
{
|
|
uuid_vec_t avatar_ids;
|
|
std::vector<LLAvatarName> avatar_names;
|
|
getSelectedAvatarData(list, avatar_ids, avatar_names);
|
|
mSelectionCallback(avatar_ids, avatar_names);
|
|
}
|
|
}
|
|
getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
|
|
getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
|
|
getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
|
|
if(mCloseOnSelect)
|
|
{
|
|
mCloseOnSelect = FALSE;
|
|
close();
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnRefresh()
|
|
{
|
|
getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
|
|
getChild<LLScrollListCtrl>("NearMe")->setCommentText(getString("searching"));
|
|
mNearMeListComplete = FALSE;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnClose()
|
|
{
|
|
close();
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onRangeAdjust()
|
|
{
|
|
onBtnRefresh();
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onList()
|
|
{
|
|
getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::populateNearMe()
|
|
{
|
|
BOOL all_loaded = TRUE;
|
|
BOOL empty = TRUE;
|
|
LLScrollListCtrl* near_me_scroller = getChild<LLScrollListCtrl>("NearMe");
|
|
near_me_scroller->deleteAllItems();
|
|
|
|
uuid_vec_t avatar_ids;
|
|
LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
|
|
for(U32 i=0; i<avatar_ids.size(); i++)
|
|
{
|
|
LLUUID& av = avatar_ids[i];
|
|
if(av == gAgent.getID()) continue;
|
|
LLSD element;
|
|
element["id"] = av; // value
|
|
LLAvatarName av_name;
|
|
|
|
if (!LLAvatarNameCache::get(av, &av_name))
|
|
{
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = LLCacheName::getDefaultName();
|
|
all_loaded = FALSE;
|
|
}
|
|
else
|
|
{
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = av_name.mDisplayName;
|
|
element["columns"][1]["column"] = "username";
|
|
element["columns"][1]["value"] = av_name.mUsername;
|
|
|
|
sAvatarNameMap[av] = av_name;
|
|
}
|
|
near_me_scroller->addElement(element);
|
|
empty = FALSE;
|
|
}
|
|
|
|
if (empty)
|
|
{
|
|
getChildView("NearMe")->setEnabled(FALSE);
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
near_me_scroller->setCommentText(getString("no_one_near"));
|
|
}
|
|
else
|
|
{
|
|
getChildView("NearMe")->setEnabled(TRUE);
|
|
getChildView("ok_btn")->setEnabled(TRUE);
|
|
near_me_scroller->selectFirstItem();
|
|
onList();
|
|
near_me_scroller->setFocus(TRUE);
|
|
}
|
|
|
|
if (all_loaded)
|
|
{
|
|
mNearMeListComplete = TRUE;
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::populateFriend()
|
|
{
|
|
LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends");
|
|
friends_scroller->deleteAllItems();
|
|
LLCollectAllBuddies collector;
|
|
LLAvatarTracker::instance().applyFunctor(collector);
|
|
LLCollectAllBuddies::buddy_map_t::iterator it;
|
|
|
|
for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
|
|
{
|
|
friends_scroller->addStringUUIDItem(it->first, it->second);
|
|
}
|
|
for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++)
|
|
{
|
|
friends_scroller->addStringUUIDItem(it->first, it->second);
|
|
}
|
|
friends_scroller->sortByColumnIndex(0, TRUE);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::draw()
|
|
{
|
|
// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
|
|
// lets check this via mOkButtonValidateSignal callback periodically.
|
|
static LLFrameTimer timer;
|
|
if (timer.hasExpired())
|
|
{
|
|
timer.setTimerExpirySec(0.33f); // three times per second should be enough.
|
|
|
|
// simulate list changes.
|
|
onList();
|
|
timer.start();
|
|
}
|
|
|
|
LLFloater::draw();
|
|
|
|
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e
|
|
// TODO-RLVa: this code needs revisiting
|
|
if (rlv_handler_t::isEnabled())
|
|
{
|
|
LLPanel* pNearMePanel = getChild<LLPanel>("NearMePanel");
|
|
if ( (pNearMePanel) && (childGetVisibleTab("ResidentChooserTabs") == pNearMePanel) )
|
|
{
|
|
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
|
|
{
|
|
if (mNearMeListComplete)
|
|
{
|
|
getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
|
|
childSetEnabled("Select", false);
|
|
}
|
|
mNearMeListComplete = FALSE;
|
|
pNearMePanel->setCtrlsEnabled(FALSE);
|
|
return;
|
|
}
|
|
pNearMePanel->setCtrlsEnabled(TRUE);
|
|
}
|
|
}
|
|
// [/RLVa:KB]
|
|
|
|
if (!mNearMeListComplete && getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel() == getChild<LLPanel>("NearMePanel"))
|
|
{
|
|
populateNearMe();
|
|
}
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
|
|
{
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
|
|
if(active_panel == getChild<LLPanel>("SearchPanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("SearchResults")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("NearMePanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("FriendsPanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("KeyPanel"))
|
|
{
|
|
LLUUID specified = getChild<LLLineEditor>("EditUUID")->getValue().asUUID();
|
|
return !specified.isNull();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
extern AIHTTPTimeoutPolicy avatarPickerResponder_timeout;
|
|
class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted
|
|
{
|
|
public:
|
|
LLUUID mQueryID;
|
|
|
|
LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
|
|
|
|
/*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
|
|
{
|
|
//std::ostringstream ss;
|
|
//LLSDSerialize::toPrettyXML(content, ss);
|
|
//llinfos << ss.str() << llendl;
|
|
|
|
// in case of invalid characters, the avatar picker returns a 400
|
|
// just set it to process so it displays 'not found'
|
|
if ((200 <= status && status < 300) || status == 400)
|
|
{
|
|
if (LLFloaterAvatarPicker::instanceExists())
|
|
{
|
|
LLFloaterAvatarPicker::getInstance()->processResponse(mQueryID, content);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
llinfos << "avatar picker failed " << status
|
|
<< " reason " << reason << llendl;
|
|
|
|
}
|
|
}
|
|
|
|
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return avatarPickerResponder_timeout; }
|
|
/*virtual*/ char const* getName(void) const { return "LLAvatarPickerResponder"; }
|
|
};
|
|
|
|
void LLFloaterAvatarPicker::find()
|
|
{
|
|
//clear our stored LLAvatarNames
|
|
sAvatarNameMap.clear();
|
|
|
|
std::string text = getChild<LLUICtrl>("Edit")->getValue().asString();
|
|
|
|
mQueryID.generate();
|
|
|
|
std::string url;
|
|
url.reserve(128); // avoid a memory allocation or two
|
|
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
url = region->getCapability("AvatarPickerSearch");
|
|
// Prefer use of capabilities to search on both SLID and display name
|
|
// but allow display name search to be manually turned off for test
|
|
if (!url.empty()
|
|
&& LLAvatarNameCache::useDisplayNames())
|
|
{
|
|
// capability urls don't end in '/', but we need one to parse
|
|
// query parameters correctly
|
|
if (url.size() > 0 && url[url.size()-1] != '/')
|
|
{
|
|
url += "/";
|
|
}
|
|
url += "?page_size=100&names=";
|
|
url += LLURI::escape(text);
|
|
llinfos << "avatar picker " << url << llendl;
|
|
LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
|
|
}
|
|
else
|
|
{
|
|
LLMessageSystem* msg = gMessageSystem;
|
|
msg->newMessage("AvatarPickerRequest");
|
|
msg->nextBlock("AgentData");
|
|
msg->addUUID("AgentID", gAgent.getID());
|
|
msg->addUUID("SessionID", gAgent.getSessionID());
|
|
msg->addUUID("QueryID", mQueryID); // not used right now
|
|
msg->nextBlock("Data");
|
|
msg->addString("Name", text);
|
|
gAgent.sendReliableMessage();
|
|
}
|
|
|
|
getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
|
|
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
|
|
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
mNumResultsReturned = 0;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
|
|
{
|
|
getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
|
|
getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
|
|
getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
|
|
}
|
|
|
|
LLScrollListCtrl* LLFloaterAvatarPicker::getActiveList()
|
|
{
|
|
std::string acvtive_panel_name;
|
|
LLScrollListCtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
if(active_panel)
|
|
{
|
|
acvtive_panel_name = active_panel->getName();
|
|
}
|
|
if(acvtive_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(acvtive_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (acvtive_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
return list;
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,
|
|
BOOL drop, EDragAndDropType cargo_type,
|
|
void *cargo_data, EAcceptance *accept,
|
|
std::string& tooltip_msg)
|
|
{
|
|
LLScrollListCtrl* list = getActiveList();
|
|
if(list)
|
|
{
|
|
LLRect rc_list;
|
|
LLRect rc_point(x,y,x,y);
|
|
if (localRectToOtherView(rc_point, &rc_list, list))
|
|
{
|
|
// Keep selected only one item
|
|
list->deselectAllItems(TRUE);
|
|
list->selectItemAt(rc_list.mLeft, rc_list.mBottom, mask);
|
|
LLScrollListItem* selection = list->getFirstSelected();
|
|
if (selection)
|
|
{
|
|
LLUUID session_id = LLUUID::null;
|
|
LLUUID dest_agent_id = selection->getUUID();
|
|
std::string avatar_name = selection->getColumn(0)->getValue().asString();
|
|
if (dest_agent_id.notNull() && dest_agent_id != gAgentID)
|
|
{
|
|
if (drop)
|
|
{
|
|
// Start up IM before give the item
|
|
session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, dest_agent_id);
|
|
}
|
|
return LLToolDragAndDrop::handleGiveDragAndDrop(dest_agent_id, session_id, drop,
|
|
cargo_type, cargo_data, accept);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*accept = ACCEPT_NO;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void LLFloaterAvatarPicker::openFriendsTab()
|
|
{
|
|
LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs");
|
|
if (tab_container == NULL)
|
|
{
|
|
llassert(tab_container != NULL);
|
|
return;
|
|
}
|
|
|
|
tab_container->selectTabByName("FriendsPanel");
|
|
}
|
|
|
|
// static
|
|
void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**)
|
|
{
|
|
LLUUID agent_id;
|
|
LLUUID query_id;
|
|
LLUUID avatar_id;
|
|
std::string first_name;
|
|
std::string last_name;
|
|
|
|
msg->getUUID("AgentData", "AgentID", agent_id);
|
|
msg->getUUID("AgentData", "QueryID", query_id);
|
|
|
|
// Not for us
|
|
if (agent_id != gAgent.getID()) return;
|
|
|
|
if(!instanceExists())
|
|
return;
|
|
LLFloaterAvatarPicker *floater = getInstance();
|
|
|
|
// floater is closed or these are not results from our last request
|
|
if (NULL == floater || query_id != floater->mQueryID)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LLScrollListCtrl* search_results = floater->getChild<LLScrollListCtrl>("SearchResults");
|
|
|
|
// clear "Searching" label on first results
|
|
if (floater->mNumResultsReturned++ == 0)
|
|
{
|
|
search_results->deleteAllItems();
|
|
}
|
|
|
|
BOOL found_one = FALSE;
|
|
S32 num_new_rows = msg->getNumberOfBlocks("Data");
|
|
for (S32 i = 0; i < num_new_rows; i++)
|
|
{
|
|
msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i);
|
|
msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);
|
|
msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i);
|
|
|
|
std::string avatar_name;
|
|
if (avatar_id.isNull())
|
|
{
|
|
LLStringUtil::format_map_t map;
|
|
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
|
|
avatar_name = floater->getString("not_found", map);
|
|
search_results->setEnabled(FALSE);
|
|
floater->getChildView("ok_btn")->setEnabled(FALSE);
|
|
}
|
|
else
|
|
{
|
|
avatar_name = LLCacheName::buildFullName(first_name, last_name);
|
|
search_results->setEnabled(TRUE);
|
|
found_one = TRUE;
|
|
|
|
LLAvatarName av_name;
|
|
av_name.mLegacyFirstName = first_name;
|
|
av_name.mLegacyLastName = last_name;
|
|
av_name.mDisplayName = avatar_name;
|
|
const LLUUID& agent_id = avatar_id;
|
|
sAvatarNameMap[agent_id] = av_name;
|
|
|
|
}
|
|
LLSD element;
|
|
element["id"] = avatar_id; // value
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = avatar_name;
|
|
search_results->addElement(element);
|
|
}
|
|
|
|
if (found_one)
|
|
{
|
|
floater->getChildView("ok_btn")->setEnabled(TRUE);
|
|
search_results->selectFirstItem();
|
|
floater->onList();
|
|
search_results->setFocus(TRUE);
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)
|
|
{
|
|
// Check for out-of-date query
|
|
if (query_id != mQueryID) return;
|
|
|
|
LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults");
|
|
|
|
LLSD agents = content["agents"];
|
|
if (agents.size() == 0)
|
|
{
|
|
LLStringUtil::format_map_t map;
|
|
map["[TEXT]"] = childGetText("Edit");
|
|
LLSD item;
|
|
item["id"] = LLUUID::null;
|
|
item["columns"][0]["column"] = "name";
|
|
item["columns"][0]["value"] = getString("not_found", map);
|
|
search_results->addElement(item);
|
|
search_results->setEnabled(false);
|
|
getChildView("ok_btn")->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
// clear "Searching" label on first results
|
|
search_results->deleteAllItems();
|
|
|
|
LLSD item;
|
|
LLSD::array_const_iterator it = agents.beginArray();
|
|
for ( ; it != agents.endArray(); ++it)
|
|
{
|
|
const LLSD& row = *it;
|
|
item["id"] = row["id"];
|
|
LLSD& columns = item["columns"];
|
|
columns[0]["column"] = "name";
|
|
columns[0]["value"] = row["display_name"];
|
|
columns[1]["column"] = "username";
|
|
columns[1]["value"] = row["username"];
|
|
search_results->addElement(item);
|
|
|
|
// add the avatar name to our list
|
|
LLAvatarName avatar_name;
|
|
avatar_name.fromLLSD(row);
|
|
sAvatarNameMap[row["id"].asUUID()] = avatar_name;
|
|
}
|
|
|
|
getChildView("ok_btn")->setEnabled(true);
|
|
search_results->setEnabled(true);
|
|
search_results->selectFirstItem();
|
|
onList();
|
|
search_results->setFocus(TRUE);
|
|
}
|
|
|
|
//static
|
|
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
|
|
{
|
|
LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)user_data;
|
|
if(caller->getName() == "Edit")
|
|
self->getChildView("Find")->setEnabled(caller->getText().size() >= 3);
|
|
else
|
|
self->childSetEnabled("Select", caller->getValue().asUUID().notNull());
|
|
}
|
|
|
|
// virtual
|
|
BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)
|
|
{
|
|
if (key == KEY_RETURN && mask == MASK_NONE)
|
|
{
|
|
if (getChild<LLUICtrl>("Edit")->hasFocus())
|
|
{
|
|
onBtnFind();
|
|
}
|
|
else
|
|
{
|
|
onBtnSelect();
|
|
}
|
|
return TRUE;
|
|
}
|
|
else if (key == KEY_ESCAPE && mask == MASK_NONE)
|
|
{
|
|
close();
|
|
return TRUE;
|
|
}
|
|
|
|
return LLFloater::handleKeyHere(key, mask);
|
|
}
|
|
|
|
bool LLFloaterAvatarPicker::isSelectBtnEnabled()
|
|
{
|
|
bool ret_val = visibleItemsSelected();
|
|
|
|
if ( ret_val && mOkButtonValidateSignal.num_slots() )
|
|
{
|
|
std::string active_panel_name;
|
|
LLUICtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
if(active_panel)
|
|
{
|
|
active_panel_name = active_panel->getName();
|
|
}
|
|
if(active_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(active_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (active_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
else if(active_panel_name == "KeyPanel")
|
|
{
|
|
list = getChild<LLLineEditor>("EditUUID");
|
|
}
|
|
|
|
if(list)
|
|
{
|
|
uuid_vec_t avatar_ids;
|
|
std::vector<LLAvatarName> avatar_names;
|
|
getSelectedAvatarData(list, avatar_ids, avatar_names);
|
|
return mOkButtonValidateSignal(avatar_ids);
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|