+ SendSelectionChangedEvent(GetItemByRow(m_currentRow));
+ }
+ else
+ RefreshRow( m_currentRow );
+ }
+
+ GetOwner()->EnsureVisible( m_currentRow, -1 );
+}
+
+wxRect wxDataViewMainWindow::GetLineRect( unsigned int row ) const
+{
+ wxRect rect;
+ rect.x = 0;
+ rect.y = m_lineHeight * row;
+ rect.width = GetEndOfLastCol();
+ rect.height = m_lineHeight;
+
+ return rect;
+}
+
+class RowToItemJob: public DoJob
+{
+public:
+ RowToItemJob( unsigned int row , int current ) { this->row = row; this->current = current ;}
+ virtual ~RowToItemJob(){};
+
+ virtual int operator() ( wxDataViewTreeNode * node )
+ {
+ current ++;
+ if( current == static_cast<int>(row))
+ {
+ ret = node->GetItem() ;
+ return DoJob::OK;
+ }
+
+ if( node->GetSubTreeCount() + current < static_cast<int>(row) )
+ {
+ current += node->GetSubTreeCount();
+ return DoJob::IGR;
+ }
+ else
+ {
+ //If the current has no child node, we can find the desired item of the row number directly.
+ //This if can speed up finding in some case, and will has a very good effect when it comes to list view
+ if( node->GetNodes().GetCount() == 0)
+ {
+ int index = static_cast<int>(row) - current - 1;
+ ret = node->GetChildren().Item( index );
+ return DoJob::OK;
+ }
+ return DoJob::CONT;
+ }
+ }
+
+ virtual int operator() ( void * n )
+ {
+ current ++;
+ if( current == static_cast<int>(row))
+ {
+ ret = wxDataViewItem( n ) ;
+ return DoJob::OK;
+ }
+ return DoJob::CONT;
+ }
+ wxDataViewItem GetResult(){ return ret; }
+private:
+ unsigned int row;
+ int current ;
+ wxDataViewItem ret;
+};
+
+wxDataViewItem wxDataViewMainWindow::GetItemByRow(unsigned int row) const
+{
+ RowToItemJob job( row, -2 );
+ Walker( m_root , job );
+ return job.GetResult();
+}
+
+class RowToTreeNodeJob: public DoJob
+{
+public:
+ RowToTreeNodeJob( unsigned int row , int current, wxDataViewTreeNode * node )
+ {
+ this->row = row;
+ this->current = current ;
+ ret = NULL ;
+ parent = node;
+ }
+ virtual ~RowToTreeNodeJob(){};
+
+ virtual int operator() ( wxDataViewTreeNode * node )
+ {
+ current ++;
+ if( current == static_cast<int>(row))
+ {
+ ret = node ;
+ return DoJob::OK;
+ }
+
+ if( node->GetSubTreeCount() + current < static_cast<int>(row) )
+ {
+ current += node->GetSubTreeCount();
+ return DoJob::IGR;
+ }
+ else
+ {
+ parent = node;
+ //If the current has no child node, we can find the desired item of the row number directly.
+ //This if can speed up finding in some case, and will has a very good effect when it comes to list view
+ if( node->GetNodes().GetCount() == 0)
+ {
+ int index = static_cast<int>(row) - current - 1;
+ void * n = node->GetChildren().Item( index );
+ ret = new wxDataViewTreeNode( parent ) ;
+ ret->SetItem( wxDataViewItem( n ));
+ ret->SetHasChildren(false);
+ return DoJob::OK;
+ }
+ return DoJob::CONT;
+ }
+
+
+ }
+
+ virtual int operator() ( void * n )
+ {
+ current ++;
+ if( current == static_cast<int>(row))
+ {
+ ret = new wxDataViewTreeNode( parent ) ;
+ ret->SetItem( wxDataViewItem( n ));
+ ret->SetHasChildren(false);
+ return DoJob::OK;
+ }
+
+ return DoJob::CONT;
+ }
+ wxDataViewTreeNode * GetResult(){ return ret; }
+private:
+ unsigned int row;
+ int current ;
+ wxDataViewTreeNode * ret;
+ wxDataViewTreeNode * parent ;
+};
+
+
+wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row)
+{
+ RowToTreeNodeJob job( row , -2, m_root );
+ Walker( m_root , job );
+ return job.GetResult();
+}
+
+wxDataViewEvent wxDataViewMainWindow::SendExpanderEvent( wxEventType type, const wxDataViewItem & item )
+{
+ wxWindow *parent = GetParent();
+ wxDataViewEvent le(type, parent->GetId());
+
+ le.SetEventObject(parent);
+ le.SetModel(GetOwner()->GetModel());
+ le.SetItem( item );
+
+ parent->GetEventHandler()->ProcessEvent(le);
+ return le;
+}
+
+void wxDataViewMainWindow::OnExpanding( unsigned int row )
+{
+ wxDataViewTreeNode * node = GetTreeNodeByRow(row);
+ if( node != NULL )
+ {
+ if( node->HasChildren())
+ {
+ if( !node->IsOpen())
+ {
+ wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,node->GetItem());
+ //Check if the user prevent expanding
+ if( e.GetSkipped() )
+ return;
+
+ node->ToggleOpen();
+ //Here I build the children of current node
+ if( node->GetChildrenNumber() == 0 )
+ {
+ SortPrepare();
+ BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node);
+ }
+ m_count = -1;
+ UpdateDisplay();
+ //Send the expanded event
+ SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,node->GetItem());
+ }
+ else
+ {
+ SelectRow( row, false );
+ SelectRow( row + 1, true );
+ ChangeCurrentRow( row + 1 );
+ SendSelectionChangedEvent( GetItemByRow(row+1));
+ }
+ }
+ else
+ delete node;
+ }
+}
+
+void wxDataViewMainWindow::OnCollapsing(unsigned int row)
+{
+ wxDataViewTreeNode * node = GetTreeNodeByRow(row);
+ if( node != NULL )
+ {
+ wxDataViewTreeNode * nd = node;
+
+ if( node->HasChildren() && node->IsOpen() )
+ {
+ wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,node->GetItem());
+ if( e.GetSkipped() )
+ return;
+ node->ToggleOpen();
+ m_count = -1;
+ UpdateDisplay();
+ SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,nd->GetItem());
+ }
+ else
+ {
+ node = node->GetParent();
+ if( node != NULL )
+ {
+ int parent = GetRowByItem( node->GetItem() ) ;
+ if( parent >= 0 )
+ {
+ SelectRow( row, false);
+ SelectRow(parent , true );
+ ChangeCurrentRow( parent );
+ SendSelectionChangedEvent( node->GetItem() );
+ }
+ }
+ }
+ if( !nd->HasChildren())
+ delete nd;
+ }
+}
+
+wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item )
+{
+ wxDataViewModel * model = GetOwner()->GetModel();
+ if( model == NULL )
+ return NULL;
+
+ //Compose the a parent-chain of the finding item
+ ItemList list;
+ list.DeleteContents( true );
+ wxDataViewItem it( item );
+ while( it.IsOk() )
+ {
+ wxDataViewItem * pItem = new wxDataViewItem( it );
+ list.Insert( pItem );
+ it = model->GetParent( it );