1 #ifndef CUSTOMVIRTLISTITEM_H_ 2 #define CUSTOMVIRTLISTITEM_H_ 3 4 #include <wx/listctrl.h> 5 6 #include <wx/timer.h> 7 #define IDD_TIP_TIMER 696 8 #define IDD_SORT_TIMER 697 9 10 #include <vector> 11 12 #include <utility> 13 #include <map> 14 15 #include "useractions.h" 16 #include "helper/sortutil.h" 17 #include "utils/globalevents.h" 18 #include "utils/mixins.hh" 19 20 const wxEventType ListctrlDoSortEventType = wxNewEventType(); 21 22 class ListctrlSortEvent : public wxCommandEvent 23 { 24 public: 25 ListctrlSortEvent( int event_id = wxNewId() ) wxCommandEvent(ListctrlDoSortEventType,event_id)26 : wxCommandEvent( ListctrlDoSortEventType, event_id ) 27 {} 28 }; 29 30 class SLTipWindow; 31 32 /** \brief Used as base class for some ListCtrls throughout SL 33 * Provides generic functionality, such as column tooltips, possiblity to prohibit column resizing and selection modifiers. \n 34 * Some of the provided functionality only makes sense for single-select lists (see grouping) \n 35 * Note: the second template param is actually just a dummy to ensure the compiler generates distinct code in case we have different listctrls with same datatype 36 * Note: Tooltips are a bitch and anyone should feel free to revise them (koshi) 37 * \tparam the type of stored data 38 */ 39 template < class DataImp, class ListCtrlImp > 40 class CustomVirtListCtrl : public wxListCtrl, public SL::NonCopyable 41 { 42 public: 43 typedef DataImp DataType; 44 protected: 45 typedef CustomVirtListCtrl< DataImp, ListCtrlImp> BaseType; 46 typedef UserActions::ActionType ActionType; 47 //! used to display tooltips for a certain amount of time 48 wxTimer m_tiptimer; 49 //! used to block sorting while mouse is moving 50 wxTimer m_sort_timer; 51 //! always set to the currrently displayed tooltip text 52 wxString m_tiptext; 53 #if wxUSE_TIPWINDOW 54 //! some wx implementations do not support this yet 55 SLTipWindow* m_tipwindow; 56 SLTipWindow** m_controlPointer; 57 #endif 58 unsigned int m_columnCount; 59 60 struct colInfo { colInfocolInfo61 colInfo(int n, wxString l, wxString t, bool c, int s): 62 col_num(n), 63 label(l), 64 tip(t), 65 can_resize(c), 66 size(s) 67 {} colInfocolInfo68 colInfo(): 69 col_num(0), 70 can_resize(false), 71 size(0) 72 {} 73 74 int col_num; 75 wxString label; 76 wxString tip; 77 bool can_resize; 78 int size; 79 }; 80 81 typedef std::vector<colInfo> colInfoVec; 82 83 //! maps outward column index to internal 84 typedef std::map<unsigned int,unsigned int> ColumnMap; 85 86 /** global Tooltip thingies (ms) 87 */ 88 static const unsigned int m_tooltip_delay = 1000; 89 static const unsigned int m_tooltip_duration = 2000; 90 static const unsigned int m_sort_block_time = 1500; 91 92 /*** these are only meaningful in single selection lists ***/ 93 //! index of curently selected data 94 long m_selected_index; 95 96 //! index of previously selected data 97 long m_prev_selected_index; 98 /***********************************************************/ 99 100 //! stores info about the columns (wxString name,bool isResizable) - pairs 101 colInfoVec m_colinfovec; 102 //! primarily used to get coulumn index in mousevents (from cur. mouse pos) 103 int getColumnFromPosition(wxPoint pos); 104 105 //! map: index in visible list <--> index in data vector 106 typedef std::map<int,int> VisibilityMap; 107 typedef VisibilityMap::iterator VisibilityMapIter; 108 /** \brief list indexes of not-filtered items 109 * use like this: when adding items set identity mapping \n 110 m_visible_idxs[m_data.size() -1] = ( m_data.size() -1 ); \n 111 when filtering clear the map, iterate thru data and only set mapping for matching items in data \n 112 when acessing data (getColoumText etc.) always access data's index thru this map 113 **/ 114 VisibilityMap m_visible_idxs; 115 116 117 wxPoint m_last_mouse_pos; 118 119 //! used as label for saving column widths 120 wxString m_name; 121 122 //!controls if highlighting should be considered 123 bool m_highlight; 124 125 //! which action should be considered? 126 ActionType m_highlightAction; 127 128 const wxColour m_bg_color; 129 130 //! list should be sorted 131 bool m_dirty_sort; 132 133 virtual void SetTipWindowText( const long item_hit, const wxPoint& position); 134 135 ColumnMap m_column_map; 136 137 /** @name Sort functionality 138 * 139 * @{ 140 */ 141 142 static SortOrder m_sortorder; 143 unsigned int m_sort_criteria_count; 144 145 /** generic comparator that gets it's real functionality 146 * in derived classes via comapre callbakc func that 147 * performs the actual comparison of two items **/ 148 template < class ObjImp > 149 struct ItemComparator { 150 typedef ObjImp ObjType; 151 SortOrder& m_order; 152 typedef int (ListCtrlImp::*CmpFunc) ( ObjType u1, ObjType u2, int, int ) const; 153 CmpFunc m_cmp_func; 154 const unsigned int m_num_criteria; 155 const BaseType* m_listctrl; 156 157 /** \param order SortOrder map that defines which columns should be sorted in what directions 158 * \param func the comparison callback func. Should return -1,0,1 for less,equal,greater 159 * \param num_criteria set to 1,2 to limit sub-ordering 160 * \todo make order const reference to eliminate assumption about existence of entries 161 */ 162 ItemComparator( const BaseType* listctrl, SortOrder& order,CmpFunc func, const unsigned int num_criteria = 3 ) m_orderItemComparator163 :m_order(order), 164 m_cmp_func(func), 165 m_num_criteria(num_criteria), 166 m_listctrl( listctrl ) 167 {} 168 operatorItemComparator169 bool operator () ( ObjType u1, ObjType u2 ) const { 170 int res = (m_listctrl->asImp().*m_cmp_func)( u1, u2, m_order[0].col, m_order[0].direction ); 171 if ( res != 0 ) 172 return res < 0; 173 174 if ( m_num_criteria > 1 ) { 175 res = (m_listctrl->asImp().*m_cmp_func)( u1, u2, m_order[1].col, m_order[1].direction ); 176 if ( res != 0 ) 177 return res < 0; 178 179 if ( m_num_criteria > 2 ) { 180 res = (m_listctrl->asImp().*m_cmp_func)( u1, u2, m_order[2].col, m_order[2].direction ); 181 if ( res != 0 ) 182 return res < 0; 183 } 184 } 185 return false; 186 } 187 }; 188 189 typedef typename ItemComparator<DataImp>::CmpFunc CompareFunction; 190 191 //! compare func usable for types with well-defined ordering (and implemented ops <,>) 192 template < typename Type > compareSimple(Type o1,Type o2)193 static inline int compareSimple( Type o1, Type o2 ) { 194 if ( o1 < o2 ) 195 return -1; 196 else if ( o1 > o2 ) 197 return 1; 198 return 0; 199 } 200 201 //! must be implemented in derived classes, should call the actual sorting on data and refreshitems 202 virtual void Sort( ) = 0; 203 204 public: 205 /** only sorts if data is marked dirty, or force is true 206 * calls Freeze(), Sort(), Thaw() */ 207 void SortList( bool force = false ); 208 /** @} 209 */ 210 211 public: 212 CustomVirtListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt, 213 const wxSize& sz,long style, const wxString& name, unsigned int sort_criteria_count, CompareFunction func, bool highlight = true, 214 UserActions::ActionType hlaction = UserActions::ActHighlight, bool periodic_sort = false, unsigned int periodic_sort_interval = 5000 /*miliseconds*/); 215 216 virtual ~CustomVirtListCtrl(); 217 218 void OnSelected( wxListEvent& event ); 219 void OnDeselected( wxListEvent& event ); 220 /** @name Single Selection methods 221 * using these funcs in a multi selection list is meaningless at best, harmful in the worst case 222 * \todo insert debug asserts to catch that 223 * @{ 224 */ 225 long GetSelectedIndex() const; 226 void SetSelectedIndex(const long newindex); 227 DataType GetDataFromIndex ( const long index ); 228 const DataType GetDataFromIndex ( const long index ) const; 229 DataType GetSelectedData(); 230 /** @} 231 */ 232 233 /** @name Multi Selection methods 234 * call this before example before sorting, inserting, etc 235 */ 236 void SaveSelection(); 237 void ResetSelection(); 238 //! and this afterwards 239 void RestoreSelection(); 240 /** @} 241 */ 242 243 //! intermediate function to add info to m_colinfovec after calling base class function 244 void AddColumn(long i, int width, const wxString& label, const wxString& tip, bool = true); 245 //! this event is triggered when delay timer (set in mousemotion) ended 246 virtual void OnTimer(wxTimerEvent& event); 247 //! prohibits resizin if so set in columnInfo 248 void OnStartResizeCol(wxListEvent& event); 249 //! we use this to automatically save column width after resizin 250 virtual void OnEndResizeCol(wxListEvent& event); 251 //! starts timer, sets tooltiptext 252 virtual void OnMouseMotion(wxMouseEvent& event); 253 //! stop timer (before displaying popup f.e.) 254 void CancelTooltipTimer(); 255 //!Override to have tooltip timer cancelled automatically 256 bool PopupMenu(wxMenu* menu, const wxPoint& pos = wxDefaultPosition); 257 //! does nothing 258 void noOp(wxMouseEvent& event); 259 //! automatically get saved column width if already saved, otherwise use parameter and save new width 260 virtual bool SetColumnWidth(int col, int& width); 261 //! reset columns with current set size (only effects columns with auto-size) 262 void ResetColumnSizes(); 263 264 // funcs that should make things easier for group highlighting 265 ///all that needs to be implemented in child class for UpdateHighlights to work 266 267 wxListItemAttr* HighlightItemUser( const wxString& name ) const; 268 269 void SetHighLightAction( UserActions::ActionType action ); 270 void RefreshVisibleItems(); 271 272 /** @name Multi Selection methods 273 * using these funcs in a single selection list is meaingless at best, harmful in the worst case 274 * \todo insert debug asserts to catch that 275 * @{ 276 */ 277 void SelectAll(); 278 void SelectInverse(); 279 /** @} 280 */ 281 282 //! sets selected index to -1 283 void SelectNone(); 284 285 //! marks the items in the control to be sorted 286 void MarkDirtySort(); 287 288 /** @name overloaded wxFunctions 289 * these are used to display items in virtual lists 290 * @{ 291 */ 292 wxString OnGetItemText(long item, long column) const; 293 int OnGetItemColumnImage(long item, long column) const; 294 wxListItemAttr* OnGetItemAttr(long item) const; 295 296 //! when using the dummy column, we provide diff impl that adjust for that 297 bool GetColumn(int col, wxListItem& item) const; 298 bool SetColumn(int col, wxListItem& item); 299 /** @} 300 */ 301 302 //! delete all data, selections, and whatnot 303 virtual void Clear(); 304 305 //! handle sort order updates 306 void OnColClick( wxListEvent& event ); 307 308 virtual int GetIndexFromData( const DataType& data ) const = 0; 309 310 void ReverseOrder(); 311 312 void OnQuit( wxCommandEvent& data ); 313 void StartTimer(); 314 void StopTimer(); 315 316 protected: 317 typedef std::vector< DataImp > DataVector; 318 typedef typename DataVector::iterator DataIter; 319 typedef typename DataVector::const_iterator DataCIter; 320 typedef typename DataVector::reverse_iterator DataRevIter; 321 typedef typename DataVector::const_reverse_iterator DataRevCIter; 322 DataVector m_data; 323 324 typedef DataType SelectedDataType; 325 typedef std::vector< SelectedDataType > SelectedDataVector; 326 SelectedDataVector m_selected_data; 327 328 //! the Comparator object passed to the SLInsertionSort function 329 ItemComparator<DataType> m_comparator; 330 331 bool RemoveItem( const DataImp& item ); 332 bool AddItem( const DataImp& item ); 333 334 long m_periodic_sort_timer_id; 335 wxTimer m_periodic_sort_timer; 336 bool m_periodic_sort; 337 unsigned int m_periodic_sort_interval; 338 void OnPeriodicSort( wxTimerEvent& evt ); 339 //! this is the sink for a custom event that can be used for async sort 340 void OnSortEvent( wxCommandEvent& evt ); 341 342 public: 343 DECLARE_EVENT_TABLE() 344 345 private: 346 typedef BaseType ThisType; asImp()347 ListCtrlImp& asImp() { 348 return static_cast<ListCtrlImp&>(*this); 349 } asImp()350 const ListCtrlImp& asImp() const { 351 return static_cast<const ListCtrlImp&>(*this); 352 } 353 354 }; 355 356 template < class ListCtrlType > class SelectionSaver 357 { 358 ListCtrlType& m_list; 359 360 public: SelectionSaver(ListCtrlType & list)361 SelectionSaver( ListCtrlType& list) 362 : m_list( list ) { 363 m_list.SaveSelection(); 364 } 365 ~SelectionSaver()366 ~SelectionSaver() { 367 m_list.RestoreSelection(); 368 } 369 }; 370 371 #include "customvirtlistctrl.cpp" 372 373 #endif /*CUSTOMLISTITEM_H_*/ 374 375 /** 376 This file is part of SpringLobby, 377 Copyright (C) 2007-2011 378 379 SpringLobby is free software: you can redistribute it and/or modify 380 it under the terms of the GNU General Public License version 2 as published by 381 the Free Software Foundation. 382 383 SpringLobby is distributed in the hope that it will be useful, 384 but WITHOUT ANY WARRANTY; without even the implied warranty of 385 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 386 GNU General Public License for more details. 387 388 You should have received a copy of the GNU General Public License 389 along with SpringLobby. If not, see <http://www.gnu.org/licenses/>. 390 **/ 391 392