llfloateravatarpicker.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /**
  2. * @file llfloateravatarpicker.cpp
  3. *
  4. * $LicenseInfo:firstyear=2003&license=viewergpl$
  5. *
  6. * Copyright (c) 2003-2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #include "llviewerprecompiledheaders.h"
  32. #include "llfloateravatarpicker.h"
  33. #include "llbutton.h"
  34. #include "llcachename.h"
  35. #include "llcorehttputil.h"
  36. #include "lllineeditor.h"
  37. #include "llscrolllistctrl.h"
  38. #include "lltabcontainer.h"
  39. #include "lltextbox.h"
  40. #include "lluictrlfactory.h"
  41. #include "llmessage.h"
  42. #include "llagent.h"
  43. #include "llavatartracker.h"
  44. #include "llfolderview.h"
  45. #include "llinventorymodel.h"
  46. //MK
  47. #include "mkrlinterface.h"
  48. //mk
  49. #include "llviewercontrol.h"
  50. #include "llworld.h"
  51. // static
  52. LLFloaterAvatarPicker::instances_list_t LLFloaterAvatarPicker::sInstances;
  53. //static
  54. LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback,
  55. void* userdata,
  56. bool allow_multiple,
  57. bool close_on_select,
  58. const std::string& name)
  59. {
  60. LLFloaterAvatarPicker* self = NULL;
  61. for (instances_list_t::iterator it = sInstances.begin(),
  62. end = sInstances.end();
  63. it != end; ++it)
  64. {
  65. LLFloaterAvatarPicker* instance = *it;
  66. if (instance && instance->mCallback == callback &&
  67. instance->mCallbackUserdata == userdata)
  68. {
  69. self = instance;
  70. break;
  71. }
  72. }
  73. if (!self)
  74. {
  75. self = new LLFloaterAvatarPicker(callback, userdata);
  76. }
  77. self->open();
  78. self->setAllowMultiple(allow_multiple);
  79. self->mNearMeListComplete = false;
  80. self->mCloseOnSelect = close_on_select;
  81. // Extension to LL's avatar picker: search for an avatar name on opening,
  82. // when requested/needed. Used by the Lua PickAvatar() function. HB
  83. if (!name.empty())
  84. {
  85. self->mEdit->setValue(name);
  86. self->find();
  87. }
  88. return self;
  89. }
  90. LLFloaterAvatarPicker* LLFloaterAvatarPicker::findInstance(const LLUUID& query_id)
  91. {
  92. for (instances_list_t::iterator it = sInstances.begin(),
  93. end = sInstances.end();
  94. it != end; ++it)
  95. {
  96. LLFloaterAvatarPicker* floater = *it;
  97. if (floater && floater->mQueryID == query_id)
  98. {
  99. return floater;
  100. }
  101. }
  102. return NULL;
  103. }
  104. LLFloaterAvatarPicker::LLFloaterAvatarPicker(LLFloaterAvatarPicker::callback_t callback,
  105. void* userdata)
  106. : mCallback(callback),
  107. mCallbackUserdata(userdata)
  108. {
  109. sInstances.insert(this);
  110. LLUICtrlFactory::getInstance()->buildFloater(this,
  111. "floater_avatar_picker.xml");
  112. }
  113. LLFloaterAvatarPicker::~LLFloaterAvatarPicker()
  114. {
  115. gFocusMgr.releaseFocusIfNeeded(this);
  116. sInstances.erase(this);
  117. }
  118. bool LLFloaterAvatarPicker::postBuild()
  119. {
  120. mEdit = getChild<LLLineEditor>("Edit");
  121. mEdit->setKeystrokeCallback(editKeystroke);
  122. mEdit->setCallbackUserData(this);
  123. mEdit->setFocus(true);
  124. mFind = getChild<LLButton>("Find");
  125. mFind->setClickedCallback(onBtnFind, this);
  126. mFind->setEnabled(false);
  127. childSetAction("Refresh", onBtnRefresh, this);
  128. childSetCommitCallback("near_me_range", onRangeAdjust, this);
  129. mSelect = getChild<LLButton>("Select");
  130. mSelect->setClickedCallback(onBtnSelect, this);
  131. mSelect->setEnabled(false);
  132. childSetAction("Close", onBtnClose, this);
  133. mSearchResults = getChild<LLScrollListCtrl>("SearchResults");
  134. mSearchResults->setDoubleClickCallback(onBtnSelect);
  135. mSearchResults->setCommitCallback(onList);
  136. mSearchResults->setCallbackUserData(this);
  137. mSearchResults->setEnabled(false);
  138. mSearchResults->addCommentText(getString("no_result"));
  139. mFriends = getChild<LLScrollListCtrl>("Friends");
  140. mFriends->setDoubleClickCallback(onBtnSelect);
  141. mFriends->setCommitCallback(onList);
  142. mFriends->setCallbackUserData(this);
  143. mNearMe = getChild<LLScrollListCtrl>("NearMe");
  144. mNearMe->setDoubleClickCallback(onBtnSelect);
  145. mNearMe->setCommitCallback(onList);
  146. mNearMe->setCallbackUserData(this);
  147. mInventoryPanel = getChild<LLInventoryPanel>("InventoryPanel");
  148. mInventoryPanel->setFilterTypes(0x1 << LLInventoryType::IT_CALLINGCARD);
  149. mInventoryPanel->setFollowsAll();
  150. mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  151. mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_CALLINGCARD);
  152. mInventoryPanel->setSelectCallback(onCallingCardSelectionChange, this);
  153. mSearchPanel = getChild<LLPanel>("SearchPanel");
  154. mSearchPanel->setDefaultBtn(mFind);
  155. mFriendsPanel = getChild<LLPanel>("FriendsPanel");
  156. mCallingCardsPanel = getChild<LLPanel>("CallingCardsPanel");
  157. mNearMePanel = getChild<LLPanel>("NearMePanel");
  158. mResidentChooserTabs = getChild<LLTabContainer>("ResidentChooserTabs");
  159. mResidentChooserTabs->setTabChangeCallback(mSearchPanel, onTabChanged);
  160. mResidentChooserTabs->setTabUserData(mSearchPanel, this);
  161. mResidentChooserTabs->setTabChangeCallback(mFriendsPanel, onTabChanged);
  162. mResidentChooserTabs->setTabUserData(mFriendsPanel, this);
  163. mResidentChooserTabs->setTabChangeCallback(mCallingCardsPanel, onTabChanged);
  164. mResidentChooserTabs->setTabUserData(mCallingCardsPanel, this);
  165. mResidentChooserTabs->setTabChangeCallback(mNearMePanel, onTabChanged);
  166. mResidentChooserTabs->setTabUserData(mNearMePanel, this);
  167. setAllowMultiple(false);
  168. center();
  169. populateFriends();
  170. return true;
  171. }
  172. //virtual
  173. void LLFloaterAvatarPicker::draw()
  174. {
  175. if (!mNearMeListComplete &&
  176. mResidentChooserTabs->getCurrentPanel() == mNearMePanel)
  177. {
  178. populateNearMe();
  179. }
  180. LLFloater::draw();
  181. }
  182. //virtual
  183. bool LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)
  184. {
  185. if (key == KEY_RETURN && mask == MASK_NONE)
  186. {
  187. if (mEdit->hasFocus())
  188. {
  189. onBtnFind(this);
  190. }
  191. else
  192. {
  193. onBtnSelect(this);
  194. }
  195. return true;
  196. }
  197. else if (key == KEY_ESCAPE && mask == MASK_NONE)
  198. {
  199. close();
  200. return true;
  201. }
  202. return LLFloater::handleKeyHere(key, mask);
  203. }
  204. // Callback for inventory picker (select from calling cards)
  205. void LLFloaterAvatarPicker::doCallingCardSelectionChange(LLFolderView* folderp)
  206. {
  207. bool panel_active =
  208. mResidentChooserTabs->getCurrentPanel() == mCallingCardsPanel;
  209. mSelectedInventoryAvatarIDs.clear();
  210. mSelectedInventoryAvatarNames.clear();
  211. if (panel_active)
  212. {
  213. mSelect->setEnabled(false);
  214. }
  215. const LLFolderView::selected_items_t& items = folderp->getSelectedItems();
  216. for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(),
  217. end = items.end();
  218. it != end; ++it)
  219. {
  220. LLFolderViewEventListener* listenerp = (*it)->getListener();
  221. if (listenerp &&
  222. listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
  223. {
  224. LLInventoryItem* item = gInventory.getItem(listenerp->getUUID());
  225. if (item)
  226. {
  227. mSelectedInventoryAvatarIDs.emplace_back(item->getCreatorUUID());
  228. mSelectedInventoryAvatarNames.emplace_back(listenerp->getName());
  229. }
  230. }
  231. }
  232. if (panel_active)
  233. {
  234. mSelect->setEnabled(visibleItemsSelected());
  235. }
  236. }
  237. void LLFloaterAvatarPicker::populateNearMe()
  238. {
  239. if (!gCacheNamep)
  240. {
  241. return;
  242. }
  243. bool all_loaded = true;
  244. bool empty = true;
  245. mNearMe->deleteAllItems();
  246. //MK
  247. if (gRLenabled &&
  248. (gRLInterface.mContainsShownames ||
  249. gRLInterface.mContainsShownametags))
  250. {
  251. return;
  252. }
  253. //mk
  254. uuid_vec_t avatar_ids;
  255. gWorld.getAvatars(avatar_ids, NULL, NULL, gAgent.getPositionGlobal(),
  256. gSavedSettings.getF32("NearMeRange"));
  257. for (U32 i = 0, count = avatar_ids.size(); i < count; ++i)
  258. {
  259. LLUUID& av = avatar_ids[i];
  260. if (av == gAgentID) continue;
  261. LLSD element;
  262. element["id"] = av; // value
  263. std::string fullname;
  264. if (!gCacheNamep->getFullName(av, fullname))
  265. {
  266. element["columns"][0]["value"] = gCacheNamep->getDefaultName();
  267. all_loaded = false;
  268. }
  269. else
  270. {
  271. element["columns"][0]["value"] = fullname;
  272. }
  273. mNearMe->addElement(element);
  274. empty = false;
  275. }
  276. if (empty)
  277. {
  278. mNearMe->setEnabled(false);
  279. mSelect->setEnabled(false);
  280. mNearMe->addCommentText(getString("no_one_near"));
  281. }
  282. else
  283. {
  284. mNearMe->setEnabled(true);
  285. mSelect->setEnabled(true);
  286. mNearMe->selectFirstItem();
  287. onList(mNearMe, this);
  288. mNearMe->setFocus(true);
  289. }
  290. if (all_loaded)
  291. {
  292. mNearMeListComplete = true;
  293. }
  294. }
  295. void LLFloaterAvatarPicker::populateFriends()
  296. {
  297. mFriends->deleteAllItems();
  298. LLCollectAllBuddies collector;
  299. gAvatarTracker.applyFunctor(collector);
  300. LLCollectAllBuddies::buddy_map_t::iterator it;
  301. for (it = collector.mOnline.begin(); it != collector.mOnline.end(); ++it)
  302. {
  303. mFriends->addStringUUIDItem(it->first, it->second);
  304. }
  305. for (it = collector.mOffline.begin(); it != collector.mOffline.end(); ++it)
  306. {
  307. mFriends->addStringUUIDItem(it->first, it->second);
  308. }
  309. mFriends->sortByColumnIndex(0, true);
  310. }
  311. bool LLFloaterAvatarPicker::visibleItemsSelected() const
  312. {
  313. LLPanel* active_panel = mResidentChooserTabs->getCurrentPanel();
  314. if (active_panel == mSearchPanel)
  315. {
  316. return mSearchResults->getFirstSelectedIndex() >= 0;
  317. }
  318. if (active_panel == mFriendsPanel)
  319. {
  320. return mFriends->getFirstSelectedIndex() >= 0;
  321. }
  322. if (active_panel == mCallingCardsPanel)
  323. {
  324. return mSelectedInventoryAvatarIDs.size() > 0;
  325. }
  326. if (active_panel == mNearMePanel)
  327. {
  328. return mNearMe->getFirstSelectedIndex() >= 0;
  329. }
  330. return false;
  331. }
  332. void LLFloaterAvatarPicker::setAllowMultiple(bool allow_multiple)
  333. {
  334. mSearchResults->setAllowMultipleSelection(allow_multiple);
  335. mFriends->setAllowMultipleSelection(allow_multiple);
  336. mInventoryPanel->setAllowMultiSelect(allow_multiple);
  337. mNearMe->setAllowMultipleSelection(allow_multiple);
  338. }
  339. void LLFloaterAvatarPicker::find()
  340. {
  341. const std::string& text = mEdit->getValue().asString();
  342. mQueryID.generate();
  343. std::string url = gAgent.getRegionCapability("AvatarPickerSearch");
  344. if (!url.empty() && LLAvatarNameCache::useDisplayNames())
  345. {
  346. // Capability URLs do not always end in '/', but we need one to parse
  347. // query parameters correctly
  348. if (url.back() != '/')
  349. {
  350. url += "/";
  351. }
  352. url += "?page_size=100&names=";
  353. url += LLURI::escape(text);
  354. llinfos << "Avatar picker request: " << url << llendl;
  355. gCoros.launch("LLFloaterAvatarPicker::findCoro",
  356. boost::bind(&LLFloaterAvatarPicker::findCoro, url,
  357. mQueryID));
  358. }
  359. else
  360. {
  361. LLMessageSystem* msg = gMessageSystemp;
  362. msg->newMessage(_PREHASH_AvatarPickerRequest);
  363. msg->nextBlock(_PREHASH_AgentData);
  364. msg->addUUID(_PREHASH_AgentID, gAgentID);
  365. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  366. msg->addUUID(_PREHASH_QueryID, mQueryID);
  367. msg->nextBlock(_PREHASH_Data);
  368. msg->addString(_PREHASH_Name, text);
  369. gAgent.sendReliableMessage();
  370. }
  371. mSearchResults->deleteAllItems();
  372. mSearchResults->addCommentText(getString("searching"));
  373. mSelect->setEnabled(false);
  374. }
  375. //static
  376. void LLFloaterAvatarPicker::findCoro(const std::string& url, LLUUID query_id)
  377. {
  378. LLCoreHttpUtil::HttpCoroutineAdapter adapter("AvatarPickerSearch");
  379. LLCore::HttpOptions::ptr_t options(new LLCore::HttpOptions);
  380. options->setTimeout(180);
  381. LLSD result = adapter.getAndSuspend(url, options);
  382. LLFloaterAvatarPicker* self =
  383. LLFloaterAvatarPicker::findInstance(query_id);
  384. if (!self)
  385. {
  386. return; // Floater closed...
  387. }
  388. LLCore::HttpStatus status =
  389. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  390. // In case of invalid characters, the avatar picker returns a 400; just set
  391. // it to process so it displays 'not found'
  392. if (status || status == gStatusBadRequest)
  393. {
  394. self->processResponse(query_id, result);
  395. }
  396. else
  397. {
  398. llwarns << "Avatar picker request failed: " << status.toString()
  399. << llendl;
  400. self->mSearchResults->deleteAllItems();
  401. self->mSearchResults->addCommentText(status.toString());
  402. }
  403. }
  404. void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id,
  405. const LLSD& content)
  406. {
  407. // Check for out-of-date query
  408. if (query_id != mQueryID) return;
  409. const std::string legacy_name = getString("legacy_name");
  410. const std::string display_name = getString("display_name");
  411. std::string search_text_raw = mEdit->getValue().asString();
  412. LLSD agents = content["agents"];
  413. if (agents.size() == 0)
  414. {
  415. LLStringUtil::format_map_t map;
  416. map["[TEXT]"] = search_text_raw;
  417. LLSD element;
  418. element["id"] = LLUUID::null;
  419. element["columns"][0]["column"] = legacy_name;
  420. element["columns"][0]["value"] = getString("not_found", map);
  421. mSearchResults->addElement(element);
  422. mSearchResults->setEnabled(false);
  423. mSearchResults->setDisplayHeading(false);
  424. mSelect->setEnabled(false);
  425. return;
  426. }
  427. std::string search_text = search_text_raw;
  428. if (search_text.find(' ') == std::string::npos)
  429. {
  430. search_text += " Resident";
  431. }
  432. LLStringUtil::toLower(search_text);
  433. LLStringUtil::toLower(search_text_raw);
  434. // Clear "Searching" label on first results
  435. mSearchResults->deleteAllItems();
  436. mSearchResults->setDisplayHeading(true);
  437. std::string name;
  438. LLUUID matching_id;
  439. LLSD element;
  440. for (LLSD::array_const_iterator it = agents.beginArray(),
  441. end = agents.endArray();
  442. it != end; ++it)
  443. {
  444. const LLSD& row = *it;
  445. LLSD& columns = element["columns"];
  446. element["id"] = row["id"];
  447. name = row["legacy_first_name"].asString();
  448. name += " ";
  449. name += row["legacy_last_name"].asString();
  450. columns[0]["column"] = legacy_name;
  451. columns[0]["value"] = name;
  452. LLStringUtil::toLower(name);
  453. if (name == search_text)
  454. {
  455. columns[0]["font-style"] = "BOLD";
  456. matching_id = row["id"].asUUID();
  457. }
  458. else
  459. {
  460. columns[0]["font-style"] = "NORMAL";
  461. }
  462. columns[1]["column"] = display_name;
  463. name = row["display_name"].asString();
  464. columns[1]["value"] = name;
  465. LLStringUtil::toLower(name);
  466. if (name == search_text_raw)
  467. {
  468. columns[1]["font-style"] = "BOLD";
  469. }
  470. else
  471. {
  472. columns[1]["font-style"] = "NORMAL";
  473. }
  474. mSearchResults->addElement(element);
  475. }
  476. mSelect->setEnabled(true);
  477. mSearchResults->selectFirstItem();
  478. mSearchResults->setEnabled(true);
  479. onList(mSearchResults, this);
  480. mSearchResults->setFocus(true);
  481. if (matching_id.notNull())
  482. {
  483. mSearchResults->selectByID(matching_id);
  484. mSearchResults->scrollToShowSelected();
  485. }
  486. }
  487. //static
  488. void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg,
  489. void**)
  490. {
  491. LLUUID agent_id;
  492. msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  493. if (agent_id != gAgentID)
  494. {
  495. // Not for us
  496. return;
  497. }
  498. LLUUID query_id;
  499. msg->getUUID(_PREHASH_AgentData, _PREHASH_QueryID, query_id);
  500. LLFloaterAvatarPicker* self =
  501. LLFloaterAvatarPicker::findInstance(query_id);
  502. if (!self)
  503. {
  504. // These are not results from our last requests
  505. return;
  506. }
  507. std::string search_text = self->mEdit->getValue().asString();
  508. if (search_text.find(' ') == std::string::npos)
  509. {
  510. search_text += " Resident";
  511. }
  512. LLStringUtil::toLower(search_text);
  513. // clear "Searching" label on first results
  514. self->mSearchResults->deleteAllItems();
  515. self->mSearchResults->setDisplayHeading(false);
  516. const std::string legacy_name = self->getString("legacy_name");
  517. bool found_one = false;
  518. LLUUID avatar_id, matching_id;
  519. std::string first_name, last_name;
  520. S32 num_new_rows = msg->getNumberOfBlocks("Data");
  521. for (S32 i = 0; i < num_new_rows; ++i)
  522. {
  523. msg->getUUIDFast(_PREHASH_Data, _PREHASH_AvatarID, avatar_id, i);
  524. msg->getStringFast(_PREHASH_Data, _PREHASH_FirstName, first_name, i);
  525. msg->getStringFast(_PREHASH_Data, _PREHASH_LastName, last_name, i);
  526. std::string avatar_name;
  527. if (avatar_id.isNull())
  528. {
  529. LLStringUtil::format_map_t map;
  530. map["[TEXT]"] = self->mEdit->getValue().asString();
  531. avatar_name = self->getString("not_found", map);
  532. self->mSearchResults->setEnabled(false);
  533. self->mSelect->setEnabled(false);
  534. }
  535. else
  536. {
  537. avatar_name = first_name + " " + last_name;
  538. self->mSearchResults->setEnabled(true);
  539. found_one = true;
  540. }
  541. LLSD element;
  542. element["id"] = avatar_id; // value
  543. element["columns"][0]["column"] = legacy_name;
  544. element["columns"][0]["value"] = avatar_name;
  545. LLStringUtil::toLower(avatar_name);
  546. if (avatar_name == search_text)
  547. {
  548. element["columns"][0]["font-style"] = "BOLD";
  549. matching_id = avatar_id;
  550. }
  551. else
  552. {
  553. element["columns"][0]["font-style"] = "NORMAL";
  554. }
  555. self->mSearchResults->addElement(element);
  556. }
  557. if (found_one)
  558. {
  559. self->mSelect->setEnabled(true);
  560. self->mSearchResults->selectFirstItem();
  561. self->onList(self->mSearchResults, self);
  562. self->mSearchResults->setFocus(true);
  563. if (matching_id.notNull())
  564. {
  565. self->mSearchResults->selectByID(matching_id);
  566. self->mSearchResults->scrollToShowSelected();
  567. }
  568. }
  569. }
  570. //static
  571. void LLFloaterAvatarPicker::onTabChanged(void* userdata, bool from_click)
  572. {
  573. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  574. if (self)
  575. {
  576. self->mSelect->setEnabled(self->visibleItemsSelected());
  577. }
  578. }
  579. //static
  580. void LLFloaterAvatarPicker::onBtnFind(void* userdata)
  581. {
  582. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  583. if (self)
  584. {
  585. self->find();
  586. }
  587. }
  588. static void getSelectedAvatarData(const LLScrollListCtrl* from,
  589. std::vector<std::string>& avatar_names,
  590. uuid_vec_t& avatar_ids)
  591. {
  592. std::vector<LLScrollListItem*> items = from->getAllSelected();
  593. for (std::vector<LLScrollListItem*>::iterator iter = items.begin(),
  594. end = items.end();
  595. iter != end; ++iter)
  596. {
  597. LLScrollListItem* item = *iter;
  598. if (item->getUUID().notNull())
  599. {
  600. avatar_names.emplace_back(item->getColumn(0)->getValue().asString());
  601. avatar_ids.emplace_back(item->getUUID());
  602. }
  603. }
  604. }
  605. //static
  606. void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
  607. {
  608. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  609. if (!self) return;
  610. if (self->mCallback)
  611. {
  612. LLPanel* active_panel = self->mResidentChooserTabs->getCurrentPanel();
  613. if (active_panel == self->mSearchPanel)
  614. {
  615. std::vector<std::string> avatar_names;
  616. uuid_vec_t avatar_ids;
  617. getSelectedAvatarData(self->mSearchResults, avatar_names,
  618. avatar_ids);
  619. self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
  620. }
  621. else if (active_panel == self->mFriendsPanel)
  622. {
  623. std::vector<std::string> avatar_names;
  624. uuid_vec_t avatar_ids;
  625. getSelectedAvatarData(self->mFriends, avatar_names, avatar_ids);
  626. self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
  627. }
  628. else if (active_panel == self->mCallingCardsPanel)
  629. {
  630. self->mCallback(self->mSelectedInventoryAvatarNames,
  631. self->mSelectedInventoryAvatarIDs,
  632. self->mCallbackUserdata);
  633. }
  634. else if (active_panel == self->mNearMePanel)
  635. {
  636. std::vector<std::string> avatar_names;
  637. uuid_vec_t avatar_ids;
  638. getSelectedAvatarData(self->mNearMe, avatar_names, avatar_ids);
  639. self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
  640. }
  641. else
  642. {
  643. llwarns << "Unknown active panel !" << llendl;
  644. }
  645. }
  646. self->mSearchResults->deselectAllItems(true);
  647. self->mFriends->deselectAllItems(true);
  648. self->mInventoryPanel->setSelection(LLUUID::null, false);
  649. self->mNearMe->deselectAllItems(true);
  650. if (self->mCloseOnSelect)
  651. {
  652. self->mCloseOnSelect = false;
  653. self->close();
  654. }
  655. }
  656. //static
  657. void LLFloaterAvatarPicker::onBtnRefresh(void* userdata)
  658. {
  659. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  660. if (self)
  661. {
  662. self->mNearMe->deleteAllItems();
  663. self->mNearMe->addCommentText(self->getString("searching"));
  664. self->mNearMeListComplete = false;
  665. }
  666. }
  667. //static
  668. void LLFloaterAvatarPicker::onBtnClose(void* userdata)
  669. {
  670. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  671. if (self)
  672. {
  673. self->close();
  674. }
  675. }
  676. void LLFloaterAvatarPicker::onRangeAdjust(LLUICtrl* source, void* data)
  677. {
  678. LLFloaterAvatarPicker::onBtnRefresh(data);
  679. }
  680. //static
  681. void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata)
  682. {
  683. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
  684. if (self)
  685. {
  686. self->mSelect->setEnabled(self->visibleItemsSelected());
  687. }
  688. }
  689. //static
  690. void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller,
  691. void* user_data)
  692. {
  693. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)user_data;
  694. if (self)
  695. {
  696. self->mFind->setEnabled(caller->getText().size() >= 3);
  697. }
  698. }
  699. // Callback for inventory picker (select from calling cards)
  700. //static
  701. void LLFloaterAvatarPicker::onCallingCardSelectionChange(LLFolderView* folderp,
  702. bool user_action,
  703. void* user_data)
  704. {
  705. LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)user_data;
  706. if (self && folderp)
  707. {
  708. self->doCallingCardSelectionChange(folderp);
  709. }
  710. }