PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/llflatlistview.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 520 lines | 168 code | 119 blank | 233 comment | 0 complexity | fdf817c74fd01c353a9a15d73e0c1a1a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llflatlistview.h
  3. * @brief LLFlatListView base class and extension to support messages for several cases of an empty list.
  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. #ifndef LL_LLFLATLISTVIEW_H
  27. #define LL_LLFLATLISTVIEW_H
  28. #include "llpanel.h"
  29. #include "llscrollcontainer.h"
  30. #include "lltextbox.h"
  31. /**
  32. * LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's.
  33. * LLSD can be associated with each added item, it can keep data from an item in digested form.
  34. * Associated LLSD's can be of any type (singular, a map etc.).
  35. * Items (LLPanel's subclasses) can be of different height.
  36. * The list is LLPanel created in itself and grows in height while new items are added.
  37. *
  38. * The control can manage selection of its items when the flag "allow_select" is set. Also ability to select
  39. * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag
  40. * is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items)
  41. * since any item of the list was selected.
  42. *
  43. * Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to
  44. * manage the list of pick items.
  45. *
  46. * ASSUMPTIONS AND STUFF
  47. * - NULL pointers and undefined LLSD's are not accepted by any method of this class unless specified otherwise
  48. * - Order of returned selected items are not guaranteed
  49. * - The control assumes that all items being added are unique.
  50. */
  51. class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
  52. {
  53. LOG_CLASS(LLFlatListView);
  54. public:
  55. /**
  56. * Abstract comparator for comparing flat list items in a form of LLPanel
  57. */
  58. class ItemComparator
  59. {
  60. public:
  61. ItemComparator() {};
  62. virtual ~ItemComparator() {};
  63. /** Returns true if item1 < item2, false otherwise */
  64. virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0;
  65. };
  66. /**
  67. * Represents reverse comparator which acts as a decorator for a comparator that need to be reversed
  68. */
  69. class ItemReverseComparator : public ItemComparator
  70. {
  71. public:
  72. ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {};
  73. virtual ~ItemReverseComparator() {};
  74. virtual bool compare(const LLPanel* item1, const LLPanel* item2) const
  75. {
  76. return mComparator.compare(item2, item1);
  77. }
  78. private:
  79. const ItemComparator& mComparator;
  80. };
  81. struct Params : public LLInitParam::Block<Params, LLScrollContainer::Params>
  82. {
  83. /** turning on/off selection support */
  84. Optional<bool> allow_select;
  85. /** turning on/off multiple selection (works while clicking and holding CTRL)*/
  86. Optional<bool> multi_select;
  87. /** don't allow to deselect all selected items (for mouse events on items only) */
  88. Optional<bool> keep_one_selected;
  89. /** try to keep selection visible after reshape */
  90. Optional<bool> keep_selection_visible_on_reshape;
  91. /** padding between items */
  92. Optional<U32> item_pad;
  93. /** textbox with info message when list is empty*/
  94. Optional<LLTextBox::Params> no_items_text;
  95. Params();
  96. };
  97. // disable traversal when finding widget to hand focus off to
  98. /*virtual*/ BOOL canFocusChildren() const { return FALSE; }
  99. /**
  100. * Connects callback to signal called when Return key is pressed.
  101. */
  102. boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }
  103. /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
  104. virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
  105. /** Returns full rect of child panel */
  106. const LLRect& getItemsRect() const;
  107. LLRect getRequiredRect() { return getItemsRect(); }
  108. /** Returns distance between items */
  109. const S32 getItemsPad() { return mItemPad; }
  110. /**
  111. * Adds and item and LLSD value associated with it to the list at specified position
  112. * @return true if the item was added, false otherwise
  113. */
  114. virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true);
  115. /**
  116. * Insert item_to_add along with associated value to the list right after the after_item.
  117. * @return true if the item was successfully added, false otherwise
  118. */
  119. virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null);
  120. /**
  121. * Remove specified item
  122. * @return true if the item was removed, false otherwise
  123. */
  124. virtual bool removeItem(LLPanel* item, bool rearrange = true);
  125. /**
  126. * Remove an item specified by value
  127. * @return true if the item was removed, false otherwise
  128. */
  129. virtual bool removeItemByValue(const LLSD& value, bool rearrange = true);
  130. /**
  131. * Remove an item specified by uuid
  132. * @return true if the item was removed, false otherwise
  133. */
  134. virtual bool removeItemByUUID(const LLUUID& uuid, bool rearrange = true);
  135. /**
  136. * Get an item by value
  137. * @return the item as LLPanel if associated with value, NULL otherwise
  138. */
  139. virtual LLPanel* getItemByValue(const LLSD& value) const;
  140. template<class T>
  141. T* getTypedItemByValue(const LLSD& value) const
  142. {
  143. return dynamic_cast<T*>(getItemByValue(value));
  144. }
  145. /**
  146. * Select or deselect specified item based on select
  147. * @return true if succeed, false otherwise
  148. */
  149. virtual bool selectItem(LLPanel* item, bool select = true);
  150. /**
  151. * Select or deselect an item by associated value based on select
  152. * @return true if succeed, false otherwise
  153. */
  154. virtual bool selectItemByValue(const LLSD& value, bool select = true);
  155. /**
  156. * Select or deselect an item by associated uuid based on select
  157. * @return true if succeed, false otherwise
  158. */
  159. virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true);
  160. /**
  161. * Get all panels stored in the list.
  162. */
  163. virtual void getItems(std::vector<LLPanel*>& items) const;
  164. /**
  165. * Get all items values.
  166. */
  167. virtual void getValues(std::vector<LLSD>& values) const;
  168. /**
  169. * Get LLSD associated with the first selected item
  170. */
  171. virtual LLSD getSelectedValue() const;
  172. /**
  173. * Get LLSD's associated with selected items.
  174. * @param selected_values std::vector being populated with LLSD associated with selected items
  175. */
  176. virtual void getSelectedValues(std::vector<LLSD>& selected_values) const;
  177. /**
  178. * Get LLUUID associated with selected item
  179. * @return LLUUID if such was associated with selected item
  180. */
  181. virtual LLUUID getSelectedUUID() const;
  182. /**
  183. * Get LLUUIDs associated with selected items
  184. * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items
  185. */
  186. virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const;
  187. /** Get the top selected item */
  188. virtual LLPanel* getSelectedItem() const;
  189. /**
  190. * Get selected items
  191. * @param selected_items An std::vector being populated with pointers to selected items
  192. */
  193. virtual void getSelectedItems(std::vector<LLPanel*>& selected_items) const;
  194. /**
  195. * Resets selection of items.
  196. *
  197. * It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true"
  198. * argument for current Flat List.
  199. * @param no_commit_on_deselection - if true onCommit callback will not be called
  200. */
  201. virtual void resetSelection(bool no_commit_on_deselection = false);
  202. /**
  203. * Sets comment text which will be shown in the list is it is empty.
  204. *
  205. * Textbox to hold passed text is created while this method is called at the first time.
  206. *
  207. * @param comment_text - string to be shown as a comment.
  208. */
  209. void setNoItemsCommentText( const std::string& comment_text);
  210. /** Turn on/off multiple selection support */
  211. void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; }
  212. /** Turn on/off selection support */
  213. void setAllowSelection(bool can_select) { mAllowSelection = can_select; }
  214. /** Sets flag whether onCommit should be fired if selection was changed */
  215. // FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly.
  216. void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; }
  217. /** Get number of selected items in the list */
  218. U32 numSelected() const {return mSelectedItemPairs.size(); }
  219. /** Get number of (visible) items in the list */
  220. U32 size(const bool only_visible_items = true) const;
  221. /** Removes all items from the list */
  222. virtual void clear();
  223. /**
  224. * Removes all items that can be detached from the list but doesn't destroy
  225. * them, caller responsible to manage items after they are detached.
  226. * Detachable item should accept "detach" action via notify() method,
  227. * where it disconnect all callbacks, does other valuable routines and
  228. * return 1.
  229. */
  230. void detachItems(std::vector<LLPanel*>& detached_items);
  231. /**
  232. * Set comparator to use for future sorts.
  233. *
  234. * This class does NOT manage lifetime of the comparator
  235. * but assumes that the comparator is always alive.
  236. */
  237. void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
  238. void sort();
  239. bool updateValue(const LLSD& old_value, const LLSD& new_value);
  240. void scrollToShowFirstSelectedItem();
  241. void selectFirstItem ();
  242. void selectLastItem ();
  243. virtual S32 notify(const LLSD& info) ;
  244. protected:
  245. /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
  246. typedef std::pair<LLPanel*, LLSD> item_pair_t;
  247. typedef std::list<item_pair_t*> pairs_list_t;
  248. typedef pairs_list_t::iterator pairs_iterator_t;
  249. typedef pairs_list_t::const_iterator pairs_const_iterator_t;
  250. /** An adapter for a ItemComparator */
  251. struct ComparatorAdaptor
  252. {
  253. ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {};
  254. bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2)
  255. {
  256. return mComparator.compare(item_pair1->first, item_pair2->first);
  257. }
  258. const ItemComparator& mComparator;
  259. };
  260. friend class LLUICtrlFactory;
  261. LLFlatListView(const LLFlatListView::Params& p);
  262. /** Manage selection on mouse events */
  263. void onItemMouseClick(item_pair_t* item_pair, MASK mask);
  264. void onItemRightMouseClick(item_pair_t* item_pair, MASK mask);
  265. /**
  266. * Updates position of items.
  267. * It does not take into account invisible items.
  268. */
  269. virtual void rearrangeItems();
  270. virtual item_pair_t* getItemPair(LLPanel* item) const;
  271. virtual item_pair_t* getItemPair(const LLSD& value) const;
  272. virtual bool selectItemPair(item_pair_t* item_pair, bool select);
  273. virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection);
  274. virtual BOOL canSelectAll() const;
  275. virtual void selectAll();
  276. virtual bool isSelected(item_pair_t* item_pair) const;
  277. virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange);
  278. /**
  279. * Notify parent about changed size of internal controls with "size_changes" action
  280. *
  281. * Size includes Items Rect width and either Items Rect height or comment text height.
  282. * Comment text height is included if comment text is set and visible.
  283. * List border size is also included into notified size.
  284. */
  285. void notifyParentItemsRectChanged();
  286. virtual BOOL handleKeyHere(KEY key, MASK mask);
  287. virtual BOOL postBuild();
  288. virtual void onFocusReceived();
  289. virtual void onFocusLost();
  290. virtual void draw();
  291. LLRect getLastSelectedItemRect();
  292. void ensureSelectedVisible();
  293. private:
  294. void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;}
  295. void setNoItemsCommentVisible(bool visible) const;
  296. protected:
  297. /** Comparator to use when sorting the list. */
  298. const ItemComparator* mItemComparator;
  299. private:
  300. LLPanel* mItemsPanel;
  301. S32 mItemsNoScrollWidth;
  302. S32 mBorderThickness;
  303. /** Items padding */
  304. S32 mItemPad;
  305. /** Selection support flag */
  306. bool mAllowSelection;
  307. /** Multiselection support flag, ignored if selection is not supported */
  308. bool mMultipleSelection;
  309. /**
  310. * Flag specified whether onCommit be called if selection is changed in the list.
  311. *
  312. * Can be ignored in the resetSelection() method.
  313. * @see resetSelection()
  314. */
  315. bool mCommitOnSelectionChange;
  316. bool mKeepOneItemSelected;
  317. bool mIsConsecutiveSelection;
  318. bool mKeepSelectionVisibleOnReshape;
  319. /** All pairs of the list */
  320. pairs_list_t mItemPairs;
  321. /** Selected pairs for faster access */
  322. pairs_list_t mSelectedItemPairs;
  323. /**
  324. * Rectangle contained previous size of items parent notified last time.
  325. * Is used to reduce amount of parentNotify() calls if size was not changed.
  326. */
  327. LLRect mPrevNotifyParentRect;
  328. LLTextBox* mNoItemsCommentTextbox;
  329. LLViewBorder* mSelectedItemsBorder;
  330. commit_signal_t mOnReturnSignal;
  331. };
  332. /**
  333. * Extends LLFlatListView functionality to show different messages when there are no items in the
  334. * list depend on whether they are filtered or not.
  335. *
  336. * Class provides one message per case of empty list.
  337. * It also provides protected updateNoItemsMessage() method to be called each time when derived list
  338. * is changed to update base mNoItemsCommentTextbox value.
  339. *
  340. * It is implemented to avoid duplication of this functionality in concrete implementations of the
  341. * lists. It is intended to be used as a base class for lists which should support two different
  342. * messages for empty state. Can be improved to support more than two messages via state-to-message map.
  343. */
  344. class LLFlatListViewEx : public LLFlatListView
  345. {
  346. public:
  347. LOG_CLASS(LLFlatListViewEx);
  348. struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
  349. {
  350. /**
  351. * Contains a message for empty list when it does not contain any items at all.
  352. */
  353. Optional<std::string> no_items_msg;
  354. /**
  355. * Contains a message for empty list when its items are removed by filtering.
  356. */
  357. Optional<std::string> no_filtered_items_msg;
  358. Params();
  359. };
  360. // *WORKAROUND: two methods to overload appropriate Params due to localization issue:
  361. // no_items_msg & no_filtered_items_msg attributes are not defined as translatable in VLT. See EXT-5931
  362. void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; }
  363. void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; }
  364. bool getForceShowingUnmatchedItems();
  365. void setForceShowingUnmatchedItems(bool show);
  366. /**
  367. * Sets up new filter string and filters the list.
  368. */
  369. void setFilterSubString(const std::string& filter_str);
  370. /**
  371. * Filters the list, rearranges and notifies parent about shape changes.
  372. * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration.
  373. */
  374. void filterItems();
  375. /**
  376. * Returns true if last call of filterItems() found at least one matching item
  377. */
  378. bool hasMatchedItems();
  379. protected:
  380. LLFlatListViewEx(const Params& p);
  381. /**
  382. * Applies a message for empty list depend on passed argument.
  383. *
  384. * @param filter_string - if is not empty, message for filtered items will be set, otherwise for
  385. * completely empty list. Value of filter string will be passed as search_term in SLURL.
  386. */
  387. void updateNoItemsMessage(const std::string& filter_string);
  388. private:
  389. std::string mNoFilteredItemsMsg;
  390. std::string mNoItemsMsg;
  391. std::string mFilterSubString;
  392. /**
  393. * Show list items that don't match current filter
  394. */
  395. bool mForceShowingUnmatchedItems;
  396. /**
  397. * True if last call of filterItems() found at least one matching item
  398. */
  399. bool mHasMatchedItems;
  400. };
  401. #endif