PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llnamelistctrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 433 lines | 326 code | 54 blank | 53 comment | 52 complexity | 082c2fe8ca758229b64632fbacc3a93a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llnamelistctrl.cpp
  3. * @brief A list of names, automatically refreshed from name cache.
  4. *
  5. * $LicenseInfo:firstyear=2003&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 "llnamelistctrl.h"
  28. #include <boost/tokenizer.hpp>
  29. #include "llavatarnamecache.h"
  30. #include "llcachename.h"
  31. #include "llfloaterreg.h"
  32. #include "llinventory.h"
  33. #include "llscrolllistitem.h"
  34. #include "llscrolllistcell.h"
  35. #include "llscrolllistcolumn.h"
  36. #include "llsdparam.h"
  37. #include "lltooltip.h"
  38. #include "lltrans.h"
  39. static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list");
  40. static const S32 info_icon_size = 16;
  41. void LLNameListCtrl::NameTypeNames::declareValues()
  42. {
  43. declare("INDIVIDUAL", LLNameListCtrl::INDIVIDUAL);
  44. declare("GROUP", LLNameListCtrl::GROUP);
  45. declare("SPECIAL", LLNameListCtrl::SPECIAL);
  46. }
  47. LLNameListCtrl::Params::Params()
  48. : name_column(""),
  49. allow_calling_card_drop("allow_calling_card_drop", false),
  50. short_names("short_names", false)
  51. {
  52. }
  53. LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
  54. : LLScrollListCtrl(p),
  55. mNameColumnIndex(p.name_column.column_index),
  56. mNameColumn(p.name_column.column_name),
  57. mAllowCallingCardDrop(p.allow_calling_card_drop),
  58. mShortNames(p.short_names)
  59. {}
  60. // public
  61. void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,
  62. BOOL enabled, const std::string& suffix)
  63. {
  64. //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl;
  65. NameItem item;
  66. item.value = agent_id;
  67. item.enabled = enabled;
  68. item.target = INDIVIDUAL;
  69. addNameItemRow(item, pos, suffix);
  70. }
  71. // virtual, public
  72. BOOL LLNameListCtrl::handleDragAndDrop(
  73. S32 x, S32 y, MASK mask,
  74. BOOL drop,
  75. EDragAndDropType cargo_type, void *cargo_data,
  76. EAcceptance *accept,
  77. std::string& tooltip_msg)
  78. {
  79. if (!mAllowCallingCardDrop)
  80. {
  81. return FALSE;
  82. }
  83. BOOL handled = FALSE;
  84. if (cargo_type == DAD_CALLINGCARD)
  85. {
  86. if (drop)
  87. {
  88. LLInventoryItem* item = (LLInventoryItem *)cargo_data;
  89. addNameItem(item->getCreatorUUID());
  90. }
  91. *accept = ACCEPT_YES_MULTI;
  92. }
  93. else
  94. {
  95. *accept = ACCEPT_NO;
  96. if (tooltip_msg.empty())
  97. {
  98. if (!getToolTip().empty())
  99. {
  100. tooltip_msg = getToolTip();
  101. }
  102. else
  103. {
  104. // backwards compatable English tooltip (should be overridden in xml)
  105. tooltip_msg.assign("Drag a calling card here\nto add a resident.");
  106. }
  107. }
  108. }
  109. handled = TRUE;
  110. lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLNameListCtrl " << getName() << llendl;
  111. return handled;
  112. }
  113. void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group)
  114. {
  115. if (is_group)
  116. LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));
  117. else
  118. LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id));
  119. }
  120. void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index )
  121. {
  122. S32 cur_index = getHighlightedItemInx();
  123. if (cur_index != target_index)
  124. {
  125. bool is_mouse_over_name_cell = false;
  126. S32 mouse_x, mouse_y;
  127. LLUI::getMousePositionLocal(this, &mouse_x, &mouse_y);
  128. S32 column_index = getColumnIndexFromOffset(mouse_x);
  129. LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y);
  130. if (hit_item && column_index == mNameColumnIndex)
  131. {
  132. // Get the name cell which is currently under the mouse pointer.
  133. LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
  134. if (hit_cell)
  135. {
  136. is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y);
  137. }
  138. }
  139. // If the tool tip is visible and the mouse is over the currently highlighted item's name cell,
  140. // we should not reset the highlighted item index i.e. set mHighlightedItem = -1
  141. // and should not increase the width of the text inside the cell because it may
  142. // overlap the tool tip icon.
  143. if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell)
  144. return;
  145. if(0 <= cur_index && cur_index < (S32)getItemList().size())
  146. {
  147. LLScrollListItem* item = getItemList()[cur_index];
  148. if (item)
  149. {
  150. LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
  151. if (cell)
  152. cell->setTextWidth(cell->getTextWidth() + info_icon_size);
  153. }
  154. else
  155. {
  156. llwarns << "highlighted name list item is NULL" << llendl;
  157. }
  158. }
  159. if(target_index != -1)
  160. {
  161. LLScrollListItem* item = getItemList()[target_index];
  162. LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
  163. if (item)
  164. {
  165. if (cell)
  166. cell->setTextWidth(cell->getTextWidth() - info_icon_size);
  167. }
  168. else
  169. {
  170. llwarns << "target name item is NULL" << llendl;
  171. }
  172. }
  173. }
  174. LLScrollListCtrl::mouseOverHighlightNthItem(target_index);
  175. }
  176. //virtual
  177. BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
  178. {
  179. BOOL handled = FALSE;
  180. S32 column_index = getColumnIndexFromOffset(x);
  181. LLScrollListItem* hit_item = hitItem(x, y);
  182. if (hit_item
  183. && column_index == mNameColumnIndex)
  184. {
  185. // ...this is the column with the avatar name
  186. LLUUID avatar_id = hit_item->getUUID();
  187. if (avatar_id.notNull())
  188. {
  189. // ...valid avatar id
  190. LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
  191. if (hit_cell)
  192. {
  193. S32 row_index = getItemIndex(hit_item);
  194. LLRect cell_rect = getCellRect(row_index, column_index);
  195. // Convert rect local to screen coordinates
  196. LLRect sticky_rect;
  197. localRectToScreen(cell_rect, &sticky_rect);
  198. // Spawn at right side of cell
  199. LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small");
  200. LLCoordGL pos( sticky_rect.mRight - info_icon_size, sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight())/2 );
  201. // Should we show a group or an avatar inspector?
  202. bool is_group = hit_item->getValue()["is_group"].asBoolean();
  203. LLToolTip::Params params;
  204. params.background_visible( false );
  205. params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) );
  206. params.delay_time(0.0f); // spawn instantly on hover
  207. params.image( icon );
  208. params.message("");
  209. params.padding(0);
  210. params.pos(pos);
  211. params.sticky_rect(sticky_rect);
  212. LLToolTipMgr::getInstance()->show(params);
  213. handled = TRUE;
  214. }
  215. }
  216. }
  217. if (!handled)
  218. {
  219. handled = LLScrollListCtrl::handleToolTip(x, y, mask);
  220. }
  221. return handled;
  222. }
  223. // public
  224. void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos,
  225. BOOL enabled)
  226. {
  227. NameItem item;
  228. item.value = group_id;
  229. item.enabled = enabled;
  230. item.target = GROUP;
  231. addNameItemRow(item, pos);
  232. }
  233. // public
  234. void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
  235. {
  236. item.target = GROUP;
  237. addNameItemRow(item, pos);
  238. }
  239. void LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
  240. {
  241. item.target = INDIVIDUAL;
  242. addNameItemRow(item, pos);
  243. }
  244. LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
  245. {
  246. LLNameListCtrl::NameItem item_params;
  247. LLParamSDParser parser;
  248. parser.readSD(element, item_params);
  249. item_params.userdata = userdata;
  250. return addNameItemRow(item_params, pos);
  251. }
  252. LLScrollListItem* LLNameListCtrl::addNameItemRow(
  253. const LLNameListCtrl::NameItem& name_item,
  254. EAddPosition pos,
  255. const std::string& suffix)
  256. {
  257. LLUUID id = name_item.value().asUUID();
  258. LLNameListItem* item = NULL;
  259. // Store item type so that we can invoke the proper inspector.
  260. // *TODO Vadim: Is there a more proper way of storing additional item data?
  261. {
  262. LLNameListCtrl::NameItem item_p(name_item);
  263. item_p.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP);
  264. item = new LLNameListItem(item_p);
  265. LLScrollListCtrl::addRow(item, item_p, pos);
  266. }
  267. if (!item) return NULL;
  268. // use supplied name by default
  269. std::string fullname = name_item.name;
  270. switch(name_item.target)
  271. {
  272. case GROUP:
  273. gCacheName->getGroupName(id, fullname);
  274. // fullname will be "nobody" if group not found
  275. break;
  276. case SPECIAL:
  277. // just use supplied name
  278. break;
  279. case INDIVIDUAL:
  280. {
  281. LLAvatarName av_name;
  282. if (id.isNull())
  283. {
  284. fullname = LLTrans::getString("AvatarNameNobody");
  285. }
  286. else if (LLAvatarNameCache::get(id, &av_name))
  287. {
  288. if (mShortNames)
  289. fullname = av_name.mDisplayName;
  290. else
  291. fullname = av_name.getCompleteName();
  292. }
  293. else
  294. {
  295. // ...schedule a callback
  296. LLAvatarNameCache::get(id,
  297. boost::bind(&LLNameListCtrl::onAvatarNameCache,
  298. this, _1, _2));
  299. }
  300. break;
  301. }
  302. default:
  303. break;
  304. }
  305. // Append optional suffix.
  306. if (!suffix.empty())
  307. {
  308. fullname.append(suffix);
  309. }
  310. LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
  311. if (cell)
  312. {
  313. cell->setValue(fullname);
  314. }
  315. dirtyColumns();
  316. // this column is resizable
  317. LLScrollListColumn* columnp = getColumn(mNameColumnIndex);
  318. if (columnp && columnp->mHeader)
  319. {
  320. columnp->mHeader->setHasResizableElement(TRUE);
  321. }
  322. return item;
  323. }
  324. // public
  325. void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
  326. {
  327. // Find the item specified with agent_id.
  328. S32 idx = -1;
  329. for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
  330. {
  331. LLScrollListItem* item = *it;
  332. if (item->getUUID() == agent_id)
  333. {
  334. idx = getItemIndex(item);
  335. break;
  336. }
  337. }
  338. // Remove it.
  339. if (idx >= 0)
  340. {
  341. selectNthItem(idx); // not sure whether this is needed, taken from previous implementation
  342. deleteSingleItem(idx);
  343. }
  344. }
  345. void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
  346. const LLAvatarName& av_name)
  347. {
  348. std::string name;
  349. if (mShortNames)
  350. name = av_name.mDisplayName;
  351. else
  352. name = av_name.getCompleteName();
  353. item_list::iterator iter;
  354. for (iter = getItemList().begin(); iter != getItemList().end(); iter++)
  355. {
  356. LLScrollListItem* item = *iter;
  357. if (item->getUUID() == agent_id)
  358. {
  359. LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
  360. if (cell)
  361. {
  362. cell->setValue(name);
  363. }
  364. }
  365. }
  366. dirtyColumns();
  367. }
  368. void LLNameListCtrl::updateColumns()
  369. {
  370. LLScrollListCtrl::updateColumns();
  371. if (!mNameColumn.empty())
  372. {
  373. LLScrollListColumn* name_column = getColumn(mNameColumn);
  374. if (name_column)
  375. {
  376. mNameColumnIndex = name_column->mIndex;
  377. }
  378. }
  379. }