33 var CPRuleEditorItemPBoardType =
@"CPRuleEditorItemPBoardType",
34 itemsContext =
"items",
35 valuesContext =
"values",
36 subrowsContext =
"subrows_array",
37 boundArrayContext =
"bound_array";
61 BOOL _suppressKeyDownHandling;
62 BOOL _allowsEmptyCompoundRows;
64 BOOL _delegateWantsValidation;
71 CPInteger _subviewIndexOfDropLine;
77 CPPredicate _predicate;
89 CPInteger _nestingMode;
91 float _alignmentGridWidth;
101 BOOL _nestingModeDidChange;
103 _CPRuleEditorLocalizer _standardLocalizer;
111 return @"rule-editor";
121 @"slice-last-bottom-border-color": [
CPNull null],
128 - (id)initWithFrame:(CGRect)frame
130 self = [
super initWithFrame:frame];
138 _allowsEmptyCompoundRows = NO;
141 [
self setFormattingStringsFilename:nil];
142 [
self setCriteriaKeyPath:@"criteria"];
143 [
self setSubrowsKeyPath:@"subrows"];
144 [
self setRowTypeKeyPath:@"rowType"];
145 [
self setDisplayValuesKeyPath:@"displayValues"];
146 [
self setBoundArrayKeyPath:@"boundArray"];
148 _slicesHolder = [[_CPRuleEditorViewSliceHolder alloc] initWithFrame:[
self bounds]];
149 [
self addSubview:_slicesHolder];
151 _boundArrayOwner = [[_CPRuleEditorViewUnboundRowHolder alloc] init];
153 [
self _initRuleEditorShared];
159 - (void)_initRuleEditorShared
162 _rowClass = [_CPRuleEditorRowObject class];
166 _delegateWantsValidation = YES;
167 _suppressKeyDownHandling = NO;
168 _nestingModeDidChange = NO;
170 _itemsAndValuesToAddForRowType = {};
171 var animation = [[
CPViewAnimation alloc] initWithDuration:0.5 animationCurve:CPAnimationEaseInOut];
172 [
self setAnimation:animation];
174 [_slicesHolder setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
176 _dropLineView = [
self _createSliceDropSeparator];
177 [_slicesHolder addSubview:_dropLineView];
179 [
self registerForDraggedTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType,nil]];
180 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
196 return _ruleDelegate;
205 - (void)setDelegate:(
id)aDelegate
207 if (_ruleDelegate === aDelegate)
212 [nc removeObserver:_ruleDelegate name:nil object:self];
214 _ruleDelegate = aDelegate;
216 if ([_ruleDelegate respondsToSelector:
@selector(ruleEditorRowsDidChange:)])
217 [nc addObserver:_ruleDelegate selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
235 - (void)setEditable:(BOOL)editable
237 if (editable === _editable)
240 _editable = editable;
245 [_slices makeObjectsPerformSelector:@selector(setEditable:) withObject:_editable];
253 - (CPRuleEditorNestingMode)nestingMode
265 - (void)setNestingMode:(CPRuleEditorNestingMode)mode
267 if (mode !== _nestingMode)
270 if ([
self numberOfRows] > 0)
271 _nestingModeDidChange = YES;
280 - (BOOL)canRemoveAllRows
282 return !_disallowEmpty;
290 - (void)setCanRemoveAllRows:(BOOL)canRemove
292 _disallowEmpty = !canRemove;
293 [
self _updateButtonVisibilities];
301 - (BOOL)allowsEmptyCompoundRows
303 return _allowsEmptyCompoundRows;
311 - (void)setAllowsEmptyCompoundRows:(BOOL)allows
313 _allowsEmptyCompoundRows = allows;
314 [
self _updateButtonVisibilities];
322 - (CPInteger)rowHeight
332 - (void)setRowHeight:(
float)height
334 if (height === _sliceHeight)
337 _sliceHeight = MAX([
self _minimumFrameHeight], height);
338 [
self _reconfigureSubviewsAnimate:NO];
353 return [_standardLocalizer dictionary];
363 - (void)setFormattingDictionary:(
CPDictionary)dictionary
365 [_standardLocalizer setDictionary:dictionary];
366 _stringsFilename = nil;
374 - (
CPString)formattingStringsFilename
376 return _stringsFilename;
386 - (void)setFormattingStringsFilename:(
CPString)stringsFilename
388 if (_standardLocalizer === nil)
389 _standardLocalizer = [_CPRuleEditorLocalizer new];
391 if (_stringsFilename !== stringsFilename)
394 _stringsFilename = stringsFilename || nil;
396 if (stringsFilename !== nil)
398 if (![stringsFilename hasSuffix:
@".strings"])
399 stringsFilename = stringsFilename +
@".strings";
417 - (void)reloadCriteria
419 var current_rows = [_boundArrayOwner valueForKey:_boundArrayKeyPath];
420 [
self _stopObservingRowObjectsRecursively:current_rows];
421 [_boundArrayOwner setValue:[CPArray arrayWithArray:current_rows] forKey:_boundArrayKeyPath];
432 - (void)setCriteria:(CPArray)criteria andDisplayValues:(CPArray)values forRowAtIndex:(
int)rowIndex
434 if (criteria === nil || values === nil)
435 [
CPException raise:CPInvalidArgumentException
reason:_cmd + @". criteria and values parameters must not be nil."];
437 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
440 var rowObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
442 [rowObject setValue:criteria forKey:_itemsKeyPath];
443 [rowObject setValue:values forKey:_valuesKeyPath];
445 [
self reloadCriteria];
453 - (id)criteriaForRow:(CPInteger)row
455 var rowcache = [
self _rowCacheForIndex:row];
457 return [[rowcache rowObject] valueForKey:_itemsKeyPath];
474 var rowcache = [
self _rowCacheForIndex:row];
476 return [[rowcache rowObject] valueForKey:_valuesKeyPath];
487 return [_slices count];
495 - (int)parentRowForRow:(CPInteger)rowIndex
497 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
500 var targetObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
502 for (var current_index = 0; current_index < rowIndex; current_index++)
506 var candidate = [[
self _rowCacheForIndex:current_index] rowObject],
507 subObjects = [[
self _subrowObjectsOfObject:candidate] _representedObject];
509 if ([subObjects indexOfObjectIdenticalTo:targetObject] !==
CPNotFound)
510 return current_index;
536 - (CPRuleEditorRowType)rowTypeForRow:(CPInteger)rowIndex
538 if (rowIndex < 0 || rowIndex > [
self numberOfRows])
541 var rowcache = [
self _rowCacheForIndex:rowIndex];
544 var rowobject = [rowcache rowObject];
545 return [rowobject valueForKey:_typeKeyPath];
557 - (
CPIndexSet)subrowIndexesForRow:(CPInteger)rowIndex
562 object = _boundArrayOwner;
564 object = [[
self _rowCacheForIndex:rowIndex] rowObject];
566 var subobjects = [
self _subrowObjectsOfObject:object],
567 objectsCount = [subobjects count],
569 count = [
self numberOfRows];
571 for (var i = rowIndex + 1; i < count; i++)
573 var candidate = [[
self _rowCacheForIndex:i] rowObject],
574 indexInSubrows = [[subobjects _representedObject] indexOfObjectIdenticalTo:candidate];
578 [indexes addIndex:i];
582 i += [[
self subrowIndexesForRow:i] count];
585 if (objectsCount === 0)
598 return [
self _selectedSliceIndices];
606 - (void)selectRowIndexes:(
CPIndexSet)indexes byExtendingSelection:(BOOL)extend
608 var count = [_slices count],
611 if (lastSelected >= [
self numberOfRows])
619 var slice = _slices[count],
620 rowIndex = [slice rowIndex],
622 shouldSelect = (contains && !(extend && [slice _isSelected]));
625 [slice _setSelected:shouldSelect];
626 [slice _setLastSelected:(rowIndex === lastSelected)];
627 [slice setNeedsDisplay:YES];
640 - (void)addRow:(
id)sender
642 var parentRowIndex = -1,
644 numberOfRows = [self numberOfRows],
645 hasRows = (numberOfRows > 0),
646 nestingMode = [self _applicableNestingMode];
667 [
CPException raise:CPInvalidArgumentException
reason:@"Not supported CPRuleEditorNestingMode " + nestingMode];
671 [
self insertRowAtIndex:numberOfRows withType:rowtype asSubrowOfRow:parentRowIndex animate:YES];
683 - (void)insertRowAtIndex:(
int)rowIndex withType:(
unsigned int)rowType asSubrowOfRow:(CPInteger)parentRow animate:(BOOL)shouldAnimate
688 var newObject = [
self _insertNewRowAtIndex:rowIndex ofType:rowType withParentRow:parentRow];
692 var subrow = [
self _insertNewRowAtIndex:(rowIndex + 1) ofType:CPRuleEditorRowTypeSimple withParentRow:rowIndex];
702 - (void)removeRowAtIndex:(
int)rowIndex
706 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
719 - (void)removeRowsAtIndexes:(
CPIndexSet)rowIndexes includeSubrows:(BOOL)includeSubrows
721 if ([rowIndexes count] === 0)
724 if ([rowIndexes lastIndex] >= [
self numberOfRows])
728 parentRowIndex = [
self parentRowForRow:current_index],
732 if (parentRowIndex === -1)
733 subrows = [
self _rootRowsArray];
736 var parentRowObject = [[
self _rowCacheForIndex:parentRowIndex] rowObject];
737 subrows = [
self _subrowObjectsOfObject:parentRowObject];
742 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
743 relativeChildIndex = [[subrows _representedObject] indexOfObjectIdenticalTo:rowObject];
746 [childsIndexes addIndex:relativeChildIndex];
750 var more_childs = [
self subrowIndexesForRow:current_index];
751 [
self removeRowsAtIndexes:more_childs includeSubrows:includeSubrows];
757 [subrows removeObjectsAtIndexes:childsIndexes];
769 - (CPPredicate)predicate
778 - (void)reloadPredicate
780 [
self _updatePredicate];
789 - (CPPredicate)predicateForRow:(CPInteger)aRow
791 var predicateParts = @{},
792 items = [
self criteriaForRow:aRow],
793 count = [items count],
797 for (i = 0; i < count; i++)
799 var item = [items objectAtIndex:i],
801 displayValue = [[
self displayValuesForRow:aRow] objectAtIndex:i],
802 predpart = [_ruleDelegate ruleEditor:self predicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
805 [predicateParts addEntriesFromDictionary:predpart];
810 var compoundPredicate,
812 subrowsIndexes = [
self subrowIndexesForRow:aRow];
814 if ([subrowsIndexes count] === 0)
817 var current_index = [subrowsIndexes firstIndex];
820 var subpredicate = [
self predicateForRow:current_index];
821 if (subpredicate !== nil)
822 [subpredicates addObject:subpredicate];
824 current_index = [subrowsIndexes indexGreaterThanIndex:current_index];
827 var compoundType = [predicateParts objectForKey:CPRuleEditorPredicateCompoundType];
829 if ([subpredicates count] === 0)
835 compoundPredicate = [[
CPCompoundPredicate alloc ] initWithType:compoundType subpredicates:subpredicates];
839 CPLogConsole(
@"Compound predicate error: [%@]\npredicateType:%i", [error description], compoundType);
840 compoundPredicate = nil;
844 return compoundPredicate;
850 var lhs = [predicateParts objectForKey:CPRuleEditorPredicateLeftExpression],
851 rhs = [predicateParts objectForKey:CPRuleEditorPredicateRightExpression],
852 operator = [predicateParts objectForKey:CPRuleEditorPredicateOperatorType],
853 options = [predicateParts objectForKey:CPRuleEditorPredicateOptions],
854 modifier = [predicateParts objectForKey:CPRuleEditorPredicateComparisonModifier],
859 CPLogConsole(
@"missing left expression in predicate parts dictionary");
865 CPLogConsole(
@"missing right expression in predicate parts dictionary");
869 if (selector === nil &&
operator === nil)
871 CPLogConsole(
@"missing operator and selector in predicate parts dictionary");
875 if (modifier === nil)
876 CPLogConsole(
@"missing modifier in predicate parts dictionary. Setting default: CPDirectPredicateModifier");
879 CPLogConsole(
@"missing options in predicate parts dictionary. Setting default: CPCaseInsensitivePredicateOption");
883 if (selector !== nil)
891 modifier:(modifier || CPDirectPredicateModifier)
893 options:(options || CPCaseInsensitivePredicateOption)
898 CPLogConsole(
@"Row predicate error: [" + [error description] +
"] for row " + aRow);
926 - (void)setRowClass:(Class)rowClass
929 rowClass = [_CPRuleEditorRowObject class];
931 _rowClass = rowClass;
951 - (void)setRowTypeKeyPath:(
CPString)keyPath
953 if (_typeKeyPath !== keyPath)
954 _typeKeyPath = keyPath;
966 return _subrowsArrayKeyPath;
974 - (void)setSubrowsKeyPath:(
CPString)keyPath
976 if (_subrowsArrayKeyPath !== keyPath)
977 _subrowsArrayKeyPath = keyPath;
989 return _itemsKeyPath;
997 - (void)setCriteriaKeyPath:(
CPString)keyPath
999 if (_itemsKeyPath !== keyPath)
1000 _itemsKeyPath = keyPath;
1012 return _valuesKeyPath;
1020 - (void)setDisplayValuesKeyPath:(
CPString)keyPath
1022 if (_valuesKeyPath !== keyPath)
1023 _valuesKeyPath = keyPath;
1037 return _currentAnimation;
1048 _currentAnimation = animation;
1049 [_currentAnimation setDelegate:self];
1097 - (BOOL)acceptsFirstResponder
1102 - (void)keyDown:(
CPEvent)event
1106 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeCompound];
1114 if (!_suppressKeyDownHandling)
1116 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeSimple];
1122 - (_CPRuleEditorViewSliceDropSeparator)_createSliceDropSeparator
1124 var view = [[_CPRuleEditorViewSliceDropSeparator alloc] initWithFrame:CGRectMake(0, -10, [
self frame].size.width, 2)];
1125 [view setAutoresizingMask:CPViewWidthSizable];
1129 - (BOOL)_suppressKeyDownHandling
1131 return _suppressKeyDownHandling;
1134 - (BOOL)_wantsRowAnimations
1136 return (_currentAnimation !== nil);
1139 - (void)_updateButtonVisibilities
1141 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1144 - (float)_alignmentGridWidth
1146 return _alignmentGridWidth;
1149 - (float)_minimumFrameHeight
1154 - (CPRuleEditorNestingMode)_applicableNestingMode
1156 if (!_nestingModeDidChange)
1157 return _nestingMode;
1163 return _nestingMode;
1168 - (BOOL)_shouldHideAddButtonForSlice:(
id)slice
1173 - (BOOL)_shouldHideSubtractButtonForSlice:(
id)slice
1178 if (!_disallowEmpty)
1182 rowIndex = [slice rowIndex],
1183 parentIndex = [
self parentRowForRow:rowIndex],
1184 subrowsIndexes = [
self subrowIndexesForRow:parentIndex],
1185 nestingMode = [
self _applicableNestingMode];
1187 switch (nestingMode)
1196 default: shouldHide = NO;
1202 #pragma mark Rows management
1204 - (id)_rowCacheForIndex:(
int)index
1206 return [_rowCache objectAtIndex:index];
1209 - (id)_searchCacheForRowObject:(
id)rowObject
1211 var count = [_rowCache count],
1214 for (i = 0; i < count; i++)
1216 var cache = _rowCache[i];
1217 if ([cache rowObject] === rowObject)
1224 - (int)_rowIndexForRowObject:(
id)rowobject
1226 if (rowobject === _boundArrayOwner)
1229 return [[
self _searchCacheForRowObject:rowobject] rowIndex];
1234 if (
object === _boundArrayOwner)
1235 return [
self _rootRowsArray];
1237 return [object mutableArrayValueForKey:_subrowsArrayKeyPath];
1240 - (
CPIndexSet)_childlessParentsIfSlicesWereDeletedAtIndexes:(
id)indexes
1243 current_index = [indexes firstIndex];
1247 var parentIndex = [
self parentRowForRow:current_index],
1248 subrowsIndexes = [
self subrowIndexesForRow:parentIndex];
1250 if ([subrowsIndexes count] === 1)
1252 if (parentIndex !== -1)
1256 [childlessParents addIndexes:childlessGranPa];
1259 current_index = [indexes indexGreaterThanIndex:current_index];
1262 return childlessParents;
1268 var subindexes = [indexes
copy],
1273 var sub = [
self subrowIndexesForRow:current_index];
1274 [subindexes addIndexes:[
self _includeSubslicesForSlicesAtIndexes:sub]];
1281 - (void)_deleteSlice:(
id)slice
1285 if (!_allowsEmptyCompoundRows)
1287 var childlessIndexes = [
self _childlessParentsIfSlicesWereDeletedAtIndexes:rowindexes];
1288 if ([childlessIndexes count] > 0)
1289 rowindexes = childlessIndexes;
1292 [
self removeRowsAtIndexes:rowindexes includeSubrows:YES];
1294 [
self _updatePredicate];
1295 [
self _sendRuleAction];
1296 [
self _postRuleOptionChangedNotification];
1297 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:rowindexes];
1300 - (CPArray)_rootRowsArray
1302 return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath];
1305 - (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(CPInteger)rowIndex forRowType:(
unsigned int)type
1307 var parentItem = [items lastObject],
1308 childrenCount = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
1311 if (childrenCount === 0)
1315 count = [
self numberOfRows],
1318 for (row = 0; row < count; row++)
1320 var aCriteria = [
self criteriaForRow:row],
1321 itemIndex = [items count];
1323 if ([
self rowTypeForRow:row] === type && itemIndex < [aCriteria count])
1325 var crit = [aCriteria objectAtIndex:itemIndex];
1326 [current_criterions addObject:crit];
1334 for (i = 0; i < childrenCount; i++)
1336 var child = [
self _queryChild:i ofItem:parentItem withRowType:type];
1337 if ([current_criterions indexOfObject:child] ===
CPNotFound)
1346 for (var k = 0; k < childrenCount; k++)
1348 var anobject = [
self _queryChild:k ofItem:parentItem withRowType:type],
1349 index = [buffer indexOfObject:anobject];
1351 [buffer removeObjectAtIndex:index];
1354 current_criterions = buffer;
1358 var foundItem = [
self _queryChild:foundIndex ofItem:parentItem withRowType:type],
1359 foundValue = [
self _queryValueForItem:foundItem inRow:rowIndex];
1361 [items addObject:foundItem];
1362 [values addObject:foundValue];
1367 - (
CPMutableArray)_getItemsAndValuesToAddForRow:(CPInteger)rowIndex ofType:(CPRuleEditorRowType)type
1379 unusedItems = [
self _nextUnusedItems:items andValues:values forRow:rowIndex forRowType:type];
1381 var count = [items count];
1383 for (var i = 0; i < count; i++)
1385 var item = [items objectAtIndex:i],
1386 value = [values objectAtIndex:i],
1392 [itemsAndValues addObject:itemAndValue];
1395 return itemsAndValues;
1398 - (void)_addOptionFromSlice:(
id)slice ofRowType:(
unsigned int)type
1402 var rowIndexEvent = [slice rowIndex],
1403 rowTypeEvent = [
self rowTypeForRow:rowIndexEvent],
1404 insertIndex = rowIndexEvent + 1,
1407 [
self insertRowAtIndex:insertIndex withType:type asSubrowOfRow:parentRowIndex animate:YES];
1410 - (id)_insertNewRowAtIndex:(
int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(CPInteger)parentRowIndex
1412 var row = [[[
self rowClass] alloc] init],
1413 itemsandvalues = [
self _getItemsAndValuesToAddForRow:insertIndex ofType:rowtype],
1414 newitems = [itemsandvalues valueForKey:@"item"],
1415 newvalues = [itemsandvalues valueForKey:@"value"];
1417 [row setValue:newitems forKey:_itemsKeyPath];
1418 [row setValue:newvalues forKey:_valuesKeyPath];
1419 [row setValue:rowtype forKey:_typeKeyPath];
1420 [row setValue:[
CPMutableArray array] forKey:_subrowsArrayKeyPath];
1424 subrowsObjects = [
self _rootRowsArray];
1427 var parentRowObject = [[
self _rowCacheForIndex:parentRowIndex] rowObject];
1428 subrowsObjects = [
self _subrowObjectsOfObject:parentRowObject];
1431 var relInsertIndex = insertIndex - parentRowIndex - 1;
1432 [subrowsObjects insertObject:row atIndex:relInsertIndex];
1434 [
self _updatePredicate];
1435 [
self _sendRuleAction];
1436 [
self _postRuleOptionChangedNotification];
1437 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:[
CPIndexSet indexSetWithIndex:insertIndex]];
1442 #pragma mark Key value observing
1444 - (void)_startObservingRowObjectsRecursively:(CPArray)rowObjects
1446 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
1448 var count = [rowObjects count];
1450 for (var i = 0; i < count; i++)
1452 var rowObject = [rowObjects objectAtIndex:i];
1454 [rowObject addObserver:self forKeyPath:_itemsKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:itemsContext];
1455 [rowObject addObserver:self forKeyPath:_valuesKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:valuesContext];
1456 [rowObject addObserver:self forKeyPath:_subrowsArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:subrowsContext];
1458 var subrows = [
self _subrowObjectsOfObject:rowObject];
1459 if ([subrows count] > 0)
1460 [
self _startObservingRowObjectsRecursively:subrows];
1465 - (void)_stopObservingRowObjectsRecursively:(CPArray)rowObjects
1467 [_boundArrayOwner removeObserver:self forKeyPath:_boundArrayKeyPath];
1469 var count = [rowObjects count];
1471 for (var i = 0; i < count; i++)
1473 var rowObject = [rowObjects objectAtIndex:i];
1474 [rowObject removeObserver:self forKeyPath:_itemsKeyPath];
1475 [rowObject removeObserver:self forKeyPath:_valuesKeyPath];
1476 [rowObject removeObserver:self forKeyPath:_subrowsArrayKeyPath];
1478 var subrows = [rowObject valueForKey:_subrowsArrayKeyPath];
1479 if ([subrows count] > 0)
1480 [
self _stopObservingRowObjectsRecursively:subrows];
1484 - (void)observeValueForKeyPath:(
CPString)keypath ofObject:(
id)object change:(
CPDictionary)change context:(
void)context
1486 var changeKind = [change
objectForKey:CPKeyValueChangeKindKey],
1487 changeNewValue = [change
objectForKey:CPKeyValueChangeNewKey],
1488 changeOldValue = [change
objectForKey:CPKeyValueChangeOldKey],
1492 if (context === boundArrayContext || context === subrowsContext)
1496 newRows = changeNewValue;
1497 oldRows = changeOldValue;
1502 newRows = [
self _subrowObjectsOfObject:object];
1503 oldRows = [CPArray arrayWithArray:newRows];
1504 [oldRows removeObjectsInArray:changeNewValue];
1507 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:object];
1508 [
self _reconfigureSubviewsAnimate:[
self _wantsRowAnimations]];
1512 - (void)_changedItem:(
id)fromItem toItem:(
id)toItem inRow:(CPInteger)aRow atCriteriaIndex:(
int)fromItemIndex
1514 var criteria = [
self criteriaForRow:aRow],
1515 displayValues = [
self displayValuesForRow:aRow],
1516 rowType = [
self rowTypeForRow:aRow],
1519 items = [criteria subarrayWithRange:CPMakeRange(0, fromItemIndex)],
1520 values = [displayValues subarrayWithRange:CPMakeRange(0, fromItemIndex)];
1526 [items addObject:anItem];
1527 var value = [
self _queryValueForItem:anItem inRow:aRow];
1528 [values addObject:value];
1530 if (![
self _queryNumberOfChildrenOfItem:anItem withRowType:rowType])
1533 anItem = [
self _queryChild:0 ofItem:anItem withRowType:rowType];
1536 var
object = [[
self _rowCacheForIndex:aRow] rowObject];
1537 [object setValue:items forKey:_itemsKeyPath];
1538 [object setValue:values forKey:_valuesKeyPath];
1540 var slice = [_slices objectAtIndex:aRow];
1541 [slice _reconfigureSubviews];
1543 [
self _updatePredicate];
1544 [
self _sendRuleAction];
1545 [
self _postRuleOptionChangedNotification];
1548 - (void)_changedRowArray:(CPArray)newRows withOldRowArray:(CPArray)oldRows forParent:(
id)parentRowObject
1550 var newRowCount = [newRows count],
1551 oldRowCount = [oldRows count],
1552 deltaCount = newRowCount - oldRowCount,
1553 minusCount = MIN(newRowCount, oldRowCount),
1554 maxCount = MAX(newRowCount, oldRowCount),
1557 newCaches = [CPArray array],
1559 parentCacheIndentation,
1560 parentCacheIndex = [self _rowIndexForRowObject:parentRowObject],
1562 newRowCacheIndex = 0,
1563 changeStartIndex = 0;
1565 [
self _stopObservingRowObjectsRecursively:oldRows];
1566 [
self _startObservingRowObjectsRecursively:newRows];
1570 if (parentCacheIndex === -1)
1571 parentCacheIndentation = -1;
1573 parentCacheIndentation = [[
self _rowCacheForIndex:parentCacheIndex] indentation];
1575 for (; newRowCacheIndex < newRowCount; newRowCacheIndex++)
1577 var newCacheGlobalIndex = (parentCacheIndex + 1) + newRowCacheIndex,
1578 obj = [newRows objectAtIndex:newRowCacheIndex],
1579 newRowType = [obj valueForKey:_typeKeyPath],
1580 cache = [[_CPRuleEditorCache alloc] init];
1582 [cache setRowObject:obj];
1583 [cache setRowIndex:newCacheGlobalIndex];
1584 [cache setIndentation:parentCacheIndentation + 1];
1586 [insertCacheIndexes addIndex:newCacheGlobalIndex];
1587 [newCaches addObject:cache];
1591 [_rowCache removeObjectsInRange:CPMakeRange(parentCacheIndex + 1, [oldRows count])];
1592 [_rowCache insertObjects:newCaches atIndexes:insertCacheIndexes];
1594 for (; changeStartIndex < minusCount; changeStartIndex++)
1596 var oldrow = [oldRows objectAtIndex:changeStartIndex],
1597 newrow = [newRows objectAtIndex:changeStartIndex];
1599 if (newrow !== oldrow)
1603 var replaceCount = (deltaCount === 0) ? maxCount : maxCount - minusCount,
1604 startIndex = parentCacheIndex + changeStartIndex + 1;
1606 if (deltaCount <= 0)
1609 removeSlices = [_slices objectsAtIndexes:removeIndexes];
1611 [removeSlices makeObjectsPerformSelector:@selector(removeFromSuperview)];
1612 [_slices removeObjectsAtIndexes:removeIndexes];
1615 if (deltaCount >= 0)
1617 var newIndentation = parentCacheIndentation + 1,
1618 newIndex = startIndex;
1620 for (; newIndex < startIndex + replaceCount; newIndex++)
1622 var newslice = [
self _newSlice],
1623 rowType = [
self rowTypeForRow:newIndex];
1625 [newslice setRowIndex:newIndex];
1626 [newslice setIndentation:newIndentation];
1627 [newslice _setRowType:rowType];
1628 [newslice _configurePlusButtonByRowType:CPRuleEditorRowTypeSimple];
1630 [_slices insertObject:newslice atIndex:newIndex];
1634 var emptyArray = [CPArray array],
1635 count = [oldRows count],
1637 for (n = 0; n < count; n++)
1639 var oldRow = [oldRows objectAtIndex:n],
1640 subOldRows = [
self _subrowObjectsOfObject:oldRow];
1642 if ([subOldRows count] > 0)
1643 [
self _changedRowArray:emptyArray withOldRowArray:subOldRows forParent:oldRow];
1646 count = [newRows count];
1647 for (n = 0; n < count; n++)
1649 var newRow = [newRows objectAtIndex:n],
1650 subnewRows = [
self _subrowObjectsOfObject:newRow];
1652 if ([subnewRows count] > 0)
1653 [
self _changedRowArray:subnewRows withOldRowArray:emptyArray forParent:newRow];
1659 if ([aBinding isEqualToString:
@"rows"])
1661 [
self unbind:aBinding];
1662 [
self _setBoundDataSource:observableController withKeyPath:aKeyPath options:options];
1664 [_rowCache removeAllObjects];
1665 [_slices removeAllObjects];
1667 var newRows = [CPArray array],
1668 oldRows = [
self _rootRowsArray];
1670 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:_boundArrayOwner];
1673 [
super bind:aBinding toObject:observableController withKeyPath:aKeyPath options:options];
1678 _rowClass = [_CPRuleEditorRowObject class];
1679 [
super unbind:object];
1682 - (void)_setBoundDataSource:(
id)datasource withKeyPath:(
CPString)keyPath options:(
CPDictionary)options
1684 if ([datasource respondsToSelector:
@selector(objectClass)])
1685 _rowClass = [datasource objectClass];
1687 _boundArrayKeyPath = keyPath;
1688 _boundArrayOwner = datasource;
1692 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
1698 - (void)_setPredicate:(CPPredicate)predicate
1700 if (_predicate !== predicate)
1701 _predicate = predicate;
1704 - (void)_updatePredicate
1706 if (_delegateWantsValidation)
1708 var selector =
@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
1709 if (![_ruleDelegate respondsToSelector:selector])
1712 _delegateWantsValidation = NO;
1716 subindexes = [
self subrowIndexesForRow:-1],
1717 current_index = [subindexes firstIndex];
1721 var subpredicate = [
self predicateForRow:current_index];
1723 if (subpredicate !== nil)
1724 [subpredicates addObject:subpredicate];
1726 current_index = [subindexes indexGreaterThanIndex:current_index];
1729 var new_predicate = [[
CPCompoundPredicate alloc] initWithType:CPOrPredicateType subpredicates:subpredicates];
1731 [
self _setPredicate:new_predicate];
1734 - (_CPRuleEditorViewSliceRow)_newSlice
1736 var sliceRect = CGRectMake(0, 0, CGRectGetWidth([
self frame]), 0),
1737 slice = [
self _createNewSliceWithFrame:sliceRect ruleEditorView:self];
1742 - (_CPRuleEditorViewSliceRow)_createNewSliceWithFrame:(CGRect)frame ruleEditorView:(
CPRuleEditor)editor
1744 return [[_CPRuleEditorViewSliceRow alloc] initWithFrame:frame ruleEditorView:editor];
1747 - (void)_reconfigureSubviewsAnimate:(BOOL)animate
1751 count = [_slices count];
1753 [
self _updateSliceRows];
1755 if ([[
self superview] isKindOfClass:[
CPClipView class]])
1756 [
self setFrameSize:CGSizeMake(CGRectGetWidth([
self frame]), count * _sliceHeight)];
1758 for (var i = 0; i < count; i++)
1760 var aslice = [_slices objectAtIndex:i],
1761 targetRect = [aslice _animationTargetRect],
1762 startRect = [aslice frame],
1763 startIndex = [aslice rowIndex] - 1;
1765 if ([aslice superview] === nil)
1767 startRect = CGRectMake(0, startIndex * _sliceHeight, CGRectGetWidth(startRect), _sliceHeight);
1768 [aslice _reconfigureSubviews];
1769 [added_slices addObject:aslice];
1774 var animation = @{};
1775 [animation setObject:aslice forKey:CPViewAnimationTargetKey];
1776 [animation setObject:startRect forKey:CPViewAnimationStartFrameKey];
1777 [animation setObject:targetRect forKey:CPViewAnimationEndFrameKey];
1779 [viewAnimations insertObject:animation atIndex:0];
1782 [aslice setFrame:targetRect];
1785 var addcount = [added_slices count];
1786 for (var i = 0; i < addcount; i++)
1787 [_slicesHolder addSubview:added_slices[i] positioned:CPWindowBelow relativeTo:nil];
1791 [_currentAnimation setViewAnimations:viewAnimations];
1792 [_currentAnimation startAnimation];
1795 _lastRow = [
self numberOfRows] - 1;
1797 if (_lastRow === -1)
1798 _nestingModeDidChange = NO;
1800 [
self setNeedsDisplay:YES];
1801 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1812 - (void)_updateSliceRows
1814 var
width = [
self frame].size.width,
1815 count = [_slices count];
1817 for (var i = 0; i < count; i++)
1819 var slice = [_slices objectAtIndex:i],
1820 targetRect = CGRectMake(0, i * _sliceHeight, width, _sliceHeight);
1822 [slice setRowIndex:i];
1823 [slice _setAnimationTargetRect:targetRect];
1827 - (CPArray)_backgroundColors
1829 return [
self valueForThemeAttribute:@"alternating-row-colors"];
1834 return [
self valueForThemeAttribute:@"selected-color"];
1837 - (
CPColor)_sliceTopBorderColor
1839 return [
self valueForThemeAttribute:@"slice-top-border-color"];
1842 - (
CPColor)_sliceBottomBorderColor
1844 return [
self valueForThemeAttribute:@"slice-bottom-border-color"];
1847 - (
CPColor)_sliceLastBottomBorderColor
1849 return [
self valueForThemeAttribute:@"slice-last-bottom-border-color"];
1854 return [
self valueForThemeAttribute:@"font"];
1859 return [
self valueForThemeAttribute:@"add-image"];
1864 return [
self valueForThemeAttribute:@"remove-image"];
1867 - (
CPString)_toolTipForAddCompoundRowButton
1869 return [_standardLocalizer localizedStringForString:@"Add compound row"];
1872 - (
CPString)_toolTipForAddSimpleRowButton
1874 return [_standardLocalizer localizedStringForString:@"Add row"];
1877 - (
CPString)_toolTipForDeleteRowButton
1879 return [_standardLocalizer localizedStringForString:@"Delete row"];
1882 - (void)_updateSliceIndentations
1884 [
self _updateSliceIndentationAtIndex:0 toIndentation:0 withIndexSet:[
self subrowIndexesForRow:0]];
1887 - (void)_updateSliceIndentationAtIndex:(
int)index toIndentation:(
int)indentation withIndexSet:(
id)indexes
1889 var current_index = [indexes firstIndex];
1893 var subindexes = [
self subrowIndexesForRow:index];
1894 [
self _updateSliceIndentationAtIndex:current_index toIndentation:indentation + 1 withIndexSet:subindexes];
1895 current_index = [indexes indexGreaterThanIndex:current_index];
1898 [[_slices objectAtIndex:index] setIndentation:indentation];
1901 - (CPArray)_selectedSlices
1904 count = [_slices count],
1907 for (i = 0; i < count; i++)
1909 var slice = _slices[i];
1910 if ([slice _isSelected])
1911 [_selectedSlices addObject:slice];
1914 return _selectedSlices;
1917 - (int)_lastSelectedSliceIndex
1920 count = [_slices count],
1923 for (i = 0; i < count; i++)
1925 var slice = _slices[i];
1926 if ([slice _isLastSelected])
1927 return [slice rowIndex];
1933 - (void)_mouseUpOnSlice:(
id)slice withEvent:(
CPEvent)event
1938 var modifierFlags = [event modifierFlags],
1940 rowIndexes = [
CPIndexSet indexSetWithIndex:[slice rowIndex]];
1942 [
self selectRowIndexes:rowIndexes byExtendingSelection:extend];
1945 - (void)_mouseDownOnSlice:(
id)slice withEvent:(
CPEvent)event
1949 - (void)_rightMouseDownOnSlice:(_CPRuleEditorViewSlice)slice withEvent:(
CPEvent)event
1953 - (void)_performClickOnSlice:(
id)slice withEvent:(
CPEvent)event
1957 - (void)_setSuppressKeyDownHandling:(BOOL)flag
1959 _suppressKeyDownHandling = flag;
1962 - (void)selectAll:(
id)sender
1964 var count = [_slices count];
1968 var slice = _slices[count];
1969 [slice _setSelected:YES];
1970 [slice setNeedsDisplay:YES];
1974 - (void)_deselectAll
1976 var count = [_slices count];
1980 var slice = _slices[count];
1981 [slice _setSelected:NO];
1982 [slice _setLastSelected:NO];
1983 [slice setNeedsDisplay:YES];
1987 - (int)_queryNumberOfChildrenOfItem:(
id)item withRowType:(CPRuleEditorRowType)type
1989 return [_ruleDelegate ruleEditor:self numberOfChildrenForCriterion:item withRowType:type];
1992 - (id)_queryChild:(
int)childIndex ofItem:(
id)item withRowType:(CPRuleEditorRowType)type
1994 return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item withRowType:type];
1997 - (id)_queryValueForItem:(
id)item inRow:(CPInteger)row
1999 return [_ruleDelegate ruleEditor:self displayValueForCriterion:item inRow:row];
2007 - (int)_countOfRowsStartingAtObject:(
id)object
2009 var index = [
self _rowIndexForRowObject:object];
2010 return ([
self numberOfRows] - index);
2013 - (void)_setAlignmentGridWidth:(
float)width
2015 _alignmentGridWidth =
width;
2018 - (BOOL)_validateItem:(
id)item value:(
id)value inRow:(CPInteger)row
2020 return [
self _queryCanSelectItem:item displayValue:value inRow:row];
2023 - (BOOL)_queryCanSelectItem:(
id)item displayValue:(
id)value inRow:(CPInteger)row
2028 - (void)_windowChangedKeyState
2030 [
self setNeedsDisplay:YES];
2033 - (void)setNeedsDisplay:(BOOL)flag
2035 [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:) withObject:flag];
2036 [
super setNeedsDisplay:flag];
2039 - (void)setFrameSize:(CGSize)size
2041 [
self setNeedsDisplay:YES];
2043 if (CGRectGetWidth([
self frame]) !== size.width)
2044 [_slices makeObjectsPerformSelector:
@selector(setNeedsLayout)];
2046 [super setFrameSize:size];
2052 count = [_slices count],
2055 for (i = 0; i < count; i++)
2057 var slice = _slices[i];
2058 if ([slice _isSelected])
2059 [selectedIndices addIndex:[slice rowIndex]];
2062 return selectedIndices;
2065 - (void)mouseDragged:(
CPEvent)event
2070 var point = [
self convertPoint:[event locationInWindow] fromView:nil],
2071 view = [_slices objectAtIndex:FLOOR(point.y / _sliceHeight)];
2073 if ([
self _dragShouldBeginFromMouseDown:view])
2074 [
self _performDragForSlice:view withEvent:event];
2077 - (BOOL)_dragShouldBeginFromMouseDown:(
CPView)view
2079 return (([
self nestingMode] ===
CPRuleEditorNestingModeList || [view rowIndex] !== 0) && _editable && [view isKindOfClass:[_CPRuleEditorViewSliceRow
class]] && _draggingRows === nil);
2082 - (BOOL)_performDragForSlice:(
id)slice withEvent:(
CPEvent)event
2085 mainRowIndex = [slice rowIndex],
2087 selected_indices = [
self _selectedSliceIndices],
2090 [pasteboard declareTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType, nil] owner: self];
2092 if ([selected_indices containsIndex:mainRowIndex])
2093 [draggingRows addIndexes:selected_indices];
2094 _draggingRows = [
self _includeSubslicesForSlicesAtIndexes:draggingRows];
2096 var firstIndex = [_draggingRows firstIndex],
2097 firstSlice = [_slices objectAtIndex:firstIndex],
2098 dragview = [[
CPView alloc] initWithFrame:[firstSlice frame]];
2101 var html = firstSlice._DOMElement.innerHTML;
2102 dragview._DOMElement.innerHTML = [html copy];
2104 [dragview setBackgroundColor:[firstSlice backgroundColor]];
2105 [dragview setAlphaValue:0.7];
2107 dragPoint = CGPointMake(0, firstIndex * _sliceHeight);
2109 [
self dragView:dragview
2111 offset:CGSizeMake(0, _sliceHeight)
2113 pasteboard:pasteboard
2120 - (CPDragOperation)draggingEntered:(
id )sender
2122 if ([sender draggingSource] ===
self)
2124 [
self _clearDropLine];
2131 - (void)draggingExited:(
id)sender
2133 [
self _clearDropLine];
2134 [
self setNeedsDisplay:YES];
2137 - (void)_clearDropLine
2139 [_dropLineView setAlphaValue:0];
2141 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < _lastRow)
2143 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2144 [previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2150 - (CPDragOperation)draggingUpdated:(
id )sender
2152 var point = [
self convertPoint:[sender draggingLocation] fromView:nil],
2153 y = point.y + _sliceHeight / 2,
2154 indexOfDropLine = FLOOR(y / _sliceHeight),
2155 numberOfRows = [self numberOfRows];
2157 if (indexOfDropLine < 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
2159 if (_subviewIndexOfDropLine !==
CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
2160 [
self _clearDropLine];
2164 if (_subviewIndexOfDropLine !== indexOfDropLine)
2166 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < numberOfRows)
2168 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2169 [previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2172 if (indexOfDropLine <= _lastRow && indexOfDropLine < numberOfRows)
2174 var belowSlice = [_slices objectAtIndex:indexOfDropLine];
2175 [belowSlice setFrameOrigin:CGPointMake(0, [belowSlice rowIndex] * _sliceHeight + 2)];
2178 [_dropLineView setAlphaValue:1];
2179 [_dropLineView setFrameOrigin:CGPointMake(CGRectGetMinX([_dropLineView frame]), indexOfDropLine * _sliceHeight)];
2181 _subviewIndexOfDropLine = indexOfDropLine;
2187 - (BOOL)prepareForDragOperation:(
id )sender
2189 return (_subviewIndexOfDropLine !==
CPNotFound);
2192 - (BOOL)performDragOperation:(
id )info
2194 var aboveInsertIndexCount = 0,
2198 var rowObjects = [_rowCache valueForKey:@"rowObject"],
2199 index = [_draggingRows lastIndex];
2201 var parentRowIndex = [
self parentRowForRow:index],
2202 parentRowObject = (parentRowIndex === -1) ? _boundArrayOwner : [[self _rowCacheForIndex:parentRowIndex] rowObject],
2203 insertIndex = _subviewIndexOfDropLine;
2207 if (index >= insertIndex)
2209 removeIndex = index + aboveInsertIndexCount;
2210 aboveInsertIndexCount += 1;
2214 removeIndex = index;
2218 object = [rowObjects objectAtIndex:removeIndex];
2219 [
self removeRowAtIndex:removeIndex];
2220 [[
self _subrowObjectsOfObject:parentRowObject] insertObject:object atIndex:insertIndex - parentRowIndex - 1];
2222 index = [_draggingRows indexLessThanIndex:index];
2225 [
self _clearDropLine];
2226 _draggingRows = nil;
2235 - (void)draggedView:(
CPView)dragView endedAt:(CGPoint)aPoint operation:(CPDragOperation)operation
2237 _draggingRows = nil;
2239 [
self _updatePredicate];
2240 [
self _sendRuleAction];
2241 [
self _postRuleOptionChangedNotification];
2242 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:nil];
2245 - (BOOL)wantsPeriodicDraggingUpdates
2250 - (void)pasteboard:(
CPPasteboard)pasteboard provideDataForType:(
int)type
2254 - (void)_setWindow:(
CPWindow)window
2256 [
super _setWindow:window];
2259 - (void)_windowUpdate:(
id)sender
2261 [
super _windowUpdate:sender];
2264 - (void)_postRuleOptionChangedNotification
2269 - (void)_postRowCountChangedNotificationOfType:(
CPString)notificationName indexes:indexes
2271 var userInfo = indexes === nil ? @{} : @{
"indexes": indexes };
2275 - (
CPIndexSet)_globalIndexesForSubrowIndexes:(
CPIndexSet)indexes ofParentObject:(
id)parentRowObject
2277 var _subrows = [
self _subrowObjectsOfObject:parentRowObject],
2278 parentRowIndex = [
self _rowIndexForRowObject:parentRowObject],
2282 numberOfChildrenOfPreviousBrother = 0;
2286 var globalChildIndex = current_index + parentRowIndex + 1 + numberOfChildrenOfPreviousBrother;
2287 [globalIndexes addIndex:globalChildIndex];
2291 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
2292 subrows = [
self _subrowObjectsOfObject:rowObject],
2295 numberOfChildrenOfPreviousBrother = [subIndexes count];
2301 return globalIndexes;
2304 - (void)_sendRuleAction
2306 var action = [
self action],
2307 target = [
self target];
2309 [
self sendAction:action to:target];
2312 - (BOOL)_sendsActionOnIncompleteTextChange
2317 - (void)_getAllAvailableItems:(
id)items values:(
id)values asChildrenOfItem:(
id)parentItem inRow:(CPInteger)aRow
2326 var criterion = nil,
2330 type = [
self rowTypeForRow:aRow];
2331 numOfChildren = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type];
2333 var criteria = [
self criteriaForRow:aRow];
2334 indexofCriterion = [criteria indexOfObject:criterion];
2336 if (parentItem !== nil
2338 && indexofCriterion < [criteria count] - 1)
2340 var next = indexofCriterion + 1;
2342 criterion = [criteria objectAtIndex:next];
2343 var values = [
self displayValuesForRow:aRow];
2344 value = [values objectAtIndex:next];
2347 for (var i = 0; i < numOfChildren; ++i)
2349 var aChild = [
self _queryChild:i ofItem:parentItem withRowType:type],
2350 availChild = aChild,
2353 if (criterion !== aChild)
2354 availValue = [
self _queryValueForItem:aChild inRow:aRow];
2357 availValue = [
self _queryValueForItem:availChild inRow:aRow];
2359 [availItems addObject:availChild];
2360 [availValues addObject:availValue];
2363 [items addObjectsFromArray:availItems];
2364 [values addObjectsFromArray:availValues];
2369 var CPRuleEditorAlignmentGridWidthKey =
@"CPRuleEditorAlignmentGridWidth",
2370 CPRuleEditorSliceHeightKey =
@"CPRuleEditorSliceHeight",
2371 CPRuleEditorStringsFilenameKey =
@"CPRuleEditorStringsFilename",
2372 CPRuleEditorEditableKey =
@"CPRuleEditorEditable",
2373 CPRuleEditorAllowsEmptyCompoundRowsKey =
@"CPRuleEditorAllowsEmptyCompoundRows",
2374 CPRuleEditorDisallowEmptyKey =
@"CPRuleEditorDisallowEmpty",
2375 CPRuleEditorNestingModeKey =
@"CPRuleEditorNestingMode",
2376 CPRuleEditorRowTypeKeyPathKey =
@"CPRuleEditorRowTypeKeyPath",
2377 CPRuleEditorItemsKeyPathKey =
@"CPRuleEditorItemsKeyPath",
2378 CPRuleEditorValuesKeyPathKey =
@"CPRuleEditorValuesKeyPath",
2379 CPRuleEditorSubrowsArrayKeyPathKey =
@"CPRuleEditorSubrowsArrayKeyPath",
2380 CPRuleEditorBoundArrayKeyPathKey =
@"CPRuleEditorBoundArrayKeyPath",
2381 CPRuleEditorRowClassKey =
@"CPRuleEditorRowClass",
2382 CPRuleEditorSlicesHolderKey =
@"CPRuleEditorSlicesHolder",
2383 CPRuleEditorSlicesKey =
@"CPRuleEditorSlices",
2384 CPRuleEditorDelegateKey =
@"CPRuleEditorDelegate",
2385 CPRuleEditorBoundArrayOwnerKey =
@"CPRuleEditorBoundArrayOwner";
2387 @implementation CPRuleEditor (CPCoding)
2389 - (id)initWithCoder:(
CPCoder)coder
2391 self = [
super initWithCoder:coder];
2394 [
self setFormattingStringsFilename:[coder decodeObjectForKey:CPRuleEditorStringsFilenameKey]];
2395 _alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey];
2396 _sliceHeight = [coder decodeDoubleForKey:CPRuleEditorSliceHeightKey];
2397 _editable = [coder decodeBoolForKey:CPRuleEditorEditableKey];
2398 _allowsEmptyCompoundRows = [coder decodeBoolForKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2399 _disallowEmpty = [coder decodeBoolForKey:CPRuleEditorDisallowEmptyKey];
2400 _nestingMode = [coder decodeIntForKey:CPRuleEditorNestingModeKey];
2401 _typeKeyPath = [coder decodeObjectForKey:CPRuleEditorRowTypeKeyPathKey];
2402 _itemsKeyPath = [coder decodeObjectForKey:CPRuleEditorItemsKeyPathKey];
2403 _valuesKeyPath = [coder decodeObjectForKey:CPRuleEditorValuesKeyPathKey];
2404 _subrowsArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorSubrowsArrayKeyPathKey];
2405 _boundArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorBoundArrayKeyPathKey];
2407 _slicesHolder = [[
self subviews] objectAtIndex:0];
2408 _boundArrayOwner = [coder decodeObjectForKey:CPRuleEditorBoundArrayOwnerKey];
2409 _slices = [coder decodeObjectForKey:CPRuleEditorSlicesKey];
2410 _ruleDelegate = [coder decodeObjectForKey:CPRuleEditorDelegateKey];
2412 [
self _initRuleEditorShared];
2418 - (void)encodeWithCoder:(
CPCoder)coder
2420 [
super encodeWithCoder:coder];
2422 [coder encodeBool:_editable forKey:CPRuleEditorEditableKey];
2423 [coder encodeBool:_allowsEmptyCompoundRows forKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2424 [coder encodeBool:_disallowEmpty forKey:CPRuleEditorDisallowEmptyKey];
2426 [coder encodeFloat:_alignmentGridWidth forKey:CPRuleEditorAlignmentGridWidthKey];
2427 [coder encodeDouble:_sliceHeight forKey:CPRuleEditorSliceHeightKey];
2428 [coder encodeInt:_nestingMode forKey:CPRuleEditorNestingModeKey];
2430 [coder encodeObject:_stringsFilename forKey:CPRuleEditorStringsFilenameKey];
2431 [coder encodeObject:_typeKeyPath forKey:CPRuleEditorRowTypeKeyPathKey];
2432 [coder encodeObject:_itemsKeyPath forKey:CPRuleEditorItemsKeyPathKey];
2433 [coder encodeObject:_valuesKeyPath forKey:CPRuleEditorValuesKeyPathKey];
2434 [coder encodeObject:_boundArrayKeyPath forKey:CPRuleEditorBoundArrayKeyPathKey];
2435 [coder encodeObject:_subrowsArrayKeyPath forKey:CPRuleEditorSubrowsArrayKeyPathKey];
2437 [coder encodeConditionalObject:_slicesHolder forKey:CPRuleEditorSlicesHolderKey];
2438 [coder encodeObject:_slices forKey:CPRuleEditorSlicesKey];
2439 [coder encodeObject:_boundArrayOwner forKey:CPRuleEditorBoundArrayOwnerKey];
2444 var CriteriaKey =
@"criteria",
2445 SubrowsKey =
@"subrows",
2446 DisplayValuesKey =
@"displayValues",
2447 RowTypeKey =
@"rowType";
2449 @implementation _CPRuleEditorRowObject :
CPObject
2453 CPArray displayValues;
2459 var copy = [[_CPRuleEditorRowObject alloc] init];
2460 [copy setSubrows:[[CPArray alloc] initWithArray:subrows copyItems:YES]];
2461 [copy setCriteria:[[CPArray alloc] initWithArray:criteria copyItems:YES]];
2462 [copy setDisplayValues:[[CPArray alloc] initWithArray:displayValues copyItems:YES]];
2463 [copy setRowType:rowType];
2470 return "<" + [self className] + ">\nsubrows = " + [subrows description] + "\ncriteria = " + [criteria description] + "\ndisplayValues = " + [displayValues description];
2473 - (id)initWithCoder:(
CPCoder)coder
2475 self = [
super init];
2478 subrows = [coder decodeObjectForKey:SubrowsKey];
2479 criteria = [coder decodeObjectForKey:CriteriaKey];
2480 displayValues = [coder decodeObjectForKey:DisplayValuesKey];
2481 rowType = [coder decodeIntForKey:RowTypeKey];
2487 - (void)encodeWithCoder:(
CPCoder)coder
2489 [coder encodeObject:subrows forKey:SubrowsKey];
2490 [coder encodeObject:criteria forKey:CriteriaKey];
2491 [coder encodeObject:displayValues forKey:DisplayValuesKey];
2492 [coder encodeInt:rowType forKey:RowTypeKey];
2497 @implementation _CPRuleEditorCache :
CPObject
2501 CPInteger indentation;
2506 return [
CPString stringWithFormat:@"<%d object:%d rowIndex:%d indentation:%d>", [
self hash], [rowObject hash], rowIndex, indentation];
2511 var CPBoundArrayKey =
@"CPBoundArray";
2513 @implementation _CPRuleEditorViewUnboundRowHolder :
CPObject
2520 if (
self = [super init])
2521 boundArray = [[CPArray alloc] init];
2526 - (id)initWithCoder:(
CPCoder)coder
2528 if (
self = [super init])
2529 boundArray = [coder decodeObjectForKey:CPBoundArrayKey];
2534 - (void)encodeWithCoder:(
CPCoder)coder
2536 [coder encodeObject:boundArray forKey:CPBoundArrayKey];
2540 @implementation _CPRuleEditorViewSliceHolder :
CPView
2545 - (void)addSubview:(
CPView)subview
2547 [
self setNeedsDisplay:YES];
2548 [
super addSubview:subview];
2554 @implementation _CPRuleEditorViewSliceDropSeparator :
CPView
2559 - (void)drawRect:(CGRect)rect
2568 @implementation CPObject (CPRuleEditorSliceRow)
2573 isString = [
self isKindOfClass:CPString];
2577 var isView = [
self isKindOfClass:CPView];
2582 var ismenuItem = [
self isKindOfClass:CPMenuItem];
2599 @implementation CPRuleEditor (CPSynthesizedAccessors)
2606 return _boundArrayKeyPath;
2612 - (void)setBoundArrayKeyPath:(
CPString)aValue
2614 _boundArrayKeyPath = aValue;
2620 - (_CPRuleEditorLocalizer)standardLocalizer
2622 return _standardLocalizer;
2628 - (void)setStandardLocalizer:(_CPRuleEditorLocalizer)aValue
2630 _standardLocalizer = aValue;