1 // 2 // This file is part of the aMule Project. 3 // 4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5 // Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6 // 7 // Any parts of this program derived from the xMule, lMule or eMule project, 8 // or contributed by third-party developers are copyrighted by their 9 // respective authors. 10 // 11 // This program is free software; you can redistribute it and/or modify 12 // it under the terms of the GNU General Public License as published by 13 // the Free Software Foundation; either version 2 of the License, or 14 // (at your option) any later version. 15 // 16 // This program 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 19 // GNU General Public License for more details. 20 // 21 // You should have received a copy of the GNU General Public License 22 // along with this program; if not, write to the Free Software 23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24 // 25 26 #ifndef MULELISTCTRL_H 27 #define MULELISTCTRL_H 28 29 #ifdef _WIN32 30 #include <wx/msw/winundef.h> 31 #endif 32 33 #include <wx/defs.h> // Do_not_auto_remove (Mac, Win32, and just good practice) 34 #include "extern/wxWidgets/listctrl.h" 35 36 #include <vector> 37 #include <list> 38 39 /** 40 * Enhanced wxListCtrl provided custom-drawing among other things. 41 * 42 * This class provides these features which the original wxListCtrl lacks: 43 * - Automatic sort arrows upon clicks on the column headers 44 * - Custom drawing of items. 45 * - Hiding of columns through auto-generated popup-menu. 46 * - Helper function for inserting items pre-sorted. 47 * - Loading and saving of column properties. 48 * - Selection of items by typing an initial part of the text (TTS). 49 */ 50 class CMuleListCtrl : public MuleExtern::wxGenericListCtrl 51 { 52 public: 53 /** 54 * The various ways in which a column can be sorted. 55 * 56 * If SORT_DES is not set, sorting is taken to be 57 * ascending. If SORT_ALT is not set, sorting is 58 * taken to be normal. 59 */ 60 enum MLOrder 61 { 62 //! If set, sorting is to be in descending order. 63 SORT_DES = 0x1000, 64 65 //! If sorting should use alternate method. 66 //! Is specified in with or without DEC. 67 SORT_ALT = 0x2000 68 }; 69 70 //! Mask which covers the column part of the sort-data. 71 static const unsigned COLUMN_MASK = 0xfff; 72 73 //! Mask which covers the sorting part of the sort-data. 74 static const unsigned SORTING_MASK = 0x3000; 75 76 /** 77 * Constructor. 78 * 79 * @see wxGenericListCtrl::wxGenericListCtrl for documentation of parameters. 80 */ 81 CMuleListCtrl( 82 wxWindow *parent, 83 wxWindowID winid = -1, 84 const wxPoint &pos = wxDefaultPosition, 85 const wxSize &size = wxDefaultSize, 86 long style = wxLC_ICON, 87 const wxValidator& validator = wxDefaultValidator, 88 const wxString &name = wxT("mulelistctrl") ); 89 90 /** 91 * Destructor. 92 * 93 * If a name for the table has been specified with SetTableName, then 94 * column settings will be saved automatically. 95 */ 96 virtual ~CMuleListCtrl(); 97 98 /** 99 * Saves column settings. 100 * 101 * Currently saves the width of all columns, hidden columns, the column 102 * to sort by and in which direction to sort. 103 */ 104 virtual void SaveSettings(); 105 106 /** 107 * Loads column settings. 108 * 109 * Currently loads the width of all columns, hidden columns, the column 110 * to sort by and in which direction to sort. This function also ensures 111 * that the items are sorted after the settings have been read. 112 */ 113 virtual void LoadSettings(); 114 115 /** 116 * This function tries to locate the best place to insert an item. 117 * 118 * @param The userdata of the new item. 119 * 120 * This function does a binary type search to locate the best place to 121 * insert the new item with the specified userdata. It then returns the 122 * item after this position. To do this, the sorter-function must be set 123 * through the SetSortFunc function, otherwise it will just return the 124 * position after the last item. 125 */ 126 long GetInsertPos( wxUIntPtr data ); 127 128 /** 129 * Sorts the list. 130 * 131 * Before you can use this function, you will need to specify a sorter 132 * function using SetSortFunc. wxListCtrl needs such a function to 133 * perform the sort. 134 */ 135 virtual void SortList(); 136 137 //! The type of the list of item specific data 138 typedef std::vector<wxUIntPtr> ItemDataList; 139 140 /** 141 * Returns a list the user-data of all selected items. 142 * 143 * @return A list of data associated with the selected items. 144 * 145 * This function will return the user-data for each selected item in a 146 * vector, which can then be manipulated with regards to changes made 147 * in the current order of the listctrl items. 148 */ 149 ItemDataList GetSelectedItems() const; 150 151 /** 152 * Sets the sorter function. 153 * 154 * @param func 155 * 156 * See the documentation on wxListCtrl::SortItems for more information 157 * about the expected function type. 158 */ SetSortFunc(MuleListCtrlCompare func)159 void SetSortFunc(MuleListCtrlCompare func) { m_sort_func = func; } 160 161 /** 162 * Deselects all selected items, but does not change focus. 163 */ 164 void ClearSelection(); 165 166 /** 167 * Insert a new column. 168 * 169 * @param[in] col Column will be inserted at this position. 170 * @param[in] heading Heading text for the column. 171 * @param[in] format Format (alignment) of the column. 172 * @param[in] width The column width. 173 * @param[in] name Internal name of the column. 174 * 175 * We override this method to allow a name to be specified for each 176 * column. The name is used for saving/loading column settings 177 * independently of their index. It is necessary to set a unique name 178 * for each column, to let column settings be saved/loaded. If you 179 * don't set a name for a column, settings for that column won't be 180 * saved. 181 * 182 * Requirements about column names: 183 * - they must not contain the ':' (colon) and ',' (comma) characters, 184 * - they should be at least one character long. 185 * 186 * @note Changing the internal name of one column results in width of 187 * that column being reset to default, and if sorting was done by that 188 * column, sorting being forgotten. If you change the name of a column, 189 * don't forget to update the list GetOldColumnOrder() returns, if 190 * necessary. 191 * 192 * For more information refer to the wxWidgets documentation of 193 * wxListCtrl::InsertColumn() 194 */ 195 long InsertColumn( 196 long col, 197 const wxString& heading, 198 int format = wxLIST_FORMAT_LEFT, 199 int width = -1, 200 const wxString& name = wxEmptyString 201 ); 202 203 /** 204 * Clears all items and all columns. 205 * 206 * Intercepted to clear column name list. 207 * 208 * For more information see the wxWidgets documentation of 209 * wxListCtrl::ClearAll() 210 */ ClearAll()211 void ClearAll() 212 { 213 m_column_names.clear(); 214 MuleExtern::wxGenericListCtrl::ClearAll(); 215 } 216 217 /** 218 * Delete one column from the list. 219 * 220 * Not implemented yet, intercepted here just as a sanity check. 221 */ DeleteColumn(int WXUNUSED (col))222 bool DeleteColumn(int WXUNUSED(col)) { wxFAIL; return false; } 223 224 /** 225 * Indicates if we're in the process of sorting. 226 */ IsSorting()227 bool IsSorting() const { return m_isSorting; } 228 229 protected: 230 231 /** 232 * Must be overwritten to enable alternate sorting. 233 * 234 * @param The column being sorted. 235 * 236 * Subclasses of CMuleListCtrl can allow alternative sorting 237 * of columns. This is done by overriding this function and 238 * returning true for the columns where alternative sorting 239 * is desired. 240 */ 241 virtual bool AltSortAllowed(unsigned column) const; 242 243 /** 244 * Returns the string used when selecting rows via Type-To-Select. 245 * 246 * @param item The index of the item being examined. 247 * 248 * By default, this function simply returns the text in the first 249 * column for the given item. However, when owner-drawing is 250 * enabled, this function _must_ be overriden. 251 */ 252 virtual wxString GetTTSText(unsigned item) const; 253 254 /** 255 * Sets the internally used table-name. 256 * 257 * @param name The new name or an empty string to disable. 258 * 259 * You need to call this function with a unique name before you can 260 * make use of the LoadSettings/SaveSettings functions. CMuleListCtrl 261 * uses the name specified in this command to create unique keynames. 262 */ SetTableName(const wxString & name)263 void SetTableName(const wxString& name) { m_name = name; } 264 265 /** 266 * Return old column order. 267 * 268 * @return The pre-2.2.2 column order. 269 * 270 * This function should be overridden in descendant classes to return a 271 * comma-separated list of the old column order, when column data was 272 * saved/loaded by index. The default implementation returns an empty 273 * string, meaning that old settings (if any) should be discarded. 274 * 275 * @note When you add or remove columns from the list control, DO NOT 276 * change this list. This list may only be updated if you changed a 277 * column name that is already in this list, to reflect the name 278 * change. List order also must be preserved. 279 */ 280 virtual wxString GetOldColumnOrder() const; 281 282 /** 283 * Returns the column which is currently used to sort the list. 284 */ GetSortColumn()285 unsigned GetSortColumn() const { return m_sort_orders.front().first; } 286 287 /** 288 * Returns the current sorting order, a combination of the DES and ALT flags. 289 */ GetSortOrder()290 unsigned GetSortOrder() const { return m_sort_orders.front().second; } 291 292 /** 293 * Set the sort column 294 * 295 * @param column The column with which the list should be sorted. 296 * @param order The order in which to sort the column. 297 * 298 * Note that attempting to sort a column in an unsupported order 299 * is an illegal operation. 300 */ 301 virtual void SetSorting(unsigned column, unsigned order); 302 303 /** 304 * Returns true if the item is sorted compared to its neighbours. 305 */ 306 bool IsItemSorted(long item); 307 308 /** 309 * Check and fix selection state. 310 * 311 * @param event The event which triggered the selection. 312 * @return The index of the item selected or -1 if none. 313 * 314 * This function checks if the clicked item is selected. 315 * If not, then the item is selected and all other items 316 * are deselected. 317 */ 318 //@{ 319 long CheckSelection(wxListEvent& event); 320 long CheckSelection(wxMouseEvent& event); 321 //@} 322 323 /** 324 * Event handler for right-clicks on the column headers. 325 */ 326 void OnColumnRClick(wxListEvent& evt); 327 328 /** 329 * Event handler for left-clicks on the column headers. 330 */ 331 void OnColumnLClick(wxListEvent& evt); 332 333 /** 334 * Event handler for the hide/show menu items. 335 */ 336 void OnMenuSelected(wxCommandEvent& evt); 337 338 /** 339 * Event handler for the mouse wheel. 340 */ 341 void OnMouseWheel(wxMouseEvent &event); 342 343 /** 344 * Event handler for key-presses, needed by TTS. 345 */ 346 void OnChar(wxKeyEvent& evt); 347 348 /** 349 * Event handler for item selection/deletion, needed by TTS. 350 */ 351 void OnItemSelected(wxListEvent& evt); 352 void OnItemDeleted(wxListEvent& evt); 353 void OnAllItemsDeleted(wxListEvent& evt); 354 355 private: 356 /** 357 * Resets the current TTS session. 358 */ 359 void ResetTTS(); 360 361 /** 362 * Sets the image of a specific column. 363 * 364 * @param col The column to change. 365 * @param order The sorting order to represent. Zero unsets the image. 366 */ 367 void SetColumnImage(unsigned col, int image); 368 369 //! The name of the table. Used to load/save settings. 370 wxString m_name; 371 372 //! The sorter function needed by wxListCtrl. 373 MuleListCtrlCompare m_sort_func; 374 375 //! Contains the current search string. 376 wxString m_tts_text; 377 378 //! Timestamp for the last TTS event. 379 unsigned m_tts_time; 380 381 //! The index of the last item selected via TTS. 382 int m_tts_item; 383 384 /** 385 * Wrapper around the user-provided sorter function. 386 * 387 * This function ensures that items are sorted in the order 388 * specified by clicking on column-headers, and also enforces 389 * that different entries are never considered equal. This is 390 * required for lists that make use of child-items, since 391 * otherwise, parents may not end up properly located in 392 * relation to child-items. 393 */ 394 static int wxCALLBACK SortProc(wxUIntPtr item1, wxUIntPtr item2, long sortData); 395 396 /** Compares two items in the list, using the current sort sequence. */ 397 int CompareItems(wxUIntPtr item1, wxUIntPtr item2); 398 399 //! This pair contains a column number and its sorting order. 400 typedef std::pair<unsigned, unsigned> CColPair; 401 typedef std::list<CColPair> CSortingList; 402 403 class MuleSortData { 404 public: MuleSortData(CSortingList sort_orders,MuleListCtrlCompare sort_func)405 MuleSortData(CSortingList sort_orders, MuleListCtrlCompare sort_func) : m_sort_orders(sort_orders), m_sort_func(sort_func) { }; 406 407 CSortingList m_sort_orders; 408 MuleListCtrlCompare m_sort_func; 409 }; 410 411 //! This list contains in order the columns sequence to sort by. 412 CSortingList m_sort_orders; 413 414 /** 415 * Get the column name by index. 416 * 417 * @param[in] column Index of the column whose name we're looking for. 418 * 419 * @return The column name or an empty string if index is invalid 420 * (out of range), or the column name hasn't been set. 421 */ 422 const wxString& GetColumnName(int column) const; 423 424 /** 425 * Get the column default width by index. 426 * 427 * @param[in] column Index of the column whose name we're looking for. 428 * 429 * @return The column default width or wx default width if index is invalid 430 * (out of range), or the column name hasn't been set. 431 */ 432 int GetColumnDefaultWidth(int column) const; 433 434 /** 435 * Get column index by name. 436 * 437 * @param[in] name Internal name of the colunm whose index is needed. 438 * 439 * @return The column index, or -1 in case the name was invalid. 440 */ 441 int GetColumnIndex(const wxString& name) const; 442 443 /** 444 * Find out the new index of the column by the old index. 445 * 446 * @param[in] oldindex Old column index which we want to turn into a 447 * new index. 448 * 449 * @return The new index of the column, or -1 if an error occured. 450 */ 451 int GetNewColumnIndex(int oldindex) const; 452 453 /** 454 * Parses old config entries. 455 * 456 * @param[in] sortOrders Old sort orders line. 457 * @param[in] columnWidths Old column widths line. 458 */ 459 void ParseOldConfigEntries(const wxString& sortOrders, const wxString& columnWidths); 460 461 /// This class contains a column index, its default width and its name. 462 class ColNameEntry { 463 public: 464 int index; 465 int defaultWidth; 466 wxString name; ColNameEntry(int _index,int _defaultWidth,const wxString & _name)467 ColNameEntry(int _index, int _defaultWidth, const wxString& _name) 468 : index(_index), defaultWidth(_defaultWidth), name(_name) {} 469 }; 470 471 /// This list contains the columns' names. 472 typedef std::list<ColNameEntry> ColNameList; 473 474 /// Container for column names, sorted by column index. 475 ColNameList m_column_names; 476 477 /// This vector contains a cache of the columns' sizes. 478 typedef std::vector<int> ColSizeVector; 479 480 /// Container for column sizes cache. 481 ColSizeVector m_column_sizes; 482 483 // True while sorting. 484 bool m_isSorting; 485 486 DECLARE_EVENT_TABLE() 487 }; 488 489 #endif // MULELISTCTRL_H 490 // File_checked_for_headers 491