}
}
+ // returns node corresponding to 'item' if its in m_nodes or NULL otherwise
+ wxDataViewTreeNode *FindItemAsNode(const wxDataViewItem& item) const
+ {
+ for ( wxDataViewTreeNodes::const_iterator i = m_nodes.begin();
+ i != m_nodes.end();
+ ++i )
+ {
+ if( (*i)->GetItem() == item )
+ return *i;
+ }
+
+ return NULL;
+ }
+
+
private:
wxDataViewTreeNode *m_parent;
wxDataViewTreeNodes m_nodes;
int LINKAGEMODE wxGenericTreeModelItemCmp( void ** id1, void ** id2)
{
- return g_model->Compare( *id1, *id2, g_column, g_asending );
+ return g_model->Compare( wxDataViewItem(*id1), wxDataViewItem(*id2), g_column, g_asending );
}
unsigned int GetRowCount();
wxDataViewItem GetSelection() const;
- wxDataViewSelection GetSelections(){ return m_selection; }
+ const wxDataViewSelection& GetSelections() const { return m_selection; }
void SetSelections( const wxDataViewSelection & sel )
{ m_selection = sel; UpdateDisplay(); }
void Select( const wxArrayInt& aSelections );
(wxDataViewVirtualListModel*) GetOwner()->GetModel();
m_count = list_model->GetCount();
- // TODO: why empty the entire selection?
- m_selection.Empty();
+ if ( !m_selection.empty() )
+ {
+ const int row = GetRowByItem(item);
+
+ const size_t selCount = m_selection.size();
+ for ( size_t i = 0; i < selCount; i++ )
+ {
+ if ( m_selection[i] > (unsigned)row )
+ m_selection[i]--;
+ }
+
+ int itemRow = m_selection.Index(row);
+ if ( itemRow != wxNOT_FOUND )
+ m_selection.RemoveAt(itemRow);
+ }
+
}
else // general case
{
wxDataViewTreeNode * node = FindNode(parent);
+ int itemPosInNode = node ? node->GetChildren().Index(item.GetID()) : wxNOT_FOUND;
// Notice that it is possible that the item being deleted is not in the
// tree at all, for example we could be deleting a never shown (because
// collapsed) item in a tree model. So it's not an error if we don't know
// about this item, just return without doing anything then.
- if ( !node || node->GetChildren().Index(item.GetID()) == wxNOT_FOUND )
+ if ( !node || itemPosInNode == wxNOT_FOUND )
return false;
- int sub = -1;
- node->GetChildren().Remove( item.GetID() );
- // Manipolate selection
- if( m_selection.GetCount() > 1 )
- {
- m_selection.Empty();
- }
bool isContainer = false;
- wxDataViewTreeNodes nds = node->GetNodes();
+ wxDataViewTreeNode *itemNode = NULL;
+
+ const wxDataViewTreeNodes nds = node->GetNodes();
for (size_t i = 0; i < nds.GetCount(); i ++)
{
if (nds[i]->GetItem() == item)
{
isContainer = true;
+ itemNode = nds[i];
break;
}
}
+
+ // Delete the item from wxDataViewTreeNode representation:
+ int itemsDeleted = 1;
+ node->GetChildren().Remove( item.GetID() );
+
if( isContainer )
{
- wxDataViewTreeNode * n = NULL;
- wxDataViewTreeNodes nodes = node->GetNodes();
- int len = nodes.GetCount();
- for( int i = 0; i < len; i ++)
- {
- if( nodes[i]->GetItem() == item )
- {
- n = nodes[i];
- break;
- }
- }
+ wxDataViewTreeNode *n = node->FindItemAsNode(item);
wxCHECK_MSG( n != NULL, false, "item not found" );
node->GetNodes().Remove( n );
- sub -= n->GetSubTreeCount();
+ itemsDeleted += n->GetSubTreeCount();
::DestroyTreeHelper(n);
}
+
// Make the row number invalid and get a new valid one when user call GetRowCount
m_count = -1;
- node->ChangeSubTreeCount(sub);
+ node->ChangeSubTreeCount(-itemsDeleted);
+
+ // Update selection by removing 'item' and its entire children tree from the selection.
+ if ( !m_selection.empty() )
+ {
+ // we can't call GetRowByItem() on 'item', as it's already deleted, so compute it from
+ // the parent ('node') and position in its list of children
+ int itemRow;
+ if ( itemPosInNode == 0 )
+ {
+ // 1st child, row number is that of the parent node + 1
+ itemRow = GetRowByItem(node->GetItem()) + 1;
+ }
+ else
+ {
+ // row number is that of the sibling above 'item' + its subtree if any + 1
+ const wxDataViewItem sibling = wxDataViewItem(node->GetChildren()[itemPosInNode - 1]);
+ const wxDataViewTreeNode *siblingNode = node->FindItemAsNode(sibling);
+
+ itemRow = GetRowByItem(sibling);
+ if ( siblingNode )
+ itemRow += siblingNode->GetSubTreeCount();
+ itemRow += 1;
+ }
+
+ wxDataViewSelection newsel(wxDataViewSelectionCmp);
+
+ const size_t numSelections = m_selection.size();
+ for ( size_t i = 0; i < numSelections; ++i )
+ {
+ const int s = m_selection[i];
+ if ( s < itemRow )
+ newsel.push_back(s);
+ else if ( s >= itemRow + itemsDeleted )
+ newsel.push_back(s - itemsDeleted);
+ // else: deleted item, remove from selection
+ }
+
+ m_selection = newsel;
+ }
}
// Change the current row to the last row if the current exceed the max row number
if( node->GetNodes().GetCount() == 0)
{
int index = static_cast<int>(row) - current - 1;
- ret = node->GetChildren().Item( index );
+ ret = wxDataViewItem(node->GetChildren().Item( index ));
return DoJob::OK;
}
return DoJob::CONT;
int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const
{
sel.Empty();
- wxDataViewSelection selection = m_clientArea->GetSelections();
- int len = selection.GetCount();
- for( int i = 0; i < len; i ++)
+ const wxDataViewSelection& selections = m_clientArea->GetSelections();
+
+ const size_t len = selections.size();
+ for ( size_t i = 0; i < len; i++ )
{
- unsigned int row = selection[i];
- sel.Add( m_clientArea->GetItemByRow( row ) );
+ wxDataViewItem item = m_clientArea->GetItemByRow(selections[i]);
+ if ( item.IsOk() )
+ {
+ sel.Add(item);
+ }
+ else
+ {
+ wxFAIL_MSG( "invalid item in selection - bad internal state" );
+ }
}
- return len;
+
+ return sel.size();
}
void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )