From dae36cda56e7ffd96b0c0dde4162a1085b0477a2 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Thu, 31 Mar 2011 20:21:13 -0400 Subject: [PATCH] Bindings support for inline table view cell editing. --- AppKit/CPTableColumn.j | 32 ++++++++++++++++++++++++++++++++ AppKit/CPTableView.j | 13 ++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 217e6bbe6..bbc307c74 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -646,6 +646,38 @@ CPTableColumnUserResizingMask = 1 << 1; } } +- (void)reverseSetDataView:(CPView)aDataView forRow:(unsigned)aRow +{ + var bindingsDictionary = [CPBinder allBindingsForObject:self], + keys = [bindingsDictionary allKeys], + newValue = [aDataView valueForKey:@"objectValue"]; + + for (var i = 0, count = [keys count]; i < count; i++) + { + var bindingName = keys[i], + bindingPath = [aDataView _replacementKeyPathForBinding:bindingName], + binding = [bindingsDictionary objectForKey:bindingName], + bindingInfo = binding._info, + destination = [bindingInfo objectForKey:CPObservedObjectKey], + keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey], + dotIndex = keyPath.lastIndexOf("."); + + if (dotIndex === CPNotFound) + [[destination valueForKeyPath:keyPath] replaceObjectAtIndex:aRow withObject:newValue]; + else + { + var firstPart = keyPath.substring(0, dotIndex), + secondPart = keyPath.substring(dotIndex + 1), + firstValue = [destination valueForKeyPath:firstPart]; + + if ([firstValue isKindOfClass:CPArray]) + [[firstValue objectAtIndex:aRow] setValue:newValue forKeyPath:secondPart]; + else + [[firstValue valueForKeyPath:secondPart] replaceObjectAtIndex:aRow withObject:newValue]; + } + } +} + //- (void)objectValue //{ // return nil; diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index f6296995b..c25433587 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -3370,7 +3370,12 @@ Your delegate can implement this method to avoid subclassing the tableview to ad { _editingCellIndex = nil; - [_dataSource tableView:self setObjectValue:[sender objectValue] forTableColumn:sender.tableViewEditedColumnObj row:sender.tableViewEditedRowIndex]; + if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_) + [_dataSource tableView:self setObjectValue:[sender objectValue] forTableColumn:sender.tableViewEditedColumnObj row:sender.tableViewEditedRowIndex]; + + // Allow the column binding to do a reverse set. Note that we do this even if the data source method above + // is implemented. + [sender.tableViewEditedColumnObj reverseSetDataView:sender forRow:sender.tableViewEditedRowIndex]; if ([sender respondsToSelector:@selector(setEditable:)]) [sender setEditable:NO]; @@ -4139,10 +4144,12 @@ Your delegate can implement this method to avoid subclassing the tableview to ad } } + // Accept either tableView:setObjectValue:forTableColumn:row: delegate method, or a binding. if (mouseIsUp - && (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_) && !_trackingPointMovedOutOfClickSlop - && ([[CPApp currentEvent] clickCount] > 1)) + && ([[CPApp currentEvent] clickCount] > 1) + && ((_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_) + || [self infoForBinding:@"content"])) { columnIndex = [self columnAtPoint:lastPoint]; if (columnIndex !== -1)