Optimize wxDataViewMainWindow::FindNode() in generic wxDataViewCtrl.

Avoid unnecessary heap allocations and extra indirections and just use the
items pointers directly.

Also avoid copying the (potentially huge) nodes arrays.

Closes #12647.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66004 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-11-03 16:29:23 +00:00
parent 5ca9771ff3
commit 10875c13e9

View File

@@ -1273,7 +1273,7 @@ void wxDataViewRenameTimer::Notify()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// The tree building helper, declared firstly // The tree building helper, declared firstly
static void BuildTreeHelper( wxDataViewModel * model, wxDataViewItem & item, static void BuildTreeHelper( const wxDataViewModel * model, const wxDataViewItem & item,
wxDataViewTreeNode * node); wxDataViewTreeNode * node);
int LINKAGEMODE wxDataViewSelectionCmp( unsigned int row1, unsigned int row2 ) int LINKAGEMODE wxDataViewSelectionCmp( unsigned int row1, unsigned int row2 )
@@ -2969,28 +2969,26 @@ void wxDataViewMainWindow::Collapse(unsigned int row)
wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item ) wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item )
{ {
wxDataViewModel * model = GetOwner()->GetModel(); const wxDataViewModel * model = GetOwner()->GetModel();
if( model == NULL ) if( model == NULL )
return NULL; return NULL;
if (!item.IsOk()) if (!item.IsOk())
return m_root; return m_root;
// Compose the a parent-chain of the finding item // Compose the parent-chain for the item we are looking for
ItemList list; wxVector<wxDataViewItem> parentChain;
list.DeleteContents( true );
wxDataViewItem it( item ); wxDataViewItem it( item );
while( it.IsOk() ) while( it.IsOk() )
{ {
wxDataViewItem * pItem = new wxDataViewItem( it ); parentChain.push_back(it);
list.Insert( pItem ); it = model->GetParent(it);
it = model->GetParent( it );
} }
// Find the item along the parent-chain. // Find the item along the parent-chain.
// This algorithm is designed to speed up the node-finding method // This algorithm is designed to speed up the node-finding method
wxDataViewTreeNode * node = m_root; wxDataViewTreeNode* node = m_root;
for( ItemList::const_iterator iter = list.begin(); iter !=list.end(); iter++ ) for( unsigned iter = parentChain.size()-1; iter>=0; --iter )
{ {
if( node->HasChildren() ) if( node->HasChildren() )
{ {
@@ -3000,18 +2998,18 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
::BuildTreeHelper(model, node->GetItem(), node); ::BuildTreeHelper(model, node->GetItem(), node);
} }
wxDataViewTreeNodes nodes = node->GetNodes(); const wxDataViewTreeNodes& nodes = node->GetNodes();
unsigned int i;
bool found = false; bool found = false;
for (i = 0; i < nodes.GetCount(); i ++) for (unsigned i = 0; i < nodes.GetCount(); ++i)
{ {
if (nodes[i]->GetItem() == (**iter)) wxDataViewTreeNode* currentNode = nodes[i];
if (currentNode->GetItem() == parentChain[iter])
{ {
if (nodes[i]->GetItem() == item) if (currentNode->GetItem() == item)
return nodes[i]; return currentNode;
node = nodes[i]; node = currentNode;
found = true; found = true;
break; break;
} }
@@ -3131,7 +3129,7 @@ int wxDataViewMainWindow::RecalculateCount()
class ItemToRowJob : public DoJob class ItemToRowJob : public DoJob
{ {
public: public:
ItemToRowJob(const wxDataViewItem& item_, ItemList::const_iterator iter) ItemToRowJob(const wxDataViewItem& item_, wxVector<wxDataViewItem>::reverse_iterator iter)
: m_iter(iter), : m_iter(iter),
item(item_) item(item_)
{ {
@@ -3147,7 +3145,7 @@ public:
return DoJob::OK; return DoJob::OK;
} }
if( node->GetItem() == **m_iter ) if( node->GetItem() == *m_iter )
{ {
m_iter++; m_iter++;
return DoJob::CONT; return DoJob::CONT;
@@ -3173,7 +3171,7 @@ public:
{ return ret -1; } { return ret -1; }
private: private:
ItemList::const_iterator m_iter; wxVector<wxDataViewItem>::reverse_iterator m_iter;
wxDataViewItem item; wxDataViewItem item;
int ret; int ret;
@@ -3194,27 +3192,27 @@ int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item) const
if( !item.IsOk() ) if( !item.IsOk() )
return -1; return -1;
// Compose the a parent-chain of the finding item // Compose the parent-chain of the item we are looking for
ItemList list; wxVector<wxDataViewItem> parentChain;
wxDataViewItem * pItem;
list.DeleteContents( true );
wxDataViewItem it( item ); wxDataViewItem it( item );
while( it.IsOk() ) while( it.IsOk() )
{ {
pItem = new wxDataViewItem( it ); parentChain.push_back(it);
list.Insert( pItem ); it = model->GetParent(it);
it = model->GetParent( it );
} }
pItem = new wxDataViewItem( );
list.Insert( pItem );
ItemToRowJob job( item, list.begin() ); // add an 'invalid' item to represent our 'invisible' root node
Walker(m_root , job ); parentChain.push_back(wxDataViewItem());
// 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() );
Walker( m_root, job );
return job.GetResult(); return job.GetResult();
} }
} }
static void BuildTreeHelper( wxDataViewModel * model, wxDataViewItem & item, static void BuildTreeHelper( const wxDataViewModel * model, const wxDataViewItem & item,
wxDataViewTreeNode * node) wxDataViewTreeNode * node)
{ {
if( !model->IsContainer( item ) ) if( !model->IsContainer( item ) )