From e1ee62bd793bc1173ac36fd429a6f54a877b37f7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 18 Dec 1998 15:37:19 +0000 Subject: [PATCH] wxTreeCtrl::Sort() changed, adapted the sample to show it. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1237 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/treectrl.h | 17 +++--- samples/treectrl/treetest.cpp | 104 ++++++++++++++++++++++++++++------ samples/treectrl/treetest.h | 17 ++++++ src/generic/treectrl.cpp | 53 +++++++++-------- 4 files changed, 143 insertions(+), 48 deletions(-) diff --git a/include/wx/generic/treectrl.h b/include/wx/generic/treectrl.h index 6903436ec3..2550b4a5cd 100644 --- a/include/wx/generic/treectrl.h +++ b/include/wx/generic/treectrl.h @@ -46,7 +46,6 @@ class wxImageList; class wxGenericTreeItem; class wxTreeItemData; -typedef int (*wxTreeItemCmpFunc)(wxTreeItemData *item1, wxTreeItemData *item2); // ----------------------------------------------------------------------------- // wxTreeItemId - unique identifier of a tree element @@ -415,13 +414,17 @@ public: // end editing and accept or discard the changes to item label void EndEditLabel(const wxTreeItemId& item, bool discardChanges = FALSE); - // sort the children of this item using the specified callback function - // (it should return -1, 0 or +1 as usual), if it's not specified - // alphabetical comparaison is performed. + // sorting + // this function is called to compare 2 items and should return -1, 0 + // or +1 if the first item is less than, equal to or greater than the + // second one. The base class version performs alphabetic comparaison + // of item labels (GetText) + virtual int OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2); + // sort the children of this item using OnCompareItems // - // NB: this function is not reentrant! - void SortChildren(const wxTreeItemId& item, - wxTreeItemCmpFunc *cmpFunction = NULL); + // NB: this function is not reentrant and not MT-safe (FIXME)! + void SortChildren(const wxTreeItemId& item); // callbacks void OnPaint( wxPaintEvent &event ); diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 58597fb2cb..b4f107e796 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -39,10 +39,22 @@ #include "treetest.h" +// verify that the item is ok and insult the user if it is not +#define CHECK_ITEM( item ) if ( !item.IsOk() ) { \ + wxMessageBox("Please select some item first!", \ + "Tree sample error", \ + wxOK | wxICON_EXCLAMATION, \ + this); \ + return; \ + } + BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(TreeTest_Quit, MyFrame::OnQuit) EVT_MENU(TreeTest_About, MyFrame::OnAbout) EVT_MENU(TreeTest_Dump, MyFrame::OnDump) + EVT_MENU(TreeTest_Rename, MyFrame::OnRename) + EVT_MENU(TreeTest_Sort, MyFrame::OnSort) + EVT_MENU(TreeTest_SortRev, MyFrame::OnSortRev) EVT_MENU(TreeTest_Bold, MyFrame::OnSetBold) EVT_MENU(TreeTest_UnBold, MyFrame::OnClearBold) EVT_MENU(TreeTest_Delete, MyFrame::OnDelete) @@ -98,24 +110,30 @@ MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) SetIcon(wxICON(mondrian)); // Make a menubar - wxMenu *file_menu = new wxMenu; + wxMenu *file_menu = new wxMenu, + *tree_menu = new wxMenu; - file_menu->Append(TreeTest_Dump, "D&ump tree items"); - file_menu->Append(TreeTest_Recreate, "&Recreate the tree"); - file_menu->AppendSeparator(); - file_menu->Append(TreeTest_Delete, "&Delete this item"); - file_menu->Append(TreeTest_DeleteChildren, "Delete &children"); - file_menu->Append(TreeTest_DeleteAll, "Delete &all items"); - file_menu->AppendSeparator(); - file_menu->Append(TreeTest_Bold, "Make item &bold"); - file_menu->Append(TreeTest_UnBold, "Make item ¬ bold"); - file_menu->AppendSeparator(); file_menu->Append(TreeTest_About, "&About..."); file_menu->AppendSeparator(); file_menu->Append(TreeTest_Quit, "E&xit"); + tree_menu->Append(TreeTest_Dump, "D&ump tree items"); + tree_menu->Append(TreeTest_Recreate, "&Recreate the tree"); + tree_menu->AppendSeparator(); + tree_menu->Append(TreeTest_Delete, "&Delete this item"); + tree_menu->Append(TreeTest_DeleteChildren, "Delete &children"); + tree_menu->Append(TreeTest_DeleteAll, "Delete &all items"); + tree_menu->AppendSeparator(); + tree_menu->Append(TreeTest_Sort, "Sort children of current item"); + tree_menu->Append(TreeTest_SortRev, "Sort in reversed order"); + tree_menu->Append(TreeTest_Rename, "Rename item..."); + tree_menu->AppendSeparator(); + tree_menu->Append(TreeTest_Bold, "Make item &bold"); + tree_menu->Append(TreeTest_UnBold, "Make item ¬ bold"); + wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); + menu_bar->Append(tree_menu, "&Tree"); SetMenuBar(menu_bar); // Make a panel with a message @@ -168,34 +186,70 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { - wxMessageDialog dialog(this, - "Tree test sample\n" - "Julian Smart (c) 1997", - "About tree test", wxOK); + wxMessageBox("Tree test sample\n" + "Julian Smart (c) 1997,\n" + "Vadim Zeitlin (c) 1998", + "About tree test", + wxOK | wxICON_INFORMATION, this); +} + +void MyFrame::OnRename(wxCommandEvent& WXUNUSED(event)) +{ + wxTreeItemId item = m_treeCtrl->GetSelection(); + + CHECK_ITEM( item ); + + static wxString s_text; + s_text = wxGetTextFromUser("New name: ", "Tree sample question", + s_text, this); + if ( !s_text.IsEmpty() ) + { + m_treeCtrl->SetItemText(item, s_text); + } +} + +void MyFrame::DoSort(bool reverse) +{ + wxTreeItemId item = m_treeCtrl->GetSelection(); - dialog.ShowModal(); + CHECK_ITEM( item ); + + m_treeCtrl->DoSortChildren(item, reverse); } void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event)) { wxTreeItemId root = m_treeCtrl->GetSelection(); + + CHECK_ITEM( root ); + m_treeCtrl->GetItemsRecursively(root, -1); } void MyFrame::DoSetBold(bool bold) { - m_treeCtrl->SetItemBold(m_treeCtrl->GetSelection(), bold); + wxTreeItemId item = m_treeCtrl->GetSelection(); + + CHECK_ITEM( item ); + + m_treeCtrl->SetItemBold(item, bold); } void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event)) { wxTreeItemId item = m_treeCtrl->GetSelection(); + + CHECK_ITEM( item ); + m_treeCtrl->Delete(item); } void MyFrame::OnDeleteChildren(wxCommandEvent& WXUNUSED(event)) { wxTreeItemId item = m_treeCtrl->GetSelection(); + + CHECK_ITEM( item ); + m_treeCtrl->DeleteChildren(item); } @@ -216,6 +270,8 @@ MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, long style) : wxTreeCtrl(parent, id, pos, size, style) { + m_reverseSort = FALSE; + // Make an image list containing small icons m_imageListNormal = new wxImageList(16, 16, TRUE); @@ -234,6 +290,20 @@ MyTreeCtrl::~MyTreeCtrl() delete m_imageListNormal; } +int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2) +{ + if ( m_reverseSort ) + { + // just exchange 1st and 2nd items + return wxTreeCtrl::OnCompareItems(item2, item1); + } + else + { + return wxTreeCtrl::OnCompareItems(item1, item2); + } +} + void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent, size_t numChildren, size_t depth, diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h index 4c5dab2d1c..b08a795631 100644 --- a/samples/treectrl/treetest.h +++ b/samples/treectrl/treetest.h @@ -62,6 +62,13 @@ public: void AddTestItemsToTree(size_t numChildren, size_t depth); + void DoSortChildren(const wxTreeItemId& item, bool reverse = FALSE) + { m_reverseSort = reverse; wxTreeCtrl::SortChildren(item); } + +protected: + virtual int OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2); + private: void AddItemsRecursively(const wxTreeItemId& idParent, size_t nChildren, @@ -69,6 +76,7 @@ private: size_t folder); wxImageList *m_imageListNormal; + bool m_reverseSort; // flag for OnCompareItems DECLARE_EVENT_TABLE() }; @@ -93,7 +101,13 @@ public: void OnSetBold(wxCommandEvent& WXUNUSED(event)) { DoSetBold(TRUE); } void OnClearBold(wxCommandEvent& WXUNUSED(event)) { DoSetBold(FALSE); } + void OnRename(wxCommandEvent& event); + void OnSort(wxCommandEvent& event) { DoSort(); } + void OnSortRev(wxCommandEvent& event) { DoSort(TRUE); } + private: + void DoSort(bool reverse = FALSE); + MyTreeCtrl *m_treeCtrl; void DoSetBold(bool bold = TRUE); @@ -107,8 +121,11 @@ enum TreeTest_Quit, TreeTest_About, TreeTest_Dump, + TreeTest_Sort, + TreeTest_SortRev, TreeTest_Bold, TreeTest_UnBold, + TreeTest_Rename, TreeTest_Delete, TreeTest_DeleteChildren, TreeTest_DeleteAll, diff --git a/src/generic/treectrl.cpp b/src/generic/treectrl.cpp index 7d29b52f64..1f986f385b 100644 --- a/src/generic/treectrl.cpp +++ b/src/generic/treectrl.cpp @@ -935,37 +935,42 @@ void wxTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item), bool WXUNUSED( wxFAIL_MSG("not implemented"); } -wxTreeItemCmpFunc tree_ctrl_compare_func_2; +// FIXME: tree sorting functions are not reentrant and not MT-safe! +static wxTreeCtrl *s_treeBeingSorted = NULL; -int tree_ctrl_compare_func_1( wxGenericTreeItem **line1, wxGenericTreeItem **line2 ) +static int tree_ctrl_compare_func(wxGenericTreeItem **item1, + wxGenericTreeItem **item2) { - if (tree_ctrl_compare_func_2 == NULL) - { - return strcmp( (*line1)->GetText(), (*line2)->GetText() ); - } - else - { - wxTreeItemData *data1 = (*line1)->GetData(); - wxTreeItemData *data2 = (*line2)->GetData(); - return tree_ctrl_compare_func_2( data1, data2 ); - } + wxCHECK_MSG( s_treeBeingSorted, 0, "bug in wxTreeCtrl::SortChildren()" ); + + return s_treeBeingSorted->OnCompareItems(*item1, *item2); } -void wxTreeCtrl::SortChildren( const wxTreeItemId& item, - wxTreeItemCmpFunc *cmpFunction) +int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2) { - wxGenericTreeItem *gitem = item.m_pItem; - - if (!gitem) return; + return strcmp(GetItemText(item1), GetItemText(item2)); +} + +void wxTreeCtrl::SortChildren(const wxTreeItemId& itemId) +{ + wxCHECK_RET( itemId.IsOk(), "invalid tree item" ); + + wxGenericTreeItem *item = itemId.m_pItem; - if (cmpFunction == NULL) - tree_ctrl_compare_func_2 = NULL; - else - tree_ctrl_compare_func_2 = *cmpFunction; - - gitem->GetChildren().Sort( *tree_ctrl_compare_func_1 ); + wxCHECK_RET( !s_treeBeingSorted, + "wxTreeCtrl::SortChildren is not reentrant" ); + + wxArrayTreeItems& children = item->GetChildren(); + if ( children.Count() > 1 ) + { + s_treeBeingSorted = this; + children.Sort(tree_ctrl_compare_func); + s_treeBeingSorted = NULL; - m_dirty = TRUE; + m_dirty = TRUE; + } + //else: don't make the tree dirty as nothing changed } wxImageList *wxTreeCtrl::GetImageList() const -- 2.45.2