llpanelpeople.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:44k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpanelpeople.cpp
  3.  * @brief Side tray "People" panel
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. // libs
  34. #include "llfloaterreg.h"
  35. #include "llmenugl.h"
  36. #include "llnotificationsutil.h"
  37. #include "lleventtimer.h"
  38. #include "llfiltereditor.h"
  39. #include "lltabcontainer.h"
  40. #include "lluictrlfactory.h"
  41. #include "llpanelpeople.h"
  42. // newview
  43. #include "llaccordionctrl.h"
  44. #include "llaccordionctrltab.h"
  45. #include "llagent.h"
  46. #include "llavataractions.h"
  47. #include "llavatarlist.h"
  48. #include "llavatarlistitem.h"
  49. #include "llcallingcard.h" // for LLAvatarTracker
  50. #include "llfloateravatarpicker.h"
  51. //#include "llfloaterminiinspector.h"
  52. #include "llfriendcard.h"
  53. #include "llgroupactions.h"
  54. #include "llgrouplist.h"
  55. #include "llinventoryobserver.h"
  56. #include "llpanelpeoplemenus.h"
  57. #include "llsidetray.h"
  58. #include "llsidetraypanelcontainer.h"
  59. #include "llrecentpeople.h"
  60. #include "llviewercontrol.h" // for gSavedSettings
  61. #include "llviewermenu.h" // for gMenuHolder
  62. #include "llvoiceclient.h"
  63. #include "llworld.h"
  64. #include "llspeakers.h"
  65. #define FRIEND_LIST_UPDATE_TIMEOUT 0.5
  66. #define NEARBY_LIST_UPDATE_INTERVAL 1
  67. static const std::string NEARBY_TAB_NAME = "nearby_panel";
  68. static const std::string FRIENDS_TAB_NAME = "friends_panel";
  69. static const std::string GROUP_TAB_NAME = "groups_panel";
  70. static const std::string RECENT_TAB_NAME = "recent_panel";
  71. static const std::string COLLAPSED_BY_USER  = "collapsed_by_user";
  72. /** Comparator for comparing avatar items by last interaction date */
  73. class LLAvatarItemRecentComparator : public LLAvatarItemComparator
  74. {
  75. public:
  76. LLAvatarItemRecentComparator() {};
  77. virtual ~LLAvatarItemRecentComparator() {};
  78. protected:
  79. virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
  80. {
  81. LLRecentPeople& people = LLRecentPeople::instance();
  82. const LLDate& date1 = people.getDate(avatar_item1->getAvatarId());
  83. const LLDate& date2 = people.getDate(avatar_item2->getAvatarId());
  84. //older comes first
  85. return date1 > date2;
  86. }
  87. };
  88. /** Compares avatar items by online status, then by name */
  89. class LLAvatarItemStatusComparator : public LLAvatarItemComparator
  90. {
  91. public:
  92. LLAvatarItemStatusComparator() {};
  93. protected:
  94. /**
  95.  * @return true if item1 < item2, false otherwise
  96.  */
  97. virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
  98. {
  99. LLAvatarTracker& at = LLAvatarTracker::instance();
  100. bool online1 = at.isBuddyOnline(item1->getAvatarId());
  101. bool online2 = at.isBuddyOnline(item2->getAvatarId());
  102. if (online1 == online2)
  103. {
  104. std::string name1 = item1->getAvatarName();
  105. std::string name2 = item2->getAvatarName();
  106. LLStringUtil::toUpper(name1);
  107. LLStringUtil::toUpper(name2);
  108. return name1 < name2;
  109. }
  110. return online1 > online2; 
  111. }
  112. };
  113. /** Compares avatar items by distance between you and them */
  114. class LLAvatarItemDistanceComparator : public LLAvatarItemComparator
  115. {
  116. public:
  117. typedef std::map < LLUUID, LLVector3d > id_to_pos_map_t;
  118. LLAvatarItemDistanceComparator() {};
  119. void updateAvatarsPositions(std::vector<LLVector3d>& positions, std::vector<LLUUID>& uuids)
  120. {
  121. std::vector<LLVector3d>::const_iterator
  122. pos_it = positions.begin(),
  123. pos_end = positions.end();
  124. std::vector<LLUUID>::const_iterator
  125. id_it = uuids.begin(),
  126. id_end = uuids.end();
  127. LLAvatarItemDistanceComparator::id_to_pos_map_t pos_map;
  128. mAvatarsPositions.clear();
  129. for (;pos_it != pos_end && id_it != id_end; ++pos_it, ++id_it )
  130. {
  131. mAvatarsPositions[*id_it] = *pos_it;
  132. }
  133. };
  134. protected:
  135. virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
  136. {
  137. const LLVector3d& me_pos = gAgent.getPositionGlobal();
  138. const LLVector3d& item1_pos = mAvatarsPositions.find(item1->getAvatarId())->second;
  139. const LLVector3d& item2_pos = mAvatarsPositions.find(item2->getAvatarId())->second;
  140. F32 dist1 = dist_vec(item1_pos, me_pos);
  141. F32 dist2 = dist_vec(item2_pos, me_pos);
  142. return dist1 < dist2;
  143. }
  144. private:
  145. id_to_pos_map_t mAvatarsPositions;
  146. };
  147. /** Comparator for comparing nearby avatar items by last spoken time */
  148. class LLAvatarItemRecentSpeakerComparator : public  LLAvatarItemNameComparator
  149. {
  150. public:
  151. LLAvatarItemRecentSpeakerComparator() {};
  152. virtual ~LLAvatarItemRecentSpeakerComparator() {};
  153. protected:
  154. virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
  155. {
  156. LLPointer<LLSpeaker> lhs = LLLocalSpeakerMgr::instance().findSpeaker(item1->getAvatarId());
  157. LLPointer<LLSpeaker> rhs = LLLocalSpeakerMgr::instance().findSpeaker(item2->getAvatarId());
  158. if ( lhs.notNull() && rhs.notNull() )
  159. {
  160. // Compare by last speaking time
  161. if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
  162. return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
  163. }
  164. else if ( lhs.notNull() )
  165. {
  166. // True if only item1 speaker info available
  167. return true;
  168. }
  169. else if ( rhs.notNull() )
  170. {
  171. // False if only item2 speaker info available
  172. return false;
  173. }
  174. // By default compare by name.
  175. return LLAvatarItemNameComparator::doCompare(item1, item2);
  176. }
  177. };
  178. static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
  179. static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
  180. static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR;
  181. static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR;
  182. static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people");
  183. //=============================================================================
  184. /**
  185.  * Updates given list either on regular basis or on external events (up to implementation). 
  186.  */
  187. class LLPanelPeople::Updater
  188. {
  189. public:
  190. typedef boost::function<void()> callback_t;
  191. Updater(callback_t cb)
  192. : mCallback(cb)
  193. {
  194. }
  195. virtual ~Updater()
  196. {
  197. }
  198. /**
  199.  * Activate/deactivate updater.
  200.  *
  201.  * This may start/stop regular updates.
  202.  */
  203. virtual void setActive(bool) {}
  204. protected:
  205. void updateList()
  206. {
  207. mCallback();
  208. }
  209. callback_t mCallback;
  210. };
  211. class LLAvatarListUpdater : public LLPanelPeople::Updater, public LLEventTimer
  212. {
  213. public:
  214. LLAvatarListUpdater(callback_t cb, F32 period)
  215. : LLEventTimer(period),
  216. LLPanelPeople::Updater(cb)
  217. {
  218. mEventTimer.stop();
  219. }
  220. virtual BOOL tick() // from LLEventTimer
  221. {
  222. return FALSE;
  223. }
  224. };
  225. /**
  226.  * Updates the friends list.
  227.  * 
  228.  * Updates the list on external events which trigger the changed() method. 
  229.  */
  230. class LLFriendListUpdater : public LLAvatarListUpdater, public LLFriendObserver
  231. {
  232. LOG_CLASS(LLFriendListUpdater);
  233. class LLInventoryFriendCardObserver;
  234. public: 
  235. friend class LLInventoryFriendCardObserver;
  236. LLFriendListUpdater(callback_t cb)
  237. : LLAvatarListUpdater(cb, FRIEND_LIST_UPDATE_TIMEOUT)
  238. {
  239. LLAvatarTracker::instance().addObserver(this);
  240. // For notification when SIP online status changes.
  241. LLVoiceClient::getInstance()->addObserver(this);
  242. mInvObserver = new LLInventoryFriendCardObserver(this);
  243. }
  244. ~LLFriendListUpdater()
  245. {
  246. // will be deleted by ~LLInventoryModel
  247. //delete mInvObserver;
  248. LLVoiceClient::getInstance()->removeObserver(this);
  249. LLAvatarTracker::instance().removeObserver(this);
  250. }
  251. /*virtual*/ void changed(U32 mask)
  252. {
  253. // events can arrive quickly in bulk - we need not process EVERY one of them -
  254. // so we wait a short while to let others pile-in, and process them in aggregate.
  255. mEventTimer.start();
  256. // save-up all the mask-bits which have come-in
  257. mMask |= mask;
  258. }
  259. /*virtual*/ BOOL tick()
  260. {
  261. if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
  262. updateList();
  263. // Stop updates.
  264. mEventTimer.stop();
  265. mMask = 0;
  266. return FALSE;
  267. }
  268. private:
  269. U32 mMask;
  270. LLInventoryFriendCardObserver* mInvObserver;
  271. /**
  272.  * This class is intended for updating Friend List when Inventory Friend Card is added/removed.
  273.  * 
  274.  * The main usage is when Inventory Friends/All content is added while synchronizing with 
  275.  * friends list on startup is performed. In this case Friend Panel should be updated when 
  276.  * missing Inventory Friend Card is created.
  277.  * *NOTE: updating is fired when Inventory item is added into CallingCards/Friends subfolder.
  278.  * Otherwise LLFriendObserver functionality is enough to keep Friends Panel synchronized.
  279.  */
  280. class LLInventoryFriendCardObserver : public LLInventoryObserver
  281. {
  282. LOG_CLASS(LLFriendListUpdater::LLInventoryFriendCardObserver);
  283. friend class LLFriendListUpdater;
  284. private:
  285. LLInventoryFriendCardObserver(LLFriendListUpdater* updater) : mUpdater(updater)
  286. {
  287. gInventory.addObserver(this);
  288. }
  289. ~LLInventoryFriendCardObserver()
  290. {
  291. gInventory.removeObserver(this);
  292. }
  293. /*virtual*/ void changed(U32 mask)
  294. {
  295. lldebugs << "Inventory changed: " << mask << llendl;
  296. // *NOTE: deleting of InventoryItem is performed via moving to Trash. 
  297. // That means LLInventoryObserver::STRUCTURE is present in MASK instead of LLInventoryObserver::REMOVE
  298. if ((CALLINGCARD_ADDED & mask) == CALLINGCARD_ADDED)
  299. {
  300. lldebugs << "Calling card added: count: " << gInventory.getChangedIDs().size() 
  301. << ", first Inventory ID: "<< (*gInventory.getChangedIDs().begin())
  302. << llendl;
  303. bool friendFound = false;
  304. std::set<LLUUID> changedIDs = gInventory.getChangedIDs();
  305. for (std::set<LLUUID>::const_iterator it = changedIDs.begin(); it != changedIDs.end(); ++it)
  306. {
  307. if (isDescendentOfInventoryFriends(*it))
  308. {
  309. friendFound = true;
  310. break;
  311. }
  312. }
  313. if (friendFound)
  314. {
  315. lldebugs << "friend found, panel should be updated" << llendl;
  316. mUpdater->changed(LLFriendObserver::ADD);
  317. }
  318. }
  319. }
  320. bool isDescendentOfInventoryFriends(const LLUUID& invItemID)
  321. {
  322. LLViewerInventoryItem * item = gInventory.getItem(invItemID);
  323. if (NULL == item)
  324. return false;
  325. return LLFriendCardsManager::instance().isItemInAnyFriendsList(item);
  326. }
  327. LLFriendListUpdater* mUpdater;
  328. static const U32 CALLINGCARD_ADDED = LLInventoryObserver::ADD | LLInventoryObserver::CALLING_CARD;
  329. };
  330. };
  331. /**
  332.  * Periodically updates the nearby people list while the Nearby tab is active.
  333.  * 
  334.  * The period is defined by NEARBY_LIST_UPDATE_INTERVAL constant.
  335.  */
  336. class LLNearbyListUpdater : public LLAvatarListUpdater
  337. {
  338. LOG_CLASS(LLNearbyListUpdater);
  339. public:
  340. LLNearbyListUpdater(callback_t cb)
  341. : LLAvatarListUpdater(cb, NEARBY_LIST_UPDATE_INTERVAL)
  342. {
  343. setActive(false);
  344. }
  345. /*virtual*/ void setActive(bool val)
  346. {
  347. if (val)
  348. {
  349. // update immediately and start regular updates
  350. updateList();
  351. mEventTimer.start(); 
  352. }
  353. else
  354. {
  355. // stop regular updates
  356. mEventTimer.stop();
  357. }
  358. }
  359. /*virtual*/ BOOL tick()
  360. {
  361. updateList();
  362. return FALSE;
  363. }
  364. private:
  365. };
  366. /**
  367.  * Updates the recent people list (those the agent has recently interacted with).
  368.  */
  369. class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2::trackable
  370. {
  371. LOG_CLASS(LLRecentListUpdater);
  372. public:
  373. LLRecentListUpdater(callback_t cb)
  374. : LLAvatarListUpdater(cb, 0)
  375. {
  376. LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this));
  377. }
  378. };
  379. //=============================================================================
  380. LLPanelPeople::LLPanelPeople()
  381. : LLPanel(),
  382. mFilterSubString(LLStringUtil::null),
  383. mFilterEditor(NULL),
  384. mTabContainer(NULL),
  385. mOnlineFriendList(NULL),
  386. mAllFriendList(NULL),
  387. mNearbyList(NULL),
  388. mRecentList(NULL),
  389. mGroupList(NULL)
  390. {
  391. mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this));
  392. mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this));
  393. mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this));
  394. mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this));
  395. }
  396. LLPanelPeople::~LLPanelPeople()
  397. {
  398. delete mNearbyListUpdater;
  399. delete mFriendListUpdater;
  400. delete mRecentListUpdater;
  401. if(LLVoiceClient::getInstance())
  402. LLVoiceClient::getInstance()->removeObserver(this);
  403. LLView::deleteViewByHandle(mGroupPlusMenuHandle);
  404. LLView::deleteViewByHandle(mNearbyViewSortMenuHandle);
  405. LLView::deleteViewByHandle(mFriendsViewSortMenuHandle);
  406. LLView::deleteViewByHandle(mGroupsViewSortMenuHandle);
  407. LLView::deleteViewByHandle(mRecentViewSortMenuHandle);
  408. }
  409. void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list)
  410. {
  411. if(!avatar_list)
  412. {
  413. llerrs << "Bad parameter" << llendl;
  414. return;
  415. }
  416. bool expanded = param.asBoolean();
  417. setAccordionCollapsedByUser(ctrl, !expanded);
  418. if(!expanded)
  419. {
  420. avatar_list->resetSelection();
  421. }
  422. }
  423. BOOL LLPanelPeople::postBuild()
  424. {
  425. setVisibleCallback(boost::bind(&LLPanelPeople::onVisibilityChange, this, _2));
  426. mFilterEditor = getChild<LLFilterEditor>("filter_input");
  427. mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
  428. mTabContainer = getChild<LLTabContainer>("tabs");
  429. mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
  430. mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
  431. mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
  432. mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
  433. mOnlineFriendList->setShowIcons("FriendsListShowIcons");
  434. mAllFriendList->setNoItemsCommentText(getString("no_friends"));
  435. mAllFriendList->setShowIcons("FriendsListShowIcons");
  436. mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
  437. mNearbyList->setNoItemsCommentText(getString("no_one_near"));
  438. mNearbyList->setShowIcons("NearbyListShowIcons");
  439. mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
  440. mRecentList->setNoItemsCommentText(getString("no_people"));
  441. mRecentList->setShowIcons("RecentListShowIcons");
  442. mGroupList = getChild<LLGroupList>("group_list");
  443. mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
  444. mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
  445. mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
  446. mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
  447. setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
  448. setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
  449. setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false);
  450. LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
  451. groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this));
  452. groups_panel->childSetAction("plus_btn", boost::bind(&LLPanelPeople::onGroupPlusButtonClicked, this));
  453. LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME);
  454. friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this));
  455. friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this));
  456. mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
  457. mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
  458. mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
  459. mRecentList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
  460. mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList));
  461. mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList));
  462. mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));
  463. mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList));
  464. // Set openning IM as default on return action for avatar lists
  465. mOnlineFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
  466. mAllFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
  467. mNearbyList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
  468. mRecentList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
  469. mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));
  470. mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));
  471. mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));
  472. LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");
  473. accordion_tab->setDropDownStateChangedCallback(
  474. boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList));
  475. accordion_tab = getChild<LLAccordionCtrlTab>("tab_online");
  476. accordion_tab->setDropDownStateChangedCallback(
  477. boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList));
  478. buttonSetAction("view_profile_btn", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this));
  479. buttonSetAction("group_info_btn", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this));
  480. buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this));
  481. buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this));
  482. buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this));
  483. buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this));
  484. buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this));
  485. buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this));
  486. getChild<LLPanel>(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this));
  487. getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this));
  488. getChild<LLPanel>(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this));
  489. getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this));
  490. // Must go after setting commit callback and initializing all pointers to children.
  491. mTabContainer->selectTabByName(NEARBY_TAB_NAME);
  492. // Create menus.
  493. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  494. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  495. registrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2));
  496. registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this));
  497. registrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2));
  498. registrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2));
  499. registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2));
  500. registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2));
  501. enable_registrar.add("People.Group.Minus.Enable", boost::bind(&LLPanelPeople::isRealGroup, this));
  502. enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2));
  503. enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2));
  504. enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2));
  505. LLMenuGL* plus_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  506. mGroupPlusMenuHandle  = plus_menu->getHandle();
  507. LLMenuGL* nearby_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_nearby_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  508. if(nearby_view_sort)
  509. mNearbyViewSortMenuHandle  = nearby_view_sort->getHandle();
  510. LLMenuGL* friend_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_friends_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  511. if(friend_view_sort)
  512. mFriendsViewSortMenuHandle  = friend_view_sort->getHandle();
  513. LLMenuGL* group_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  514. if(group_view_sort)
  515. mGroupsViewSortMenuHandle  = group_view_sort->getHandle();
  516. LLMenuGL* recent_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_recent_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  517. if(recent_view_sort)
  518. mRecentViewSortMenuHandle  = recent_view_sort->getHandle();
  519. gVoiceClient->addObserver(this);
  520. // call this method in case some list is empty and buttons can be in inconsistent state
  521. updateButtons();
  522. mOnlineFriendList->setRefreshCompleteCallback(boost::bind(&LLPanelPeople::onFriendListRefreshComplete, this, _1, _2));
  523. mAllFriendList->setRefreshCompleteCallback(boost::bind(&LLPanelPeople::onFriendListRefreshComplete, this, _1, _2));
  524. return TRUE;
  525. }
  526. // virtual
  527. void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal)
  528. {
  529. if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
  530. {
  531. return;
  532. }
  533. updateButtons();
  534. }
  535. void LLPanelPeople::updateFriendList()
  536. {
  537. if (!mOnlineFriendList || !mAllFriendList)
  538. return;
  539. // get all buddies we know about
  540. const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  541. LLAvatarTracker::buddy_map_t all_buddies;
  542. av_tracker.copyBuddyList(all_buddies);
  543. // save them to the online and all friends vectors
  544. LLAvatarList::uuid_vector_t& online_friendsp = mOnlineFriendList->getIDs();
  545. LLAvatarList::uuid_vector_t& all_friendsp = mAllFriendList->getIDs();
  546. all_friendsp.clear();
  547. online_friendsp.clear();
  548. LLFriendCardsManager::folderid_buddies_map_t listMap;
  549. // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
  550. LLFriendCardsManager::instance().collectFriendsLists(listMap);
  551. if (listMap.size() > 0)
  552. {
  553. lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
  554. all_friendsp = listMap.begin()->second;
  555. }
  556. else
  557. {
  558. lldebugs << "Friends Cards were not found" << llendl;
  559. }
  560. // show special help text for just created account to help found friends. EXT-4836
  561. static LLTextBox* no_friends_text = getChild<LLTextBox>("no_friends_msg");
  562. no_friends_text->setVisible(all_friendsp.size() == 0);
  563. LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
  564. for (; buddy_it != all_buddies.end(); ++buddy_it)
  565. {
  566. LLUUID buddy_id = buddy_it->first;
  567. if (av_tracker.isBuddyOnline(buddy_id))
  568. online_friendsp.push_back(buddy_id);
  569. }
  570. mOnlineFriendList->setDirty();
  571. mAllFriendList->setDirty();
  572. showFriendsAccordionsIfNeeded();
  573. }
  574. void LLPanelPeople::updateNearbyList()
  575. {
  576. if (!mNearbyList)
  577. return;
  578. std::vector<LLVector3d> positions;
  579. LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
  580. mNearbyList->setDirty();
  581. DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs());
  582. LLLocalSpeakerMgr::instance().update(TRUE);
  583. }
  584. void LLPanelPeople::updateRecentList()
  585. {
  586. if (!mRecentList)
  587. return;
  588. LLRecentPeople::instance().get(mRecentList->getIDs());
  589. mRecentList->setDirty();
  590. }
  591. void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible)
  592. {
  593. // To make sure we're referencing the right widget (a child of the button bar).
  594. LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
  595. button->setVisible(visible);
  596. }
  597. void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled)
  598. {
  599. // To make sure we're referencing the right widget (a child of the button bar).
  600. LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
  601. button->setEnabled(enabled);
  602. }
  603. void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb)
  604. {
  605. // To make sure we're referencing the right widget (a child of the button bar).
  606. LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
  607. button->setClickedCallback(cb);
  608. }
  609. bool LLPanelPeople::isFriendOnline(const LLUUID& id)
  610. {
  611. LLAvatarList::uuid_vector_t ids = mOnlineFriendList->getIDs();
  612. return std::find(ids.begin(), ids.end(), id) != ids.end();
  613. }
  614. void LLPanelPeople::updateButtons()
  615. {
  616. std::string cur_tab = getActiveTabName();
  617. bool nearby_tab_active = (cur_tab == NEARBY_TAB_NAME);
  618. bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME);
  619. bool group_tab_active = (cur_tab == GROUP_TAB_NAME);
  620. //bool recent_tab_active = (cur_tab == RECENT_TAB_NAME);
  621. LLUUID selected_id;
  622. std::vector<LLUUID> selected_uuids;
  623. getCurrentItemIDs(selected_uuids);
  624. bool item_selected = (selected_uuids.size() == 1);
  625. bool multiple_selected = (selected_uuids.size() >= 1);
  626. buttonSetVisible("group_info_btn", group_tab_active);
  627. buttonSetVisible("chat_btn", group_tab_active);
  628. buttonSetVisible("view_profile_btn", !group_tab_active);
  629. buttonSetVisible("im_btn", !group_tab_active);
  630. buttonSetVisible("call_btn", !group_tab_active);
  631. buttonSetVisible("group_call_btn", group_tab_active);
  632. buttonSetVisible("teleport_btn", friends_tab_active);
  633. buttonSetVisible("share_btn", nearby_tab_active || friends_tab_active);
  634. if (group_tab_active)
  635. {
  636. bool cur_group_active = true;
  637. if (item_selected)
  638. {
  639. selected_id = mGroupList->getSelectedUUID();
  640. cur_group_active = (gAgent.getGroupID() == selected_id);
  641. }
  642. LLPanel* groups_panel = mTabContainer->getCurrentPanel();
  643. groups_panel->childSetEnabled("activate_btn", item_selected && !cur_group_active); // "none" or a non-active group selected
  644. groups_panel->childSetEnabled("minus_btn", item_selected && selected_id.notNull());
  645. }
  646. else
  647. {
  648. bool is_friend = true;
  649. // Check whether selected avatar is our friend.
  650. if (item_selected)
  651. {
  652. selected_id = selected_uuids.front();
  653. is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
  654. }
  655. LLPanel* cur_panel = mTabContainer->getCurrentPanel();
  656. if (cur_panel)
  657. {
  658. cur_panel->childSetEnabled("add_friend_btn", !is_friend);
  659. if (friends_tab_active)
  660. {
  661. cur_panel->childSetEnabled("del_btn", multiple_selected);
  662. }
  663. }
  664. }
  665. bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled();
  666. buttonSetEnabled("teleport_btn", friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));
  667. buttonSetEnabled("view_profile_btn", item_selected);
  668. buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection
  669. buttonSetEnabled("call_btn", multiple_selected && enable_calls);
  670. buttonSetEnabled("share_btn", item_selected); // not implemented yet
  671. bool none_group_selected = item_selected && selected_id.isNull();
  672. buttonSetEnabled("group_info_btn", !none_group_selected);
  673. buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls);
  674. buttonSetEnabled("chat_btn", !none_group_selected);
  675. }
  676. std::string LLPanelPeople::getActiveTabName() const
  677. {
  678. return mTabContainer->getCurrentPanel()->getName();
  679. }
  680. LLUUID LLPanelPeople::getCurrentItemID() const
  681. {
  682. std::string cur_tab = getActiveTabName();
  683. if (cur_tab == FRIENDS_TAB_NAME) // this tab has two lists
  684. {
  685. LLUUID cur_online_friend;
  686. if ((cur_online_friend = mOnlineFriendList->getSelectedUUID()).notNull())
  687. return cur_online_friend;
  688. return mAllFriendList->getSelectedUUID();
  689. }
  690. if (cur_tab == NEARBY_TAB_NAME)
  691. return mNearbyList->getSelectedUUID();
  692. if (cur_tab == RECENT_TAB_NAME)
  693. return mRecentList->getSelectedUUID();
  694. if (cur_tab == GROUP_TAB_NAME)
  695. return mGroupList->getSelectedUUID();
  696. llassert(0 && "unknown tab selected");
  697. return LLUUID::null;
  698. }
  699. void LLPanelPeople::getCurrentItemIDs(std::vector<LLUUID>& selected_uuids) const
  700. {
  701. std::string cur_tab = getActiveTabName();
  702. if (cur_tab == FRIENDS_TAB_NAME)
  703. {
  704. // friends tab has two lists
  705. mOnlineFriendList->getSelectedUUIDs(selected_uuids);
  706. mAllFriendList->getSelectedUUIDs(selected_uuids);
  707. }
  708. else if (cur_tab == NEARBY_TAB_NAME)
  709. mNearbyList->getSelectedUUIDs(selected_uuids);
  710. else if (cur_tab == RECENT_TAB_NAME)
  711. mRecentList->getSelectedUUIDs(selected_uuids);
  712. else if (cur_tab == GROUP_TAB_NAME)
  713. mGroupList->getSelectedUUIDs(selected_uuids);
  714. else
  715. llassert(0 && "unknown tab selected");
  716. }
  717. void LLPanelPeople::showGroupMenu(LLMenuGL* menu)
  718. {
  719. // Shows the menu at the top of the button bar.
  720. // Calculate its coordinates.
  721. // (assumes that groups panel is the current tab)
  722. LLPanel* bottom_panel = mTabContainer->getCurrentPanel()->getChild<LLPanel>("bottom_panel"); 
  723. LLPanel* parent_panel = mTabContainer->getCurrentPanel();
  724. menu->arrangeAndClear();
  725. S32 menu_height = menu->getRect().getHeight();
  726. S32 menu_x = -2; // *HACK: compensates HPAD in showPopup()
  727. S32 menu_y = bottom_panel->getRect().mTop + menu_height;
  728. // Actually show the menu.
  729. menu->buildDrawLabels();
  730. menu->updateParent(LLMenuGL::sMenuContainer);
  731. LLMenuGL::showPopup(parent_panel, menu, menu_x, menu_y);
  732. }
  733. void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save)
  734. {
  735. switch (order)
  736. {
  737. case E_SORT_BY_NAME:
  738. list->sortByName();
  739. break;
  740. case E_SORT_BY_STATUS:
  741. list->setComparator(&STATUS_COMPARATOR);
  742. list->sort();
  743. break;
  744. case E_SORT_BY_MOST_RECENT:
  745. list->setComparator(&RECENT_COMPARATOR);
  746. list->sort();
  747. break;
  748. case E_SORT_BY_RECENT_SPEAKERS:
  749. list->setComparator(&RECENT_SPEAKER_COMPARATOR);
  750. list->sort();
  751. break;
  752. case E_SORT_BY_DISTANCE:
  753. list->setComparator(&DISTANCE_COMPARATOR);
  754. list->sort();
  755. break;
  756. default:
  757. llwarns << "Unrecognized people sort order for " << list->getName() << llendl;
  758. return;
  759. }
  760. if (save)
  761. {
  762. std::string setting;
  763. if (list == mAllFriendList || list == mOnlineFriendList)
  764. setting = "FriendsSortOrder";
  765. else if (list == mRecentList)
  766. setting = "RecentPeopleSortOrder";
  767. else if (list == mNearbyList)
  768. setting = "NearbyPeopleSortOrder";
  769. if (!setting.empty())
  770. gSavedSettings.setU32(setting, order);
  771. }
  772. }
  773. void LLPanelPeople::onVisibilityChange(const LLSD& new_visibility)
  774. {
  775. if (new_visibility.asBoolean() == FALSE)
  776. {
  777. // Don't update anything while we're invisible.
  778. mNearbyListUpdater->setActive(FALSE);
  779. }
  780. else
  781. {
  782. reSelectedCurrentTab();
  783. }
  784. }
  785. // Make the tab-container re-select current tab
  786. // for onTabSelected() callback to get called.
  787. // (currently this is needed to reactivate nearby list updates
  788. // when we get visible)
  789. void LLPanelPeople::reSelectedCurrentTab()
  790. {
  791. mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
  792. }
  793. bool LLPanelPeople::isRealGroup()
  794. {
  795. return getCurrentItemID() != LLUUID::null;
  796. }
  797. void LLPanelPeople::onFilterEdit(const std::string& search_string)
  798. {
  799. std::string search_upper = search_string;
  800. // Searches are case-insensitive
  801. LLStringUtil::toUpper(search_upper);
  802. LLStringUtil::trimHead(search_upper);
  803. if (mFilterSubString == search_upper)
  804. return;
  805. mFilterSubString = search_upper;
  806. //store accordion tabs state before any manipulation with accordion tabs
  807. if(!mFilterSubString.empty())
  808. {
  809. notifyChildren(LLSD().with("action","store_state"));
  810. }
  811. // Apply new filter.
  812. mNearbyList->setNameFilter(mFilterSubString);
  813. mOnlineFriendList->setNameFilter(mFilterSubString);
  814. mAllFriendList->setNameFilter(mFilterSubString);
  815. mRecentList->setNameFilter(mFilterSubString);
  816. mGroupList->setNameFilter(mFilterSubString);
  817. setAccordionCollapsedByUser("tab_online", false);
  818. setAccordionCollapsedByUser("tab_all", false);
  819. showFriendsAccordionsIfNeeded();
  820. //restore accordion tabs state _after_ all manipulations...
  821. if(mFilterSubString.empty())
  822. {
  823. notifyChildren(LLSD().with("action","restore_state"));
  824. }
  825. }
  826. void LLPanelPeople::onTabSelected(const LLSD& param)
  827. {
  828. std::string tab_name = getChild<LLPanel>(param.asString())->getName();
  829. mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);
  830. updateButtons();
  831. showFriendsAccordionsIfNeeded();
  832. if (GROUP_TAB_NAME == tab_name)
  833. mFilterEditor->setLabel(getString("groups_filter_label"));
  834. else
  835. mFilterEditor->setLabel(getString("people_filter_label"));
  836. }
  837. void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl)
  838. {
  839. LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl);
  840. if(!item)
  841. {
  842. return;
  843. }
  844. LLUUID clicked_id = item->getAvatarId();
  845. #if 0 // SJB: Useful for testing, but not currently functional or to spec
  846. LLAvatarActions::showProfile(clicked_id);
  847. #else // spec says open IM window
  848. LLAvatarActions::startIM(clicked_id);
  849. #endif
  850. }
  851. void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)
  852. {
  853. // Make sure only one of the friends lists (online/all) has selection.
  854. if (getActiveTabName() == FRIENDS_TAB_NAME)
  855. {
  856. if (list == mOnlineFriendList)
  857. mAllFriendList->resetSelection(true);
  858. else if (list == mAllFriendList)
  859. mOnlineFriendList->resetSelection(true);
  860. else
  861. llassert(0 && "commit on unknown friends list");
  862. }
  863. updateButtons();
  864. }
  865. void LLPanelPeople::onViewProfileButtonClicked()
  866. {
  867. LLUUID id = getCurrentItemID();
  868. LLAvatarActions::showProfile(id);
  869. }
  870. void LLPanelPeople::onAddFriendButtonClicked()
  871. {
  872. LLUUID id = getCurrentItemID();
  873. if (id.notNull())
  874. {
  875. LLAvatarActions::requestFriendshipDialog(id);
  876. }
  877. }
  878. bool LLPanelPeople::isItemsFreeOfFriends(const std::vector<LLUUID>& uuids)
  879. {
  880. const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  881. for ( std::vector<LLUUID>::const_iterator
  882.   id = uuids.begin(),
  883.   id_end = uuids.end();
  884.   id != id_end; ++id )
  885. {
  886. if (av_tracker.isBuddy (*id))
  887. {
  888. return false;
  889. }
  890. }
  891. return true;
  892. }
  893. void LLPanelPeople::onAddFriendWizButtonClicked()
  894. {
  895. // Show add friend wizard.
  896. LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE);
  897. // Need to disable 'ok' button when friend occurs in selection
  898. if (picker) picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));
  899. LLFloater* root_floater = gFloaterView->getParentFloater(this);
  900. if (root_floater)
  901. {
  902. root_floater->addDependentFloater(picker);
  903. }
  904. }
  905. void LLPanelPeople::onDeleteFriendButtonClicked()
  906. {
  907. std::vector<LLUUID> selected_uuids;
  908. getCurrentItemIDs(selected_uuids);
  909. if (selected_uuids.size() == 1)
  910. {
  911. LLAvatarActions::removeFriendDialog( selected_uuids.front() );
  912. }
  913. else if (selected_uuids.size() > 1)
  914. {
  915. LLAvatarActions::removeFriendsDialog( selected_uuids );
  916. }
  917. }
  918. void LLPanelPeople::onGroupInfoButtonClicked()
  919. {
  920. LLGroupActions::show(getCurrentItemID());
  921. }
  922. void LLPanelPeople::onChatButtonClicked()
  923. {
  924. LLUUID group_id = getCurrentItemID();
  925. if (group_id.notNull())
  926. LLGroupActions::startIM(group_id);
  927. }
  928. void LLPanelPeople::onImButtonClicked()
  929. {
  930. std::vector<LLUUID> selected_uuids;
  931. getCurrentItemIDs(selected_uuids);
  932. if ( selected_uuids.size() == 1 )
  933. {
  934. // if selected only one person then start up IM
  935. LLAvatarActions::startIM(selected_uuids.at(0));
  936. }
  937. else if ( selected_uuids.size() > 1 )
  938. {
  939. // for multiple selection start up friends conference
  940. LLAvatarActions::startConference(selected_uuids);
  941. }
  942. }
  943. void LLPanelPeople::onActivateButtonClicked()
  944. {
  945. LLGroupActions::activate(mGroupList->getSelectedUUID());
  946. }
  947. // static
  948. void LLPanelPeople::onAvatarPicked(
  949. const std::vector<std::string>& names,
  950. const std::vector<LLUUID>& ids)
  951. {
  952. if (!names.empty() && !ids.empty())
  953. LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
  954. }
  955. void LLPanelPeople::onGroupPlusButtonClicked()
  956. {
  957. if (!gAgent.canJoinGroups())
  958. {
  959. LLNotificationsUtil::add("JoinedTooManyGroups");
  960. return;
  961. }
  962. LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get();
  963. if (!plus_menu)
  964. return;
  965. showGroupMenu(plus_menu);
  966. }
  967. void LLPanelPeople::onGroupMinusButtonClicked()
  968. {
  969. LLUUID group_id = getCurrentItemID();
  970. if (group_id.notNull())
  971. LLGroupActions::leave(group_id);
  972. }
  973. void LLPanelPeople::onGroupPlusMenuItemClicked(const LLSD& userdata)
  974. {
  975. std::string chosen_item = userdata.asString();
  976. if (chosen_item == "join_group")
  977. LLGroupActions::search();
  978. else if (chosen_item == "new_group")
  979. LLGroupActions::createGroup();
  980. }
  981. void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
  982. {
  983. std::string chosen_item = userdata.asString();
  984. if (chosen_item == "sort_name")
  985. {
  986. setSortOrder(mAllFriendList, E_SORT_BY_NAME);
  987. }
  988. else if (chosen_item == "sort_status")
  989. {
  990. setSortOrder(mAllFriendList, E_SORT_BY_STATUS);
  991. }
  992. else if (chosen_item == "view_icons")
  993. {
  994. mAllFriendList->toggleIcons();
  995. mOnlineFriendList->toggleIcons();
  996. }
  997. }
  998. void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata)
  999. {
  1000. std::string chosen_item = userdata.asString();
  1001. if (chosen_item == "show_icons")
  1002. {
  1003. mGroupList->toggleIcons();
  1004. }
  1005. }
  1006. void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
  1007. {
  1008. std::string chosen_item = userdata.asString();
  1009. if (chosen_item == "sort_by_recent_speakers")
  1010. {
  1011. setSortOrder(mNearbyList, E_SORT_BY_RECENT_SPEAKERS);
  1012. }
  1013. else if (chosen_item == "sort_name")
  1014. {
  1015. setSortOrder(mNearbyList, E_SORT_BY_NAME);
  1016. }
  1017. else if (chosen_item == "view_icons")
  1018. {
  1019. mNearbyList->toggleIcons();
  1020. }
  1021. else if (chosen_item == "sort_distance")
  1022. {
  1023. setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);
  1024. }
  1025. }
  1026. bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata)
  1027. {
  1028. std::string item = userdata.asString();
  1029. U32 sort_order = gSavedSettings.getU32("NearbyPeopleSortOrder");
  1030. if (item == "sort_by_recent_speakers")
  1031. return sort_order == E_SORT_BY_RECENT_SPEAKERS;
  1032. if (item == "sort_name")
  1033. return sort_order == E_SORT_BY_NAME;
  1034. if (item == "sort_distance")
  1035. return sort_order == E_SORT_BY_DISTANCE;
  1036. return false;
  1037. }
  1038. void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
  1039. {
  1040. std::string chosen_item = userdata.asString();
  1041. if (chosen_item == "sort_recent")
  1042. {
  1043. setSortOrder(mRecentList, E_SORT_BY_MOST_RECENT);
  1044. else if (chosen_item == "sort_name")
  1045. {
  1046. setSortOrder(mRecentList, E_SORT_BY_NAME);
  1047. }
  1048. else if (chosen_item == "view_icons")
  1049. {
  1050. mRecentList->toggleIcons();
  1051. }
  1052. }
  1053. bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata) 
  1054. {
  1055. std::string item = userdata.asString();
  1056. U32 sort_order = gSavedSettings.getU32("FriendsSortOrder");
  1057. if (item == "sort_name") 
  1058. return sort_order == E_SORT_BY_NAME;
  1059. if (item == "sort_status")
  1060. return sort_order == E_SORT_BY_STATUS;
  1061. return false;
  1062. }
  1063. bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata) 
  1064. {
  1065. std::string item = userdata.asString();
  1066. U32 sort_order = gSavedSettings.getU32("RecentPeopleSortOrder");
  1067. if (item == "sort_recent")
  1068. return sort_order == E_SORT_BY_MOST_RECENT;
  1069. if (item == "sort_name") 
  1070. return sort_order == E_SORT_BY_NAME;
  1071. return false;
  1072. }
  1073. void LLPanelPeople::onCallButtonClicked()
  1074. {
  1075. std::vector<LLUUID> selected_uuids;
  1076. getCurrentItemIDs(selected_uuids);
  1077. if (selected_uuids.size() == 1)
  1078. {
  1079. // initiate a P2P voice chat with the selected user
  1080. LLAvatarActions::startCall(getCurrentItemID());
  1081. }
  1082. else if (selected_uuids.size() > 1)
  1083. {
  1084. // initiate an ad-hoc voice chat with multiple users
  1085. LLAvatarActions::startAdhocCall(selected_uuids);
  1086. }
  1087. }
  1088. void LLPanelPeople::onGroupCallButtonClicked()
  1089. {
  1090. LLGroupActions::startCall(getCurrentItemID());
  1091. }
  1092. void LLPanelPeople::onTeleportButtonClicked()
  1093. {
  1094. LLAvatarActions::offerTeleport(getCurrentItemID());
  1095. }
  1096. void LLPanelPeople::onShareButtonClicked()
  1097. {
  1098. LLAvatarActions::share(getCurrentItemID());
  1099. }
  1100. void LLPanelPeople::onMoreButtonClicked()
  1101. {
  1102. // *TODO: not implemented yet
  1103. }
  1104. void LLPanelPeople::onFriendsViewSortButtonClicked()
  1105. {
  1106. LLMenuGL* menu = (LLMenuGL*)mFriendsViewSortMenuHandle.get();
  1107. if (!menu)
  1108. return;
  1109. showGroupMenu(menu);
  1110. }
  1111. void LLPanelPeople::onGroupsViewSortButtonClicked()
  1112. {
  1113. LLMenuGL* menu = (LLMenuGL*)mGroupsViewSortMenuHandle.get();
  1114. if (!menu)
  1115. return;
  1116. showGroupMenu(menu);
  1117. }
  1118. void LLPanelPeople::onRecentViewSortButtonClicked()
  1119. {
  1120. LLMenuGL* menu = (LLMenuGL*)mRecentViewSortMenuHandle.get();
  1121. if (!menu)
  1122. return;
  1123. showGroupMenu(menu);
  1124. }
  1125. void LLPanelPeople::onNearbyViewSortButtonClicked()
  1126. {
  1127. LLMenuGL* menu = (LLMenuGL*)mNearbyViewSortMenuHandle.get();
  1128. if (!menu)
  1129. return;
  1130. showGroupMenu(menu);
  1131. }
  1132. void LLPanelPeople::onOpen(const LLSD& key)
  1133. {
  1134. std::string tab_name = key["people_panel_tab_name"];
  1135. mFilterEditor -> clear();
  1136. onFilterEdit("");
  1137. if (!tab_name.empty())
  1138. mTabContainer->selectTabByName(tab_name);
  1139. else
  1140. reSelectedCurrentTab();
  1141. }
  1142. bool LLPanelPeople::notifyChildren(const LLSD& info)
  1143. {
  1144. if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")
  1145. {
  1146. LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
  1147. if (!container)
  1148. {
  1149. llwarns << "Cannot find People panel container" << llendl;
  1150. return true;
  1151. }
  1152. if (container->getCurrentPanelIndex() > 0) 
  1153. {
  1154. // if not on the default panel, switch to it
  1155. container->onOpen(LLSD().with(LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME, getName()));
  1156. }
  1157. else
  1158. LLSideTray::getInstance()->collapseSideBar();
  1159. return true; // this notification is only supposed to be handled by task panels
  1160. }
  1161. return LLPanel::notifyChildren(info);
  1162. }
  1163. void LLPanelPeople::showAccordion(const std::string name, bool show)
  1164. {
  1165. if(name.empty())
  1166. {
  1167. llwarns << "No name provided" << llendl;
  1168. return;
  1169. }
  1170. LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name);
  1171. tab->setVisible(show);
  1172. if(show)
  1173. {
  1174. // don't expand accordion if it was collapsed by user
  1175. if(!isAccordionCollapsedByUser(tab))
  1176. {
  1177. // expand accordion
  1178. tab->changeOpenClose(false);
  1179. }
  1180. }
  1181. }
  1182. void LLPanelPeople::showFriendsAccordionsIfNeeded()
  1183. {
  1184. if(FRIENDS_TAB_NAME == getActiveTabName())
  1185. {
  1186. // Expand and show accordions if needed, else - hide them
  1187. showAccordion("tab_online", mOnlineFriendList->filterHasMatches());
  1188. showAccordion("tab_all", mAllFriendList->filterHasMatches());
  1189. // Rearrange accordions
  1190. LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
  1191. accordion->arrange();
  1192. }
  1193. }
  1194. void LLPanelPeople::onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param)
  1195. {
  1196. if(ctrl == mOnlineFriendList)
  1197. {
  1198. showAccordion("tab_online", param.asInteger());
  1199. }
  1200. else if(ctrl == mAllFriendList)
  1201. {
  1202. showAccordion("tab_all", param.asInteger());
  1203. }
  1204. LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
  1205. accordion->arrange();
  1206. }
  1207. void LLPanelPeople::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
  1208. {
  1209. if(!acc_tab)
  1210. {
  1211. llwarns << "Invalid parameter" << llendl;
  1212. return;
  1213. }
  1214. LLSD param = acc_tab->getValue();
  1215. param[COLLAPSED_BY_USER] = collapsed;
  1216. acc_tab->setValue(param);
  1217. }
  1218. void LLPanelPeople::setAccordionCollapsedByUser(const std::string& name, bool collapsed)
  1219. {
  1220. setAccordionCollapsedByUser(getChild<LLUICtrl>(name), collapsed);
  1221. }
  1222. bool LLPanelPeople::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
  1223. {
  1224. if(!acc_tab)
  1225. {
  1226. llwarns << "Invalid parameter" << llendl;
  1227. return false;
  1228. }
  1229. LLSD param = acc_tab->getValue();
  1230. if(!param.has(COLLAPSED_BY_USER))
  1231. {
  1232. return false;
  1233. }
  1234. return param[COLLAPSED_BY_USER].asBoolean();
  1235. }
  1236. bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)
  1237. {
  1238. return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));
  1239. }
  1240. // EOF