diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index fb83cd49cb..2dfd7a953c 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -74,6 +74,13 @@ static const int PADDING_RIGHTLEFT = 3; namespace { +// Flags for Walker() function defined below. +enum WalkFlags +{ + Walk_All, // Visit all items. + Walk_ExpandedOnly // Visit only expanded items. +}; + // The column is either the index of the column to be used for sorting or one // of the special values in this enum: enum @@ -854,7 +861,8 @@ public: // Some useful functions for row and item mapping wxDataViewItem GetItemByRow( unsigned int row ) const; - int GetRowByItem( const wxDataViewItem & item ) const; + int GetRowByItem( const wxDataViewItem & item, + WalkFlags flags = Walk_All ) const; wxDataViewTreeNode * GetTreeNodeByRow( unsigned int row ) const; // We did not need this temporarily @@ -2993,6 +3001,10 @@ void wxDataViewHeaderWindow::FinishEditing() //----------------------------------------------------------------------------- // Helper class for do operation on the tree node //----------------------------------------------------------------------------- + +namespace +{ + class DoJob { public: @@ -3010,7 +3022,8 @@ public: virtual int operator() ( wxDataViewTreeNode * node ) = 0; }; -bool Walker( wxDataViewTreeNode * node, DoJob & func ) +bool +Walker(wxDataViewTreeNode * node, DoJob & func, WalkFlags flags = Walk_All) { wxCHECK_MSG( node, false, "can't walk NULL node" ); @@ -3024,7 +3037,7 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func ) break; } - if ( node->HasChildren() ) + if ( node->HasChildren() && (flags != Walk_ExpandedOnly || node->IsOpen()) ) { const wxDataViewTreeNodes& nodes = node->GetChildNodes(); @@ -3032,7 +3045,7 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func ) i != nodes.end(); ++i ) { - if ( Walker(*i, func) ) + if ( Walker(*i, func, flags) ) return true; } } @@ -3040,6 +3053,8 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func ) return false; } +} // anonymous namespace + bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxDataViewItem & item) { if (IsVirtualList()) @@ -3060,14 +3075,6 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData parentNode->SetHasChildren(true); - // If the parent node isn't and hadn't been opened yet, we don't have - // anything to do here, all the items will be added to it when it's - // opened for the first time. - if ( !parentNode->IsOpen() && parentNode->GetChildNodes().empty() ) - { - return true; - } - wxDataViewTreeNode *itemNode = new wxDataViewTreeNode(parentNode, item); itemNode->SetHasChildren(GetModel()->IsContainer(item)); @@ -4137,7 +4144,7 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, xpos = 0; } - const int row = GetRowByItem(item); + const int row = GetRowByItem(item, Walk_ExpandedOnly); if ( row == -1 ) { // This means the row is currently not visible at all. @@ -4238,7 +4245,9 @@ private: }; -int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item) const +int +wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item, + WalkFlags flags) const { const wxDataViewModel * model = GetModel(); if( model == NULL ) @@ -4268,7 +4277,7 @@ int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item) const // the parent chain was created by adding the deepest parent first. // so if we want to start at the root node, we have to iterate backwards through the vector ItemToRowJob job( item, parentChain.rbegin() ); - if ( !Walker( m_root, job ) ) + if ( !Walker( m_root, job, flags ) ) return -1; return job.GetResult(); diff --git a/tests/controls/dataviewctrltest.cpp b/tests/controls/dataviewctrltest.cpp index c88eac22ca..2f88a0aa17 100644 --- a/tests/controls/dataviewctrltest.cpp +++ b/tests/controls/dataviewctrltest.cpp @@ -297,6 +297,12 @@ TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase, CHECK( rect1.y < rect2.y ); } + // This forces generic implementation to add m_grandchild to the tree, as + // it does it only on demand. We want the item to really be there to check + // that GetItemRect() returns an empty rectangle for collapsed items. + m_dvc->Expand(m_child1); + m_dvc->Collapse(m_child1); + const wxRect rectNotShown = m_dvc->GetItemRect(m_grandchild); CHECK( rectNotShown == wxRect() );