From 1e28312035a97461d1615deae8b69acd8a868457 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 13:52:48 +0100 Subject: [PATCH 1/5] Override DoExpand() in wxQt wxDataViewCtrl stub This code doesn't work (and probably doesn't compile) anyhow, but at least try to do the right thing in it and override DoExpand() instead of adding a virtual Expand() hiding the non-virtual version in the base class. --- include/wx/qt/dataview.h | 2 +- src/qt/dataview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/wx/qt/dataview.h b/include/wx/qt/dataview.h index e53695fcfb..b61f803f75 100644 --- a/include/wx/qt/dataview.h +++ b/include/wx/qt/dataview.h @@ -115,7 +115,6 @@ public: virtual wxRect GetItemRect( const wxDataViewItem &item, const wxDataViewColumn *column = NULL ) const; - virtual void Expand( const wxDataViewItem & item ); virtual void Collapse( const wxDataViewItem & item ); virtual bool IsExpanded( const wxDataViewItem & item ) const; @@ -132,6 +131,7 @@ public: protected: virtual void DoSetExpanderColumn(); virtual void DoSetIndent(); + virtual void DoExpand( const wxDataViewItem & item ); private: virtual wxDataViewItem DoGetCurrentItem() const; diff --git a/src/qt/dataview.cpp b/src/qt/dataview.cpp index 1b16d555e8..ee2b5177d8 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::Expand( const wxDataViewItem & item ) +void wxDataViewCtrl::DoExpand( const wxDataViewItem & item ) { } From faffc5fe0a6deb21f6f35cfe252d9cf43f63fbf6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 14:16:17 +0100 Subject: [PATCH 2/5] Only invalidate row height cache when a row is really expanded It's wasteful to do it if it's already expanded or won't be expanded because the EXPANDING event is vetoed. --- src/generic/datavgen.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 2dfd7a953c..4b3ae669ec 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -3919,13 +3919,6 @@ void wxDataViewMainWindow::Expand( unsigned int row ) if (!node->HasChildren()) return; - if ( m_rowHeightCache ) - { - // Expand makes new rows visible thus we invalidates all following - // rows in the height cache - m_rowHeightCache->Remove(row); - } - if (!node->IsOpen()) { if ( !SendExpanderEvent(wxEVT_DATAVIEW_ITEM_EXPANDING, node->GetItem()) ) @@ -3934,6 +3927,13 @@ void wxDataViewMainWindow::Expand( unsigned int row ) return; } + if ( m_rowHeightCache ) + { + // Expand makes new rows visible thus we invalidates all following + // rows in the height cache + m_rowHeightCache->Remove(row); + } + node->ToggleOpen(this); // build the children of current node From d47fa718cdbb5190b59eff38e8ec60ae994b07dd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 14:41:09 +0100 Subject: [PATCH 3/5] 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, From a53e69beb0a1a97aee5e136b71093339319326b7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 14:42:56 +0100 Subject: [PATCH 4/5] Allow expanding/collapsing items from keyboard in generic wxDVC Add the usual handlers for '-', '+' and '*' keys. The last one is especially convenient, as it does something that couldn't be easily done at all interactively before. --- src/generic/datavgen.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index d2c5a03a75..2e47cfbae8 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -4612,7 +4612,27 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) case WXK_DOWN: OnVerticalNavigation(event, +1); break; - // Add the process for tree expanding/collapsing + + case '+': + case WXK_ADD: + Expand(m_currentRow); + break; + + case '*': + case WXK_MULTIPLY: + if ( !IsExpanded(m_currentRow) ) + { + Expand(m_currentRow, true /* recursively */); + break; + } + //else: fall through to Collapse() + wxFALLTHROUGH; + + case '-': + case WXK_SUBTRACT: + Collapse(m_currentRow); + break; + case WXK_LEFT: OnLeftKey(event); break; From 3b92572eb6ea66230e07dfe523174bec66840054 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 5 Dec 2020 14:43:53 +0100 Subject: [PATCH 5/5] Focus the data view control on the sample startup Previously focus stayed on the log text control, which was useless and inconvenient. --- samples/dataview/dataview.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 98630dc39a..db9150bb15 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -742,6 +742,9 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int mainSizer->Add( m_log, 0, wxGROW ); SetSizerAndFit(mainSizer); + + // Allow using the control from keyboard on startup. + m_ctrl[Page_Music]->SetFocus(); } MyFrame::~MyFrame()