44 BOOL _automaticallyPreparesContent;
45 BOOL _usesLazyFetching;
46 BOOL _isUsingManagedProxy;
47 _CPManagedProxy _managedProxy;
63 return [CPSet setWithObjects:"content"];
66 + (BOOL)automaticallyNotifiesObserversForKey:(
CPString)aKey
68 if (aKey ===
@"contentObject")
76 return [CPSet setWithObject:"editable"];
81 return [CPSet setWithObject:"editable"];
86 return [CPSet setWithObjects:"editable", "selection"];
103 - (id)initWithContent:(
id)aContent
105 if (
self = [super
init])
125 return _contentObject;
132 - (void)setContent:(
id)aContent
135 [
self _selectionWillChange];
137 _contentObject = aContent;
139 [
self _selectionDidChange];
146 - (void)_setContentObject:(
id)aContent
166 - (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
168 _automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
177 return _automaticallyPreparesContent;
187 [_managedProxy setEntityName:newEntityName];
197 return [_managedProxy entityName];
205 - (void)setFetchPredicate:(CPPredicate)newPredicate
207 [_managedProxy setFetchPredicate:newPredicate];
217 return [_managedProxy fetchPredicate];
233 - (void)setObjectClass:(Class)aClass
235 _objectClass = aClass;
251 - (id)_defaultNewObject
262 return [
self _defaultNewObject];
269 - (void)addObject:(
id)anObject
273 var binderClass = [[
self class] _binderClassForBinding:@"contentObject"];
274 [[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
281 - (void)removeObject:(
id)anObject
283 if ([
self content] === anObject)
286 var binderClass = [[
self class] _binderClassForBinding:@"contentObject"];
287 [[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
294 - (void)add:(
id)aSender
312 - (void)remove:(
id)aSender
330 - (void)setEditable:(BOOL)shouldBeEditable
332 _isEditable = shouldBeEditable;
348 return [[_CPObservableArray alloc] initWithArray:[_contentObject]];
362 - (void)_selectionWillChange
364 [_selection controllerWillChange];
371 - (void)_selectionDidChange
373 if (_selection === undefined || _selection === nil)
376 [_selection controllerDidChange];
385 return _observedKeys;
388 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
390 [_observedKeys addObject:aKeyPath];
394 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath
396 [_observedKeys removeObject:aKeyPath];
418 var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
420 content = [aCoder decodeObjectForKey:CPObjectControllerContentKey];
423 [
self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
425 [
self setUsesLazyFetching:[aCoder decodeBoolForKey:CPObjectControllerUsesLazyFetchingKey]];
426 _isUsingManagedProxy = [aCoder decodeBoolForKey:CPObjectControllerIsUsingManagedProxyKey];
427 _managedProxy = [aCoder decodeObjectForKey:CPObjectControllerManagedProxyKey];
440 [aCoder encodeObject:[
self content]
forKey:CPObjectControllerContentKey];
443 [aCoder encodeObject:CPStringFromClass(_objectClass) forKey:CPObjectControllerObjectClassNameKey];
444 else if (_objectClassName)
445 [aCoder encodeObject:_objectClassName forKey:CPObjectControllerObjectClassNameKey];
447 [aCoder encodeBool:[
self isEditable] forKey:CPObjectControllerIsEditableKey];
449 [aCoder encodeBool:[
self usesLazyFetching] forKey:CPObjectControllerUsesLazyFetchingKey];
450 [aCoder encodeBool:_isUsingManagedProxy forKey:CPObjectControllerIsUsingManagedProxyKey];
453 [aCoder encodeObject:_managedProxy forKey:CPObjectControllerManagedProxyKey];
464 @implementation _CPObservationProxy :
CPObject 476 - (id)initWithKeyPath:(
id)aKeyPath observer:(id)anObserver
object:(
id)anObject
478 if (
self = [super
init])
481 _observer = anObserver;
508 - (void)setNotifyObject:(BOOL)notify
510 _notifyObject = notify;
515 if (
self === anObject)
518 if (!anObject || [anObject
class] !== [
self class] || anObject._observer !== _observer || anObject._keyPath !== _keyPath || anObject._object !== _object)
524 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(id)anObject change:(
CPDictionary)change context:(id)context
527 [_object observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
529 [_observer observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
540 @implementation _CPObservableArray : _CPJavaScriptArray
542 CPArray _observationProxies;
550 var ivars = class_copyIvarList(
self),
551 count = ivars.length;
554 a[ivar_getName(ivars[count])] = nil;
561 return "<_CPObservableArray: " + [
super description] +
" >";
564 - (id)initWithArray:(CPArray)anArray
566 self = [
super initWithArray:anArray];
568 self.isa = [_CPObservableArray class];
569 self._observationProxies = [];
574 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
576 if (aKeyPath.charAt(0) ===
"@")
579 if ([_CPCollectionKVCOperator isSimpleCollectionOperator:aKeyPath])
582 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
584 proxy._options = options;
585 proxy._context = context;
587 [_observationProxies addObject:proxy];
589 var dotIndex = aKeyPath.indexOf(
"."),
590 remaining = aKeyPath.substring(dotIndex + 1),
593 [
self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
598 [
self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
602 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath
604 if (aKeyPath.charAt(0) ===
"@")
607 if ([_CPCollectionKVCOperator isSimpleCollectionOperator:aKeyPath])
610 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
611 index = [_observationProxies indexOfObject:proxy];
613 proxy = [_observationProxies objectAtIndex:index];
615 var dotIndex = aKeyPath.indexOf(
"."),
616 remaining = aKeyPath.substring(dotIndex + 1),
619 [
self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
624 [
self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
628 - (void)insertObject:(
id)anObject atIndex:(CPUInteger)anIndex
630 for (var i = 0, count = [_observationProxies count]; i < count; i++)
632 var proxy = [_observationProxies objectAtIndex:i],
633 keyPath = [proxy keyPath],
634 operator = keyPath.charAt(0) ===
".";
639 [anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
645 [
super insertObject:anObject atIndex:anIndex];
648 - (void)removeObjectAtIndex:(CPUInteger)anIndex
650 var currentObject = [
self objectAtIndex:anIndex];
652 for (var i = 0, count = [_observationProxies count]; i < count; i++)
654 var proxy = [_observationProxies objectAtIndex:i],
655 keyPath = [proxy keyPath],
656 operator = keyPath.charAt(0) ===
".";
661 [currentObject removeObserver:proxy forKeyPath:keyPath];
667 [
super removeObjectAtIndex:anIndex];
670 - (CPArray)objectsAtIndexes:(
CPIndexSet)theIndexes
672 return [_CPObservableArray arrayWithArray:[
super objectsAtIndexes:theIndexes]];
675 - (void)addObject:(
id)anObject
677 [
self insertObject:anObject atIndex:[
self count]];
680 - (void)removeLastObject
682 [
self removeObjectAtIndex:[
self count]];
685 - (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(id)anObject
687 var currentObject = [
self objectAtIndex:anIndex];
689 for (var i = 0, count = [_observationProxies count]; i < count; i++)
691 var proxy = [_observationProxies objectAtIndex:i],
692 keyPath = [proxy keyPath],
693 operator = keyPath.charAt(0) ===
".";
698 [currentObject removeObserver:proxy forKeyPath:keyPath];
699 [anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
705 [
super replaceObjectAtIndex:anIndex withObject:anObject];
716 CPArray _observationProxies;
718 Object _observedObjectsByKeyPath;
721 - (id)initWithController:(
id)aController
723 if (
self = [super
init])
726 _observationProxies = [CPArray array];
727 _controller = aController;
728 _observedObjectsByKeyPath = {};
734 - (id)_controllerMarkerForValues:(CPArray)theValues
736 var count = [theValues count],
741 else if (count === 1)
742 value = [theValues objectAtIndex:0];
745 if ([_controller alwaysUsesMultipleValuesMarker])
749 value = [theValues objectAtIndex:0];
753 if (![value
isEqual:[theValues objectAtIndex:i]])
759 if (value === nil || value.isa && [value
isEqual:[
CPNull null]])
767 var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
770 if ([values isKindOfClass:CPArray] || [values isKindOfClass:CPSet])
772 var value = [
self _controllerMarkerForValues:values];
773 [_cachedValues setObject:value forKey:theKeyPath];
786 - (void)setValue:(
id)theValue forKeyPath:(
CPString)theKeyPath
788 [[_controller selectedObjects] setValue:theValue forKeyPath:theKeyPath];
789 [_cachedValues removeObjectForKey:theKeyPath];
803 - (void)setValue:(
id)theValue forKey:(
CPString)theKeyPath
810 return [_cachedValues count];
815 return [_cachedValues keyEnumerator];
818 - (void)controllerWillChange
820 _keys = [_cachedValues allKeys];
825 for (var i = 0, count = _keys.length; i < count; i++)
828 [_cachedValues removeAllObjects];
831 - (void)controllerDidChange
833 [_cachedValues removeAllObjects];
838 for (var i = 0, count = _keys.length; i < count; i++)
844 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(
CPDictionary)change context:(
id)context
846 [_cachedValues removeObjectForKey:aKeyPath];
849 - (void)addObserver:(
id)anObject forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
851 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
853 [proxy setNotifyObject:YES];
854 [_observationProxies addObject:proxy];
857 var observedObjects = [_controller selectedObjects];
858 _observedObjectsByKeyPath[aKeyPath] = observedObjects;
859 [observedObjects addObserver:proxy forKeyPath:aKeyPath options:options context:context];
862 - (void)removeObserver:(
id)anObject forKeyPath:(
CPString)aKeyPath
864 [_observationProxies enumerateObjectsUsingBlock:function(aProxy, idx, stop)
866 if (aProxy._object === self && aProxy._keyPath == aKeyPath && aProxy._observer === anObject)
868 var observedObjects = _observedObjectsByKeyPath[aKeyPath];
870 [observedObjects removeObserver:aProxy forKeyPath:aKeyPath];
871 [_observationProxies removeObjectAtIndex:idx];
873 _observedObjectsByKeyPath[aKeyPath] = nil;
883 @implementation _CPManagedProxy :
CPObject 886 CPPredicate _fetchPredicate;
894 @implementation _CPManagedProxy (CPCoding)
896 - (id)initWithCoder:(
CPCoder)aCoder
902 [
self setEntityName:[aCoder decodeObjectForKey:CPManagedProxyEntityNameKey]];
903 [
self setFetchPredicate:[aCoder decodeObjectForKey:CPManagedProxyFetchPredicateKey]];
909 - (void)encodeWithCoder:(
CPCoder)aCoder
911 [aCoder encodeObject:[
self entityName] forKey:CPManagedProxyEntityNameKey];
912 [aCoder encodeObject:[
self fetchPredicate] forKey:CPManagedProxyFetchPredicateKey];
924 return _usesLazyFetching;
930 - (void)setUsesLazyFetching:(BOOL)aValue
932 _usesLazyFetching = aValue;
void setValue:forKeyPath:(id theValue, [forKeyPath] CPString theKeyPath)
void setAutomaticallyPreparesContent:(BOOL shouldAutomaticallyPrepareContent)
CPSet keyPathsForValuesAffectingCanInsert()
void removeObject:(id anObject)
void willChangeValueForKey:(CPString aKey)
CPSet keyPathsForValuesAffectingCanRemove()
An object representation of nil.
var CPObjectControllerAutomaticallyPreparesContentKey
BOOL automaticallyPreparesContent()
void addObject:(id anObject)
var CPManagedProxyEntityNameKey
id valueForKeyPath:(CPString theKeyPath)
A collection of unique integers.
void setEditable:(BOOL shouldBeEditable)
void setUsesLazyFetching:(BOOL aValue)
A mutable key-value pair collection.
var CPManagedProxyFetchPredicateKey
CPArray selectedObjects()
var CPObjectControllerManagedProxyKey
void setContent:(id aContent)
void encodeObject:forKey:(id anObject, [forKey] CPString aKey)
An immutable string (collection of characters).
var CPObjectControllerObjectClassNameKey
CPSet keyPathsForValuesAffectingContentObject()
CPBinder getBinding:forObject:(CPString aBinding, [forObject] id anObject)
var CPObjectControllerUsesLazyFetchingKey
CPSet keyPathsForValuesAffectingCanAdd()
void addObserver:forKeyPath:options:context:(id anObserver, [forKeyPath] CPString aPath, [options] CPKeyValueObservingOptions options, [context] id aContext)
void exposeBinding:(CPString aBinding)
void didChangeValueForKey:(CPString aKey)
An mutable collection which may contain a specific object numerous times.
Defines methods for use when archiving & restoring (enc/decoding).
void removeObserver:forKeyPath:(id anObserver, [forKeyPath] CPString aPath)
var CPObjectControllerIsEditableKey
var CPObjectControllerContentKey
id stringWithFormat:(CPString format, [,]...)
id indexSetWithIndexesInRange:(CPRange aRange)
id initWithContent:(id aContent)
CPPredicate fetchPredicate()
void setObjectClass:(Class aClass)
var CPObjectControllerIsUsingManagedProxyKey
function CPClassFromString(aClassName)