37 BOOL _avoidsEmptySelection;
38 BOOL _clearsFilterPredicateOnInsertion;
39 BOOL _filterRestrictsInsertion;
40 BOOL _preservesSelection;
41 BOOL _selectsInsertedObjects;
42 BOOL _alwaysUsesMultipleValuesMarker;
44 BOOL _automaticallyRearrangesObjects;
51 BOOL _disableSetContent;
63 + (
CPSet)keyPathsForValuesAffectingContentArray
68 + (
CPSet)keyPathsForValuesAffectingArrangedObjects
74 + (
CPSet)keyPathsForValuesAffectingSelection
79 + (
CPSet)keyPathsForValuesAffectingSelectionIndex
84 + (
CPSet)keyPathsForValuesAffectingSelectionIndexes
91 + (
CPSet)keyPathsForValuesAffectingSelectedObjects
97 + (
CPSet)keyPathsForValuesAffectingCanRemove
102 + (
CPSet)keyPathsForValuesAffectingCanSelectNext
107 + (
CPSet)keyPathsForValuesAffectingCanSelectPrevious
119 _preservesSelection = YES;
120 _selectsInsertedObjects = YES;
121 _avoidsEmptySelection = YES;
122 _clearsFilterPredicateOnInsertion = YES;
123 _alwaysUsesMultipleValuesMarker = NO;
124 _automaticallyRearrangesObjects = NO;
126 _filterRestrictsInsertion = YES;
137 _filterPredicate = nil;
142 - (void)prepareContent
144 [
self _setContentArray:[[
self newObject]]];
150 - (BOOL)preservesSelection
152 return _preservesSelection;
160 - (void)setPreservesSelection:(BOOL)value
162 _preservesSelection = value;
168 - (BOOL)selectsInsertedObjects
170 return _selectsInsertedObjects;
177 - (void)setSelectsInsertedObjects:(BOOL)value
179 _selectsInsertedObjects = value;
185 - (BOOL)avoidsEmptySelection
187 return _avoidsEmptySelection;
194 - (void)setAvoidsEmptySelection:(BOOL)value
196 _avoidsEmptySelection = value;
204 - (BOOL)clearsFilterPredicateOnInsertion
206 return _clearsFilterPredicateOnInsertion;
214 - (void)setClearsFilterPredicateOnInsertion:(BOOL)aFlag
216 _clearsFilterPredicateOnInsertion = aFlag;
225 - (BOOL)alwaysUsesMultipleValuesMarker
227 return _alwaysUsesMultipleValuesMarker;
236 - (void)setAlwaysUsesMultipleValuesMarker:(BOOL)aFlag
238 _alwaysUsesMultipleValuesMarker = aFlag;
250 - (BOOL)automaticallyRearrangesObjects
252 return _automaticallyRearrangesObjects;
264 - (void)setAutomaticallyRearrangesObjects:(BOOL)aFlag
266 _automaticallyRearrangesObjects = aFlag;
274 - (void)setContent:(
id)value
279 if (_disableSetContent)
285 if (![value isKindOfClass:[
CPArray class]])
288 var oldSelectedObjects = nil,
289 oldSelectionIndexes = nil;
291 if ([
self preservesSelection])
308 if (_clearsFilterPredicateOnInsertion)
315 _contentObject = value;
317 if (_clearsFilterPredicateOnInsertion && _filterPredicate != nil)
318 [
self __setFilterPredicate:nil];
320 [
self _rearrangeObjects];
322 if ([
self preservesSelection])
323 [
self __setSelectedObjects:oldSelectedObjects];
325 [
self __setSelectionIndexes:oldSelectionIndexes];
327 if (_clearsFilterPredicateOnInsertion)
334 - (void)_setContentArray:(
id)anArray
336 [
self setContent:anArray];
342 - (void)_setContentSet:(
id)aSet
344 [
self setContent:[aSet allObjects]];
377 if (filterPredicate && [sortDescriptors count] > 0)
380 [sortedObjects sortUsingDescriptors:sortDescriptors];
381 return sortedObjects;
383 else if (filterPredicate)
385 else if ([sortDescriptors count] > 0)
388 return [objects
copy];
394 - (void)rearrangeObjects
397 [
self _rearrangeObjects];
405 - (void)_rearrangeObjects
411 var oldSelectedObjects = nil,
412 oldSelectionIndexes = nil;
414 if ([
self preservesSelection])
415 oldSelectedObjects = [
self selectedObjects];
417 oldSelectionIndexes = [
self selectionIndexes];
419 [
self __setArrangedObjects:[
self arrangeObjects:[
self contentArray]]];
421 if ([
self preservesSelection])
422 [
self __setSelectedObjects:oldSelectedObjects];
424 [
self __setSelectionIndexes:oldSelectionIndexes];
430 - (void)__setArrangedObjects:(
id)value
432 if (_arrangedObjects === value)
435 _arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
442 - (id)arrangedObjects
444 return _arrangedObjects;
453 return _sortDescriptors;
463 if (_sortDescriptors === value)
466 _sortDescriptors = [value
copy];
469 [
self _rearrangeObjects];
480 return _filterPredicate;
491 if (_filterPredicate === value)
497 [
self __setFilterPredicate:value];
507 if (_filterPredicate === value)
510 _filterPredicate = value;
512 [
self _rearrangeObjects];
519 - (BOOL)alwaysUsesMultipleValuesMarker
521 return _alwaysUsesMultipleValuesMarker;
529 - (unsigned)selectionIndex
531 return [_selectionIndexes firstIndex];
540 - (BOOL)setSelectionIndex:(
unsigned)index
552 return _selectionIndexes;
563 [
self _selectionWillChange]
564 var r = [
self __setSelectionIndexes:indexes avoidEmpty:NO];
565 [
self _selectionDidChange];
573 - (BOOL)__setSelectionIndex:(
int)theIndex
582 - (BOOL)__setSelectionIndexes:(
CPIndexSet)indexes
584 return [
self __setSelectionIndexes:indexes avoidEmpty:_avoidsEmptySelection];
587 - (BOOL)__setSelectionIndexes:(
CPIndexSet)indexes avoidEmpty:(BOOL)avoidEmpty
589 var newIndexes = indexes;
594 if (![newIndexes count])
596 if (avoidEmpty && [[
self arrangedObjects] count])
601 var objectsCount = [[
self arrangedObjects] count];
606 newIndexes = [newIndexes copy];
609 [newIndexes removeIndexesInRange:CPMakeRange(objectsCount, [newIndexes lastIndex] + 1)];
611 if (![newIndexes count] && avoidEmpty && objectsCount)
615 if ([_selectionIndexes isEqualToIndexSet:newIndexes])
620 _selectionIndexes = indexes === newIndexes ? [indexes
copy] : newIndexes;
624 var binderClass = [[
self class] _binderClassForBinding:@"selectionIndexes"];
625 [[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
638 return [_CPObservableArray arrayWithArray:(objects || [])];
650 [
self _selectionWillChange];
652 var r = [
self __setSelectedObjects:objects avoidEmpty:NO];
655 [
self _selectionDidChange];
663 - (BOOL)__setSelectedObjects:(
CPArray)objects
665 [
self __setSelectedObjects:objects avoidEmpty:_avoidsEmptySelection];
668 - (BOOL)__setSelectedObjects:(
CPArray)objects avoidEmpty:(BOOL)avoidEmpty
671 count = [objects
count],
672 arrangedObjects = [
self arrangedObjects];
674 for (var i = 0; i < count; i++)
676 var index = [arrangedObjects indexOfObject:[objects
objectAtIndex:i]];
679 [
set addIndex:index];
682 [
self __setSelectionIndexes:set avoidEmpty:avoidEmpty];
692 - (BOOL)canSelectPrevious
701 - (void)selectPrevious:(
id)sender
706 [
self setSelectionIndexes:[
CPIndexSet indexSetWithIndex:index]];
714 - (BOOL)canSelectNext
723 - (void)selectNext:(
id)sender
727 if (index < [[
self arrangedObjects] count])
728 [
self setSelectionIndexes:[
CPIndexSet indexSetWithIndex:index]];
738 - (void)addObject:(
id)object
743 var willClearPredicate = NO;
744 if (_clearsFilterPredicateOnInsertion && _filterPredicate)
747 willClearPredicate = YES;
759 _disableSetContent = YES;
760 [_contentObject addObject:object];
765 _disableSetContent = NO;
767 if (willClearPredicate)
770 _filterPredicate = nil;
771 [
self _rearrangeObjects];
773 else if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:
object])
776 var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
780 if (_selectsInsertedObjects)
781 [
self __setSelectionIndex:pos];
783 [_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
794 if (willClearPredicate)
795 [
self didChangeValueForKey:
@"filterPredicate"];
805 - (void)insertObject:(
id)anObject atArrangedObjectIndex:(
int)anIndex
810 var willClearPredicate = NO;
811 if (_clearsFilterPredicateOnInsertion && _filterPredicate)
814 willClearPredicate = YES;
822 _disableSetContent = YES;
827 [_contentObject addObject:anObject];
831 _disableSetContent = NO;
833 if (willClearPredicate)
834 [
self __setFilterPredicate:nil];
840 if ([
self selectsInsertedObjects])
841 [
self __setSelectionIndex:anIndex];
845 if ([
self avoidsEmptySelection] && [[
self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
846 [
self __setSelectionIndexes:[
CPIndexSet indexSetWithIndex:0]];
849 if (willClearPredicate)
850 [
self didChangeValueForKey:
@"filterPredicate"];
858 - (void)removeObject:(
id)object
863 _disableSetContent = YES;
865 [_contentObject removeObject:object];
869 _disableSetContent = NO;
871 if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:
object])
875 var pos = [_arrangedObjects indexOfObject:object];
877 [_arrangedObjects removeObjectAtIndex:pos];
878 [_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
881 [
self __setSelectionIndexes:_selectionIndexes];
892 - (void)add:(
id)sender
904 - (void)insert:(
id)sender
906 if (![
self canInsert])
918 - (void)remove:(
id)sender
927 - (void)removeObjectAtArrangedObjectIndex:(
int)index
936 - (void)removeObjectsAtArrangedObjectIndexes:(
CPIndexSet)anIndexSet
943 _disableSetContent = YES;
947 newSelectionIndexes = [_selectionIndexes copy];
955 if ([_contentObject objectAtIndex:anIndex] === object)
956 [_contentObject removeObjectAtIndex:anIndex];
964 contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
965 [_contentObject removeObjectAtIndex:contentIndex];
969 if (!_avoidsEmptySelection || [newSelectionIndexes count] > 1)
971 [newSelectionIndexes removeIndex:anIndex];
972 [newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
974 else if ([newSelectionIndexes lastIndex] !== anIndex)
975 [newSelectionIndexes shiftIndexesStartingAtIndex:anIndex by:-1];
980 _disableSetContent = NO;
983 [
self __setSelectionIndexes:newSelectionIndexes];
999 count = [objects
count];
1001 for (var i = 0; i < count; i++)
1002 [contentArray addObject:[objects objectAtIndex:i]];
1015 [
self _removeObjects:objects];
1021 - (void)_removeObjects:(
CPArray)objects
1023 [
self willChangeValueForKey:@"content"];
1026 _disableSetContent = YES;
1028 [_contentObject removeObjectsInArray:objects];
1032 _disableSetContent = NO;
1034 var arrangedObjects = [
self arrangedObjects],
1035 position = [arrangedObjects indexOfObject:[objects
objectAtIndex:0]];
1037 [arrangedObjects removeObjectsInArray:objects];
1039 var objectsCount = [arrangedObjects count],
1042 if ([
self preservesSelection] || [
self avoidsEmptySelection])
1047 if (objectsCount <= 0)
1051 else if (position >= objectsCount)
1052 selectionIndexes = [
CPIndexSet indexSetWithIndex:objectsCount - 1];
1055 _selectionIndexes = selectionIndexes;
1057 [
self didChangeValueForKey:@"content"];
1073 + (Class)_binderClassForBinding:(
CPString)theBinding
1075 if (theBinding ==
@"contentArray")
1076 return [_CPArrayControllerContentBinder
class];
1078 return [
super _binderClassForBinding:theBinding];
1082 @implementation _CPArrayControllerContentBinder :
CPBinder
1087 - (void)setValueFor:(
CPString)aBinding
1089 var destination = [_info objectForKey:CPObservedObjectKey],
1090 keyPath = [_info objectForKey:CPObservedKeyPathKey],
1091 options = [_info objectForKey:CPOptionsKey],
1092 isCompound = [
self handlesContentAsCompoundValue],
1093 dotIndex = keyPath.lastIndexOf(
"."),
1094 firstPart = dotIndex !==
CPNotFound ? keyPath.substring(0, dotIndex) : nil,
1095 isSelectionProxy = firstPart && [[destination valueForKeyPath:firstPart] isKindOfClass:CPControllerSelectionProxy];
1097 if (!isCompound && !isSelectionProxy)
1099 newValue = [destination mutableArrayValueForKeyPath:keyPath];
1111 newValue = [destination valueForKeyPath:keyPath];
1120 reason:@"can't transform non applicable key on: " + _source + " value: " + newValue];
1123 newValue = [
self _placeholderForMarker:newValue];
1130 newValue = [
self transformValue:newValue withOptions:options];
1136 newValue = [newValue mutableCopy];
1139 [_source setValue:newValue forKey:aBinding];
1142 - (void)_contentArrayDidChange
1151 if ([
self handlesContentAsCompoundValue])
1153 var destination = [_info objectForKey:CPObservedObjectKey],
1154 keyPath = [_info objectForKey:CPObservedKeyPathKey];
1156 [
self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
1157 [
self reverseSetValueFor:@"contentArray"];
1158 [
self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
1180 _avoidsEmptySelection = [aCoder decodeBoolForKey:CPArrayControllerAvoidsEmptySelection];
1181 _clearsFilterPredicateOnInsertion = [aCoder decodeBoolForKey:CPArrayControllerClearsFilterPredicateOnInsertion];
1182 _filterRestrictsInsertion = [aCoder decodeBoolForKey:CPArrayControllerFilterRestrictsInsertion];
1183 _preservesSelection = [aCoder decodeBoolForKey:CPArrayControllerPreservesSelection];
1184 _selectsInsertedObjects = [aCoder decodeBoolForKey:CPArrayControllerSelectsInsertedObjects];
1185 _alwaysUsesMultipleValuesMarker = [aCoder decodeBoolForKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
1186 _automaticallyRearrangesObjects = [aCoder decodeBoolForKey:CPArrayControllerAutomaticallyRearrangesObjects];
1189 if (![
self content] && [
self automaticallyPreparesContent])
1191 else if (![
self content])
1192 [
self _setContentArray:[]];
1202 [aCoder encodeBool:_avoidsEmptySelection forKey:CPArrayControllerAvoidsEmptySelection];
1203 [aCoder encodeBool:_clearsFilterPredicateOnInsertion forKey:CPArrayControllerClearsFilterPredicateOnInsertion];
1204 [aCoder encodeBool:_filterRestrictsInsertion forKey:CPArrayControllerFilterRestrictsInsertion];
1205 [aCoder encodeBool:_preservesSelection forKey:CPArrayControllerPreservesSelection];
1206 [aCoder encodeBool:_selectsInsertedObjects forKey:CPArrayControllerSelectsInsertedObjects];
1207 [aCoder encodeBool:_alwaysUsesMultipleValuesMarker forKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
1208 [aCoder encodeBool:_automaticallyRearrangesObjects forKey:CPArrayControllerAutomaticallyRearrangesObjects];
1211 - (void)awakeFromCib
1213 [
self _selectionWillChange];
1214 [
self _selectionDidChange];