From: Vadim Zeitlin Date: Fri, 13 Nov 1998 20:47:22 +0000 (+0000) Subject: 1. GetNextChild() bug fixed in generic version X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/4832f7c06cfb85e5152489c052630df7b002e92e 1. GetNextChild() bug fixed in generic version 2. GetChildrenCount(bool recursive) added to all versions, implemented only in the generic one so far 3. Sample slightly modified to show new function git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@996 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/treectrl.h b/include/wx/generic/treectrl.h index 7b79534513..313c86d6d4 100644 --- a/include/wx/generic/treectrl.h +++ b/include/wx/generic/treectrl.h @@ -268,6 +268,13 @@ public: // is this item currently selected (the same as has focus)? bool IsSelected(const wxTreeItemId& item) const; + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + // navigation // ---------- diff --git a/include/wx/gtk/treectrl.h b/include/wx/gtk/treectrl.h index 24a0bc74c4..34ac6d2df6 100644 --- a/include/wx/gtk/treectrl.h +++ b/include/wx/gtk/treectrl.h @@ -6,7 +6,7 @@ // Created: 08/08/98 // RCS-ID: $Id$ // Copyright: (c) Denis Pershin -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TREECTRL_H_ @@ -234,6 +234,13 @@ public: // is this item currently selected (the same as has focus)? bool IsSelected(const wxTreeItemId& item) const; + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + // navigation // ---------- diff --git a/include/wx/gtk1/treectrl.h b/include/wx/gtk1/treectrl.h index 24a0bc74c4..34ac6d2df6 100644 --- a/include/wx/gtk1/treectrl.h +++ b/include/wx/gtk1/treectrl.h @@ -6,7 +6,7 @@ // Created: 08/08/98 // RCS-ID: $Id$ // Copyright: (c) Denis Pershin -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TREECTRL_H_ @@ -234,6 +234,13 @@ public: // is this item currently selected (the same as has focus)? bool IsSelected(const wxTreeItemId& item) const; + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + // navigation // ---------- diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index 021c68d66a..1c2dd8b348 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -250,6 +250,13 @@ public: // is this item currently selected (the same as has focus)? bool IsSelected(const wxTreeItemId& item) const; + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + // navigation // ---------- diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 6c04b00506..068853eac0 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -42,6 +42,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(TreeTest_Quit, MyFrame::OnQuit) EVT_MENU(TreeTest_About, MyFrame::OnAbout) + EVT_MENU(TreeTest_Dump, MyFrame::OnDump) END_EVENT_TABLE() BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl) @@ -58,7 +59,7 @@ BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl) EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing) EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged) EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging) - EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnKeyDown) + EVT_CHAR(MyTreeCtrl::OnKeyDown) END_EVENT_TABLE() IMPLEMENT_APP(MyApp) @@ -92,8 +93,12 @@ MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) // Make a menubar wxMenu *file_menu = new wxMenu; + file_menu->Append(TreeTest_Dump, "&Dump tree items"); + file_menu->AppendSeparator(); file_menu->Append(TreeTest_About, "&About..."); + file_menu->AppendSeparator(); file_menu->Append(TreeTest_Quit, "E&xit"); + wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); SetMenuBar(menu_bar); @@ -142,12 +147,20 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { - wxMessageDialog dialog(this, "Tree test sample\nJulian Smart (c) 1997", + wxMessageDialog dialog(this, + "Tree test sample\n" + "Julian Smart (c) 1997", "About tree test", wxOK); dialog.ShowModal(); } +void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event)) +{ + wxTreeItemId root=m_treeCtrl->GetSelection(); + m_treeCtrl->GetItemsRecursively(root, -1); +} + // MyTreeCtrl implementation MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -164,7 +177,7 @@ MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, SetImageList(m_imageListNormal); // Add some items to the tree - AddTestItemsToTree(4, 3); + AddTestItemsToTree(3, 2); } MyTreeCtrl::~MyTreeCtrl() @@ -174,7 +187,8 @@ MyTreeCtrl::~MyTreeCtrl() void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent, size_t numChildren, - size_t depth) + size_t depth, + size_t folder) { if ( depth > 0 ) { @@ -182,11 +196,15 @@ void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent, for ( size_t n = 0; n < numChildren; n++ ) { // at depth 1 elements won't have any more children - str.Printf("%s child %d", depth == 1 ? "File" : "Folder", n + 1); + if (depth == 1) + str.Printf("%s child %d.%d", "File", folder, n + 1); + else + str.Printf("%s child %d","Folder", n + 1); + int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder; wxTreeItemId id = AppendItem(idParent, str, image, image, new MyTreeItemData(str)); - AddItemsRecursively(id, numChildren, depth - 1); + AddItemsRecursively(id, numChildren, depth - 1,n+1); } } //else: done! @@ -199,9 +217,31 @@ void MyTreeCtrl::AddTestItemsToTree(size_t numChildren, TreeCtrlIcon_Folder, TreeCtrlIcon_Folder, new MyTreeItemData("Root item")); - AddItemsRecursively(rootId, numChildren, depth); + AddItemsRecursively(rootId, numChildren, depth,0); +} + +void MyTreeCtrl::GetItemsRecursively(const wxTreeItemId& idParent, long cookie) +{ + wxTreeItemId id; + + if( cookie == -1 ) + id = GetFirstChild(idParent, cookie); + else + id = GetNextChild(idParent, cookie); + + if(id <= 0) + return; + + wxString text=GetItemText(id); + wxLogMessage(text); + + if (ItemHasChildren(id)) + GetItemsRecursively(id,-1); + + GetItemsRecursively(idParent, cookie); } + // avoid repetition #define TREE_EVENT_HANDLER(name) \ void MyTreeCtrl::name(wxTreeEvent& WXUNUSED(event)) \ @@ -259,8 +299,11 @@ static inline const char *Bool2String(bool b) void MyTreeItemData::ShowInfo(wxTreeCtrl *tree) { - wxLogMessage("Item '%s': %sselected, %sexpanded.", + wxLogMessage("Item '%s': %sselected, %sexpanded, " + "%u children (%u immediately under this item).", m_desc.c_str(), Bool2String(tree->IsSelected(GetId())), - Bool2String(tree->IsExpanded(GetId()))); + Bool2String(tree->IsExpanded(GetId())), + tree->GetChildrenCount(GetId()), + tree->GetChildrenCount(GetId(), FALSE)); } diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h index 68279c9208..68a4583b0a 100644 --- a/samples/treectrl/treetest.h +++ b/samples/treectrl/treetest.h @@ -56,10 +56,13 @@ public: void OnSelChanging(wxTreeEvent& event); void OnKeyDown(wxTreeEvent& event); + void GetItemsRecursively(const wxTreeItemId& idParent, long cookie); + private: void AddItemsRecursively(const wxTreeItemId& idParent, size_t nChildren, - size_t depth); + size_t depth, + size_t folder); void AddTestItemsToTree(size_t numChildren, size_t depth); @@ -80,6 +83,7 @@ public: // menu callbacks void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); + void OnDump(wxCommandEvent& event); private: MyTreeCtrl *m_treeCtrl; @@ -92,6 +96,7 @@ enum { TreeTest_Quit, TreeTest_About, + TreeTest_Dump, TreeTest_Ctrl = 100 }; diff --git a/src/generic/treectrl.cpp b/src/generic/treectrl.cpp index 45b776dce1..c214bbe26a 100644 --- a/src/generic/treectrl.cpp +++ b/src/generic/treectrl.cpp @@ -81,8 +81,8 @@ public: // operations void Reset(); - // get count of all children (and grand children and ...) of this item - size_t GetTotalNumberOfChildren() const; + // get count of all children (and grand children if 'recursively') + size_t GetChildrenCount(bool recursively = TRUE) const; void Insert(wxGenericTreeItem *child, size_t index) { m_children.Insert(child, index); } @@ -113,7 +113,7 @@ private: m_selImage; wxTreeItemData *m_data; - + // @@ probably should use bitfields to save size bool m_isCollapsed, m_hasHilight, // same as focused @@ -176,7 +176,7 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent, wxGenericTreeItem::~wxGenericTreeItem() { delete m_data; - + size_t count = m_children.Count(); for ( size_t n = 0; n < count; n++ ) delete m_children[n]; @@ -208,13 +208,16 @@ void wxGenericTreeItem::Reset() m_parent = (wxGenericTreeItem *)NULL; } -size_t wxGenericTreeItem::GetTotalNumberOfChildren() const +size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const { size_t count = m_children.Count(); + if ( !recursively ) + return count; + size_t total = count; for ( size_t n = 0; n < count; n++ ) { - total += m_children[n]->GetTotalNumberOfChildren(); + total += m_children[n]->GetChildrenCount(); } return total; @@ -237,7 +240,7 @@ void wxGenericTreeItem::GetSize( int &x, int &y ) { size_t count = m_children.Count(); for ( size_t n = 0; n < count; n++ ) - { + { m_children[n]->GetSize( x, y ); } } @@ -344,7 +347,7 @@ wxTreeCtrl::~wxTreeCtrl() size_t wxTreeCtrl::GetCount() const { - return m_anchor == NULL ? 0u : m_anchor->GetTotalNumberOfChildren(); + return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount(); } void wxTreeCtrl::SetIndent(unsigned int indent) @@ -353,53 +356,78 @@ void wxTreeCtrl::SetIndent(unsigned int indent) Refresh(); } +size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively) +{ + wxCHECK_MSG( item.IsOk(), 0u, "invalid tree item" ); + + return item.m_pItem->GetChildrenCount(recursively); +} + // ----------------------------------------------------------------------------- // functions to work with tree items // ----------------------------------------------------------------------------- wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), "", "invalid tree item" ); + return item.m_pItem->GetText(); } int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); + return item.m_pItem->GetImage(); } int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); + return item.m_pItem->GetSelectedImage(); } wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); + return item.m_pItem->GetData(); } void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) { + wxCHECK_RET( item.IsOk(), "invalid tree item" ); + wxClientDC dc(this); item.m_pItem->SetText(text, dc); } void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image) { + wxCHECK_RET( item.IsOk(), "invalid tree item" ); + item.m_pItem->SetImage(image); } void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image) { + wxCHECK_RET( item.IsOk(), "invalid tree item" ); + item.m_pItem->SetSelectedImage(image); } void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) { + wxCHECK_RET( item.IsOk(), "invalid tree item" ); + item.m_pItem->SetData(data); } void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) { + wxCHECK_RET( item.IsOk(), "invalid tree item" ); + item.m_pItem->SetHasPlus(has); } @@ -416,16 +444,22 @@ bool wxTreeCtrl::IsVisible(const wxTreeItemId& WXUNUSED(item)) const bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); + return !item.m_pItem->GetChildren().IsEmpty(); } bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); + return item.m_pItem->IsExpanded(); } bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const { + wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); + return item.m_pItem->HasHilight(); } @@ -452,7 +486,16 @@ wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) co { wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); - return item.m_pItem->GetChildren().Item(cookie++); + wxArrayTreeItems& children = item.m_pItem->GetChildren(); + if ( (size_t)cookie < children.Count() ) + { + return item.m_pItem->GetChildren().Item(cookie++); + } + else + { + // there are no more of them + return NULL; + } } wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const @@ -466,7 +509,7 @@ wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const // root item doesn't have any siblings return NULL; } - + wxArrayTreeItems& siblings = parent->GetChildren(); int index = siblings.Index(i); wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? @@ -486,7 +529,7 @@ wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const // root item doesn't have any siblings return NULL; } - + wxArrayTreeItems& siblings = parent->GetChildren(); int index = siblings.Index(i); wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? @@ -535,7 +578,7 @@ wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, // should we give a warning here? return AddRoot(text, image, selImage, data); } - + wxClientDC dc(this); wxGenericTreeItem *item = new wxGenericTreeItem(parent, text, dc, @@ -557,7 +600,7 @@ wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, PrepareDC( dc ); wxRectangle rect; - rect.x = dc.LogicalToDeviceX( 0 ); + rect.x = dc.LogicalToDeviceX( 0 ); rect.y = 0; rect.width = 10000; // @@@ not very elegant... rect.height = ch; @@ -677,7 +720,7 @@ void wxTreeCtrl::Expand(const wxTreeItemId& itemId) // cancelled by program return; } - + item->Expand(); RefreshSubtree(item); @@ -701,7 +744,7 @@ void wxTreeCtrl::Collapse(const wxTreeItemId& itemId) // cancelled by program return; } - + item->Collapse(); wxArrayTreeItems& children = item->GetChildren(); @@ -867,14 +910,14 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int & int exposed_x = dc.LogicalToDeviceX( 0 ); int exposed_y = dc.LogicalToDeviceY( item->GetY()-2 ); - + if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 )) // 10000 = very much { int startX = horizX; int endX = horizX + 10; if (!item->HasChildren()) endX += 20; - + dc.DrawLine( startX, y, endX, y ); if (item->HasPlus()) @@ -893,11 +936,11 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int & { dc.SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); dc.SetBrush( *m_hilightBrush ); - + long text_w = 0; long text_h = 0; dc.GetTextExtent( item->GetText(), &text_w, &text_h ); - + int image_h = 0; int image_w = 0; if (item->GetImage() != -1) @@ -905,14 +948,14 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int & m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); image_w += 4; } - + if (m_hasFocus) dc.SetPen( *wxBLACK_PEN ); else dc.SetPen( *wxTRANSPARENT_PEN ); - + dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); - + if (item->GetImage() != -1) { dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); @@ -929,11 +972,11 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int & { dc.SetBrush( *wxWHITE_BRUSH ); dc.SetPen( *wxTRANSPARENT_PEN ); - + long text_w = 0; long text_h = 0; dc.GetTextExtent( item->GetText(), &text_w, &text_h ); - + int image_h = 0; int image_w = 0; if (item->GetImage() != -1) @@ -941,16 +984,16 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int & m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); image_w += 4; } - + dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); - + if (item->GetImage() != -1) { dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); m_imageListNormal->Draw( item->GetImage(), dc, item->GetX(), item->GetY()-1, wxIMAGELIST_DRAW_TRANSPARENT ); dc.DestroyClippingRegion(); } - + dc.DrawText( item->GetText(), image_w+item->GetX(), item->GetY() ); dc.SetPen( *wxBLACK_PEN ); } @@ -1096,11 +1139,11 @@ void wxTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) { wxClientDC dc(this); PrepareDC(dc); - + int cw = 0; int ch = 0; GetClientSize( &cw, &ch ); - + wxRect rect; rect.x = dc.LogicalToDeviceX( 0 ); rect.width = cw;