44 BOOL _automaticallyPreparesContent;
45 BOOL _usesLazyFetching;
46 BOOL _isUsingManagedProxy;
47 _CPManagedProxy _managedProxy;
61 + (CPSet)keyPathsForValuesAffectingContentObject
63 return [CPSet setWithObjects:"content"];
66 + (BOOL)automaticallyNotifiesObserversForKey:(
CPString)aKey
68 if (aKey ===
@"contentObject")
74 + (CPSet)keyPathsForValuesAffectingCanAdd
76 return [CPSet setWithObject:"editable"];
79 + (CPSet)keyPathsForValuesAffectingCanInsert
81 return [CPSet setWithObject:"editable"];
84 + (CPSet)keyPathsForValuesAffectingCanRemove
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
148 [
self setContent:aContent];
156 return [
self content];
166 - (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
168 _automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
175 - (BOOL)automaticallyPreparesContent
177 return _automaticallyPreparesContent;
189 _managedProxy = [[_CPManagedProxy alloc] init];
190 _isUsingManagedProxy = YES;
193 [_managedProxy setEntityName:newEntityName];
203 return [_managedProxy entityName];
211 - (void)setFetchPredicate:(CPPredicate)newPredicate
213 [_managedProxy setFetchPredicate:newPredicate];
221 - (CPPredicate)fetchPredicate
223 return [_managedProxy fetchPredicate];
229 - (void)prepareContent
239 - (void)setObjectClass:(Class)aClass
241 _objectClass = aClass;
257 - (id)_defaultNewObject
259 return [[[
self objectClass] alloc] init];
268 return [
self _defaultNewObject];
275 - (void)addObject:(
id)anObject
279 var binderClass = [[
self class] _binderClassForBinding:@"contentObject"];
280 [[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
287 - (void)removeObject:(
id)anObject
289 if ([
self content] === anObject)
292 var binderClass = [[
self class] _binderClassForBinding:@"contentObject"];
293 [[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
300 - (void)add:(
id)aSender
318 - (void)remove:(
id)aSender
336 - (void)setEditable:(BOOL)shouldBeEditable
338 _isEditable = shouldBeEditable;
352 - (CPArray)selectedObjects
354 return [[_CPObservableArray alloc] initWithArray:[_contentObject]];
368 - (void)_selectionWillChange
370 [_selection controllerWillChange];
371 [
self willChangeValueForKey:@"selection"];
377 - (void)_selectionDidChange
379 if (_selection === undefined || _selection === nil)
382 [_selection controllerDidChange];
383 [
self didChangeValueForKey:@"selection"];
391 return _observedKeys;
394 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
396 [_observedKeys addObject:aKeyPath];
400 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath
402 [_observedKeys removeObject:aKeyPath];
424 var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
426 content = [aCoder decodeObjectForKey:CPObjectControllerContentKey];
429 [
self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
431 [
self setUsesLazyFetching:[aCoder decodeBoolForKey:CPObjectControllerUsesLazyFetchingKey]];
432 _isUsingManagedProxy = [aCoder decodeBoolForKey:CPObjectControllerIsUsingManagedProxyKey];
433 _managedProxy = [aCoder decodeObjectForKey:CPObjectControllerManagedProxyKey];
446 [aCoder encodeObject:[
self content]
forKey:CPObjectControllerContentKey];
449 [aCoder encodeObject:CPStringFromClass(_objectClass) forKey:CPObjectControllerObjectClassNameKey];
450 else if (_objectClassName)
451 [aCoder encodeObject:_objectClassName forKey:CPObjectControllerObjectClassNameKey];
453 [aCoder encodeBool:[
self isEditable] forKey:CPObjectControllerIsEditableKey];
455 [aCoder encodeBool:[
self usesLazyFetching] forKey:CPObjectControllerUsesLazyFetchingKey];
456 [aCoder encodeBool:_isUsingManagedProxy forKey:CPObjectControllerIsUsingManagedProxyKey];
459 [aCoder encodeObject:_managedProxy forKey:CPObjectControllerManagedProxyKey];
464 if (![
self content] && [
self automaticallyPreparesContent])
470 @implementation _CPObservationProxy :
CPObject 482 - (id)initWithKeyPath:(
id)aKeyPath observer:(
id)anObserver object:(
id)anObject
484 if (
self = [super
init])
487 _observer = anObserver;
514 - (void)setNotifyObject:(BOOL)notify
516 _notifyObject = notify;
521 if (
self === anObject)
524 if (!anObject || [anObject
class] !== [
self class] || anObject._observer !== _observer || anObject._keyPath !== _keyPath || anObject._object !== _object)
530 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(
CPDictionary)change context:(
id)context
533 [_object observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
535 [_observer observeValueForKeyPath:aKeyPath ofObject:_object change:change context:context];
540 return [
super description] + [
CPString stringWithFormat:
@"observation proxy for %@ on key path %@", _observer, _keyPath];
546 @implementation _CPObservableArray : _CPJavaScriptArray
548 CPArray _observationProxies;
556 var ivars = class_copyIvarList(
self),
557 count = ivars.length;
560 a[ivar_getName(ivars[count])] = nil;
567 return "<_CPObservableArray: " + [super
description] + " >";
570 - (id)initWithArray:(CPArray)anArray
572 self = [
super initWithArray:anArray];
574 self.isa = [_CPObservableArray class];
575 self._observationProxies = [];
580 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
582 if (aKeyPath.charAt(0) ===
"@")
585 if ([_CPCollectionKVCOperator isSimpleCollectionOperator:aKeyPath])
588 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
590 proxy._options = options;
591 proxy._context = context;
593 [_observationProxies addObject:proxy];
595 var dotIndex = aKeyPath.indexOf(
"."),
596 remaining = aKeyPath.substring(dotIndex + 1),
599 [
self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
604 [
self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
608 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aKeyPath
610 if (aKeyPath.charAt(0) ===
"@")
613 if ([_CPCollectionKVCOperator isSimpleCollectionOperator:aKeyPath])
616 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
617 index = [_observationProxies indexOfObject:proxy];
619 proxy = [_observationProxies objectAtIndex:index];
621 var dotIndex = aKeyPath.indexOf(
"."),
622 remaining = aKeyPath.substring(dotIndex + 1),
625 [
self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
630 [
self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
634 - (void)insertObject:(
id)anObject atIndex:(CPUInteger)anIndex
636 for (var i = 0, count = [_observationProxies count]; i < count; i++)
638 var proxy = [_observationProxies objectAtIndex:i],
639 keyPath = [proxy keyPath],
640 operator = keyPath.charAt(0) ===
".";
643 [
self willChangeValueForKey:keyPath];
645 [anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
648 [
self didChangeValueForKey:keyPath];
651 [
super insertObject:anObject atIndex:anIndex];
654 - (void)removeObjectAtIndex:(CPUInteger)anIndex
656 var currentObject = [
self objectAtIndex:anIndex];
658 for (var i = 0, count = [_observationProxies count]; i < count; i++)
660 var proxy = [_observationProxies objectAtIndex:i],
661 keyPath = [proxy keyPath],
662 operator = keyPath.charAt(0) ===
".";
665 [
self willChangeValueForKey:keyPath];
667 [currentObject removeObserver:proxy forKeyPath:keyPath];
670 [
self didChangeValueForKey:keyPath];
673 [
super removeObjectAtIndex:anIndex];
676 - (CPArray)objectsAtIndexes:(
CPIndexSet)theIndexes
678 return [_CPObservableArray arrayWithArray:[
super objectsAtIndexes:theIndexes]];
681 - (void)addObject:(
id)anObject
683 [
self insertObject:anObject atIndex:[
self count]];
686 - (void)removeLastObject
688 [
self removeObjectAtIndex:[
self count]];
691 - (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(
id)anObject
693 var currentObject = [
self objectAtIndex:anIndex];
695 for (var i = 0, count = [_observationProxies count]; i < count; i++)
697 var proxy = [_observationProxies objectAtIndex:i],
698 keyPath = [proxy keyPath],
699 operator = keyPath.charAt(0) ===
".";
702 [
self willChangeValueForKey:keyPath];
704 [currentObject removeObserver:proxy forKeyPath:keyPath];
705 [anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
708 [
self didChangeValueForKey:keyPath];
711 [
super replaceObjectAtIndex:anIndex withObject:anObject];
722 CPArray _observationProxies;
724 Object _observedObjectsByKeyPath;
727 - (id)initWithController:(
id)aController
729 if (
self = [super
init])
732 _observationProxies = [CPArray array];
733 _controller = aController;
734 _observedObjectsByKeyPath = {};
740 - (id)_controllerMarkerForValues:(CPArray)theValues
742 var count = [theValues count],
746 value = CPNoSelectionMarker;
747 else if (count === 1)
748 value = [theValues objectAtIndex:0];
751 if ([_controller alwaysUsesMultipleValuesMarker])
752 value = CPMultipleValuesMarker;
755 value = [theValues objectAtIndex:0];
757 for (var i = 0, count = [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
759 if (![value
isEqual:[theValues objectAtIndex:i]])
760 value = CPMultipleValuesMarker;
765 if (value === nil || value.isa && [value
isEqual:[
CPNull null]])
766 value = CPNullMarker;
773 var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
776 if ([values isKindOfClass:CPArray] || [values isKindOfClass:CPSet])
778 var value = [
self _controllerMarkerForValues:values];
779 [_cachedValues setObject:value forKey:theKeyPath];
792 - (void)setValue:(
id)theValue forKeyPath:(
CPString)theKeyPath
794 [[_controller selectedObjects] setValue:theValue forKeyPath:theKeyPath];
795 [_cachedValues removeObjectForKey:theKeyPath];
809 - (void)setValue:(
id)theValue forKey:(
CPString)theKeyPath
816 return [_cachedValues count];
821 return [_cachedValues keyEnumerator];
824 - (void)controllerWillChange
826 _keys = [_cachedValues allKeys];
831 for (var i = 0, count = _keys.length; i < count; i++)
832 [
self willChangeValueForKey:_keys[i]];
834 [_cachedValues removeAllObjects];
837 - (void)controllerDidChange
839 [_cachedValues removeAllObjects];
844 for (var i = 0, count = _keys.length; i < count; i++)
845 [
self didChangeValueForKey:_keys[i]];
850 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(
CPDictionary)change context:(
id)context
852 [_cachedValues removeObjectForKey:aKeyPath];
855 - (void)addObserver:(
id)anObject forKeyPath:(
CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(
id)context
857 var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
859 [proxy setNotifyObject:YES];
860 [_observationProxies addObject:proxy];
863 var observedObjects = [_controller selectedObjects];
864 _observedObjectsByKeyPath[aKeyPath] = observedObjects;
865 [observedObjects addObserver:proxy forKeyPath:aKeyPath options:options context:context];
868 - (void)removeObserver:(
id)anObject forKeyPath:(
CPString)aKeyPath
870 [_observationProxies enumerateObjectsUsingBlock:function(aProxy, idx, stop)
872 if (aProxy._object === self && aProxy._keyPath == aKeyPath && aProxy._observer === anObject)
874 var observedObjects = _observedObjectsByKeyPath[aKeyPath];
876 [observedObjects removeObserver:aProxy forKeyPath:aKeyPath];
877 [_observationProxies removeObjectAtIndex:idx];
879 _observedObjectsByKeyPath[aKeyPath] = nil;
889 @implementation _CPManagedProxy :
CPObject 892 CPPredicate _fetchPredicate;
900 @implementation _CPManagedProxy (CPCoding)
902 - (id)initWithCoder:(
CPCoder)aCoder
908 [
self setEntityName:[aCoder decodeObjectForKey:CPManagedProxyEntityNameKey]];
909 [
self setFetchPredicate:[aCoder decodeObjectForKey:CPManagedProxyFetchPredicateKey]];
915 - (void)encodeWithCoder:(
CPCoder)aCoder
917 [aCoder encodeObject:[
self entityName] forKey:CPManagedProxyEntityNameKey];
918 [aCoder encodeObject:[
self fetchPredicate] forKey:CPManagedProxyFetchPredicateKey];
928 - (BOOL)usesLazyFetching
930 return _usesLazyFetching;
936 - (void)setUsesLazyFetching:(BOOL)aValue
938 _usesLazyFetching = aValue;
void setValue:forKeyPath:(id theValue, [forKeyPath] CPString theKeyPath)
void setAutomaticallyPreparesContent:(BOOL shouldAutomaticallyPrepareContent)
void removeObject:(id anObject)
void willChangeValueForKey:(CPString aKey)
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
CPBinder getBinding:forObject:(CPString aBinding, [forObject] id anObject)
var CPObjectControllerUsesLazyFetchingKey
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 indexSetWithIndexesInRange:(CPRange aRange)
id initWithContent:(id aContent)
void setObjectClass:(Class aClass)
var CPObjectControllerIsUsingManagedProxyKey
function CPClassFromString(aClassName)
FrameUpdater prototype description