Previously _CPObservationProxy would only trigger notifications for the key path it was created with. For example a notification for department would be forwarded to the controller and observer as a notification on department.name because that was the key path the observation proxy was created for.
- setValue:forKeyPath will now get call setValue:forKeyPath again on the value of the first part of the key path
- override valueForKeyPath: and valueForKey: in CPObjectController's CPControllerSelectionProxy to return controller markers when appropriate
- override setValue:forKeyPath: and setValue:forKey: in CPObjectController's CPControllerSelectionProxy to bypass possible controller markers
This commit also removes previous hacks for compound paths and adds test cases for the errors. All this is related to issue #967.
CPObjectController would attempt to remove observations from the new selection in stead of the old selection. This would throw an error when binding to longer compound key paths like selection.customer.name
Fixes#967
Before the table view would send a CPTableViewSelectionDidChangeNotification whenever the number of rows in the table decreased, regardless of if any selected rows actually became deselected. This could be a needless performance drain in the common case where other program components update and reload on selection changes in a table or outline view.
This would break key-value binding setups where a CPCollectionView's content property was hooked up to a CPArrayController's content or arrangedObjects property since the CPArrayController maintains the same object and calls setValue:forKey: with the same object the CPCollectionView already has. Therefore we cannot skip calling reloadContent even when the incoming content array is the same one we got before, because most likely the contents have changed out from under us.
CPArrayController was erroneously using canRemove to determine whether explicit removal could take place, when in fact the documentation for [NSObjectController canRemove] (NSArrayController does not override canRemove) states that it returns "YES if an object can be removed from the receiver using remove:, otherwise NO", implying that it should only be used to check whether there is a selected element that can be removed (for example, to bind the enabled state of a toolbar button to a CPArrayController's canRemove property). It should not be used to decide whether a specific object can be removed or not.