PageRenderTime 37ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

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