1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #ifndef MYGUI_MULTI_LIST_BOX_H_
8 #define MYGUI_MULTI_LIST_BOX_H_
9 
10 #include "MyGUI_Prerequest.h"
11 #include "MyGUI_Widget.h"
12 #include "MyGUI_ListBox.h"
13 #include "MyGUI_Any.h"
14 #include "MyGUI_BiIndexBase.h"
15 #include "MyGUI_EventPair.h"
16 #include "MyGUI_IItem.h"
17 #include "MyGUI_IItemContainer.h"
18 #include "MyGUI_ResizingPolicy.h"
19 
20 namespace MyGUI
21 {
22 
23 	//OBSOLETE
24 	typedef delegates::CMultiDelegate5<Widget*, size_t, const UString&, const UString&, bool&> EventHandle_WidgetIntUTFStringUTFStringBool;
25 
26 	typedef delegates::CDelegate5<MultiListBox*, size_t, const UString&, const UString&, bool&> EventHandle_MultiListPtrSizeTCUTFStringRefCUTFStringRefBoolRef;
27 	typedef delegates::CDelegate5<MultiListBox*, size_t, size_t, size_t, bool&> EventHandle_MultiListPtrSizeTSizeTSizeTBoolRef;
28 	typedef delegates::CMultiDelegate2<MultiListBox*, size_t> EventHandle_MultiListPtrSizeT;
29 	typedef delegates::CMultiDelegate2<MultiListBox*, const IBNotifyItemData&> EventHandle_MultiListPtrCIBNotifyCellDataRef;
30 
31 	/** \brief @wpage{MultiListBox}
32 		MultiListBox widget description should be here.
33 	*/
34 	class MYGUI_EXPORT MultiListBox :
35 		public Widget,
36 		public BiIndexBase,
37 		public IItemContainer,
38 		public MemberObsolete<MultiListBox>
39 	{
40 		MYGUI_RTTI_DERIVED( MultiListBox )
41 
42 	public:
43 		MultiListBox();
44 
45 		//! @copydoc Widget::setPosition(const IntPoint& _value)
46 		void setPosition(const IntPoint& _value) override;
47 		//! @copydoc Widget::setSize(const IntSize& _value)
48 		void setSize(const IntSize& _value) override;
49 		//! @copydoc Widget::setCoord(const IntCoord& _value)
50 		void setCoord(const IntCoord& _value) override;
51 
52 		using Widget::setPosition;
53 		using Widget::setSize;
54 		using Widget::setCoord;
55 
56 		//------------------------------------------------------------------------------//
57 		// Methods for work with columns (RU:методы для работы со столбцами)
58 		//------------------------------------------------------------------------------//
59 		// манипуляции айтемами
60 
61 		//! Get number of columns
62 		size_t getColumnCount() const;
63 
64 		/** Insert new column
65 			@param _column New column will be inserted before _column
66 			@param _name Name of new column
67 			@param _width Width of new column
68 			@param _data Any data associated with new column
69 		*/
70 		void insertColumnAt(size_t _column, const UString& _name, int _width = 0, Any _data = Any::Null);
71 
72 		/** Add new column at last position
73 			@param _width Width of new column
74 			@param _name Name of new column
75 			@param _data Any data associated with new column
76 		*/
77 		void addColumn(const UString& _name, int _width = 0, Any _data = Any::Null);
78 
79 		/** Delete column */
80 		void removeColumnAt(size_t _column);
81 
82 		/** Delete all columns */
83 		void removeAllColumns();
84 
85 		//! Swap columns at a specified positions
86 		void swapColumnsAt(size_t _index1, size_t _index2);
87 
88 		//------------------------------------------------------------------------------//
89 		// манипуляции отображением
90 
91 		/** Set column name
92 			@param _column Index of column
93 			@param _name New name of column
94 		*/
95 		void setColumnNameAt(size_t _column, const UString& _name);
96 
97 		/** Set column name
98 			@param _item column
99 			@param _name New name of column
100 		*/
101 		void setColumnName(MultiListItem* _item, const UString& _name);
102 
103 		/** Set column width
104 			@param _column Index of column
105 			@param _width New width of column
106 		*/
107 		void setColumnWidthAt(size_t _column, int _width);
108 
109 		/** Set column width
110 			@param _item column
111 			@param _width New width of column
112 		*/
113 		void setColumnWidth(MultiListItem* _item, int _width);
114 
115 		/** Get _column name */
116 		const UString& getColumnNameAt(size_t _column);
117 
118 		/** Get _column name */
119 		const UString& getColumnName(MultiListItem* _item);
120 
121 		/** Get _column width */
122 		int getColumnWidthAt(size_t _column);
123 
124 		/** Sort multilist by column */
125 		void sortByColumn(size_t _column, bool _backward = false);
126 
127 		//! Get column index
128 		size_t getColumnIndex(MultiListItem* _item);
129 
130 		/** Set resizing policy of column. \sa ResizingPolicy
131 			@param _item Pointer to column
132 			@param _value New resizing policy for column
133 		*/
134 		void setColumnResizingPolicy(MultiListItem* _item, ResizingPolicy _value);
135 		/** Set resizing policy of column. \sa ResizingPolicy
136 			@param _index Index of column
137 			@param _value New resizing policy for column
138 		*/
139 		void setColumnResizingPolicyAt(size_t _index, ResizingPolicy _value);
140 
141 		//------------------------------------------------------------------------------//
142 		// манипуляции данными
143 
144 		//! Replace an item data at a specified position
145 		void setColumnDataAt(size_t _index, Any _data);
146 
147 		//! Clear an item data at a specified position
148 		void clearColumnDataAt(size_t _index);
149 
150 		//! Get item data from specified position
151 		template <typename ValueType>
152 		ValueType* getColumnDataAt(size_t _index, bool _throw = true)
153 		{
154 			MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::getItemDataAt");
155 			return mVectorColumnInfo[_index].data.castType<ValueType>(_throw);
156 		}
157 
158 		//------------------------------------------------------------------------------//
159 		// Methods for work with lines (RU:методы для работы со строками)
160 		/** @note
161 		All indexes used here is indexes of unsorted Multilist. Even if you sorted
162 			it - all items indexes will be same as before sort.
163 		*/
164 
165 		//------------------------------------------------------------------------------//
166 		// манипуляции айтемами
167 
168 		/** Get number of items (lines) */
169 		size_t getItemCount() const;
170 
171 		/** Insert new item before _index line */
172 		void insertItemAt(size_t _index, const UString& _name, Any _data = Any::Null);
173 
174 		/** Add new item at the end */
175 		void addItem(const UString& _name, Any _data = Any::Null);
176 
177 		//! Remove item at a specified position
178 		void removeItemAt(size_t _index);
179 
180 		/** Delete all items */
181 		void removeAllItems();
182 
183 		//! Swap items at a specified positions
184 		void swapItemsAt(size_t _index1, size_t _index2);
185 
186 
187 		//------------------------------------------------------------------------------//
188 		// манипуляции отображением
189 
190 		//! Replace an item name
191 		void setItemNameAt(size_t _index, const UString& _name);
192 
193 		//! Get item name from specified position
194 		const UString& getItemNameAt(size_t _index);
195 
196 
197 		//------------------------------------------------------------------------------//
198 		// манипуляции выделениями
199 
200 		/** Get index of selected item (ITEM_NONE if none selected) */
201 		size_t getIndexSelected() const;
202 
203 		/** Select specified _index */
204 		void setIndexSelected(size_t _index);
205 
206 		/** Clear item selection */
207 		void clearIndexSelected();
208 
209 
210 		//------------------------------------------------------------------------------//
211 		// манипуляции данными
212 
213 		//! Replace an item data at a specified position
214 		void setItemDataAt(size_t _index, Any _data);
215 
216 		//! Clear an item data at a specified position
217 		void clearItemDataAt(size_t _index);
218 
219 		//! Get item data from specified position
220 		template <typename ValueType>
221 		ValueType* getItemDataAt(size_t _index, bool _throw = true)
222 		{
223 			return getSubItemDataAt<ValueType>(0, _index, _throw);
224 		}
225 
226 
227 		//------------------------------------------------------------------------------//
228 		// Methods for work with sub lines (RU:методы для работы со саб строками)
229 		//------------------------------------------------------------------------------//
230 		// манипуляции данными
231 
232 		/** Set sub item
233 			@param _column Index of column
234 			@param _index Index of line
235 			@param _name New sub item value
236 		*/
237 		void setSubItemNameAt(size_t _column, size_t _index, const UString& _name);
238 
239 		/** Get sub item name*/
240 		const UString& getSubItemNameAt(size_t _column, size_t _index);
241 
242 		/** Search item in specified _column, returns index of the first occurrence in column or ITEM_NONE if item not found */
243 		size_t findSubItemWith(size_t _column, const UString& _name);
244 
245 		//------------------------------------------------------------------------------//
246 		// манипуляции данными
247 
248 		//! Replace an item data at a specified position
249 		void setSubItemDataAt(size_t _column, size_t _index, Any _data);
250 
251 		//! Clear an item data at a specified position
252 		void clearSubItemDataAt(size_t _column, size_t _index);
253 
254 		//! Get item data from specified position
255 		template <typename ValueType>
256 		ValueType* getSubItemDataAt(size_t _column, size_t _index, bool _throw = true)
257 		{
258 			MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::getSubItemDataAt");
259 
260 			size_t index = BiIndexBase::convertToBack(_index);
261 			return getSubItemAt(_column)->getItemDataAt<ValueType>(index, _throw);
262 		}
263 
264 		/*events:*/
265 		/** Event : Enter pressed or double click.\n
266 			signature : void method(MyGUI::MultiListBox* _sender, size_t _index)\n
267 			@param _sender widget that called this event
268 			@param _index of selected item
269 		*/
270 		EventPair<EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT> eventListSelectAccept;
271 
272 		/** Event : Selected item position changed.\n
273 			signature : void method(MyGUI::MultiListBox* _sender, size_t _index)\n
274 			@param _sender widget that called this event
275 			@param _index of new item
276 		*/
277 		EventPair<EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT> eventListChangePosition;
278 
279 		/** Event : Less than operator for sort multilist by columns.\n
280 			signature : void method(MyGUI::MultiListBox* _sender, size_t _column, size_t _index1, size_t _index2, bool& _less)\n
281 			@param _sender widget that called this event
282 			@param _column Index of column
283 			@param _index1 Index of row for compare
284 			@param _index2 Index of row for compare
285 			@param _less Comparsion result (write your value here)
286 		*/
287 		EventPair<EventHandle_MultiListPtrSizeTCUTFStringRefCUTFStringRefBoolRef, EventHandle_MultiListPtrSizeTSizeTSizeTBoolRef> requestOperatorLess;
288 
289 		/** Event : Notify about event in item widget.\n
290 		signature : void method(MyGUI::MultiList* _sender, const MyGUI::IBNotifyItemData& _info)
291 		@param _sender widget that called this event
292 		@param _info info about item notify
293 		*/
294 		EventHandle_MultiListPtrCIBNotifyCellDataRef eventNotifyItem;
295 
296 		/*internal:*/
297 		// IItemContainer impl
298 		size_t _getItemCount() override;
299 		void _addItem(const MyGUI::UString& _name) override;
300 		void _removeItemAt(size_t _index) override;
301 		Widget* _getItemAt(size_t _index) override;
302 		void _setItemNameAt(size_t _index, const UString& _name) override;
303 		const UString& _getItemNameAt(size_t _index) override;
304 
305 	protected:
306 		void initialiseOverride() override;
307 		void shutdownOverride() override;
308 
309 		void onWidgetCreated(Widget* _widget) override;
310 		void onWidgetDestroy(Widget* _widget) override;
311 
312 	private:
313 		void notifyListChangePosition(ListBox* _sender, size_t _position);
314 		void notifyListChangeFocus(ListBox* _sender, size_t _position);
315 		void notifyListChangeScrollPosition(ListBox* _sender, size_t _position);
316 		void notifyButtonClick(Widget* _sender);
317 		void notifyListSelectAccept(ListBox* _sender, size_t _position);
318 		void notifyListNotifyItem(ListBox* _sender, const MyGUI::IBNotifyItemData& _info);
319 
320 		void updateColumns();
321 		void redrawButtons();
322 		void updateOnlyEmpty();
323 
324 		bool compare(ListBox* _list, size_t _left, size_t _right);
325 		void sortList();
326 		void flipList();
327 
328 		Widget* getSeparator(size_t _index);
329 
330 		void updateBackSelected(size_t _index);
331 
332 		struct ColumnInfo
333 		{
334 			MultiListItem* item;
335 			ListBox* list;
336 			Button* button;
337 			int width;
338 			int realWidth;
339 			UString name;
340 			Any data;
341 			ResizingPolicy sizeType;
342 		};
343 
344 		typedef std::vector<ColumnInfo> VectorColumnInfo;
345 
346 		void frameEntered(float _frame);
347 		void frameAdvise(bool _advise);
348 
349 		ListBox* getSubItemAt(size_t _column);
350 		int getButtonHeight() const;
351 
352 		void _wrapItem(MultiListItem* _item);
353 		void _unwrapItem(MultiListItem* _item);
354 		void _swapColumnsAt(size_t _index1, size_t _index2);
355 
356 		int getColumnWidth(size_t _index, int _freeSpace, size_t _countStars, size_t _lastIndexStar, int _starWidth) const;
357 		bool getUpdateByResize();
358 		int updateWidthColumns(size_t& _countStars, size_t& _lastIndexStar);
359 
360 	private:
361 		int mHeightButton;
362 		int mWidthBar;
363 		std::string mSkinButton;
364 		std::string mSkinList;
365 		Widget* mWidgetEmpty;
366 
367 		VectorColumnInfo mVectorColumnInfo;
368 
369 		VectorWidgetPtr mSeparators;
370 
371 		size_t mLastMouseFocusIndex;
372 
373 		bool mSortUp;
374 		size_t mSortColumnIndex;
375 
376 		int mWidthSeparator;
377 		std::string mSkinSeparator;
378 
379 		size_t mItemSelected;
380 
381 		bool mFrameAdvise;
382 		Widget* mHeaderPlace;
383 	};
384 
385 } // namespace MyGUI
386 
387 #endif // MYGUI_MULTI_LIST_BOX_H_
388