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

/indra/newview/llgrouplist.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 425 lines | 278 code | 79 blank | 68 comment | 47 complexity | 20f0b354fd99eede3dd20f733217bbb1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llgrouplist.cpp
  3. * @brief List of the groups the agent belongs to.
  4. *
  5. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llgrouplist.h"
  28. // libs
  29. #include "llbutton.h"
  30. #include "lliconctrl.h"
  31. #include "llmenugl.h"
  32. #include "lltextbox.h"
  33. #include "lltextutil.h"
  34. #include "lltrans.h"
  35. // newview
  36. #include "llagent.h"
  37. #include "llgroupactions.h"
  38. #include "llfloaterreg.h"
  39. #include "llviewercontrol.h" // for gSavedSettings
  40. #include "llviewermenu.h" // for gMenuHolder
  41. #include "llvoiceclient.h"
  42. static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
  43. S32 LLGroupListItem::sIconWidth = 0;
  44. class LLGroupComparator : public LLFlatListView::ItemComparator
  45. {
  46. public:
  47. /** Returns true if item1 < item2, false otherwise */
  48. /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
  49. {
  50. std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
  51. std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
  52. LLStringUtil::toUpper(name1);
  53. LLStringUtil::toUpper(name2);
  54. return name1 < name2;
  55. }
  56. };
  57. static const LLGroupComparator GROUP_COMPARATOR;
  58. LLGroupList::LLGroupList(const Params& p)
  59. : LLFlatListViewEx(p)
  60. , mDirty(true) // to force initial update
  61. {
  62. // Listen for agent group changes.
  63. gAgent.addListener(this, "new group");
  64. mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");
  65. setCommitOnSelectionChange(true);
  66. // Set default sort order.
  67. setComparator(&GROUP_COMPARATOR);
  68. // Set up context menu.
  69. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  70. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  71. registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
  72. enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
  73. LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml",
  74. gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  75. if(context_menu)
  76. mContextMenuHandle = context_menu->getHandle();
  77. }
  78. LLGroupList::~LLGroupList()
  79. {
  80. gAgent.removeListener(this);
  81. if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
  82. }
  83. // virtual
  84. void LLGroupList::draw()
  85. {
  86. if (mDirty)
  87. refresh();
  88. LLFlatListView::draw();
  89. }
  90. // virtual
  91. BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
  92. {
  93. BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
  94. LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get();
  95. if (context_menu && size() > 0)
  96. {
  97. context_menu->buildDrawLabels();
  98. context_menu->updateParent(LLMenuGL::sMenuContainer);
  99. LLMenuGL::showPopup(this, context_menu, x, y);
  100. }
  101. return handled;
  102. }
  103. void LLGroupList::setNameFilter(const std::string& filter)
  104. {
  105. std::string filter_upper = filter;
  106. LLStringUtil::toUpper(filter_upper);
  107. if (mNameFilter != filter_upper)
  108. {
  109. mNameFilter = filter_upper;
  110. // set no items message depend on filter state
  111. updateNoItemsMessage(filter);
  112. setDirty();
  113. }
  114. }
  115. static bool findInsensitive(std::string haystack, const std::string& needle_upper)
  116. {
  117. LLStringUtil::toUpper(haystack);
  118. return haystack.find(needle_upper) != std::string::npos;
  119. }
  120. void LLGroupList::refresh()
  121. {
  122. const LLUUID& highlight_id = gAgent.getGroupID();
  123. S32 count = gAgent.mGroups.count();
  124. LLUUID id;
  125. bool have_filter = !mNameFilter.empty();
  126. clear();
  127. for(S32 i = 0; i < count; ++i)
  128. {
  129. id = gAgent.mGroups.get(i).mID;
  130. const LLGroupData& group_data = gAgent.mGroups.get(i);
  131. if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
  132. continue;
  133. addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM);
  134. }
  135. // Sort the list.
  136. sort();
  137. // Add "none" to list at top if filter not set (what's the point of filtering "none"?).
  138. // but only if some real groups exists. EXT-4838
  139. if (!have_filter && count > 0)
  140. {
  141. std::string loc_none = LLTrans::getString("GroupsNone");
  142. addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
  143. }
  144. selectItemByUUID(highlight_id);
  145. setDirty(false);
  146. onCommit();
  147. }
  148. void LLGroupList::toggleIcons()
  149. {
  150. // Save the new value for new items to use.
  151. mShowIcons = !mShowIcons;
  152. gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons);
  153. // Show/hide icons for all existing items.
  154. std::vector<LLPanel*> items;
  155. getItems(items);
  156. for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
  157. {
  158. static_cast<LLGroupListItem*>(*it)->setGroupIconVisible(mShowIcons);
  159. }
  160. }
  161. //////////////////////////////////////////////////////////////////////////
  162. // PRIVATE Section
  163. //////////////////////////////////////////////////////////////////////////
  164. void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos)
  165. {
  166. LLGroupListItem* item = new LLGroupListItem();
  167. item->setGroupID(id);
  168. item->setName(name, mNameFilter);
  169. item->setGroupIconID(icon_id);
  170. item->getChildView("info_btn")->setVisible( false);
  171. item->getChildView("profile_btn")->setVisible( false);
  172. item->setGroupIconVisible(mShowIcons);
  173. addItem(item, id, pos);
  174. // setCommentVisible(false);
  175. }
  176. // virtual
  177. bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  178. {
  179. // Why is "new group" sufficient?
  180. if (event->desc() == "new group")
  181. {
  182. setDirty();
  183. return true;
  184. }
  185. return false;
  186. }
  187. bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
  188. {
  189. std::string action = userdata.asString();
  190. LLUUID selected_group = getSelectedUUID();
  191. if (action == "view_info")
  192. {
  193. LLGroupActions::show(selected_group);
  194. }
  195. else if (action == "chat")
  196. {
  197. LLGroupActions::startIM(selected_group);
  198. }
  199. else if (action == "call")
  200. {
  201. LLGroupActions::startCall(selected_group);
  202. }
  203. else if (action == "activate")
  204. {
  205. LLGroupActions::activate(selected_group);
  206. }
  207. else if (action == "leave")
  208. {
  209. LLGroupActions::leave(selected_group);
  210. }
  211. return true;
  212. }
  213. bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
  214. {
  215. LLUUID selected_group_id = getSelectedUUID();
  216. bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
  217. // each group including "none" can be activated
  218. if (userdata.asString() == "activate")
  219. return gAgent.getGroupID() != selected_group_id;
  220. if (userdata.asString() == "call")
  221. return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
  222. return real_group_selected;
  223. }
  224. /************************************************************************/
  225. /* LLGroupListItem implementation */
  226. /************************************************************************/
  227. LLGroupListItem::LLGroupListItem()
  228. : LLPanel(),
  229. mGroupIcon(NULL),
  230. mGroupNameBox(NULL),
  231. mInfoBtn(NULL),
  232. mGroupID(LLUUID::null)
  233. {
  234. buildFromFile( "panel_group_list_item.xml");
  235. // Remember group icon width including its padding from the name text box,
  236. // so that we can hide and show the icon again later.
  237. if (!sIconWidth)
  238. {
  239. sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft;
  240. }
  241. }
  242. LLGroupListItem::~LLGroupListItem()
  243. {
  244. LLGroupMgr::getInstance()->removeObserver(this);
  245. }
  246. //virtual
  247. BOOL LLGroupListItem::postBuild()
  248. {
  249. mGroupIcon = getChild<LLIconCtrl>("group_icon");
  250. mGroupNameBox = getChild<LLTextBox>("group_name");
  251. mInfoBtn = getChild<LLButton>("info_btn");
  252. mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this));
  253. childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this));
  254. return TRUE;
  255. }
  256. //virtual
  257. void LLGroupListItem::setValue( const LLSD& value )
  258. {
  259. if (!value.isMap()) return;
  260. if (!value.has("selected")) return;
  261. getChildView("selected_icon")->setVisible( value["selected"]);
  262. }
  263. void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)
  264. {
  265. getChildView("hovered_icon")->setVisible( true);
  266. if (mGroupID.notNull()) // don't show the info button for the "none" group
  267. {
  268. mInfoBtn->setVisible(true);
  269. getChildView("profile_btn")->setVisible( true);
  270. }
  271. LLPanel::onMouseEnter(x, y, mask);
  272. }
  273. void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)
  274. {
  275. getChildView("hovered_icon")->setVisible( false);
  276. mInfoBtn->setVisible(false);
  277. getChildView("profile_btn")->setVisible( false);
  278. LLPanel::onMouseLeave(x, y, mask);
  279. }
  280. void LLGroupListItem::setName(const std::string& name, const std::string& highlight)
  281. {
  282. mGroupName = name;
  283. LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight);
  284. mGroupNameBox->setToolTip(name);
  285. }
  286. void LLGroupListItem::setGroupID(const LLUUID& group_id)
  287. {
  288. LLGroupMgr::getInstance()->removeObserver(this);
  289. mID = group_id;
  290. mGroupID = group_id;
  291. setActive(group_id == gAgent.getGroupID());
  292. LLGroupMgr::getInstance()->addObserver(this);
  293. }
  294. void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id)
  295. {
  296. if (group_icon_id.notNull())
  297. {
  298. mGroupIcon->setValue(group_icon_id);
  299. }
  300. }
  301. void LLGroupListItem::setGroupIconVisible(bool visible)
  302. {
  303. // Already done? Then do nothing.
  304. if (mGroupIcon->getVisible() == (BOOL)visible)
  305. return;
  306. // Show/hide the group icon.
  307. mGroupIcon->setVisible(visible);
  308. // Move the group name horizontally by icon size + its distance from the group name.
  309. LLRect name_rect = mGroupNameBox->getRect();
  310. name_rect.mLeft += visible ? sIconWidth : -sIconWidth;
  311. mGroupNameBox->setRect(name_rect);
  312. }
  313. //////////////////////////////////////////////////////////////////////////
  314. // Private Section
  315. //////////////////////////////////////////////////////////////////////////
  316. void LLGroupListItem::setActive(bool active)
  317. {
  318. // *BUG: setName() overrides the style params.
  319. // Active group should be bold.
  320. LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc());
  321. // *NOTE dzaporozhan
  322. // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
  323. // is predefined as bold (SansSerifSmallBold, for example)
  324. new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
  325. LLFontGL* new_font = LLFontGL::getFont(new_desc);
  326. mGroupNameStyle.font = new_font;
  327. // *NOTE: You cannot set the style on a text box anymore, you must
  328. // rebuild the text. This will cause problems if the text contains
  329. // hyperlinks, as their styles will be wrong.
  330. mGroupNameBox->setText(mGroupName, mGroupNameStyle);
  331. }
  332. void LLGroupListItem::onInfoBtnClick()
  333. {
  334. LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", mGroupID));
  335. }
  336. void LLGroupListItem::onProfileBtnClick()
  337. {
  338. LLGroupActions::show(mGroupID);
  339. }
  340. void LLGroupListItem::changed(LLGroupChange gc)
  341. {
  342. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID);
  343. if(group_data)
  344. setGroupIconID(group_data->mInsigniaID);
  345. }
  346. //EOF