wxTreeCtrl

From WxWiki
Jump to: navigation, search
Official Classes SmallBlocks.png Archive Containers Controls Data Structures Database Date & Time Debug Device Contexts Dialogs Document & Views Drag & Drop Events Filesystem Frames Graphics Grid Cell Help HTML Logging Miscellaneous Networking Printing Sizers Streams Threading Windows

A tree control presents information as a hierarchy, with items that may be expanded to show further items.

Items in a tree control are referenced by wxTreeItemId handles, which may be tested for validity by calling wxTreeItemId::IsOk().

A similar control with a fully native implementation for GTK+ and OS X as well is wxDataViewTreeCtrl.

To intercept events from a tree control, use the event table macros described in wxTreeEvent.

Drag and Dropping Items

Tree controls in wxWidgets also provide built in support for manipulating tree items by dragging and dropping them, this is kind of necessary for using them to emulate directory structures or a hierarchy in an Interactive Development Evironment.

Context Menus

Context menu's can be applied to a wxTreeCtrl or view through either attaching them to the right mouse event, context menu event, or the item context menu event.

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.

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:

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;
}
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;
}


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();
}


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

See Also