From d47fa718cdbb5190b59eff38e8ec60ae994b07dd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 14:41:09 +0100 Subject: [PATCH] Add wxDataViewCtrl::ExpandChildren() This convenient method allows to expand all children of the item recursively. This is directly supported by both native implementations, so it makes sense to have this in wxDataViewCtrl itself, even if it could be also (less efficiently) implemented in the user code. --- include/wx/dataview.h | 5 +++- include/wx/generic/dataview.h | 2 +- include/wx/gtk/dataview.h | 2 +- include/wx/osx/cocoa/dataview.h | 2 +- include/wx/osx/core/dataview.h | 2 +- include/wx/osx/dataview.h | 2 +- include/wx/qt/dataview.h | 2 +- interface/wx/dataview.h | 10 +++++++ src/common/datavcmn.cpp | 11 ++++++-- src/generic/datavgen.cpp | 41 ++++++++++++++++++++++++++--- src/gtk/dataview.cpp | 5 ++-- src/osx/cocoa/dataview.mm | 4 +-- src/osx/dataview_osx.cpp | 4 +-- src/qt/dataview.cpp | 2 +- tests/controls/dataviewctrltest.cpp | 13 +++++++++ 15 files changed, 87 insertions(+), 20 deletions(-) diff --git a/include/wx/dataview.h b/include/wx/dataview.h index bb831d0df8..0d7f46cd8f 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -740,6 +740,7 @@ public: virtual void UnselectAll() = 0; void Expand( const wxDataViewItem & item ); + void ExpandChildren( const wxDataViewItem & item ); void ExpandAncestors( const wxDataViewItem & item ); virtual void Collapse( const wxDataViewItem & item ) = 0; virtual bool IsExpanded( const wxDataViewItem & item ) const = 0; @@ -793,7 +794,9 @@ protected: // Just expand this item assuming it is already shown, i.e. its parent has // been already expanded using ExpandAncestors(). - virtual void DoExpand(const wxDataViewItem & item) = 0; + // + // If expandChildren is true, also expand all its children recursively. + virtual void DoExpand(const wxDataViewItem & item, bool expandChildren) = 0; private: // Implementation of the public Set/GetCurrentItem() methods which are only diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index d15991e810..b773882488 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -364,7 +364,7 @@ private: virtual wxDataViewItem DoGetCurrentItem() const wxOVERRIDE; virtual void DoSetCurrentItem(const wxDataViewItem& item) wxOVERRIDE; - virtual void DoExpand(const wxDataViewItem& item) wxOVERRIDE; + virtual void DoExpand(const wxDataViewItem& item, bool expandChildren) wxOVERRIDE; void InvalidateColBestWidths(); void InvalidateColBestWidth(int idx); diff --git a/include/wx/gtk/dataview.h b/include/wx/gtk/dataview.h index ae2d2f0165..b5933cd33a 100644 --- a/include/wx/gtk/dataview.h +++ b/include/wx/gtk/dataview.h @@ -218,7 +218,7 @@ protected: virtual void DoSetExpanderColumn() wxOVERRIDE; virtual void DoSetIndent() wxOVERRIDE; - virtual void DoExpand(const wxDataViewItem& item) wxOVERRIDE; + virtual void DoExpand(const wxDataViewItem& item, bool expandChildren) wxOVERRIDE; virtual void DoApplyWidgetStyle(GtkRcStyle *style) wxOVERRIDE; virtual GdkWindow* GTKGetWindow(wxArrayGdkWindows& windows) const wxOVERRIDE; diff --git a/include/wx/osx/cocoa/dataview.h b/include/wx/osx/cocoa/dataview.h index 41d16201d8..97b2946ede 100644 --- a/include/wx/osx/cocoa/dataview.h +++ b/include/wx/osx/cocoa/dataview.h @@ -530,7 +530,7 @@ public: // virtual void DoSetIndent(int indent); - virtual void DoExpand(const wxDataViewItem& item); + virtual void DoExpand(const wxDataViewItem& item, bool expandChildren); virtual void HitTest(const wxPoint& point, wxDataViewItem& item, diff --git a/include/wx/osx/core/dataview.h b/include/wx/osx/core/dataview.h index f3ac6d33fd..c9b7bde6ae 100644 --- a/include/wx/osx/core/dataview.h +++ b/include/wx/osx/core/dataview.h @@ -105,7 +105,7 @@ public: // other methods // virtual void DoSetIndent (int indent) = 0; // sets the indentation in the native control - virtual void DoExpand (wxDataViewItem const& item) = 0; // expands the passed item in the native control + virtual void DoExpand (wxDataViewItem const& item, bool expandChildren) = 0; // expands the passed item in the native control virtual void HitTest (wxPoint const& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const = 0; // return the item and column pointer that contains with the passed point virtual void SetRowHeight(int height) = 0; // sets the height of all rows diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index a7a58d6f54..28e4d557c2 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -276,7 +276,7 @@ protected: virtual void DoSetExpanderColumn() wxOVERRIDE; virtual void DoSetIndent() wxOVERRIDE; - virtual void DoExpand(const wxDataViewItem& item) wxOVERRIDE; + virtual void DoExpand(const wxDataViewItem& item, bool expandChildren) wxOVERRIDE; virtual wxSize DoGetBestSize() const wxOVERRIDE; diff --git a/include/wx/qt/dataview.h b/include/wx/qt/dataview.h index b61f803f75..778bda4d67 100644 --- a/include/wx/qt/dataview.h +++ b/include/wx/qt/dataview.h @@ -131,7 +131,7 @@ public: protected: virtual void DoSetExpanderColumn(); virtual void DoSetIndent(); - virtual void DoExpand( const wxDataViewItem & item ); + virtual void DoExpand( const wxDataViewItem & item, bool expandChildren ); private: virtual wxDataViewItem DoGetCurrentItem() const; diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index 76266e4126..582af1ac53 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -1402,6 +1402,16 @@ public: */ void ExpandAncestors( const wxDataViewItem & item ); + /** + Expand all all children of the given item recursively. + + This is the same as calling Expand() on the @a item itself and then + calling it for all of its children, grandchildren etc recursively. + + @since 3.1.5 + */ + void ExpandChildren( const wxDataViewItem & item ); + /** Returns pointer to the column. @a pos refers to the position in the control which may change after reordering columns by the user. diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 14609bbccd..1f5fd4d66b 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -1265,7 +1265,14 @@ void wxDataViewCtrlBase::Expand(const wxDataViewItem& item) { ExpandAncestors(item); - DoExpand(item); + DoExpand(item, false); +} + +void wxDataViewCtrlBase::ExpandChildren(const wxDataViewItem& item) +{ + ExpandAncestors(item); + + DoExpand(item, true); } void wxDataViewCtrlBase::ExpandAncestors( const wxDataViewItem & item ) @@ -1287,7 +1294,7 @@ void wxDataViewCtrlBase::ExpandAncestors( const wxDataViewItem & item ) // then we expand the parents, starting at the root while (!parentChain.empty()) { - DoExpand(parentChain.back()); + DoExpand(parentChain.back(), false); parentChain.pop_back(); } } diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 4b3ae669ec..d2c5a03a75 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -874,7 +874,7 @@ public: void HitTest( const wxPoint & point, wxDataViewItem & item, wxDataViewColumn* &column ); wxRect GetItemRect( const wxDataViewItem & item, const wxDataViewColumn* column ); - void Expand( unsigned int row ); + void Expand( unsigned int row, bool expandChildren = false ); void Collapse( unsigned int row ); bool IsExpanded( unsigned int row ) const; bool HasChildren( unsigned int row ) const; @@ -990,6 +990,9 @@ private: return NULL; } + // Helper of public Expand(), must be called with a valid node. + void DoExpand(wxDataViewTreeNode* node, unsigned int row, bool expandChildren); + private: wxDataViewCtrl *m_owner; int m_lineHeight; @@ -3907,7 +3910,7 @@ bool wxDataViewMainWindow::HasChildren( unsigned int row ) const return true; } -void wxDataViewMainWindow::Expand( unsigned int row ) +void wxDataViewMainWindow::Expand( unsigned int row, bool expandChildren ) { if (IsList()) return; @@ -3916,6 +3919,14 @@ void wxDataViewMainWindow::Expand( unsigned int row ) if (!node) return; + return DoExpand(node, row, expandChildren); +} + +void +wxDataViewMainWindow::DoExpand(wxDataViewTreeNode* node, + unsigned int row, + bool expandChildren) +{ if (!node->HasChildren()) return; @@ -3961,6 +3972,28 @@ void wxDataViewMainWindow::Expand( unsigned int row ) // Send the expanded event SendExpanderEvent(wxEVT_DATAVIEW_ITEM_EXPANDED,node->GetItem()); } + + // Note that we have to expand the children when expanding recursively even + // when this node itself was already open. + if ( expandChildren ) + { + const wxDataViewTreeNodes& children = node->GetChildNodes(); + + for ( wxDataViewTreeNodes::const_iterator i = children.begin(); + i != children.end(); + ++i ) + { + wxDataViewTreeNode* const child = *i; + + // Row currently corresponds to the previous item, so increment it + // first to correspond to this child. + DoExpand(child, ++row, true); + + // We don't need +1 here because we'll increment the row during the + // next loop iteration. + row += child->GetSubTreeCount(); + } + } } void wxDataViewMainWindow::Collapse(unsigned int row) @@ -6309,11 +6342,11 @@ int wxDataViewCtrl::GetRowByItem( const wxDataViewItem & item ) const return m_clientArea->GetRowByItem( item ); } -void wxDataViewCtrl::DoExpand( const wxDataViewItem & item ) +void wxDataViewCtrl::DoExpand( const wxDataViewItem & item, bool expandChildren ) { int row = m_clientArea->GetRowByItem( item ); if (row != -1) - m_clientArea->Expand(row); + m_clientArea->Expand(row, expandChildren); } void wxDataViewCtrl::Collapse( const wxDataViewItem & item ) diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 39c18815a3..43e13deb6e 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -5068,12 +5068,13 @@ wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const return m_internal->GetDataViewSortColumn(); } -void wxDataViewCtrl::DoExpand( const wxDataViewItem & item ) +void wxDataViewCtrl::DoExpand( const wxDataViewItem & item, bool expandChildren ) { GtkTreeIter iter; iter.user_data = item.GetID(); wxGtkTreePath path(m_internal->get_path( &iter )); - gtk_tree_view_expand_row( GTK_TREE_VIEW(m_treeview), path, false ); + gtk_tree_view_expand_row( GTK_TREE_VIEW(m_treeview), path, + expandChildren ? TRUE : FALSE ); } void wxDataViewCtrl::Collapse( const wxDataViewItem & item ) diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 770719e4a9..9b5cc05f59 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -2314,9 +2314,9 @@ void wxCocoaDataViewControl::EnsureVisible(const wxDataViewItem& item, const wxD } } -void wxCocoaDataViewControl::DoExpand(const wxDataViewItem& item) +void wxCocoaDataViewControl::DoExpand(const wxDataViewItem& item, bool expandChildren) { - [m_OutlineView expandItem:[m_DataSource getDataViewItemFromBuffer:item]]; + [m_OutlineView expandItem:[m_DataSource getDataViewItemFromBuffer:item] expandChildren:expandChildren]; } unsigned int wxCocoaDataViewControl::GetCount() const diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index ad197cc85c..9812036eef 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -516,9 +516,9 @@ void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn } } -void wxDataViewCtrl::DoExpand(wxDataViewItem const& item) +void wxDataViewCtrl::DoExpand(wxDataViewItem const& item, bool expandChildren) { - return GetDataViewPeer()->DoExpand(item); + return GetDataViewPeer()->DoExpand(item, expandChildren); } bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const diff --git a/src/qt/dataview.cpp b/src/qt/dataview.cpp index ee2b5177d8..61cf681ca0 100644 --- a/src/qt/dataview.cpp +++ b/src/qt/dataview.cpp @@ -267,7 +267,7 @@ wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem &item, return wxRect(); } -void wxDataViewCtrl::DoExpand( const wxDataViewItem & item ) +void wxDataViewCtrl::DoExpand( const wxDataViewItem & item, bool expandChildren ) { } diff --git a/tests/controls/dataviewctrltest.cpp b/tests/controls/dataviewctrltest.cpp index 2f88a0aa17..f970c886b2 100644 --- a/tests/controls/dataviewctrltest.cpp +++ b/tests/controls/dataviewctrltest.cpp @@ -271,6 +271,19 @@ TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase, CHECK( !m_dvc->IsExpanded(m_grandchild) ); #endif CHECK( !m_dvc->IsExpanded(m_child2) ); + + m_dvc->Collapse(m_root); + CHECK( !m_dvc->IsExpanded(m_root) ); + + m_dvc->ExpandChildren(m_root); + CHECK( m_dvc->IsExpanded(m_root) ); + CHECK( m_dvc->IsExpanded(m_child1) ); + + // Expanding an already expanded node must still expand all its children. + m_dvc->Collapse(m_child1); + CHECK( !m_dvc->IsExpanded(m_child1) ); + m_dvc->ExpandChildren(m_root); + CHECK( m_dvc->IsExpanded(m_child1) ); } TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,