Fixed race condition when editing table cells

Previously, when double-clicking on a table cell to edit it, there was a possibility of a race condition. A refresh of the display was requested, then the run loop was passed through once. But it was possible for the display refresh to not be queued when the run loop was passed through, in which case the refresh would cancel the editing. Or at least I think that's what was happening.  ;-)

This commit (hopefully) eliminates the race condition by synchronously refreshing the layout and display.

Made some miscellaneous formatting fixes as well.
This commit is contained in:
Aparajita Fishman
2016-01-19 23:12:11 -08:00
parent 346a0b84ae
commit 8f1191733b
3 changed files with 35 additions and 24 deletions
+17 -11
View File
@@ -644,12 +644,8 @@ NOT YET IMPLEMENTED
}];
}
// Reloads the views AND the data
- (void)_reloadDataViews
- (void)_setupReload
{
//if (!_dataSource)
// return;
_reloadAllRows = YES;
_objectValues = { };
_cachedRowHeights = [];
@@ -661,11 +657,24 @@ NOT YET IMPLEMENTED
// This updates the size too.
[self noteNumberOfRowsChanged];
}
// Reloads the views AND the data
- (void)_reloadDataViews
{
[self _setupReload];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
// Reloads the views AND the data
- (void)_reloadDataViewsSynchronously
{
[self _setupReload];
[self layout];
[self display];
}
//Target-action Behavior
/*!
Sets the message sent to the target when the user double-clicks an
@@ -4680,7 +4689,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
if ([self _sendDelegateShouldEditTableColumn:column row:rowIndex])
{
[self editColumn:columnIndex row:rowIndex withEvent:nil select:YES];
[self editColumn:columnIndex row:rowIndex withEvent:[CPApp currentEvent] select:YES];
return;
}
}
@@ -5303,6 +5312,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if ([aView isKindOfClass:[CPTextField class]])
[aView setBezeled:editingState];
}
/*!
Edits the dataview at a given row and column. This method is usually invoked automatically and should rarely be invoked directly
The row at supplied rowIndex must be selected otherwise an exception is thrown.
@@ -5317,11 +5327,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (![self isRowSelected:rowIndex])
[[CPException exceptionWithName:@"Error" reason:@"Attempt to edit row " + rowIndex + " when not selected." userInfo:nil] raise];
[self reloadData];
// Process all events immediately to make sure table data views are reloaded.
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
[self _reloadDataViewsSynchronously];
[self scrollRowToVisible:rowIndex];
[self scrollColumnToVisible:columnIndex];
+4 -2
View File
@@ -94,7 +94,8 @@ function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resig
inputElement.focus();
[owner _restorePreviousScrollingOrigin:previousScrollingOrigin];
} argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}
}
@@ -838,6 +839,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self _resignFirstKeyResponder];
_isEditing = NO;
if ([self isEditable])
{
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
@@ -1213,7 +1215,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)textDidFocus:(CPNotification)note
{
// this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
if ([note object] !== self)
return;
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_)
+14 -11
View File
@@ -2684,20 +2684,23 @@ setBoundsOrigin:
return _needsLayout;
}
- (void)layout
{
_needsLayout = NO;
if (_viewClassFlags & CPViewHasCustomViewWillLayout)
[self viewWillLayout];
if (_viewClassFlags & CPViewHasCustomLayoutSubviews)
[self layoutSubviews];
[self viewDidLayout];
}
- (void)layoutIfNeeded
{
if (_needsLayout)
{
_needsLayout = NO;
if (_viewClassFlags & CPViewHasCustomViewWillLayout)
[self viewWillLayout];
if (_viewClassFlags & CPViewHasCustomLayoutSubviews)
[self layoutSubviews];
[self viewDidLayout];
}
[self layout];
}
/*!