PageRenderTime 46ms CodeModel.GetById 13ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llui/llscrolllistctrl.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 513 lines | 322 code | 107 blank | 84 comment | 6 complexity | b65b9664b98bfba18c579f68e806fb5d MD5 | raw file
  1/** 
  2 * @file llscrolllistctrl.h
  3 * @brief A scrolling list of items.  This is the one you want to use
  4 * in UI code.  LLScrollListCell, LLScrollListItem, etc. are utility
  5 * classes.
  6 *
  7 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#ifndef LL_SCROLLLISTCTRL_H
 30#define LL_SCROLLLISTCTRL_H
 31
 32#include <vector>
 33#include <deque>
 34
 35#include "lluictrl.h"
 36#include "llctrlselectioninterface.h"
 37//#include "lldarray.h"
 38#include "llfontgl.h"
 39#include "llui.h"
 40#include "llstring.h"	// LLWString
 41#include "lleditmenuhandler.h"
 42#include "llframetimer.h"
 43
 44#include "llscrollbar.h"
 45#include "lldate.h"
 46#include "llscrolllistitem.h"
 47#include "llscrolllistcolumn.h"
 48#include "llviewborder.h"
 49
 50class LLScrollListCell;
 51class LLTextBox;
 52class LLContextMenu;
 53
 54class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, 
 55	public LLCtrlListInterface, public LLCtrlScrollInterface
 56{
 57public:
 58	struct Contents : public LLInitParam::Block<Contents>
 59	{
 60		Multiple<LLScrollListColumn::Params>	columns;
 61		Multiple<LLScrollListItem::Params>		rows;
 62
 63		//Multiple<Contents>						groups;
 64
 65		Contents();
 66	};
 67
 68	// *TODO: Add callbacks to Params
 69	typedef boost::function<void (void)> callback_t;
 70
 71	template<typename T> struct maximum
 72	{
 73		typedef T result_type;
 74
 75		template<typename InputIterator>
 76		T operator()(InputIterator first, InputIterator last) const
 77		{
 78			// If there are no slots to call, just return the
 79			// default-constructed value
 80			if(first == last ) return T();
 81			T max_value = *first++;
 82			while (first != last) {
 83				if (max_value < *first)
 84				max_value = *first;
 85				++first;
 86			}
 87
 88			return max_value;
 89		}
 90	};
 91
 92	
 93	typedef boost::signals2::signal<S32 (S32,const LLScrollListItem*,const LLScrollListItem*),maximum<S32> > sort_signal_t;
 94	
 95	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
 96	{
 97		// behavioral flags
 98		Optional<bool>	multi_select,
 99						commit_on_keyboard_movement,
100						mouse_wheel_opaque;
101
102		// display flags
103		Optional<bool>	has_border,
104						draw_heading,
105						draw_stripes,
106						background_visible,
107						scroll_bar_bg_visible;
108
109		// layout
110		Optional<S32>	column_padding,
111							page_lines,
112						heading_height;
113
114		// sort and search behavior
115		Optional<S32>	search_column,
116						sort_column;
117		Optional<bool>	sort_ascending;
118
119		// colors
120		Optional<LLUIColor>	fg_unselected_color,
121							fg_selected_color,
122							bg_selected_color,
123							fg_disable_color,
124							bg_writeable_color,
125							bg_readonly_color,
126							bg_stripe_color,
127							hovered_color,
128							highlighted_color,
129							scroll_bar_bg_color;
130
131		Optional<Contents> contents;
132
133		Optional<LLViewBorder::Params> border;
134		
135		Params();
136	};
137
138protected:
139	friend class LLUICtrlFactory;
140
141	LLScrollListCtrl(const Params&);
142
143public:
144	virtual ~LLScrollListCtrl();
145
146	S32				isEmpty() const;
147
148	void			deleteAllItems() { clearRows(); }
149	
150	// Sets an array of column descriptors
151	void 	   		setColumnHeadings(const LLSD& headings);
152	void   			sortByColumnIndex(U32 column, BOOL ascending);
153	
154	// LLCtrlListInterface functions
155	virtual S32  getItemCount() const;
156	// Adds a single column descriptor: ["name" : string, "label" : string, "width" : integer, "relwidth" : integer ]
157	virtual void addColumn(const LLScrollListColumn::Params& column, EAddPosition pos = ADD_BOTTOM);
158	virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM);	
159	virtual void clearColumns();
160	virtual void setColumnLabel(const std::string& column, const std::string& label);
161	virtual bool 	preProcessChildNode(LLXMLNodePtr child);
162	virtual LLScrollListColumn* getColumn(S32 index);
163	virtual LLScrollListColumn* getColumn(const std::string& name);
164	virtual S32 getNumColumns() const { return mColumnsIndexed.size(); }
165
166	// Adds a single element, from an array of:
167	// "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid
168	// Creates missing columns automatically.
169	virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
170	virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);
171	virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);
172	// Simple add element. Takes a single array of:
173	// [ "value" => value, "font" => font, "font-style" => style ]
174	virtual void clearRows(); // clears all elements
175	virtual void sortByColumn(const std::string& name, BOOL ascending);
176
177	// These functions take and return an array of arrays of elements, as above
178	virtual void	setValue(const LLSD& value );
179	virtual LLSD	getValue() const;
180
181	LLCtrlSelectionInterface*	getSelectionInterface()	{ return (LLCtrlSelectionInterface*)this; }
182	LLCtrlListInterface*		getListInterface()		{ return (LLCtrlListInterface*)this; }
183	LLCtrlScrollInterface*		getScrollInterface()	{ return (LLCtrlScrollInterface*)this; }
184
185	// DEPRECATED: Use setSelectedByValue() below.
186	BOOL			setCurrentByID( const LLUUID& id )	{ return selectByID(id); }
187	virtual LLUUID	getCurrentID() const				{ return getStringUUIDSelectedItem(); }
188
189	BOOL			operateOnSelection(EOperation op);
190	BOOL			operateOnAll(EOperation op);
191
192	// returns FALSE if unable to set the max count so low
193	BOOL 			setMaxItemCount(S32 max_count);
194
195	BOOL			selectByID( const LLUUID& id );		// FALSE if item not found
196
197	// Match item by value.asString(), which should work for string, integer, uuid.
198	// Returns FALSE if not found.
199	BOOL			setSelectedByValue(const LLSD& value, BOOL selected);
200
201	BOOL			isSorted() const { return mSorted; }
202
203	virtual BOOL	isSelected(const LLSD& value) const;
204
205	BOOL			handleClick(S32 x, S32 y, MASK mask);
206	BOOL			selectFirstItem();
207	BOOL			selectNthItem( S32 index );
208	BOOL			selectItemRange( S32 first, S32 last );
209	BOOL			selectItemAt(S32 x, S32 y, MASK mask);
210	
211	void			deleteSingleItem( S32 index );
212	void			deleteItems(const LLSD& sd);
213	void 			deleteSelectedItems();
214	void			deselectAllItems(BOOL no_commit_on_change = FALSE);	// by default, go ahead and commit on selection change
215
216	void			clearHighlightedItems();
217	
218	virtual void	mouseOverHighlightNthItem( S32 index );
219
220	S32				getHighlightedItemInx() const { return mHighlightedItem; } 
221	
222	void			setDoubleClickCallback( callback_t cb ) { mOnDoubleClickCallback = cb; }
223	void			setMaximumSelectCallback( callback_t cb) { mOnMaximumSelectCallback = cb; }
224	void			setSortChangedCallback( callback_t cb) 	{ mOnSortChangedCallback = cb; }
225	// Convenience function; *TODO: replace with setter above + boost::bind() in calling code
226	void			setDoubleClickCallback( boost::function<void (void* userdata)> cb, void* userdata) { mOnDoubleClickCallback = boost::bind(cb, userdata); }
227
228	void			swapWithNext(S32 index);
229	void			swapWithPrevious(S32 index);
230
231	void			setCanSelect(BOOL can_select)		{ mCanSelect = can_select; }
232	virtual BOOL	getCanSelect() const				{ return mCanSelect; }
233
234	S32				getItemIndex( LLScrollListItem* item ) const;
235	S32				getItemIndex( const LLUUID& item_id ) const;
236
237	void setCommentText( const std::string& comment_text);
238	LLScrollListItem* addSeparator(EAddPosition pos);
239
240	// "Simple" interface: use this when you're creating a list that contains only unique strings, only
241	// one of which can be selected at a time.
242	virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
243
244	BOOL			selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE );		// FALSE if item not found
245	BOOL			selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);
246	BOOL			selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
247	LLScrollListItem*  getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
248	const std::string	getSelectedItemLabel(S32 column = 0) const;
249	LLSD			getSelectedValue();
250
251	// DEPRECATED: Use LLSD versions of setCommentText() and getSelectedValue().
252	// "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
253	// has an associated, unique UUID, and only one of which can be selected at a time.
254	LLScrollListItem*	addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
255	LLUUID				getStringUUIDSelectedItem() const;
256
257	LLScrollListItem*	getFirstSelected() const;
258	virtual S32			getFirstSelectedIndex() const;
259	std::vector<LLScrollListItem*> getAllSelected() const;
260	LLScrollListItem*	getLastSelectedItem() const { return mLastSelected; }
261
262	// iterate over all items
263	LLScrollListItem*	getFirstData() const;
264	LLScrollListItem*	getLastData() const;
265	std::vector<LLScrollListItem*>	getAllData() const;
266
267	LLScrollListItem*	getItem(const LLSD& sd) const;
268	
269	void setAllowMultipleSelection(BOOL mult )	{ mAllowMultipleSelection = mult; }
270
271	void setBgWriteableColor(const LLColor4 &c)	{ mBgWriteableColor = c; }
272	void setReadOnlyBgColor(const LLColor4 &c)	{ mBgReadOnlyColor = c; }
273	void setBgSelectedColor(const LLColor4 &c)	{ mBgSelectedColor = c; }
274	void setBgStripeColor(const LLColor4& c)	{ mBgStripeColor = c; }
275	void setFgSelectedColor(const LLColor4 &c)	{ mFgSelectedColor = c; }
276	void setFgUnselectedColor(const LLColor4 &c){ mFgUnselectedColor = c; }
277	void setHoveredColor(const LLColor4 &c)		{ mHoveredColor = c; }
278	void setHighlightedColor(const LLColor4 &c) { mHighlightedColor = c; }
279	void setFgDisableColor(const LLColor4 &c)	{ mFgDisabledColor = c; }
280
281	void setBackgroundVisible(BOOL b)			{ mBackgroundVisible = b; }
282	void setDrawStripes(BOOL b)					{ mDrawStripes = b; }
283	void setColumnPadding(const S32 c)          { mColumnPadding = c; }
284	S32  getColumnPadding()						{ return mColumnPadding; }
285	void setCommitOnKeyboardMovement(BOOL b)	{ mCommitOnKeyboardMovement = b; }
286	void setCommitOnSelectionChange(BOOL b)		{ mCommitOnSelectionChange = b; }
287	void setAllowKeyboardMovement(BOOL b)		{ mAllowKeyboardMovement = b; }
288
289	void			setMaxSelectable(U32 max_selected) { mMaxSelectable = max_selected; }
290	S32				getMaxSelectable() { return mMaxSelectable; }
291
292
293	virtual S32		getScrollPos() const;
294	virtual void	setScrollPos( S32 pos );
295	S32 getSearchColumn();
296	void			setSearchColumn(S32 column) { mSearchColumn = column; }
297	S32				getColumnIndexFromOffset(S32 x);
298	S32				getColumnOffsetFromIndex(S32 index);
299	S32				getRowOffsetFromIndex(S32 index);
300
301	void			clearSearchString() { mSearchString.clear(); }
302
303	// support right-click context menus for avatar/group lists
304	enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP };
305	void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; }
306
307	// Overridden from LLView
308	/*virtual*/ void    draw();
309	/*virtual*/ BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
310	/*virtual*/ BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
311	/*virtual*/ BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
312	/*virtual*/ BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
313	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);
314	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask);
315	/*virtual*/ BOOL	handleUnicodeCharHere(llwchar uni_char);
316	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks);
317	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask);
318	/*virtual*/ void	setEnabled(BOOL enabled);
319	/*virtual*/ void	setFocus( BOOL b );
320	/*virtual*/ void	onFocusReceived();
321	/*virtual*/ void	onFocusLost();
322	/*virtual*/ void	onMouseLeave(S32 x, S32 y, MASK mask);
323	/*virtual*/ void	reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
324
325	virtual BOOL	isDirty() const;
326	virtual void	resetDirty();		// Clear dirty state
327
328	virtual void	updateLayout();
329	virtual void	fitContents(S32 max_width, S32 max_height);
330
331	virtual LLRect	getRequiredRect();
332	static  BOOL    rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row);
333
334	LLRect			getItemListRect() { return mItemListRect; }
335
336	/// Returns rect, in local coords, of a given row/column
337	LLRect			getCellRect(S32 row_index, S32 column_index);
338
339	// Used "internally" by the scroll bar.
340	void			onScrollChange( S32 new_pos, LLScrollbar* src );
341
342	static void onClickColumn(void *userdata);
343
344	virtual void updateColumns();
345	void calcColumnWidths();
346	S32 getMaxContentWidth() { return mMaxContentWidth; }
347
348	void setHeadingHeight(S32 heading_height);
349	/**
350	 * Sets  max visible  lines without scroolbar, if this value equals to 0,
351	 * then display all items.
352	 */
353	void setPageLines(S32 page_lines );
354	void setCollapseEmptyColumns(BOOL collapse);
355
356	LLScrollListItem*	hitItem(S32 x,S32 y);
357	virtual void		scrollToShowSelected();
358
359	// LLEditMenuHandler functions
360	virtual void	copy();
361	virtual BOOL	canCopy() const;
362	virtual void	cut();
363	virtual BOOL	canCut() const;
364	virtual void	selectAll();
365	virtual BOOL	canSelectAll() const;
366	virtual void	deselect();
367	virtual BOOL	canDeselect() const;
368
369	void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; }
370	void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width);
371	S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; }
372
373	std::string     getSortColumnName();
374	BOOL			getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
375	BOOL			hasSortOrder() const;
376
377	S32		selectMultiple( uuid_vec_t ids );
378	// conceptually const, but mutates mItemList
379	void			updateSort() const;
380	// sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example)
381	void			sortOnce(S32 column, BOOL ascending);
382
383	// manually call this whenever editing list items in place to flag need for resorting
384	void			setNeedsSort(bool val = true) { mSorted = !val; }
385	void			dirtyColumns(); // some operation has potentially affected column layout or ordering
386
387	boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb )
388	{
389		if (!mSortCallback) mSortCallback = new sort_signal_t();
390		return mSortCallback->connect(cb);
391	}
392
393
394protected:
395	// "Full" interface: use this when you're creating a list that has one or more of the following:
396	// * contains icons
397	// * contains multiple columns
398	// * allows multiple selection
399	// * has items that are not guarenteed to have unique names
400	// * has additional per-item data (e.g. a UUID or void* userdata)
401	//
402	// To add items using this approach, create new LLScrollListItems and LLScrollListCells.  Add the
403	// cells (column entries) to each item, and add the item to the LLScrollListCtrl.
404	//
405	// The LLScrollListCtrl owns its items and is responsible for deleting them
406	// (except in the case that the addItem() call fails, in which case it is up
407	// to the caller to delete the item)
408	//
409	// returns FALSE if item faile to be added to list, does NOT delete 'item'
410	BOOL			addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM, BOOL requires_column = TRUE );
411
412	typedef std::deque<LLScrollListItem *> item_list;
413	item_list&		getItemList() { return mItemList; }
414
415	void			updateLineHeight();
416
417private:
418	void			selectPrevItem(BOOL extend_selection);
419	void			selectNextItem(BOOL extend_selection);
420	void			drawItems();
421	
422	void            updateLineHeightInsert(LLScrollListItem* item);
423	void			reportInvalidInput();
424	BOOL			isRepeatedChars(const LLWString& string) const;
425	void			selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
426	void			deselectItem(LLScrollListItem* itemp);
427	void			commitIfChanged();
428	BOOL			setSort(S32 column, BOOL ascending);
429	S32				getLinesPerPage();
430
431	static void		showNameDetails(std::string id, bool is_group);
432	static void		copyNameToClipboard(std::string id, bool is_group);
433	static void		copySLURLToClipboard(std::string id, bool is_group);
434
435	S32				mLineHeight;	// the max height of a single line
436	S32				mScrollLines;	// how many lines we've scrolled down
437	S32				mPageLines;		// max number of lines is it possible to see on the screen given mRect and mLineHeight
438	S32				mHeadingHeight;	// the height of the column header buttons, if visible
439	U32				mMaxSelectable; 
440	LLScrollbar*	mScrollbar;
441	BOOL 			mAllowMultipleSelection;
442	BOOL			mAllowKeyboardMovement;
443	BOOL			mCommitOnKeyboardMovement;
444	BOOL			mCommitOnSelectionChange;
445	BOOL			mSelectionChanged;
446	BOOL			mNeedsScroll;
447	BOOL			mMouseWheelOpaque;
448	BOOL			mCanSelect;
449	const BOOL		mDisplayColumnHeaders;
450	BOOL			mColumnsDirty;
451
452	mutable item_list	mItemList;
453
454	LLScrollListItem *mLastSelected;
455
456	S32				mMaxItemCount; 
457
458	LLRect			mItemListRect;
459	S32				mMaxContentWidth;
460	S32             mColumnPadding;
461
462	BOOL			mBackgroundVisible;
463	BOOL			mDrawStripes;
464
465	LLUIColor		mBgWriteableColor;
466	LLUIColor		mBgReadOnlyColor;
467	LLUIColor		mBgSelectedColor;
468	LLUIColor		mBgStripeColor;
469	LLUIColor		mFgSelectedColor;
470	LLUIColor		mFgUnselectedColor;
471	LLUIColor		mFgDisabledColor;
472	LLUIColor		mHoveredColor;
473	LLUIColor		mHighlightedColor;
474
475	S32				mBorderThickness;
476	callback_t		mOnDoubleClickCallback;
477	callback_t 		mOnMaximumSelectCallback;
478	callback_t 		mOnSortChangedCallback;
479
480	S32				mHighlightedItem;
481	class LLViewBorder*	mBorder;
482	LLContextMenu	*mPopupMenu;
483	
484	LLView			*mCommentTextView;
485
486	LLWString		mSearchString;
487	LLFrameTimer	mSearchTimer;
488	
489	S32				mSearchColumn;
490	S32				mNumDynamicWidthColumns;
491	S32				mTotalStaticColumnWidth;
492	S32				mTotalColumnPadding;
493
494	mutable bool	mSorted;
495	
496	typedef std::map<std::string, LLScrollListColumn*> column_map_t;
497	column_map_t mColumns;
498
499	BOOL			mDirty;
500	S32				mOriginalSelection;
501
502	ContextMenuType mContextMenuType;
503
504	typedef std::vector<LLScrollListColumn*> ordered_columns_t;
505	ordered_columns_t	mColumnsIndexed;
506
507	typedef std::pair<S32, BOOL> sort_column_t;
508	std::vector<sort_column_t>	mSortColumns;
509
510	sort_signal_t*	mSortCallback;
511}; // end class LLScrollListCtrl
512
513#endif  // LL_SCROLLLISTCTRL_H