Implement sorting in wxTreeListCtrl.

Allow the user to sort the control contents by clicking on the columns with
wxCOL_SORTABLE flag and also provide SetSortColumn() method to sort the
control programmatically.

Also add wxTreeListItemComparator class and SetItemComparator() method to
allow customizing the way the items are compared.

Update the sample to show how to define a custom comparator.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69176 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2011-09-21 15:07:53 +00:00
parent 15b8afdcb8
commit da2e758f83
4 changed files with 429 additions and 22 deletions

View File

@@ -50,9 +50,10 @@
#endif
// ----------------------------------------------------------------------------
// Constants for menu items
// Constants
// ----------------------------------------------------------------------------
// Menu items.
enum
{
Id_MultiSelect = 100,
@@ -72,6 +73,89 @@ enum
Id_Select_HTMLDocs
};
// Tree list columns.
enum
{
Col_Component,
Col_Files,
Col_Size
};
// ----------------------------------------------------------------------------
// Custom comparator for tree list items comparison
// ----------------------------------------------------------------------------
// This is a toy class as in a real program you would have the original numeric
// data somewhere and wouldn't need to parse it back from strings presumably.
// Nevertheless it shows how to implement a custom comparator which is needed
// if you want to sort by a column with non-textual contents.
class MyComparator : public wxTreeListItemComparator
{
public:
virtual int
Compare(wxTreeListCtrl* treelist,
unsigned column,
wxTreeListItem item1,
wxTreeListItem item2)
{
wxString text1 = treelist->GetItemText(item1, column),
text2 = treelist->GetItemText(item2, column);
switch ( column )
{
case Col_Component:
// Simple alphabetical comparison is fine for those.
return text1.CmpNoCase(text2);
case Col_Files:
// Compare strings as numbers.
return GetNumFilesFromText(text1) - GetNumFilesFromText(text2);
case Col_Size:
// Compare strings as numbers but also take care of "KiB" and
// "MiB" suffixes.
return GetSizeFromText(text1) - GetSizeFromText(text2);
}
wxFAIL_MSG( "Sorting on unknown column?" );
return 0;
}
private:
// Return the number of files handling special value "many". Notice that
// the returned value is signed to allow using it in subtraction above.
int GetNumFilesFromText(const wxString& text) const
{
unsigned long n;
if ( !text.ToULong(&n) )
{
if ( text == "many" )
n = 9999;
else
n = 0;
}
return n;
}
// Return the size in KiB from a string with either KiB or MiB suffix.
int GetSizeFromText(const wxString& text) const
{
wxString size;
unsigned factor = 1;
if ( text.EndsWith(" MiB", &size) )
factor = 1024;
else if ( !text.EndsWith(" KiB", &size) )
return 0;
unsigned long n = 0;
size.ToULong(&n);
return n*factor;
}
};
// ----------------------------------------------------------------------------
// Application class
// ----------------------------------------------------------------------------
@@ -140,6 +224,8 @@ private:
wxTreeListCtrl* m_treelist;
MyComparator m_comparator;
wxTreeListItem m_itemHTMLDocs;
wxLog* m_oldLogTarget;
@@ -304,20 +390,18 @@ wxTreeListCtrl* MyFrame::CreateTreeListCtrl(long style)
style);
tree->SetImageList(m_imageList);
enum
{
Col_Component,
Col_Files,
Col_Size
};
tree->AppendColumn("Component");
tree->AppendColumn("Component",
wxCOL_WIDTH_AUTOSIZE,
wxALIGN_LEFT,
wxCOL_RESIZABLE | wxCOL_SORTABLE);
tree->AppendColumn("# Files",
tree->WidthFor("1,000,000"),
wxALIGN_RIGHT);
wxALIGN_RIGHT,
wxCOL_RESIZABLE | wxCOL_SORTABLE);
tree->AppendColumn("Size",
tree->WidthFor("1,000,000 KiB"),
wxALIGN_RIGHT);
wxALIGN_RIGHT,
wxCOL_RESIZABLE | wxCOL_SORTABLE);
// Define a shortcut to save on typing here.
#define ADD_ITEM(item, parent, files, size) \
@@ -351,6 +435,9 @@ wxTreeListCtrl* MyFrame::CreateTreeListCtrl(long style)
// Remember this one for subsequent tests.
m_itemHTMLDocs = HTML;
// Set a custom comparator to compare strings containing numbers correctly.
tree->SetItemComparator(&m_comparator);
return tree;
}