PageRenderTime 111ms CodeModel.GetById 15ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llfloateravatarpicker.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 738 lines | 580 code | 98 blank | 60 comment | 108 complexity | a4c284471b4bb6c5a17a709b7bfc3305 MD5 | raw file
  1/** 
  2 * @file llfloateravatarpicker.cpp
  3 *
  4 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#include "llviewerprecompiledheaders.h"
 27
 28#include "llfloateravatarpicker.h"
 29
 30// Viewer includes
 31#include "llagent.h"
 32#include "llcallingcard.h"
 33#include "llfocusmgr.h"
 34#include "llfloaterreg.h"
 35#include "llimview.h"			// for gIMMgr
 36#include "lltooldraganddrop.h"	// for LLToolDragAndDrop
 37#include "llviewercontrol.h"
 38#include "llviewerregion.h"		// getCapability()
 39#include "llworld.h"
 40
 41// Linden libraries
 42#include "llavatarnamecache.h"	// IDEVO
 43#include "llbutton.h"
 44#include "llcachename.h"
 45#include "llhttpclient.h"		// IDEVO
 46#include "lllineeditor.h"
 47#include "llscrolllistctrl.h"
 48#include "llscrolllistitem.h"
 49#include "llscrolllistcell.h"
 50#include "lltabcontainer.h"
 51#include "lluictrlfactory.h"
 52#include "message.h"
 53
 54//#include "llsdserialize.h"
 55
 56//put it back as a member once the legacy path is out?
 57static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
 58
 59LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
 60												   BOOL allow_multiple,
 61												   BOOL closeOnSelect)
 62{
 63	// *TODO: Use a key to allow this not to be an effective singleton
 64	LLFloaterAvatarPicker* floater = 
 65		LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
 66	
 67	floater->mSelectionCallback = callback;
 68	floater->setAllowMultiple(allow_multiple);
 69	floater->mNearMeListComplete = FALSE;
 70	floater->mCloseOnSelect = closeOnSelect;
 71	
 72	if (!closeOnSelect)
 73	{
 74		// Use Select/Close
 75		std::string select_string = floater->getString("Select");
 76		std::string close_string = floater->getString("Close");
 77		floater->getChild<LLButton>("ok_btn")->setLabel(select_string);
 78		floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
 79	}
 80
 81	return floater;
 82}
 83
 84// Default constructor
 85LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
 86  : LLFloater(key),
 87	mNumResultsReturned(0),
 88	mNearMeListComplete(FALSE),
 89	mCloseOnSelect(FALSE)
 90{
 91	mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
 92}
 93
 94BOOL LLFloaterAvatarPicker::postBuild()
 95{
 96	getChild<LLLineEditor>("Edit")->setKeystrokeCallback( boost::bind(&LLFloaterAvatarPicker::editKeystroke, this, _1, _2),NULL);
 97
 98	childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this));
 99	getChildView("Find")->setEnabled(FALSE);
100	childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this));
101	getChild<LLUICtrl>("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this));
102	
103	LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>("SearchResults");
104	searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
105	searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
106	getChildView("SearchResults")->setEnabled(FALSE);
107	
108	LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
109	nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
110	nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
111
112	LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
113	friends->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
114	getChild<LLUICtrl>("Friends")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
115
116	childSetAction("ok_btn", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
117	getChildView("ok_btn")->setEnabled(FALSE);
118	childSetAction("cancel_btn", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this));
119
120	getChild<LLUICtrl>("Edit")->setFocus(TRUE);
121
122	LLPanel* search_panel = getChild<LLPanel>("SearchPanel");
123	if (search_panel)
124	{
125		// Start searching when Return is pressed in the line editor.
126		search_panel->setDefaultBtn("Find");
127	}
128
129	getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("no_results"));
130
131	getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(
132		boost::bind(&LLFloaterAvatarPicker::onTabChanged, this));
133	
134	setAllowMultiple(FALSE);
135	
136	center();
137	
138	populateFriend();
139
140	return TRUE;
141}
142
143void LLFloaterAvatarPicker::setOkBtnEnableCb(validate_callback_t cb)
144{
145	mOkButtonValidateSignal.connect(cb);
146}
147
148void LLFloaterAvatarPicker::onTabChanged()
149{
150	getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
151}
152
153// Destroys the object
154LLFloaterAvatarPicker::~LLFloaterAvatarPicker()
155{
156	gFocusMgr.releaseFocusIfNeeded( this );
157}
158
159void LLFloaterAvatarPicker::onBtnFind()
160{
161	find();
162}
163
164static void getSelectedAvatarData(const LLScrollListCtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
165{
166	std::vector<LLScrollListItem*> items = from->getAllSelected();
167	for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
168	{
169		LLScrollListItem* item = *iter;
170		if (item->getUUID().notNull())
171		{
172			avatar_ids.push_back(item->getUUID());
173
174			std::map<LLUUID, LLAvatarName>::iterator iter = sAvatarNameMap.find(item->getUUID());
175			if (iter != sAvatarNameMap.end())
176			{
177				avatar_names.push_back(iter->second);
178			}
179			else
180			{
181				// the only case where it isn't in the name map is friends
182				// but it should be in the name cache
183				LLAvatarName av_name;
184				LLAvatarNameCache::get(item->getUUID(), &av_name);
185				avatar_names.push_back(av_name);
186			}
187		}
188	}
189}
190
191void LLFloaterAvatarPicker::onBtnSelect()
192{
193
194	// If select btn not enabled then do not callback
195	if (!isSelectBtnEnabled())
196		return;
197
198	if(mSelectionCallback)
199	{
200		std::string acvtive_panel_name;
201		LLScrollListCtrl* list =  NULL;
202		LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
203		if(active_panel)
204		{
205			acvtive_panel_name = active_panel->getName();
206		}
207		if(acvtive_panel_name == "SearchPanel")
208		{
209			list = getChild<LLScrollListCtrl>("SearchResults");
210		}
211		else if(acvtive_panel_name == "NearMePanel")
212		{
213			list = getChild<LLScrollListCtrl>("NearMe");
214		}
215		else if (acvtive_panel_name == "FriendsPanel")
216		{
217			list = getChild<LLScrollListCtrl>("Friends");
218		}
219
220		if(list)
221		{
222			uuid_vec_t			avatar_ids;
223			std::vector<LLAvatarName>	avatar_names;
224			getSelectedAvatarData(list, avatar_ids, avatar_names);
225			mSelectionCallback(avatar_ids, avatar_names);
226		}
227	}
228	getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
229	getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
230	getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
231	if(mCloseOnSelect)
232	{
233		mCloseOnSelect = FALSE;
234		closeFloater();		
235	}
236}
237
238void LLFloaterAvatarPicker::onBtnRefresh()
239{
240	getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
241	getChild<LLScrollListCtrl>("NearMe")->setCommentText(getString("searching"));
242	mNearMeListComplete = FALSE;
243}
244
245void LLFloaterAvatarPicker::onBtnClose()
246{
247	closeFloater();
248}
249
250void LLFloaterAvatarPicker::onRangeAdjust()
251{
252	onBtnRefresh();
253}
254
255void LLFloaterAvatarPicker::onList()
256{
257	getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
258}
259
260void LLFloaterAvatarPicker::populateNearMe()
261{
262	BOOL all_loaded = TRUE;
263	BOOL empty = TRUE;
264	LLScrollListCtrl* near_me_scroller = getChild<LLScrollListCtrl>("NearMe");
265	near_me_scroller->deleteAllItems();
266
267	uuid_vec_t avatar_ids;
268	LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
269	for(U32 i=0; i<avatar_ids.size(); i++)
270	{
271		LLUUID& av = avatar_ids[i];
272		if(av == gAgent.getID()) continue;
273		LLSD element;
274		element["id"] = av; // value
275		LLAvatarName av_name;
276
277		if (!LLAvatarNameCache::get(av, &av_name))
278		{
279			element["columns"][0]["column"] = "name";
280			element["columns"][0]["value"] = LLCacheName::getDefaultName();
281			all_loaded = FALSE;
282		}			
283		else
284		{
285			element["columns"][0]["column"] = "name";
286			element["columns"][0]["value"] = av_name.mDisplayName;
287			element["columns"][1]["column"] = "username";
288			element["columns"][1]["value"] = av_name.mUsername;
289
290			sAvatarNameMap[av] = av_name;
291		}
292		near_me_scroller->addElement(element);
293		empty = FALSE;
294	}
295
296	if (empty)
297	{
298		getChildView("NearMe")->setEnabled(FALSE);
299		getChildView("ok_btn")->setEnabled(FALSE);
300		near_me_scroller->setCommentText(getString("no_one_near"));
301	}
302	else 
303	{
304		getChildView("NearMe")->setEnabled(TRUE);
305		getChildView("ok_btn")->setEnabled(TRUE);
306		near_me_scroller->selectFirstItem();
307		onList();
308		near_me_scroller->setFocus(TRUE);
309	}
310
311	if (all_loaded)
312	{
313		mNearMeListComplete = TRUE;
314	}
315}
316
317void LLFloaterAvatarPicker::populateFriend()
318{
319	LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends");
320	friends_scroller->deleteAllItems();
321	LLCollectAllBuddies collector;
322	LLAvatarTracker::instance().applyFunctor(collector);
323	LLCollectAllBuddies::buddy_map_t::iterator it;
324	
325	for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
326	{
327		friends_scroller->addStringUUIDItem(it->first, it->second);
328	}
329	for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++)
330	{
331			friends_scroller->addStringUUIDItem(it->first, it->second);
332	}
333	friends_scroller->sortByColumnIndex(0, TRUE);
334}
335
336void LLFloaterAvatarPicker::draw()
337{
338	// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
339	// lets check this via mOkButtonValidateSignal callback periodically.
340	static LLFrameTimer timer;
341	if (timer.hasExpired())
342	{
343		timer.setTimerExpirySec(0.33f); // three times per second should be enough.
344
345		// simulate list changes.
346		onList();
347		timer.start();
348	}
349
350	LLFloater::draw();
351	if (!mNearMeListComplete && getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel() == getChild<LLPanel>("NearMePanel"))
352	{
353		populateNearMe();
354	}
355}
356
357BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
358{
359	LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
360
361	if(active_panel == getChild<LLPanel>("SearchPanel"))
362	{
363		return getChild<LLScrollListCtrl>("SearchResults")->getFirstSelectedIndex() >= 0;
364	}
365	else if(active_panel == getChild<LLPanel>("NearMePanel"))
366	{
367		return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
368	}
369	else if(active_panel == getChild<LLPanel>("FriendsPanel"))
370	{
371		return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
372	}
373	return FALSE;
374}
375
376class LLAvatarPickerResponder : public LLHTTPClient::Responder
377{
378public:
379	LLUUID mQueryID;
380
381	LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
382
383	/*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
384	{
385		//std::ostringstream ss;
386		//LLSDSerialize::toPrettyXML(content, ss);
387		//llinfos << ss.str() << llendl;
388
389		// in case of invalid characters, the avatar picker returns a 400
390		// just set it to process so it displays 'not found'
391		if (isGoodStatus(status) || status == 400)
392		{
393			LLFloaterAvatarPicker* floater =
394				LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
395			if (floater)
396			{
397				floater->processResponse(mQueryID, content);
398			}
399		}
400		else
401		{
402			llinfos << "avatar picker failed " << status
403					<< " reason " << reason << llendl;
404			
405		}
406	}
407};
408
409void LLFloaterAvatarPicker::find()
410{
411	//clear our stored LLAvatarNames
412	sAvatarNameMap.clear();
413
414	std::string text = getChild<LLUICtrl>("Edit")->getValue().asString();
415
416	mQueryID.generate();
417
418	std::string url;
419	url.reserve(128); // avoid a memory allocation or two
420
421	LLViewerRegion* region = gAgent.getRegion();
422	url = region->getCapability("AvatarPickerSearch");
423	// Prefer use of capabilities to search on both SLID and display name
424	// but allow display name search to be manually turned off for test
425	if (!url.empty()
426		&& LLAvatarNameCache::useDisplayNames())
427	{
428		// capability urls don't end in '/', but we need one to parse
429		// query parameters correctly
430		if (url.size() > 0 && url[url.size()-1] != '/')
431		{
432			url += "/";
433		}
434		url += "?page_size=100&names=";
435		url += LLURI::escape(text);
436		llinfos << "avatar picker " << url << llendl;
437		LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
438	}
439	else
440	{
441		LLMessageSystem* msg = gMessageSystem;
442		msg->newMessage("AvatarPickerRequest");
443		msg->nextBlock("AgentData");
444		msg->addUUID("AgentID", gAgent.getID());
445		msg->addUUID("SessionID", gAgent.getSessionID());
446		msg->addUUID("QueryID", mQueryID);	// not used right now
447		msg->nextBlock("Data");
448		msg->addString("Name", text);
449		gAgent.sendReliableMessage();
450	}
451
452	getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
453	getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
454	
455	getChildView("ok_btn")->setEnabled(FALSE);
456	mNumResultsReturned = 0;
457}
458
459void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
460{
461	getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
462	getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
463	getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
464}
465
466LLScrollListCtrl* LLFloaterAvatarPicker::getActiveList()
467{
468	std::string acvtive_panel_name;
469	LLScrollListCtrl* list = NULL;
470	LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
471	if(active_panel)
472	{
473		acvtive_panel_name = active_panel->getName();
474	}
475	if(acvtive_panel_name == "SearchPanel")
476	{
477		list = getChild<LLScrollListCtrl>("SearchResults");
478	}
479	else if(acvtive_panel_name == "NearMePanel")
480	{
481		list = getChild<LLScrollListCtrl>("NearMe");
482	}
483	else if (acvtive_panel_name == "FriendsPanel")
484	{
485		list = getChild<LLScrollListCtrl>("Friends");
486	}
487	return list;
488}
489
490BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,
491											  BOOL drop, EDragAndDropType cargo_type,
492											  void *cargo_data, EAcceptance *accept,
493											  std::string& tooltip_msg)
494{
495	LLScrollListCtrl* list = getActiveList();
496	if(list)
497	{
498		LLRect rc_list;
499		LLRect rc_point(x,y,x,y);
500		if (localRectToOtherView(rc_point, &rc_list, list))
501		{
502			// Keep selected only one item
503			list->deselectAllItems(TRUE);
504			list->selectItemAt(rc_list.mLeft, rc_list.mBottom, mask);
505			LLScrollListItem* selection = list->getFirstSelected();
506			if (selection)
507			{
508				LLUUID session_id = LLUUID::null;
509				LLUUID dest_agent_id = selection->getUUID();
510				std::string avatar_name = selection->getColumn(0)->getValue().asString();
511				if (dest_agent_id.notNull() && dest_agent_id != gAgentID)
512				{
513					if (drop)
514					{
515						// Start up IM before give the item
516						session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, dest_agent_id);
517					}
518					return LLToolDragAndDrop::handleGiveDragAndDrop(dest_agent_id, session_id, drop,
519																	cargo_type, cargo_data, accept, getName());
520				}
521			}
522		}
523	}
524	*accept = ACCEPT_NO;
525	return TRUE;
526}
527
528
529void LLFloaterAvatarPicker::openFriendsTab()
530{
531	LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs");
532	if (tab_container == NULL)
533	{
534		llassert(tab_container != NULL);
535		return;
536	}
537
538	tab_container->selectTabByName("FriendsPanel");
539}
540
541// static 
542void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**)
543{
544	LLUUID	agent_id;
545	LLUUID	query_id;
546	LLUUID	avatar_id;
547	std::string first_name;
548	std::string last_name;
549
550	msg->getUUID("AgentData", "AgentID", agent_id);
551	msg->getUUID("AgentData", "QueryID", query_id);
552
553	// Not for us
554	if (agent_id != gAgent.getID()) return;
555	
556	LLFloaterAvatarPicker* floater = LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
557
558	// floater is closed or these are not results from our last request
559	if (NULL == floater || query_id != floater->mQueryID)
560	{
561		return;
562	}
563
564	LLScrollListCtrl* search_results = floater->getChild<LLScrollListCtrl>("SearchResults");
565
566	// clear "Searching" label on first results
567	if (floater->mNumResultsReturned++ == 0)
568	{
569		search_results->deleteAllItems();
570	}
571
572	BOOL found_one = FALSE;
573	S32 num_new_rows = msg->getNumberOfBlocks("Data");
574	for (S32 i = 0; i < num_new_rows; i++)
575	{			
576		msg->getUUIDFast(  _PREHASH_Data,_PREHASH_AvatarID,	avatar_id, i);
577		msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);
578		msg->getStringFast(_PREHASH_Data,_PREHASH_LastName,	last_name, i);
579	
580		std::string avatar_name;
581		if (avatar_id.isNull())
582		{
583			LLStringUtil::format_map_t map;
584			map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
585			avatar_name = floater->getString("not_found", map);
586			search_results->setEnabled(FALSE);
587			floater->getChildView("ok_btn")->setEnabled(FALSE);
588		}
589		else
590		{
591			avatar_name = LLCacheName::buildFullName(first_name, last_name);
592			search_results->setEnabled(TRUE);
593			found_one = TRUE;
594
595			LLAvatarName av_name;
596			av_name.mLegacyFirstName = first_name;
597			av_name.mLegacyLastName = last_name;
598			av_name.mDisplayName = avatar_name;
599			const LLUUID& agent_id = avatar_id;
600			sAvatarNameMap[agent_id] = av_name;
601
602		}
603		LLSD element;
604		element["id"] = avatar_id; // value
605		element["columns"][0]["column"] = "name";
606		element["columns"][0]["value"] = avatar_name;
607		search_results->addElement(element);
608	}
609
610	if (found_one)
611	{
612		floater->getChildView("ok_btn")->setEnabled(TRUE);
613		search_results->selectFirstItem();
614		floater->onList();
615		search_results->setFocus(TRUE);
616	}
617}
618
619void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)
620{
621	// Check for out-of-date query
622	if (query_id != mQueryID) return;
623
624	LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults");
625
626	LLSD agents = content["agents"];
627	if (agents.size() == 0)
628	{
629		LLStringUtil::format_map_t map;
630		map["[TEXT]"] = childGetText("Edit");
631		LLSD item;
632		item["id"] = LLUUID::null;
633		item["columns"][0]["column"] = "name";
634		item["columns"][0]["value"] = getString("not_found", map);
635		search_results->addElement(item);
636		search_results->setEnabled(false);
637		getChildView("ok_btn")->setEnabled(false);
638		return;
639	}
640
641	// clear "Searching" label on first results
642	search_results->deleteAllItems();
643
644	LLSD item;
645	LLSD::array_const_iterator it = agents.beginArray();
646	for ( ; it != agents.endArray(); ++it)
647	{
648		const LLSD& row = *it;
649		item["id"] = row["id"];
650		LLSD& columns = item["columns"];
651		columns[0]["column"] = "name";
652		columns[0]["value"] = row["display_name"];
653		columns[1]["column"] = "username";
654		columns[1]["value"] = row["username"];
655		search_results->addElement(item);
656
657		// add the avatar name to our list
658		LLAvatarName avatar_name;
659		avatar_name.fromLLSD(row);
660		sAvatarNameMap[row["id"].asUUID()] = avatar_name;
661	}
662
663	getChildView("ok_btn")->setEnabled(true);
664	search_results->setEnabled(true);
665	search_results->selectFirstItem();
666	onList();
667	search_results->setFocus(TRUE);
668}
669
670//static
671void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
672{
673	getChildView("Find")->setEnabled(caller->getText().size() > 0);
674}
675
676// virtual
677BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)
678{
679	if (key == KEY_RETURN && mask == MASK_NONE)
680	{
681		if (getChild<LLUICtrl>("Edit")->hasFocus())
682		{
683			onBtnFind();
684		}
685		else
686		{
687			onBtnSelect();
688		}
689		return TRUE;
690	}
691	else if (key == KEY_ESCAPE && mask == MASK_NONE)
692	{
693		closeFloater();
694		return TRUE;
695	}
696
697	return LLFloater::handleKeyHere(key, mask);
698}
699
700bool LLFloaterAvatarPicker::isSelectBtnEnabled()
701{
702	bool ret_val = visibleItemsSelected();
703
704	if ( ret_val && mOkButtonValidateSignal.num_slots() )
705	{
706		std::string acvtive_panel_name;
707		LLScrollListCtrl* list =  NULL;
708		LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
709
710		if(active_panel)
711		{
712			acvtive_panel_name = active_panel->getName();
713		}
714
715		if(acvtive_panel_name == "SearchPanel")
716		{
717			list = getChild<LLScrollListCtrl>("SearchResults");
718		}
719		else if(acvtive_panel_name == "NearMePanel")
720		{
721			list = getChild<LLScrollListCtrl>("NearMe");
722		}
723		else if (acvtive_panel_name == "FriendsPanel")
724		{
725			list = getChild<LLScrollListCtrl>("Friends");
726		}
727
728		if(list)
729		{
730			uuid_vec_t avatar_ids;
731			std::vector<LLAvatarName> avatar_names;
732			getSelectedAvatarData(list, avatar_ids, avatar_names);
733			return mOkButtonValidateSignal(avatar_ids);
734		}
735	}
736
737	return ret_val;
738}