diff --git a/AppKit/CPArrayController.j b/AppKit/CPArrayController.j index 484fdecd5..4223b168c 100644 --- a/AppKit/CPArrayController.j +++ b/AppKit/CPArrayController.j @@ -609,6 +609,25 @@ return YES; } +- (void)_selectionWillChange +{ + // Push back all data from the dirty editors before it is too late. + + var editorsCount = [_editors count]; + + while (editorsCount--) + { + var allBindings = [CPBinder allBindingsForObject:_editors[editorsCount]], + allKeys = [allBindings allKeys], + keysCount = allKeys.length; + + while (keysCount--) + [[allBindings objectForKey:allKeys[keysCount]] reverseSetValueFor:allKeys[keysCount]]; + } + + [super _selectionWillChange]; +} + /*! Returns an array of the selected objects. diff --git a/AppKit/CPDatePicker/CPDatePicker.j b/AppKit/CPDatePicker/CPDatePicker.j index 4f3bf3b7d..e246dabde 100644 --- a/AppKit/CPDatePicker/CPDatePicker.j +++ b/AppKit/CPDatePicker/CPDatePicker.j @@ -706,6 +706,7 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey", @end +// FIXME: add support for CPEditorRegistrationProtocol as implemented for CPTextField @implementation _CPDatePickerValueBinder : CPBinder { } diff --git a/AppKit/CPObjectController.j b/AppKit/CPObjectController.j index 479d3a4e1..f52eb1bc7 100644 --- a/AppKit/CPObjectController.j +++ b/AppKit/CPObjectController.j @@ -391,6 +391,28 @@ [self didChangeValueForKey:@"selection"]; } +/*! + @ignore + These two private methods map CPTextField notifications to the CPEditorRegistration protocol + This should be generalized in the future: + + The CPEditorRegistrationProtocol can be implemented in all controls that support editing, not just CPTextField. + In CPArrayController there are other cases than selection change when we need to review all editor pending changes. They should be covered, including the selection change, by the wider concept described by the methods commitEditing: (forces to end editing) and discardEditing: (pending changes are lost). +*/ +- (void)_objectDidBeginEditing:(CPNotification)notification +{ + [self objectDidBeginEditing:[notification object]]; +} + +/*! + @ignore +*/ +- (void) _objectDidEndEditing:(CPNotification)notification +{ + [self objectDidEndEditing:[notification object]]; +} + + /*! @return id - Returns the keys which are being observed. */ diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 3cccc3003..921419e7c 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -2151,6 +2151,56 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey", @implementation _CPTextFieldValueBinder : CPBinder ++ (void)unbind:(CPString)aBinding forObject:(id)anObject +{ + var theBinding = [self getBinding:aBinding forObject:anObject], + notificationCenter = [CPNotificationCenter defaultCenter]; + + if (theBinding) + { + [notificationCenter removeObserver:[theBinding._info objectForKey:CPObservedObjectKey] + name:CPControlTextDidBeginEditingNotification + object:anObject]; + + [notificationCenter removeObserver:[theBinding._info objectForKey:CPObservedObjectKey] + name:CPControlTextDidEndEditingNotification + object:anObject]; + + [super unbind:aBinding forObject:anObject]; + } +} + +- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource +{ + self = [super initWithBinding:aBinding + name:aName + to:aDestination + keyPath:aKeyPath + options:options + from:aSource]; + + var notificationCenter = [CPNotificationCenter defaultCenter]; + + // This gives us support for the CPEditorRegistration informal protocol + if ([aDestination respondsToSelector:@selector(_objectDidBeginEditing:)]) + { + [notificationCenter addObserver:aDestination + selector:@selector(_objectDidBeginEditing:) + name:CPControlTextDidBeginEditingNotification + object:aSource]; + } + + if ([aDestination respondsToSelector:@selector(_objectDidEndEditing:)]) + { + [notificationCenter addObserver:aDestination + selector:@selector(_objectDidEndEditing:) + name:CPControlTextDidEndEditingNotification + object:aSource]; + } + + return self; +} + - (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding { [super _updatePlaceholdersWithOptions:options];