Fix restored columns getting an almost-zero width
[amule.git] / src / MuleListCtrl.h
blob330f2e32a5489af1e5f82da16dfba93589abf553
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 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.
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.
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
26 #ifndef MULELISTCTRL_H
27 #define MULELISTCTRL_H
29 #ifdef _WIN32
30 #include <wx/msw/winundef.h>
31 #endif
33 #include <wx/defs.h> // Do_not_auto_remove (Mac, Win32, and just good practice)
34 #include "extern/wxWidgets/listctrl.h"
36 #include <vector>
37 #include <list>
39 /**
40 * Enhanced wxListCtrl provided custom-drawing among other things.
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).
50 class CMuleListCtrl : public MuleExtern::wxGenericListCtrl
52 public:
53 /**
54 * The various ways in which a column can be sorted.
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.
60 enum MLOrder
62 //! If set, sorting is to be in descending order.
63 SORT_DES = 0x1000,
65 //! If sorting should use alternate method.
66 //! Is specified in with or without DEC.
67 SORT_ALT = 0x2000
70 //! Mask which covers the column part of the sort-data.
71 static const unsigned COLUMN_MASK = 0xfff;
73 //! Mask which covers the sorting part of the sort-data.
74 static const unsigned SORTING_MASK = 0x3000;
76 /**
77 * Constructor.
79 * @see wxGenericListCtrl::wxGenericListCtrl for documentation of parameters.
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") );
90 /**
91 * Destructor.
93 * If a name for the table has been specified with SetTableName, then
94 * column settings will be saved automatically.
95 */
96 virtual ~CMuleListCtrl();
98 /**
99 * Saves column settings.
101 * Currently saves the width of all columns, hidden columns, the column
102 * to sort by and in which direction to sort.
104 virtual void SaveSettings();
107 * Loads column settings.
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.
113 virtual void LoadSettings();
116 * This function tries to locate the best place to insert an item.
118 * @param The userdata of the new item.
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.
126 long GetInsertPos( wxUIntPtr data );
129 * Sorts the list.
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.
135 virtual void SortList();
137 //! The type of the list of item specific data
138 typedef std::vector<wxUIntPtr> ItemDataList;
141 * Returns a list the user-data of all selected items.
143 * @return A list of data associated with the selected items.
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.
149 ItemDataList GetSelectedItems() const;
152 * Sets the sorter function.
154 * @param func
156 * See the documentation on wxListCtrl::SortItems for more information
157 * about the expected function type.
159 void SetSortFunc(MuleListCtrlCompare func) { m_sort_func = func; }
162 * Deselects all selected items, but does not change focus.
164 void ClearSelection();
167 * Insert a new column.
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.
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.
182 * Requirements about column names:
183 * - they must not contain the ':' (colon) and ',' (comma) characters,
184 * - they should be at least one character long.
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.
192 * For more information refer to the wxWidgets documentation of
193 * wxListCtrl::InsertColumn()
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
204 * Clears all items and all columns.
206 * Intercepted to clear column name list.
208 * For more information see the wxWidgets documentation of
209 * wxListCtrl::ClearAll()
211 void ClearAll()
213 m_column_names.clear();
214 MuleExtern::wxGenericListCtrl::ClearAll();
218 * Delete one column from the list.
220 * Not implemented yet, intercepted here just as a sanity check.
222 bool DeleteColumn(int WXUNUSED(col)) { wxFAIL; return false; }
225 * Indicates if we're in the process of sorting.
227 bool IsSorting() const { return m_isSorting; }
229 protected:
232 * Must be overwritten to enable alternate sorting.
234 * @param The column being sorted.
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.
241 virtual bool AltSortAllowed(unsigned column) const;
244 * Returns the string used when selecting rows via Type-To-Select.
246 * @param item The index of the item being examined.
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.
252 virtual wxString GetTTSText(unsigned item) const;
255 * Sets the internally used table-name.
257 * @param name The new name or an empty string to disable.
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.
263 void SetTableName(const wxString& name) { m_name = name; }
266 * Return old column order.
268 * @return The pre-2.2.2 column order.
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.
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.
280 virtual wxString GetOldColumnOrder() const;
283 * Returns the column which is currently used to sort the list.
285 unsigned GetSortColumn() const { return m_sort_orders.front().first; }
288 * Returns the current sorting order, a combination of the DES and ALT flags.
290 unsigned GetSortOrder() const { return m_sort_orders.front().second; }
293 * Set the sort column
295 * @param column The column with which the list should be sorted.
296 * @param order The order in which to sort the column.
298 * Note that attempting to sort a column in an unsupported order
299 * is an illegal operation.
301 void SetSorting(unsigned column, unsigned order);
304 * Returns true if the item is sorted compared to its neighbours.
306 bool IsItemSorted(long item);
309 * Check and fix selection state.
311 * @param event The event which triggered the selection.
312 * @return The index of the item selected or -1 if none.
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.
318 //@{
319 long CheckSelection(wxListEvent& event);
320 long CheckSelection(wxMouseEvent& event);
321 //@}
324 * Event handler for right-clicks on the column headers.
326 void OnColumnRClick(wxListEvent& evt);
329 * Event handler for left-clicks on the column headers.
331 void OnColumnLClick(wxListEvent& evt);
334 * Event handler for the hide/show menu items.
336 void OnMenuSelected(wxCommandEvent& evt);
339 * Event handler for the mouse wheel.
341 void OnMouseWheel(wxMouseEvent &event);
344 * Event handler for key-presses, needed by TTS.
346 void OnChar(wxKeyEvent& evt);
349 * Event handler for item selection/deletion, needed by TTS.
351 void OnItemSelected(wxListEvent& evt);
352 void OnItemDeleted(wxListEvent& evt);
353 void OnAllItemsDeleted(wxListEvent& evt);
355 private:
357 * Resets the current TTS session.
359 void ResetTTS();
362 * Sets the image of a specific column.
364 * @param col The column to change.
365 * @param order The sorting order to represent. Zero unsets the image.
367 void SetColumnImage(unsigned col, int image);
369 //! The name of the table. Used to load/save settings.
370 wxString m_name;
372 //! The sorter function needed by wxListCtrl.
373 MuleListCtrlCompare m_sort_func;
375 //! Contains the current search string.
376 wxString m_tts_text;
378 //! Timestamp for the last TTS event.
379 unsigned m_tts_time;
381 //! The index of the last item selected via TTS.
382 int m_tts_item;
385 * Wrapper around the user-provided sorter function.
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.
394 static int wxCALLBACK SortProc(wxUIntPtr item1, wxUIntPtr item2, long sortData);
396 /** Compares two items in the list, using the current sort sequence. */
397 int CompareItems(wxUIntPtr item1, wxUIntPtr item2);
399 //! This pair contains a column number and its sorting order.
400 typedef std::pair<unsigned, unsigned> CColPair;
401 typedef std::list<CColPair> CSortingList;
403 class MuleSortData {
404 public:
405 MuleSortData(CSortingList sort_orders, MuleListCtrlCompare sort_func) : m_sort_orders(sort_orders), m_sort_func(sort_func) { };
407 CSortingList m_sort_orders;
408 MuleListCtrlCompare m_sort_func;
411 //! This list contains in order the columns sequence to sort by.
412 CSortingList m_sort_orders;
415 * Get the column name by index.
417 * @param[in] column Index of the column whose name we're looking for.
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.
422 const wxString& GetColumnName(int column) const;
425 * Get the column default width by index.
427 * @param[in] column Index of the column whose name we're looking for.
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.
432 int GetColumnDefaultWidth(int column) const;
435 * Get column index by name.
437 * @param[in] name Internal name of the colunm whose index is needed.
439 * @return The column index, or -1 in case the name was invalid.
441 int GetColumnIndex(const wxString& name) const;
444 * Find out the new index of the column by the old index.
446 * @param[in] oldindex Old column index which we want to turn into a
447 * new index.
449 * @return The new index of the column, or -1 if an error occured.
451 int GetNewColumnIndex(int oldindex) const;
454 * Parses old config entries.
456 * @param[in] sortOrders Old sort orders line.
457 * @param[in] columnWidths Old column widths line.
459 void ParseOldConfigEntries(const wxString& sortOrders, const wxString& columnWidths);
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;
467 ColNameEntry(int _index, int _defaultWidth, const wxString& _name)
468 : index(_index), defaultWidth(_defaultWidth), name(_name) {}
471 /// This list contains the colunms' names.
472 typedef std::list<ColNameEntry> ColNameList;
474 /// Container for column names, sorted by column index.
475 ColNameList m_column_names;
477 // True while sorting.
478 bool m_isSorting;
480 DECLARE_EVENT_TABLE()
483 #endif // MULELISTCTRL_H
484 // File_checked_for_headers