+wxTreeCtrl::~wxTreeCtrl()
+{
+ // delete any attributes
+ if ( m_hasAnyAttr )
+ {
+ WX_CLEAR_HASH_MAP(wxMapTreeAttr, m_attrs);
+
+ // prevent TVN_DELETEITEM handler from deleting the attributes again!
+ m_hasAnyAttr = false;
+ }
+
+ DeleteTextCtrl();
+
+ // delete user data to prevent memory leaks
+ // also deletes hidden root node storage.
+ DeleteAllItems();
+
+ if (m_ownsImageListNormal) delete m_imageListNormal;
+ if (m_ownsImageListState) delete m_imageListState;
+}
+
+// ----------------------------------------------------------------------------
+// accessors
+// ----------------------------------------------------------------------------
+
+// simple wrappers which add error checking in debug mode
+
+bool wxTreeCtrl::DoGetItem(wxTreeViewItem* tvItem) const
+{
+ wxCHECK_MSG( tvItem->hItem != TVI_ROOT, false,
+ _T("can't retrieve virtual root item") );
+
+ if ( !TreeView_GetItem(GetHwnd(), tvItem) )
+ {
+ wxLogLastError(wxT("TreeView_GetItem"));
+
+ return false;
+ }
+
+ return true;
+}
+
+void wxTreeCtrl::DoSetItem(wxTreeViewItem* tvItem)
+{
+ if ( TreeView_SetItem(GetHwnd(), tvItem) == -1 )
+ {
+ wxLogLastError(wxT("TreeView_SetItem"));
+ }
+}
+
+size_t wxTreeCtrl::GetCount() const
+{
+ return (size_t)TreeView_GetCount(GetHwnd());
+}
+
+unsigned int wxTreeCtrl::GetIndent() const
+{
+ return TreeView_GetIndent(GetHwnd());
+}
+
+void wxTreeCtrl::SetIndent(unsigned int indent)
+{
+ TreeView_SetIndent(GetHwnd(), indent);
+}
+
+wxImageList *wxTreeCtrl::GetImageList() const
+{
+ return m_imageListNormal;
+}
+
+wxImageList *wxTreeCtrl::GetStateImageList() const
+{
+ return m_imageListState;
+}
+
+void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which)
+{
+ // no error return
+ TreeView_SetImageList(GetHwnd(),
+ imageList ? imageList->GetHIMAGELIST() : 0,
+ which);
+}
+
+void wxTreeCtrl::SetImageList(wxImageList *imageList)
+{
+ if (m_ownsImageListNormal)
+ delete m_imageListNormal;
+
+ SetAnyImageList(m_imageListNormal = imageList, TVSIL_NORMAL);
+ m_ownsImageListNormal = false;
+}
+
+void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
+{
+ if (m_ownsImageListState) delete m_imageListState;
+ SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
+ m_ownsImageListState = false;
+}
+
+void wxTreeCtrl::AssignImageList(wxImageList *imageList)
+{
+ SetImageList(imageList);
+ m_ownsImageListNormal = true;
+}
+
+void wxTreeCtrl::AssignStateImageList(wxImageList *imageList)
+{
+ SetStateImageList(imageList);
+ m_ownsImageListState = true;
+}
+
+size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
+ bool recursively) const
+{
+ TraverseCounter counter(this, item, recursively);
+
+ return counter.GetCount() - 1;
+}
+
+// ----------------------------------------------------------------------------
+// control colours
+// ----------------------------------------------------------------------------
+
+bool wxTreeCtrl::SetBackgroundColour(const wxColour &colour)
+{
+#if !wxUSE_COMCTL32_SAFELY
+ if ( !wxWindowBase::SetBackgroundColour(colour) )
+ return false;
+
+ SendMessage(GetHwnd(), TVM_SETBKCOLOR, 0, colour.GetPixel());
+#endif
+
+ return true;
+}
+
+bool wxTreeCtrl::SetForegroundColour(const wxColour &colour)
+{
+#if !wxUSE_COMCTL32_SAFELY
+ if ( !wxWindowBase::SetForegroundColour(colour) )
+ return false;
+
+ SendMessage(GetHwnd(), TVM_SETTEXTCOLOR, 0, colour.GetPixel());
+#endif
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// Item access
+// ----------------------------------------------------------------------------
+
+wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
+{
+ wxChar buf[512]; // the size is arbitrary...
+
+ wxTreeViewItem tvItem(item, TVIF_TEXT);
+ tvItem.pszText = buf;
+ tvItem.cchTextMax = WXSIZEOF(buf);
+ if ( !DoGetItem(&tvItem) )
+ {
+ // don't return some garbage which was on stack, but an empty string
+ buf[0] = wxT('\0');
+ }
+
+ return wxString(buf);
+}
+
+void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
+{
+ if ( IS_VIRTUAL_ROOT(item) )
+ return;
+
+ wxTreeViewItem tvItem(item, TVIF_TEXT);
+ tvItem.pszText = (wxChar *)text.c_str(); // conversion is ok
+ DoSetItem(&tvItem);
+
+ // when setting the text of the item being edited, the text control should
+ // be updated to reflect the new text as well, otherwise calling
+ // SetItemText() in the OnBeginLabelEdit() handler doesn't have any effect
+ //
+ // don't use GetEditControl() here because m_textCtrl is not set yet
+ HWND hwndEdit = TreeView_GetEditControl(GetHwnd());
+ if ( hwndEdit )
+ {
+ if ( item == GetSelection() )
+ {
+ ::SetWindowText(hwndEdit, text);
+ }
+ }
+}
+
+int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item,
+ wxTreeItemIcon which) const
+{
+ wxTreeViewItem tvItem(item, TVIF_PARAM);
+ if ( !DoGetItem(&tvItem) )
+ {
+ return -1;
+ }
+
+ return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which);
+}
+
+void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item,
+ int image,
+ wxTreeItemIcon which) const
+{
+ wxTreeViewItem tvItem(item, TVIF_PARAM);
+ if ( !DoGetItem(&tvItem) )
+ {
+ return;
+ }
+
+ wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam);
+
+ data->SetImage(image, which);
+
+ // make sure that we have selected images as well
+ if ( which == wxTreeItemIcon_Normal &&
+ !data->HasImage(wxTreeItemIcon_Selected) )
+ {
+ data->SetImage(image, wxTreeItemIcon_Selected);
+ }
+
+ if ( which == wxTreeItemIcon_Expanded &&
+ !data->HasImage(wxTreeItemIcon_SelectedExpanded) )
+ {
+ data->SetImage(image, wxTreeItemIcon_SelectedExpanded);
+ }
+}
+
+void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
+ int image,
+ int imageSel)
+{
+ wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE);
+ tvItem.iSelectedImage = imageSel;
+ tvItem.iImage = image;
+ DoSetItem(&tvItem);
+}
+
+int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
+ wxTreeItemIcon which) const
+{
+ if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+ {
+ // TODO: Maybe a hidden root can still provide images?
+ return -1;
+ }
+
+ if ( HasIndirectData(item) )
+ {
+ return DoGetItemImageFromData(item, which);
+ }
+
+ UINT mask;
+ switch ( which )
+ {
+ default:
+ wxFAIL_MSG( wxT("unknown tree item image type") );
+
+ case wxTreeItemIcon_Normal:
+ mask = TVIF_IMAGE;
+ break;
+
+ case wxTreeItemIcon_Selected:
+ mask = TVIF_SELECTEDIMAGE;
+ break;
+
+ case wxTreeItemIcon_Expanded:
+ case wxTreeItemIcon_SelectedExpanded:
+ return -1;
+ }
+
+ wxTreeViewItem tvItem(item, mask);
+ DoGetItem(&tvItem);
+
+ return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage;
+}
+
+void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
+ wxTreeItemIcon which)
+{
+ if ( IS_VIRTUAL_ROOT(item) )
+ {
+ // TODO: Maybe a hidden root can still store images?
+ return;
+ }
+
+ int imageNormal,
+ imageSel;
+
+ switch ( which )
+ {
+ default:
+ wxFAIL_MSG( wxT("unknown tree item image type") );
+ // fall through
+
+ case wxTreeItemIcon_Normal:
+ {
+ const int imageNormalOld = GetItemImage(item);
+ const int imageSelOld =
+ GetItemImage(item, wxTreeItemIcon_Selected);
+
+ // always set the normal image
+ imageNormal = image;