72 BOOL _suppressKeyDownHandling;
73 BOOL _allowsEmptyCompoundRows;
75 BOOL _delegateWantsValidation;
82 CPInteger _subviewIndexOfDropLine;
100 CPInteger _nestingMode;
102 float _alignmentGridWidth;
112 BOOL _nestingModeDidChange;
114 _CPRuleEditorLocalizer _standardLocalizer;
122 return @"rule-editor";
125 + (id)themeAttributes
128 forKeys:[@"alternating-row-colors", @"selected-color", @"slice-top-border-color", @"slice-bottom-border-color", @"slice-last-bottom-border-color", @"font", @"add-image", @"remove-image"]];
131 - (id)initWithFrame:(CGRect)frame
133 self = [
super initWithFrame:frame];
141 _allowsEmptyCompoundRows = NO;
144 [
self setFormattingStringsFilename:nil];
145 [
self setCriteriaKeyPath:@"criteria"];
146 [
self setSubrowsKeyPath:@"subrows"];
147 [
self setRowTypeKeyPath:@"rowType"];
148 [
self setDisplayValuesKeyPath:@"displayValues"];
149 [
self setBoundArrayKeyPath:@"boundArray"];
151 _slicesHolder = [[_CPRuleEditorViewSliceHolder alloc] initWithFrame:[
self bounds]];
152 [
self addSubview:_slicesHolder];
154 _boundArrayOwner = [[_CPRuleEditorViewUnboundRowHolder alloc] init];
156 [
self _initRuleEditorShared];
162 - (void)_initRuleEditorShared
165 _rowClass = [_CPRuleEditorRowObject class];
169 _delegateWantsValidation = YES;
170 _suppressKeyDownHandling = NO;
171 _nestingModeDidChange = NO;
173 _itemsAndValuesToAddForRowType = {};
175 [
self setAnimation:animation];
177 [_slicesHolder setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
179 _dropLineView = [
self _createSliceDropSeparator];
180 [_slicesHolder addSubview:_dropLineView];
183 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
199 return _ruleDelegate;
208 - (void)setDelegate:(
id)aDelegate
210 if (_ruleDelegate === aDelegate)
215 [nc removeObserver:_ruleDelegate name:nil object:self];
217 _ruleDelegate = aDelegate;
219 if ([_ruleDelegate respondsToSelector:
@selector(ruleEditorRowsDidChange:)])
220 [nc addObserver:_ruleDelegate selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
238 - (void)setEditable:(BOOL)editable
240 if (editable === _editable)
243 _editable = editable;
248 [_slices makeObjectsPerformSelector:@selector(setEditable:) withObject:_editable];
256 - (CPRuleEditorNestingMode)nestingMode
268 - (void)setNestingMode:(CPRuleEditorNestingMode)mode
270 if (mode !== _nestingMode)
273 if ([
self numberOfRows] > 0)
274 _nestingModeDidChange = YES;
283 - (BOOL)canRemoveAllRows
285 return !_disallowEmpty;
293 - (void)setCanRemoveAllRows:(BOOL)canRemove
295 _disallowEmpty = !canRemove;
296 [
self _updateButtonVisibilities];
304 - (BOOL)allowsEmptyCompoundRows
306 return _allowsEmptyCompoundRows;
314 - (void)setAllowsEmptyCompoundRows:(BOOL)allows
316 _allowsEmptyCompoundRows = allows;
317 [
self _updateButtonVisibilities];
325 - (CPInteger)rowHeight
335 - (void)setRowHeight:(
float)height
337 if (height === _sliceHeight)
340 _sliceHeight = MAX([
self _minimumFrameHeight], height);
341 [
self _reconfigureSubviewsAnimate:NO];
356 return [_standardLocalizer dictionary];
368 [_standardLocalizer setDictionary:dictionary];
369 _stringsFilename = nil;
379 return _stringsFilename;
389 - (void)setFormattingStringsFilename:(
CPString)stringsFilename
391 if (_standardLocalizer === nil)
392 _standardLocalizer = [_CPRuleEditorLocalizer new];
394 if (_stringsFilename !== stringsFilename)
397 _stringsFilename = stringsFilename || nil;
399 if (stringsFilename !== nil)
401 if (![stringsFilename hasSuffix:
@".strings"])
402 stringsFilename = stringsFilename +
@".strings";
420 - (void)reloadCriteria
422 var current_rows = [_boundArrayOwner valueForKey:_boundArrayKeyPath];
423 [
self _stopObservingRowObjectsRecursively:current_rows];
435 - (void)setCriteria:(
CPArray)criteria andDisplayValues:(
CPArray)values forRowAtIndex:(
int)rowIndex
437 if (criteria === nil || values === nil)
438 [
CPException raise:CPInvalidArgumentException
reason:_cmd + @". criteria and values parameters must not be nil."];
440 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
443 var rowObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
445 [rowObject setValue:criteria forKey:_itemsKeyPath];
446 [rowObject setValue:values forKey:_valuesKeyPath];
456 - (id)criteriaForRow:(
int)row
458 var rowcache = [
self _rowCacheForIndex:row];
460 return [[rowcache rowObject] valueForKey:_itemsKeyPath];
477 var rowcache = [
self _rowCacheForIndex:row];
479 return [[rowcache rowObject] valueForKey:_valuesKeyPath];
490 return [_slices count];
498 - (int)parentRowForRow:(
int)rowIndex
500 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
503 var targetObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
505 for (var current_index = 0; current_index < rowIndex; current_index++)
509 var candidate = [[
self _rowCacheForIndex:current_index] rowObject],
510 subObjects = [[
self _subrowObjectsOfObject:candidate] _representedObject];
512 if ([subObjects indexOfObjectIdenticalTo:targetObject] !==
CPNotFound)
513 return current_index;
539 - (CPRuleEditorRowType)rowTypeForRow:(
int)rowIndex
541 if (rowIndex < 0 || rowIndex > [
self numberOfRows])
544 var rowcache = [
self _rowCacheForIndex:rowIndex];
547 var rowobject = [rowcache rowObject];
548 return [rowobject valueForKey:_typeKeyPath];
565 object = _boundArrayOwner;
567 object = [[
self _rowCacheForIndex:rowIndex] rowObject];
569 var subobjects = [
self _subrowObjectsOfObject:object],
570 objectsCount = [subobjects count],
574 for (var i = rowIndex + 1; i < count; i++)
576 var candidate = [[
self _rowCacheForIndex:i] rowObject],
577 indexInSubrows = [[subobjects _representedObject] indexOfObjectIdenticalTo:candidate];
581 [indexes addIndex:i];
588 if (objectsCount === 0)
601 return [
self _selectedSliceIndices];
609 - (void)selectRowIndexes:(
CPIndexSet)indexes byExtendingSelection:(BOOL)extend
611 var count = [_slices count],
614 if (lastSelected >= [
self numberOfRows])
622 var slice = _slices[count],
623 rowIndex = [slice rowIndex],
625 shouldSelect = (contains && !(extend && [slice _isSelected]));
628 [slice _setSelected:shouldSelect];
629 [slice _setLastSelected:(rowIndex === lastSelected)];
630 [slice setNeedsDisplay:YES];
643 - (void)addRow:(
id)sender
645 var parentRowIndex = -1,
648 hasRows = (numberOfRows > 0),
649 nestingMode = [
self _applicableNestingMode];
670 [
CPException raise:CPInvalidArgumentException
reason:@"Not supported CPRuleEditorNestingMode " + nestingMode];
686 - (void)insertRowAtIndex:(
int)rowIndex withType:(
unsigned int)rowType asSubrowOfRow:(
int)parentRow animate:(BOOL)shouldAnimate
691 var newObject = [
self _insertNewRowAtIndex:rowIndex ofType:rowType withParentRow:parentRow];
695 var subrow = [
self _insertNewRowAtIndex:(rowIndex + 1) ofType:CPRuleEditorRowTypeSimple withParentRow:rowIndex];
705 - (void)removeRowAtIndex:(
int)rowIndex
709 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
722 - (void)removeRowsAtIndexes:(
CPIndexSet)rowIndexes includeSubrows:(BOOL)includeSubrows
724 if ([rowIndexes count] === 0)
727 if ([rowIndexes lastIndex] >= [
self numberOfRows])
735 if (parentRowIndex === -1)
736 subrows = [
self _rootRowsArray];
739 var parentRowObject = [[
self _rowCacheForIndex:parentRowIndex] rowObject];
740 subrows = [
self _subrowObjectsOfObject:parentRowObject];
745 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
746 relativeChildIndex = [[subrows _representedObject] indexOfObjectIdenticalTo:rowObject];
749 [childsIndexes addIndex:relativeChildIndex];
760 [subrows removeObjectsAtIndexes:childsIndexes];
781 - (void)reloadPredicate
783 [
self _updatePredicate];
796 count = [items count],
800 for (i = 0; i < count; i++)
802 var item = [items objectAtIndex:i],
805 predpart = [_ruleDelegate ruleEditor:self predicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
808 [predicateParts addEntriesFromDictionary:predpart];
813 var compoundPredicate,
817 if ([subrowsIndexes count] === 0)
820 var current_index = [subrowsIndexes firstIndex];
824 if (subpredicate !== nil)
825 [subpredicates addObject:subpredicate];
827 current_index = [subrowsIndexes indexGreaterThanIndex:current_index];
830 var compoundType = [predicateParts objectForKey:CPRuleEditorPredicateCompoundType];
832 if ([subpredicates count] === 0)
842 CPLogConsole(
@"Compound predicate error: [%@]\npredicateType:%i", [error description], compoundType);
843 compoundPredicate = nil;
847 return compoundPredicate;
853 var lhs = [predicateParts objectForKey:CPRuleEditorPredicateLeftExpression],
854 rhs = [predicateParts objectForKey:CPRuleEditorPredicateRightExpression],
855 operator = [predicateParts objectForKey:CPRuleEditorPredicateOperatorType],
856 options = [predicateParts objectForKey:CPRuleEditorPredicateOptions],
857 modifier = [predicateParts objectForKey:CPRuleEditorPredicateComparisonModifier],
862 CPLogConsole(
@"missing left expression in predicate parts dictionary");
868 CPLogConsole(
@"missing right expression in predicate parts dictionary");
872 if (selector === nil &&
operator === nil)
874 CPLogConsole(
@"missing operator and selector in predicate parts dictionary");
878 if (modifier === nil)
879 CPLogConsole(
@"missing modifier in predicate parts dictionary. Setting default: CPDirectPredicateModifier");
882 CPLogConsole(
@"missing options in predicate parts dictionary. Setting default: CPCaseInsensitivePredicateOption");
886 if (selector !== nil)
894 modifier:(modifier || CPDirectPredicateModifier)
896 options:(options || CPCaseInsensitivePredicateOption)
901 CPLogConsole(
@"Row predicate error: [" + [error description] +
"] for row " + aRow);
929 - (void)setRowClass:(Class)rowClass
932 rowClass = [_CPRuleEditorRowObject class];
934 _rowClass = rowClass;
956 if (_typeKeyPath !== keyPath)
957 _typeKeyPath = keyPath;
969 return _subrowsArrayKeyPath;
979 if (_subrowsArrayKeyPath !== keyPath)
980 _subrowsArrayKeyPath = keyPath;
992 return _itemsKeyPath;
1002 if (_itemsKeyPath !== keyPath)
1003 _itemsKeyPath = keyPath;
1015 return _valuesKeyPath;
1025 if (_valuesKeyPath !== keyPath)
1026 _valuesKeyPath = keyPath;
1040 return _currentAnimation;
1051 _currentAnimation = animation;
1052 [_currentAnimation setDelegate:self];
1100 - (BOOL)acceptsFirstResponder
1105 - (void)keyDown:(
CPEvent)event
1109 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeCompound];
1117 if (!_suppressKeyDownHandling)
1119 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeSimple];
1125 - (_CPRuleEditorViewSliceDropSeparator)_createSliceDropSeparator
1127 var view = [[_CPRuleEditorViewSliceDropSeparator alloc] initWithFrame:CGRectMake(0, -10, [
self frame].size.width, 2)];
1128 [view setAutoresizingMask:CPViewWidthSizable];
1132 - (BOOL)_suppressKeyDownHandling
1134 return _suppressKeyDownHandling;
1137 - (BOOL)_wantsRowAnimations
1139 return (_currentAnimation !== nil);
1142 - (void)_updateButtonVisibilities
1144 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1147 - (float)_alignmentGridWidth
1149 return _alignmentGridWidth;
1152 - (float)_minimumFrameHeight
1157 - (CPRuleEditorNestingMode)_applicableNestingMode
1159 if (!_nestingModeDidChange)
1160 return _nestingMode;
1166 return _nestingMode;
1171 - (BOOL)_shouldHideAddButtonForSlice:(
id)slice
1176 - (BOOL)_shouldHideSubtractButtonForSlice:(
id)slice
1181 if (!_disallowEmpty)
1185 rowIndex = [slice rowIndex],
1186 parentIndex = [
self parentRowForRow:rowIndex],
1187 subrowsIndexes = [
self subrowIndexesForRow:parentIndex],
1188 nestingMode = [
self _applicableNestingMode];
1190 switch (nestingMode)
1199 default: shouldHide = NO;
1205 #pragma mark Rows management
1207 - (id)_rowCacheForIndex:(
int)index
1209 return [_rowCache objectAtIndex:index];
1212 - (id)_searchCacheForRowObject:(
id)rowObject
1214 var count = [_rowCache count],
1217 for (i = 0; i < count; i++)
1219 var cache = _rowCache[i];
1220 if ([cache rowObject] === rowObject)
1227 - (int)_rowIndexForRowObject:(
id)rowobject
1229 if (rowobject === _boundArrayOwner)
1232 return [[
self _searchCacheForRowObject:rowobject] rowIndex];
1237 if (
object === _boundArrayOwner)
1238 return [
self _rootRowsArray];
1240 return [object mutableArrayValueForKey:_subrowsArrayKeyPath];
1243 - (
CPIndexSet)_childlessParentsIfSlicesWereDeletedAtIndexes:(
id)indexes
1246 current_index = [indexes firstIndex];
1250 var parentIndex = [
self parentRowForRow:current_index],
1251 subrowsIndexes = [
self subrowIndexesForRow:parentIndex];
1253 if ([subrowsIndexes count] === 1)
1255 if (parentIndex !== -1)
1259 [childlessParents addIndexes:childlessGranPa];
1262 current_index = [indexes indexGreaterThanIndex:current_index];
1265 return childlessParents;
1271 var subindexes = [indexes
copy],
1276 var sub = [
self subrowIndexesForRow:current_index];
1277 [subindexes addIndexes:[
self _includeSubslicesForSlicesAtIndexes:sub]];
1284 - (void)_deleteSlice:(
id)slice
1288 if (!_allowsEmptyCompoundRows)
1290 var childlessIndexes = [
self _childlessParentsIfSlicesWereDeletedAtIndexes:rowindexes];
1291 if ([childlessIndexes count] > 0)
1292 rowindexes = childlessIndexes;
1295 [
self removeRowsAtIndexes:rowindexes includeSubrows:YES];
1297 [
self _updatePredicate];
1298 [
self _sendRuleAction];
1299 [
self _postRuleOptionChangedNotification];
1300 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:rowindexes];
1305 return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath];
1308 - (BOOL)_nextUnusedItems:(
CPArray)items andValues:(
CPArray)values forRow:(
int)rowIndex forRowType:(
unsigned int)type
1311 childrenCount = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
1314 if (childrenCount === 0)
1318 count = [
self numberOfRows],
1321 for (row = 0; row < count; row++)
1323 var aCriteria = [
self criteriaForRow:row],
1324 itemIndex = [items
count];
1326 if ([
self rowTypeForRow:row] === type && itemIndex < [aCriteria count])
1328 var crit = [aCriteria objectAtIndex:itemIndex];
1329 [current_criterions addObject:crit];
1337 for (i = 0; i < childrenCount; i++)
1339 var child = [
self _queryChild:i ofItem:parentItem withRowType:type];
1340 if ([current_criterions indexOfObject:child] ===
CPNotFound)
1349 for (var k = 0; k < childrenCount; k++)
1351 var anobject = [
self _queryChild:k ofItem:parentItem withRowType:type],
1352 index = [buffer indexOfObject:anobject];
1354 [buffer removeObjectAtIndex:index];
1357 current_criterions = buffer;
1361 var foundItem = [
self _queryChild:foundIndex ofItem:parentItem withRowType:type],
1362 foundValue = [
self _queryValueForItem:foundItem inRow:rowIndex];
1364 [items addObject:foundItem];
1365 [values addObject:foundValue];
1370 - (
CPMutableArray)_getItemsAndValuesToAddForRow:(
int)rowIndex ofType:(CPRuleEditorRowType)type
1382 unusedItems = [
self _nextUnusedItems:items andValues:values forRow:rowIndex forRowType:type];
1384 var count = [items
count];
1386 for (var i = 0; i < count; 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:(
int)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];
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++)
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++)
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],
1496 newRows = changeNewValue;
1497 oldRows = changeOldValue;
1502 newRows = [
self _subrowObjectsOfObject:object];
1504 [oldRows removeObjectsInArray:changeNewValue];
1508 newRows = [
self _subrowObjectsOfObject:object];
1510 var delIndexes = [change
objectForKey:CPKeyValueChangeIndexesKey];
1511 [oldRows insertObjects:delObjects atIndexes:changeOldValue];
1514 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:object];
1515 [
self _reconfigureSubviewsAnimate:[
self _wantsRowAnimations]];
1525 - (void)_changedItem:(
id)fromItem toItem:(
id)toItem inRow:(
int)aRow atCriteriaIndex:(
int)fromItemIndex
1527 var criteria = [
self criteriaForRow:aRow],
1528 displayValues = [
self displayValuesForRow:aRow],
1529 rowType = [
self rowTypeForRow:aRow],
1532 items = [criteria subarrayWithRange:CPMakeRange(0, fromItemIndex)],
1533 values = [displayValues subarrayWithRange:CPMakeRange(0, fromItemIndex)];
1539 [items addObject:anItem];
1540 var value = [
self _queryValueForItem:anItem inRow:aRow];
1541 [values addObject:value];
1543 if (![
self _queryNumberOfChildrenOfItem:anItem withRowType:rowType])
1546 anItem = [
self _queryChild:0 ofItem:anItem withRowType:rowType];
1549 var
object = [[
self _rowCacheForIndex:aRow] rowObject];
1550 [object setValue:items forKey:_itemsKeyPath];
1551 [object setValue:values forKey:_valuesKeyPath];
1553 var slice = [_slices objectAtIndex:aRow];
1554 [slice _reconfigureSubviews];
1556 [
self _updatePredicate];
1557 [
self _sendRuleAction];
1558 [
self _postRuleOptionChangedNotification];
1561 - (void)_changedRowArray:(
CPArray)newRows withOldRowArray:(
CPArray)oldRows forParent:(
id)parentRowObject
1563 var newRowCount = [newRows
count],
1564 oldRowCount = [oldRows
count],
1565 deltaCount = newRowCount - oldRowCount,
1566 minusCount = MIN(newRowCount, oldRowCount),
1567 maxCount = MAX(newRowCount, oldRowCount),
1572 parentCacheIndentation,
1573 parentCacheIndex = [self _rowIndexForRowObject:parentRowObject],
1575 newRowCacheIndex = 0,
1576 changeStartIndex = 0;
1578 [
self _stopObservingRowObjectsRecursively:oldRows];
1579 [
self _startObservingRowObjectsRecursively:newRows];
1583 if (parentCacheIndex === -1)
1584 parentCacheIndentation = -1;
1586 parentCacheIndentation = [[
self _rowCacheForIndex:parentCacheIndex] indentation];
1588 for (; newRowCacheIndex < newRowCount; newRowCacheIndex++)
1590 var newCacheGlobalIndex = (parentCacheIndex + 1) + newRowCacheIndex,
1591 obj = [newRows objectAtIndex:newRowCacheIndex],
1592 newRowType = [obj valueForKey:_typeKeyPath],
1593 cache = [[_CPRuleEditorCache alloc] init];
1595 [cache setRowObject:obj];
1596 [cache setRowIndex:newCacheGlobalIndex];
1597 [cache setIndentation:parentCacheIndentation + 1];
1599 [insertCacheIndexes addIndex:newCacheGlobalIndex];
1600 [newCaches addObject:cache];
1604 [_rowCache removeObjectsInRange:CPMakeRange(parentCacheIndex + 1, [oldRows
count])];
1605 [_rowCache insertObjects:newCaches atIndexes:insertCacheIndexes];
1607 for (; changeStartIndex < minusCount; changeStartIndex++)
1612 if (newrow !== oldrow)
1616 var replaceCount = (deltaCount === 0) ? maxCount : maxCount - minusCount,
1617 startIndex = parentCacheIndex + changeStartIndex + 1;
1619 if (deltaCount <= 0)
1622 removeSlices = [_slices objectsAtIndexes:removeIndexes];
1624 [removeSlices makeObjectsPerformSelector:@selector(removeFromSuperview)];
1625 [_slices removeObjectsAtIndexes:removeIndexes];
1628 if (deltaCount >= 0)
1630 var newIndentation = parentCacheIndentation + 1,
1631 newIndex = startIndex;
1633 for (; newIndex < startIndex + replaceCount; newIndex++)
1635 var newslice = [
self _newSlice],
1636 rowType = [
self rowTypeForRow:newIndex];
1638 [newslice setRowIndex:newIndex];
1639 [newslice setIndentation:newIndentation];
1640 [newslice _setRowType:rowType];
1641 [newslice _configurePlusButtonByRowType:CPRuleEditorRowTypeSimple];
1643 [_slices insertObject:newslice atIndex:newIndex];
1648 count = [oldRows
count],
1650 for (n = 0; n < count; n++)
1653 subOldRows = [
self _subrowObjectsOfObject:oldRow];
1655 if ([subOldRows count] > 0)
1656 [
self _changedRowArray:emptyArray withOldRowArray:subOldRows forParent:oldRow];
1659 count = [newRows
count];
1660 for (n = 0; n < count; n++)
1663 subnewRows = [
self _subrowObjectsOfObject:newRow];
1665 if ([subnewRows count] > 0)
1666 [
self _changedRowArray:subnewRows withOldRowArray:emptyArray forParent:newRow];
1672 if ([aBinding isEqualToString:
@"rows"])
1674 [
self unbind:aBinding];
1675 [
self _setBoundDataSource:observableController withKeyPath:aKeyPath options:options];
1677 [_rowCache removeAllObjects];
1678 [_slices removeAllObjects];
1681 oldRows = [
self _rootRowsArray];
1683 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:_boundArrayOwner];
1686 [
super bind:aBinding toObject:observableController withKeyPath:aKeyPath options:options];
1689 - (void)unbind:(
id)object
1691 _rowClass = [_CPRuleEditorRowObject class];
1692 [
super unbind:object];
1695 - (void)_setBoundDataSource:(
id)datasource withKeyPath:(
CPString)keyPath options:(
CPDictionary)options
1697 if ([observableController respondsToSelector:
@selector(objectClass)])
1698 _rowClass = [observableController objectClass];
1700 _boundArrayKeyPath = keyPath;
1701 _boundArrayOwner = datasource;
1705 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
1713 if (_predicate !== predicate)
1714 _predicate = predicate;
1717 - (void)_updatePredicate
1719 if (_delegateWantsValidation)
1721 var selector =
@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
1722 if (![_ruleDelegate respondsToSelector:selector])
1725 _delegateWantsValidation = NO;
1729 subindexes = [
self subrowIndexesForRow:-1],
1730 current_index = [subindexes firstIndex];
1734 var subpredicate = [
self predicateForRow:current_index];
1736 if (subpredicate !== nil)
1737 [subpredicates addObject:subpredicate];
1739 current_index = [subindexes indexGreaterThanIndex:current_index];
1744 [
self _setPredicate:new_predicate];
1747 - (_CPRuleEditorViewSliceRow)_newSlice
1749 var sliceRect = CGRectMake(0, 0, CGRectGetWidth([
self frame]), 0),
1750 slice = [
self _createNewSliceWithFrame:sliceRect ruleEditorView:self];
1755 - (_CPRuleEditorViewSliceRow)_createNewSliceWithFrame:(CGRect)frame ruleEditorView:(
CPRuleEditor)editor
1757 return [[_CPRuleEditorViewSliceRow alloc] initWithFrame:frame ruleEditorView:editor];
1760 - (void)_reconfigureSubviewsAnimate:(BOOL)animate
1764 count = [_slices count];
1766 [
self _updateSliceRows];
1768 if ([[
self superview] isKindOfClass:[
CPClipView class]])
1769 [
self setFrameSize:CGSizeMake(CGRectGetWidth([
self frame]), count * _sliceHeight)];
1771 for (var i = 0; i < count; i++)
1773 var aslice = [_slices objectAtIndex:i],
1774 targetRect = [aslice _animationTargetRect],
1775 startRect = [aslice frame],
1776 startIndex = [aslice rowIndex] - 1;
1778 if ([aslice superview] === nil)
1780 startRect = CGRectMake(0, startIndex * _sliceHeight, CGRectGetWidth(startRect), _sliceHeight);
1781 [aslice _reconfigureSubviews];
1782 [added_slices addObject:aslice];
1788 [animation setObject:aslice forKey:CPViewAnimationTargetKey];
1789 [animation setObject:startRect forKey:CPViewAnimationStartFrameKey];
1790 [animation setObject:targetRect forKey:CPViewAnimationEndFrameKey];
1792 [viewAnimations insertObject:animation atIndex:0];
1795 [aslice setFrame:targetRect];
1798 var addcount = [added_slices count];
1799 for (var i = 0; i < addcount; i++)
1800 [_slicesHolder addSubview:added_slices[i] positioned:CPWindowBelow relativeTo:nil];
1804 [_currentAnimation setViewAnimations:viewAnimations];
1805 [_currentAnimation startAnimation];
1808 _lastRow = [
self numberOfRows] - 1;
1810 if (_lastRow === -1)
1811 _nestingModeDidChange = NO;
1813 [
self setNeedsDisplay:YES];
1814 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1825 - (void)_updateSliceRows
1827 var
width = [
self frame].size.width,
1828 count = [_slices count];
1830 for (var i = 0; i < count; i++)
1832 var slice = [_slices objectAtIndex:i],
1833 targetRect = CGRectMake(0, i * _sliceHeight, width, _sliceHeight);
1835 [slice setRowIndex:i];
1836 [slice _setAnimationTargetRect:targetRect];
1842 return [
self valueForThemeAttribute:@"alternating-row-colors"];
1847 return [
self valueForThemeAttribute:@"selected-color"];
1850 - (
CPColor)_sliceTopBorderColor
1852 return [
self valueForThemeAttribute:@"slice-top-border-color"];
1855 - (
CPColor)_sliceBottomBorderColor
1857 return [
self valueForThemeAttribute:@"slice-bottom-border-color"];
1860 - (
CPColor)_sliceLastBottomBorderColor
1862 return [
self valueForThemeAttribute:@"slice-last-bottom-border-color"];
1867 return [
self valueForThemeAttribute:@"font"];
1872 return [
self valueForThemeAttribute:@"add-image"];
1877 return [
self valueForThemeAttribute:@"remove-image"];
1880 - (
CPString)_toolTipForAddCompoundRowButton
1882 return @"Add Compound row";
1885 - (
CPString)_toolTipForAddSimpleRowButton
1890 - (
CPString)_toolTipForDeleteRowButton
1892 return @"Delete row";
1895 - (void)_updateSliceIndentations
1897 [
self _updateSliceIndentationAtIndex:0 toIndentation:0 withIndexSet:[
self subrowIndexesForRow:0]];
1900 - (void)_updateSliceIndentationAtIndex:(
int)index toIndentation:(
int)indentation withIndexSet:(
id)indexes
1902 var current_index = [indexes firstIndex];
1906 var subindexes = [
self subrowIndexesForRow:index];
1907 [
self _updateSliceIndentationAtIndex:current_index toIndentation:indentation + 1 withIndexSet:subindexes];
1908 current_index = [indexes indexGreaterThanIndex:current_index];
1911 [[_slices objectAtIndex:index] setIndentation:indentation];
1917 count = [_slices count],
1920 for (i = 0; i < count; i++)
1922 var slice = _slices[i];
1923 if ([slice _isSelected])
1924 [_selectedSlices addObject:slice];
1927 return _selectedSlices;
1930 - (int)_lastSelectedSliceIndex
1933 count = [_slices count],
1936 for (i = 0; i < count; i++)
1938 var slice = _slices[i];
1939 if ([slice _isLastSelected])
1940 return [slice rowIndex];
1946 - (void)_mouseUpOnSlice:(
id)slice withEvent:(
CPEvent)event
1953 rowIndexes = [
CPIndexSet indexSetWithIndex:[slice rowIndex]];
1955 [
self selectRowIndexes:rowIndexes byExtendingSelection:extend];
1958 - (void)_mouseDownOnSlice:(
id)slice withEvent:(
CPEvent)event
1962 - (void)_rightMouseDownOnSlice:(_CPRuleEditorViewSlice)slice withEvent:(
CPEvent)event
1966 - (void)_performClickOnSlice:(
id)slice withEvent:(
CPEvent)event
1970 - (void)_setSuppressKeyDownHandling:(BOOL)flag
1972 _suppressKeyDownHandling = flag;
1975 - (void)selectAll:(
id)sender
1977 var count = [_slices count];
1981 var slice = _slices[count];
1982 [slice _setSelected:YES];
1983 [slice setNeedsDisplay:YES];
1987 - (void)_deselectAll
1989 var count = [_slices count];
1993 var slice = _slices[count];
1994 [slice _setSelected:NO];
1995 [slice _setLastSelected:NO];
1996 [slice setNeedsDisplay:YES];
2000 - (int)_queryNumberOfChildrenOfItem:(
id)item withRowType:(CPRuleEditorRowType)type
2002 return [_ruleDelegate ruleEditor:self numberOfChildrenForCriterion:item withRowType:type];
2005 - (id)_queryChild:(
int)childIndex ofItem:(
id)item withRowType:(CPRuleEditorRowType)type
2007 return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item withRowType:type];
2010 - (id)_queryValueForItem:(
id)item inRow:(
int)row
2012 return [_ruleDelegate ruleEditor:self displayValueForCriterion:item inRow:row];
2020 - (int)_countOfRowsStartingAtObject:(
id)object
2022 var index = [
self _rowIndexForRowObject:object];
2023 return ([
self numberOfRows] - index);
2026 - (void)_setAlignmentGridWidth:(
float)width
2028 _alignmentGridWidth =
width;
2031 - (BOOL)_validateItem:(
id)item value:(
id)value inRow:(
int)row
2033 return [
self _queryCanSelectItem:item displayValue:value inRow:row];
2036 - (BOOL)_queryCanSelectItem:(
id)item displayValue:(
id)value inRow:(
int)row
2041 - (void)_windowChangedKeyState
2043 [
self setNeedsDisplay:YES];
2046 - (void)setNeedsDisplay:(BOOL)flag
2048 [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:) withObject:flag];
2049 [
super setNeedsDisplay:flag];
2052 - (void)setFrameSize:(CPSize)size
2054 [
self setNeedsDisplay:YES];
2056 if (CGRectGetWidth([
self frame]) !== size.width)
2057 [_slices makeObjectsPerformSelector:
@selector(setNeedsLayout)];
2059 [super setFrameSize:size];
2065 count = [_slices count],
2068 for (i = 0; i < count; i++)
2070 var slice = _slices[i];
2071 if ([slice _isSelected])
2072 [selectedIndices addIndex:[slice rowIndex]];
2075 return selectedIndices;
2078 - (void)mouseDragged:(
CPEvent)event
2084 view = [_slices objectAtIndex:FLOOR(point.y / _sliceHeight)];
2086 if ([
self _dragShouldBeginFromMouseDown:view])
2087 [
self _performDragForSlice:view withEvent:event];
2090 - (BOOL)_dragShouldBeginFromMouseDown:(
CPView)view
2092 return (([
self nestingMode] ===
CPRuleEditorNestingModeList || [view rowIndex] !== 0) && _editable && [view isKindOfClass:[_CPRuleEditorViewSliceRow
class]] && _draggingRows === nil);
2095 - (BOOL)_performDragForSlice:(
id)slice withEvent:(
CPEvent)event
2098 mainRowIndex = [slice rowIndex],
2100 selected_indices = [
self _selectedSliceIndices],
2105 if ([selected_indices containsIndex:mainRowIndex])
2106 [draggingRows addIndexes:selected_indices];
2107 _draggingRows = [
self _includeSubslicesForSlicesAtIndexes:draggingRows];
2109 var firstIndex = [_draggingRows firstIndex],
2110 firstSlice = [_slices objectAtIndex:firstIndex],
2111 dragview = [[
CPView alloc] initWithFrame:[firstSlice frame]];
2114 var html = firstSlice._DOMElement.innerHTML;
2115 dragview._DOMElement.innerHTML = [html copy];
2117 [dragview setBackgroundColor:[firstSlice backgroundColor]];
2118 [dragview setAlphaValue:0.7];
2120 dragPoint =
CPMakePoint(0, firstIndex * _sliceHeight);
2122 [
self dragView:dragview
2124 offset:CGSizeMake(0, _sliceHeight)
2126 pasteboard:pasteboard
2135 if ([sender draggingSource] ===
self)
2137 [
self _clearDropLine];
2144 - (void)draggingExited:(
id)sender
2146 [
self _clearDropLine];
2147 [
self setNeedsDisplay:YES];
2150 - (void)_clearDropLine
2152 [_dropLineView setAlphaValue:0];
2154 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < _lastRow)
2156 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2157 [previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2166 y = point.y + _sliceHeight / 2,
2167 indexOfDropLine = FLOOR(y / _sliceHeight),
2168 numberOfRows = [self numberOfRows];
2170 if (indexOfDropLine < 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
2172 if (_subviewIndexOfDropLine !==
CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
2173 [
self _clearDropLine];
2177 if (_subviewIndexOfDropLine !== indexOfDropLine)
2179 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < numberOfRows)
2181 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2182 [previousBelowSlice setFrameOrigin:CPMakePoint(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2185 if (indexOfDropLine <= _lastRow && indexOfDropLine < numberOfRows)
2187 var belowSlice = [_slices objectAtIndex:indexOfDropLine];
2188 [belowSlice setFrameOrigin:CGPointMake(0, [belowSlice rowIndex] * _sliceHeight + 2)];
2191 [_dropLineView setAlphaValue:1];
2192 [_dropLineView setFrameOrigin:CGPointMake(CGRectGetMinX([_dropLineView frame]), indexOfDropLine * _sliceHeight)];
2194 _subviewIndexOfDropLine = indexOfDropLine;
2202 return (_subviewIndexOfDropLine !==
CPNotFound);
2207 var aboveInsertIndexCount = 0,
2211 var rowObjects = [_rowCache valueForKey:@"rowObject"],
2212 index = [_draggingRows lastIndex];
2214 var parentRowIndex = [
self parentRowForRow:index],
2215 parentRowObject = (parentRowIndex === -1) ? _boundArrayOwner : [[self _rowCacheForIndex:parentRowIndex] rowObject],
2216 insertIndex = _subviewIndexOfDropLine;
2220 if (index >= insertIndex)
2222 removeIndex = index + aboveInsertIndexCount;
2223 aboveInsertIndexCount += 1;
2227 removeIndex = index;
2231 object = [rowObjects objectAtIndex:removeIndex];
2232 [
self removeRowAtIndex:removeIndex];
2233 [[
self _subrowObjectsOfObject:parentRowObject] insertObject:object atIndex:insertIndex - parentRowIndex - 1];
2235 index = [_draggingRows indexLessThanIndex:index];
2238 [
self _clearDropLine];
2239 _draggingRows = nil;
2248 - (void)draggedView:(
CPView)dragView endedAt:(CPPoint)aPoint operation:(CPDragOperation)operation
2250 _draggingRows = nil;
2252 [
self _updatePredicate];
2253 [
self _sendRuleAction];
2254 [
self _postRuleOptionChangedNotification];
2255 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:nil];
2258 - (BOOL)wantsPeriodicDraggingUpdates
2263 - (void)pasteboard:(
CPPasteboard)pasteboard provideDataForType:(
int)type
2267 - (void)_setWindow:(
id)window
2269 [
super _setWindow:window];
2272 - (void)_windowUpdate:(
id)sender
2274 [
super _windowUpdate:sender];
2277 - (void)_postRuleOptionChangedNotification
2282 - (void)_postRowCountChangedNotificationOfType:(
CPString)notificationName indexes:indexes
2288 - (
CPIndexSet)_globalIndexesForSubrowIndexes:(
CPIndexSet)indexes ofParentObject:(
id)parentRowObject
2290 var _subrows = [
self _subrowObjectsOfObject:parentRowObject],
2291 parentRowIndex = [
self _rowIndexForRowObject:parentRowObject],
2295 numberOfChildrenOfPreviousBrother = 0;
2299 var globalChildIndex = current_index + parentRowIndex + 1 + numberOfChildrenOfPreviousBrother;
2300 [globalIndexes addIndex:globalChildIndex];
2304 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
2305 subrows = [
self _subrowObjectsOfObject:rowObject],
2308 numberOfChildrenOfPreviousBrother = [subIndexes count];
2314 return globalIndexes;
2317 - (void)_sendRuleAction
2319 var action = [
self action],
2320 target = [
self target];
2322 [
self sendAction:action to:target];
2325 - (BOOL)_sendsActionOnIncompleteTextChange
2330 - (void)_getAllAvailableItems:(
id)items values:(
id)values asChildrenOfItem:(
id)parentItem inRow:(
int)aRow
2339 var criterion = nil,
2343 type = [
self rowTypeForRow:aRow];
2344 numOfChildren = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type];
2346 var criteria = [
self criteriaForRow:aRow];
2347 indexofCriterion = [criteria indexOfObject:criterion];
2349 if (parentItem !== nil
2351 && indexofCriterion < [criteria count] - 1)
2353 var next = indexofCriterion + 1;
2355 criterion = [criteria objectAtIndex:next];
2356 var values = [
self displayValuesForRow:aRow];
2357 value = [values objectAtIndex:next];
2360 for (var i = 0; i < numOfChildren; ++i)
2362 var aChild = [
self _queryChild:i ofItem:parentItem withRowType:type],
2363 availChild = aChild,
2366 if (criterion !== aChild)
2367 availValue = [
self _queryValueForItem:aChild inRow:aRow];
2370 availValue = [
self _queryValueForItem:availChild inRow:aRow];
2372 [availItems addObject:availChild];
2373 [availValues addObject:availValue];
2376 [items addObjectsFromArray:availItems];
2377 [values addObjectsFromArray:availValues];
2382 var CPRuleEditorAlignmentGridWidthKey =
@"CPRuleEditorAlignmentGridWidth",
2383 CPRuleEditorSliceHeightKey =
@"CPRuleEditorSliceHeight",
2384 CPRuleEditorStringsFilenameKey =
@"CPRuleEditorStringsFilename",
2385 CPRuleEditorEditableKey =
@"CPRuleEditorEditable",
2386 CPRuleEditorAllowsEmptyCompoundRowsKey =
@"CPRuleEditorAllowsEmptyCompoundRows",
2387 CPRuleEditorDisallowEmptyKey =
@"CPRuleEditorDisallowEmpty",
2388 CPRuleEditorNestingModeKey =
@"CPRuleEditorNestingMode",
2389 CPRuleEditorRowTypeKeyPathKey =
@"CPRuleEditorRowTypeKeyPath",
2390 CPRuleEditorItemsKeyPathKey =
@"CPRuleEditorItemsKeyPath",
2391 CPRuleEditorValuesKeyPathKey =
@"CPRuleEditorValuesKeyPath",
2392 CPRuleEditorSubrowsArrayKeyPathKey =
@"CPRuleEditorSubrowsArrayKeyPath",
2393 CPRuleEditorBoundArrayKeyPathKey =
@"CPRuleEditorBoundArrayKeyPath",
2394 CPRuleEditorRowClassKey =
@"CPRuleEditorRowClass",
2395 CPRuleEditorSlicesHolderKey =
@"CPRuleEditorSlicesHolder",
2396 CPRuleEditorSlicesKey =
@"CPRuleEditorSlices",
2397 CPRuleEditorDelegateKey =
@"CPRuleEditorDelegate",
2398 CPRuleEditorBoundArrayOwnerKey =
@"CPRuleEditorBoundArrayOwner";
2400 @implementation CPRuleEditor (CPCoding)
2402 - (id)initWithCoder:(
CPCoder)coder
2404 self = [
super initWithCoder:coder];
2407 [
self setFormattingStringsFilename:[coder decodeObjectForKey:CPRuleEditorStringsFilenameKey]];
2408 _alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey];
2409 _sliceHeight = [coder decodeDoubleForKey:CPRuleEditorSliceHeightKey];
2410 _editable = [coder decodeBoolForKey:CPRuleEditorEditableKey];
2411 _allowsEmptyCompoundRows = [coder decodeBoolForKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2412 _disallowEmpty = [coder decodeBoolForKey:CPRuleEditorDisallowEmptyKey];
2413 _nestingMode = [coder decodeIntForKey:CPRuleEditorNestingModeKey];
2414 _typeKeyPath = [coder decodeObjectForKey:CPRuleEditorRowTypeKeyPathKey];
2415 _itemsKeyPath = [coder decodeObjectForKey:CPRuleEditorItemsKeyPathKey];
2416 _valuesKeyPath = [coder decodeObjectForKey:CPRuleEditorValuesKeyPathKey];
2417 _subrowsArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorSubrowsArrayKeyPathKey];
2418 _boundArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorBoundArrayKeyPathKey];
2420 _slicesHolder = [[
self subviews] objectAtIndex:0];
2421 _boundArrayOwner = [coder decodeObjectForKey:CPRuleEditorBoundArrayOwnerKey];
2422 _slices = [coder decodeObjectForKey:CPRuleEditorSlicesKey];
2423 _ruleDelegate = [coder decodeObjectForKey:CPRuleEditorDelegateKey];
2425 [
self _initRuleEditorShared];
2431 - (void)encodeWithCoder:(
id)coder
2433 [
super encodeWithCoder:coder];
2435 [coder encodeBool:_editable forKey:CPRuleEditorEditableKey];
2436 [coder encodeBool:_allowsEmptyCompoundRows forKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2437 [coder encodeBool:_disallowEmpty forKey:CPRuleEditorDisallowEmptyKey];
2439 [coder encodeFloat:_alignmentGridWidth forKey:CPRuleEditorAlignmentGridWidthKey];
2440 [coder encodeDouble:_sliceHeight forKey:CPRuleEditorSliceHeightKey];
2441 [coder encodeInt:_nestingMode forKey:CPRuleEditorNestingModeKey];
2443 [coder encodeObject:_stringsFilename forKey:CPRuleEditorStringsFilenameKey];
2444 [coder encodeObject:_typeKeyPath forKey:CPRuleEditorRowTypeKeyPathKey];
2445 [coder encodeObject:_itemsKeyPath forKey:CPRuleEditorItemsKeyPathKey];
2446 [coder encodeObject:_valuesKeyPath forKey:CPRuleEditorValuesKeyPathKey];
2447 [coder encodeObject:_boundArrayKeyPath forKey:CPRuleEditorBoundArrayKeyPathKey];
2448 [coder encodeObject:_subrowsArrayKeyPath forKey:CPRuleEditorSubrowsArrayKeyPathKey];
2450 [coder encodeConditionalObject:_slicesHolder forKey:CPRuleEditorSlicesHolderKey];
2451 [coder encodeObject:_slices forKey:CPRuleEditorSlicesKey];
2452 [coder encodeObject:_boundArrayOwner forKey:CPRuleEditorBoundArrayOwnerKey];
2457 var CriteriaKey =
@"criteria",
2458 SubrowsKey =
@"subrows",
2459 DisplayValuesKey =
@"displayValues",
2460 RowTypeKey =
@"rowType";
2462 @implementation _CPRuleEditorRowObject :
CPObject
2472 var copy = [[_CPRuleEditorRowObject alloc] init];
2476 [copy setRowType:rowType];
2483 return "<" + [self className] + ">\nsubrows = " + [subrows description] + "\ncriteria = " + [criteria description] + "\ndisplayValues = " + [displayValues description];
2486 - (id)initWithCoder:(
id)coder
2488 self = [
super init];
2491 subrows = [coder decodeObjectForKey:SubrowsKey];
2492 criteria = [coder decodeObjectForKey:CriteriaKey];
2493 displayValues = [coder decodeObjectForKey:DisplayValuesKey];
2494 rowType = [coder decodeIntForKey:RowTypeKey];
2500 - (void)encodeWithCoder:(
id)coder
2502 [coder encodeObject:subrows forKey:SubrowsKey];
2503 [coder encodeObject:criteria forKey:CriteriaKey];
2504 [coder encodeObject:displayValues forKey:DisplayValuesKey];
2505 [coder encodeInt:rowType forKey:RowTypeKey];
2510 @implementation _CPRuleEditorCache :
CPObject
2514 CPInteger indentation;
2519 return [
CPString stringWithFormat:@"<%d object:%d rowIndex:%d indentation:%d>", [
self hash], [rowObject hash], rowIndex, indentation];
2524 var CPBoundArrayKey =
@"CPBoundArray";
2526 @implementation _CPRuleEditorViewUnboundRowHolder :
CPObject
2533 if (
self = [super init])
2534 boundArray = [[
CPArray alloc] init];
2539 - (id)initWithCoder:(
id)coder
2541 if (
self = [super init])
2542 boundArray = [coder decodeObjectForKey:CPBoundArrayKey];
2547 - (void)encodeWithCoder:(
id)coder
2549 [coder encodeObject:boundArray forKey:CPBoundArrayKey];
2553 @implementation _CPRuleEditorViewSliceHolder :
CPView
2558 - (void)addSubview:(
CPView)subview
2560 [
self setNeedsDisplay:YES];
2561 [
super addSubview:subview];
2567 @implementation _CPRuleEditorViewSliceDropSeparator :
CPView
2572 - (void)drawRect:(CPRect)rect
2581 @implementation CPObject (CPRuleEditorSliceRow)
2586 isString = [
self isKindOfClass:CPString];
2590 var isView = [
self isKindOfClass:CPView];
2595 var ismenuItem = [
self isKindOfClass:CPMenuItem];
2612 @implementation CPRuleEditor (CPSynthesizedAccessors)
2619 return _boundArrayKeyPath;
2625 - (void)setBoundArrayKeyPath:(
CPString)aValue
2627 _boundArrayKeyPath = aValue;
2633 - (_CPRuleEditorLocalizer)standardLocalizer
2635 return _standardLocalizer;
2641 - (void)setStandardLocalizer:(_CPRuleEditorLocalizer)aValue
2643 _standardLocalizer = aValue;