Fix crash when editing wxDVC items in place in wxOSX/Cocoa.

NSOutlineView::editedColumn: and editedRow: return -1 when they are called
from textDidEndEditing so we need to store their values in textDidBeginEditing
and reuse them later.

This fixes the crash in the sample with out-of-range array index exception
which happened whenever a cell was edited.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62434 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-10-17 01:04:13 +00:00
parent c937bcac0f
commit f32eb96401
2 changed files with 27 additions and 12 deletions

View File

@@ -418,7 +418,9 @@ private:
@interface wxCocoaOutlineView : NSOutlineView @interface wxCocoaOutlineView : NSOutlineView
{ {
@private @private
BOOL isEditingCell; // flag indicating if a cell is currently being edited // column and row of the cell being edited or -1 if none
int currentlyEditedColumn,
currentlyEditedRow;
wxCocoaDataViewControl* implementation; wxCocoaDataViewControl* implementation;
} }

View File

@@ -1338,7 +1338,9 @@ wxWidgetImplType* CreateDataView(wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(pare
self = [super init]; self = [super init];
if (self != nil) if (self != nil)
{ {
isEditingCell = NO; currentlyEditedColumn =
currentlyEditedRow = -1;
[self registerForDraggedTypes:[NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil]]; [self registerForDraggedTypes:[NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil]];
[self setDelegate:self]; [self setDelegate:self];
[self setDoubleAction:@selector(actionDoubleClick:)]; [self setDoubleAction:@selector(actionDoubleClick:)];
@@ -1644,21 +1646,26 @@ wxWidgetImplType* CreateDataView(wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(pare
// informed about a change of data): // informed about a change of data):
[super textDidBeginEditing:notification]; [super textDidBeginEditing:notification];
wxDataViewColumn* const dataViewColumnPtr = reinterpret_cast<wxDataViewColumn*>([[[[self tableColumns] objectAtIndex:[self editedColumn]] identifier] pointer]); // remember the column being edited, it will be used in textDidEndEditing:
currentlyEditedColumn = [self editedColumn];
currentlyEditedRow = [self editedRow];
wxDataViewColumn* const dataViewColumnPtr =
static_cast<wxDataViewColumn*>(
[[[[self tableColumns] objectAtIndex:currentlyEditedColumn] identifier] pointer]);
wxDataViewCtrl* const dataViewCtrlPtr = implementation->GetDataViewCtrl(); wxDataViewCtrl* const dataViewCtrlPtr = implementation->GetDataViewCtrl();
// stop editing of a custom item first (if necessary) // stop editing of a custom item first (if necessary)
dataViewCtrlPtr->FinishCustomItemEditing(); dataViewCtrlPtr->FinishCustomItemEditing();
// set the flag that currently a cell is being edited (see also textDidEndEditing:):
isEditingCell = YES;
// now, send the event: // now, send the event:
wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dataViewCtrlPtr->GetId()); // variable definition
dataViewEvent.SetEventObject(dataViewCtrlPtr); dataViewEvent.SetEventObject(dataViewCtrlPtr);
dataViewEvent.SetItem(wxDataViewItem([((wxPointerObject*) [self itemAtRow:[self editedRow]]) pointer])); dataViewEvent.SetItem(
wxDataViewItem([((wxPointerObject*) [self itemAtRow:currentlyEditedRow]) pointer]));
dataViewEvent.SetColumn(dataViewCtrlPtr->GetColumnPosition(dataViewColumnPtr)); dataViewEvent.SetColumn(dataViewCtrlPtr->GetColumnPosition(dataViewColumnPtr));
dataViewEvent.SetDataViewColumn(dataViewColumnPtr); dataViewEvent.SetDataViewColumn(dataViewColumnPtr);
dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent); dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
@@ -1674,10 +1681,12 @@ wxWidgetImplType* CreateDataView(wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(pare
// editing session has been sent (see Documentation for NSControl controlTextDidEndEditing:); this is not expected by a user // editing session has been sent (see Documentation for NSControl controlTextDidEndEditing:); this is not expected by a user
// of the wxWidgets library and therefore an wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE event is only sent if a corresponding // of the wxWidgets library and therefore an wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE event is only sent if a corresponding
// wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED has been sent before; to check if a wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED // wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED has been sent before; to check if a wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED
// has been sent the flag isEditingCell is used: // has been sent the last edited column/row are valid:
if (isEditingCell == YES) if ( currentlyEditedColumn != -1 && currentlyEditedRow != -1 )
{ {
wxDataViewColumn* const dataViewColumnPtr = reinterpret_cast<wxDataViewColumn*>([[[[self tableColumns] objectAtIndex:[self editedColumn]] identifier] pointer]); wxDataViewColumn* const dataViewColumnPtr =
static_cast<wxDataViewColumn*>(
[[[[self tableColumns] objectAtIndex:currentlyEditedColumn] identifier] pointer]);
wxDataViewCtrl* const dataViewCtrlPtr = implementation->GetDataViewCtrl(); wxDataViewCtrl* const dataViewCtrlPtr = implementation->GetDataViewCtrl();
@@ -1685,12 +1694,16 @@ wxWidgetImplType* CreateDataView(wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(pare
wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition wxDataViewEvent dataViewEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dataViewCtrlPtr->GetId()); // variable definition
dataViewEvent.SetEventObject(dataViewCtrlPtr); dataViewEvent.SetEventObject(dataViewCtrlPtr);
dataViewEvent.SetItem(wxDataViewItem([((wxPointerObject*) [self itemAtRow:[self editedRow]]) pointer])); dataViewEvent.SetItem(
wxDataViewItem([((wxPointerObject*) [self itemAtRow:currentlyEditedRow]) pointer]));
dataViewEvent.SetColumn(dataViewCtrlPtr->GetColumnPosition(dataViewColumnPtr)); dataViewEvent.SetColumn(dataViewCtrlPtr->GetColumnPosition(dataViewColumnPtr));
dataViewEvent.SetDataViewColumn(dataViewColumnPtr); dataViewEvent.SetDataViewColumn(dataViewColumnPtr);
dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent); dataViewCtrlPtr->GetEventHandler()->ProcessEvent(dataViewEvent);
// set flag to the inactive state:
isEditingCell = NO;
// we're not editing any more
currentlyEditedColumn =
currentlyEditedRow = -1;
} }
} }