WxTreeCtrl
From WxWiki
A tree control presents information as a hierarchy, with items that may be expanded to show further items.
[edit] Iterating through all items in the wxTreeCtrl
I had the need to iterate through all the items, including children and siblings, in a tree, and search for some text. I ended up writing recursive code.
wxTreeCtrl Recursive Access
wxTreeItemId CMyDialog::FindItem( wxTreeItemId root, const wxString& sSearchFor ) { wxTreeItemIdValue cookie; wxTreeItemId search; wxTreeItemId item = m_ctlTreeCtrl->GetFirstChild( root, cookie ); wxTreeItemId child; while( item.IsOk() ) { wxString sData = m_ctlTreeCtrl->GetItemText(item); if( sSearchFor.CompareTo(sData) == 0 ) { return item; } if( m_ctlTreeCtrl->ItemHasChildren( item ) ) { wxTreeItemId search = FindItem( item, sSearchFor ); if( search.IsOk() ) { return search; } } item = m_ctlTreeCtrl->GetNextChild( root, cookie); } /* Not found */ wxTreeItemId dummy; return dummy; }
As an alternative, you could use the code below:
wxTreeCtrl Recursive Tree Item String Search
wxTreeItemId findTreeItem(wxTreeCtrl* pTreeCtrl, const wxTreeItemId& root, const wxString& text, bool bCaseSensitive, bool bExactMatch) { wxTreeItemId item=root, child; wxTreeItemIdValue cookie; wxString findtext(text), itemtext; bool bFound; if(!bCaseSensitive) findtext.MakeLower(); while(item.IsOk()) { itemtext = pTreeCtrl->GetItemText(item); if(!bCaseSensitive) itemtext.MakeLower(); bFound = bExactMatch ? (itemtext == findtext) : itemtext.Contains(findtext); if(bFound) return item; child = pTreeCtrl->GetFirstChild(item, cookie); if(child.IsOk()) child = findTreeItem(pTreeCtrl, child, text, bCaseSensitive, bExactMatch); if(child.IsOk()) return child; item = pTreeCtrl->GetNextSibling(item); } // while(item.IsOk()) return item; }
Example usage of the wxTreeCtrl String Search
void MyDialog::findMessage(wxCommandEvent& e) { wxArrayTreeItemIds Selections; wxTreeItemId item; wxTreeItemIdValue cookie; // fill wxString m_search, bool m_bCaseSensitive, m_bExactMatch from an external source/dialog before this if(m_search.IsEmpty()) return; if(m_TreeCtrl->GetSelections(Selections)) item = Selections[0]; else item=m_TreeCtrl->GetFirstChild(m_TreeCtrl->GetRootItem(), cookie); if(!m_TreeCtrl->GetCount()) return; // empty tree control - i.e. just cleared it? item = findTreeItem(m_TreeCtrl, item, m_search, m_bCaseSensitive, m_bExactMatch); if(!item.IsOk()) return; // found an item m_TreeCtrl->UnselectAll(); m_TreeCtrl->SelectItem(item, true); m_TreeCtrl->EnsureVisible(item); return; }
An alternative non-recursive way of finding an element
wxTreeItemId FindItemNamed(wxTreeCtrl &tree, const std::wstring &name) { std::stack<wxTreeItemId> items; if (tree->GetRootItem().IsOk()) items.push(tree->GetRootItem()); while (!items.empty()) { wxTreeItemId next = items.top(); items.pop(); if (next != tree->GetRootItem() && tree->GetItemText(next) == name) return next; wxTreeItemIdValue cookie; wxTreeItemId nextChild = tree->GetFirstChild(next, cookie); while (nextChild.IsOk()) { items.push(nextChild); nextChild = tree->GetNextSibling(nextChild); } } return wxTreeItemId(); }
[edit] Using Connect() with wxTreeCtrl
Just in case you're trying to guess what these events are named, based on the macros.
wxTreeEvent types:
wxEVT_COMMAND_TREE_BEGIN_DRAG wxEVT_COMMAND_TREE_BEGIN_RDRAG wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT wxEVT_COMMAND_TREE_END_LABEL_EDIT wxEVT_COMMAND_TREE_DELETE_ITEM wxEVT_COMMAND_TREE_GET_INFO wxEVT_COMMAND_TREE_SET_INFO wxEVT_COMMAND_TREE_ITEM_EXPANDED wxEVT_COMMAND_TREE_ITEM_EXPANDING wxEVT_COMMAND_TREE_ITEM_COLLAPSED wxEVT_COMMAND_TREE_ITEM_COLLAPSING wxEVT_COMMAND_TREE_SEL_CHANGED wxEVT_COMMAND_TREE_SEL_CHANGING wxEVT_COMMAND_TREE_KEY_DOWN wxEVT_COMMAND_TREE_ITEM_ACTIVATED wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK wxEVT_COMMAND_TREE_END_DRAG wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
