34 - (id)ruleEditor:(
CPRuleEditor)editor child:(CPInteger)index forCriterion:(
id)criterion withRowType:(CPRuleEditorRowType)rowType;
35 - (id)ruleEditor:(
CPRuleEditor)editor displayValueForCriterion:(
id)criterion inRow:(CPInteger)row;
36 - (CPInteger)ruleEditor:(
CPRuleEditor)editor numberOfChildrenForCriterion:(
id)criterion withRowType:(CPRuleEditorRowType)rowType;
39 - (
CPDictionary)ruleEditor:(
CPRuleEditor)editor predicatePartsForCriterion:(
id)criterion withDisplayValue:(
id)value inRow:(CPInteger)row;
73 BOOL _suppressKeyDownHandling;
74 BOOL _allowsEmptyCompoundRows;
76 BOOL _delegateWantsValidation;
83 CPInteger _subviewIndexOfDropLine;
89 CPPredicate _predicate;
101 CPInteger _nestingMode;
103 float _alignmentGridWidth;
107 id <CPRuleEditorDelegate> _ruleDelegate;
109 unsigned _implementedDelegateMethods;
114 BOOL _nestingModeDidChange;
116 _CPRuleEditorLocalizer _standardLocalizer;
124 return @"rule-editor";
134 @"slice-last-bottom-border-color": [
CPNull null],
143 - (id)initWithFrame:(CGRect)frame
145 self = [
super initWithFrame:frame];
153 _allowsEmptyCompoundRows = NO;
156 [
self setFormattingStringsFilename:nil];
157 [
self setCriteriaKeyPath:@"criteria"];
158 [
self setSubrowsKeyPath:@"subrows"];
159 [
self setRowTypeKeyPath:@"rowType"];
160 [
self setDisplayValuesKeyPath:@"displayValues"];
161 [
self setBoundArrayKeyPath:@"boundArray"];
163 _slicesHolder = [[_CPRuleEditorViewSliceHolder alloc] initWithFrame:[
self bounds]];
164 [
self addSubview:_slicesHolder];
166 _boundArrayOwner = [[_CPRuleEditorViewUnboundRowHolder alloc] init];
168 [
self _initRuleEditorShared];
174 - (void)_initRuleEditorShared
177 _rowClass = [_CPRuleEditorRowObject class];
181 _delegateWantsValidation = YES;
182 _suppressKeyDownHandling = NO;
183 _nestingModeDidChange = NO;
185 _itemsAndValuesToAddForRowType = {};
187 [
self setAnimation:animation];
189 [_slicesHolder setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
191 _dropLineView = [
self _createSliceDropSeparator];
192 [_slicesHolder addSubview:_dropLineView];
194 [
self registerForDraggedTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType,nil]];
195 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
211 return _ruleDelegate;
220 - (void)setDelegate:(
id <CPRuleEditorDelegate>)aDelegate
222 if (_ruleDelegate === aDelegate)
228 [nc removeObserver:_ruleDelegate name:nil object:self];
230 _ruleDelegate = aDelegate;
231 _implementedDelegateMethods = 0;
233 if ([_ruleDelegate respondsToSelector:
@selector(ruleEditorRowsDidChange:)])
234 [nc addObserver:_ruleDelegate selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
236 if ([_ruleDelegate respondsToSelector:
@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:)])
255 - (void)setEditable:(BOOL)editable
257 if (editable === _editable)
260 _editable = editable;
265 [_slices makeObjectsPerformSelector:@selector(setEditable:) withObject:_editable];
273 - (CPRuleEditorNestingMode)nestingMode
285 - (void)setNestingMode:(CPRuleEditorNestingMode)mode
287 if (mode !== _nestingMode)
290 if ([
self numberOfRows] > 0)
291 _nestingModeDidChange = YES;
300 - (BOOL)canRemoveAllRows
302 return !_disallowEmpty;
310 - (void)setCanRemoveAllRows:(BOOL)canRemove
312 _disallowEmpty = !canRemove;
313 [
self _updateButtonVisibilities];
321 - (BOOL)allowsEmptyCompoundRows
323 return _allowsEmptyCompoundRows;
331 - (void)setAllowsEmptyCompoundRows:(BOOL)allows
333 _allowsEmptyCompoundRows = allows;
334 [
self _updateButtonVisibilities];
342 - (CPInteger)rowHeight
352 - (void)setRowHeight:(
float)height
354 if (height === _sliceHeight)
357 _sliceHeight = MAX([
self _minimumFrameHeight], height);
358 [
self _reconfigureSubviewsAnimate:NO];
373 return [_standardLocalizer dictionary];
385 [_standardLocalizer setDictionary:dictionary];
386 _stringsFilename = nil;
396 return _stringsFilename;
406 - (void)setFormattingStringsFilename:(
CPString)stringsFilename
408 if (_standardLocalizer === nil)
409 _standardLocalizer = [_CPRuleEditorLocalizer new];
411 if (_stringsFilename !== stringsFilename)
414 _stringsFilename = stringsFilename || nil;
416 if (stringsFilename !== nil)
418 if (![stringsFilename hasSuffix:
@".strings"])
419 stringsFilename = stringsFilename +
@".strings";
437 - (void)reloadCriteria
439 var current_rows = [_boundArrayOwner valueForKey:_boundArrayKeyPath];
440 [
self _stopObservingRowObjectsRecursively:current_rows];
441 [_boundArrayOwner setValue:[CPArray arrayWithArray:current_rows] forKey:_boundArrayKeyPath];
452 - (void)setCriteria:(CPArray)criteria andDisplayValues:(CPArray)values forRowAtIndex:(
int)rowIndex
454 if (criteria === nil || values === nil)
455 [
CPException raise:CPInvalidArgumentException
reason:_cmd + @". criteria and values parameters must not be nil."];
457 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
460 var rowObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
462 [rowObject setValue:criteria forKey:_itemsKeyPath];
463 [rowObject setValue:values forKey:_valuesKeyPath];
473 - (id)criteriaForRow:(CPInteger)row
475 var rowcache = [
self _rowCacheForIndex:row];
477 return [[rowcache rowObject] valueForKey:_itemsKeyPath];
494 var rowcache = [
self _rowCacheForIndex:row];
496 return [[rowcache rowObject] valueForKey:_valuesKeyPath];
507 return [_slices count];
515 - (int)parentRowForRow:(CPInteger)rowIndex
517 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
520 var targetObject = [[
self _rowCacheForIndex:rowIndex] rowObject];
522 for (var current_index = 0; current_index < rowIndex; current_index++)
526 var candidate = [[
self _rowCacheForIndex:current_index] rowObject],
527 subObjects = [[
self _subrowObjectsOfObject:candidate] _representedObject];
529 if ([subObjects indexOfObjectIdenticalTo:targetObject] !==
CPNotFound)
530 return current_index;
556 - (CPRuleEditorRowType)rowTypeForRow:(CPInteger)rowIndex
558 if (rowIndex < 0 || rowIndex > [
self numberOfRows])
561 var rowcache = [
self _rowCacheForIndex:rowIndex];
564 var rowobject = [rowcache rowObject];
565 return [rowobject valueForKey:_typeKeyPath];
582 object = _boundArrayOwner;
584 object = [[
self _rowCacheForIndex:rowIndex] rowObject];
586 var subobjects = [
self _subrowObjectsOfObject:object],
587 objectsCount = [subobjects count],
591 for (var i = rowIndex + 1; i < count; i++)
593 var candidate = [[
self _rowCacheForIndex:i] rowObject],
594 indexInSubrows = [[subobjects _representedObject] indexOfObjectIdenticalTo:candidate];
598 [indexes addIndex:i];
605 if (objectsCount === 0)
618 return [
self _selectedSliceIndices];
626 - (void)selectRowIndexes:(
CPIndexSet)indexes byExtendingSelection:(BOOL)extend
628 var count = [_slices count],
631 if (lastSelected >= [
self numberOfRows])
639 var slice = _slices[count],
640 rowIndex = [slice rowIndex],
642 shouldSelect = (contains && !(extend && [slice _isSelected]));
645 [slice _setSelected:shouldSelect];
646 [slice _setLastSelected:(rowIndex === lastSelected)];
647 [slice setNeedsDisplay:YES];
660 - (void)addRow:(
id)sender
662 var parentRowIndex = -1,
665 hasRows = (numberOfRows > 0),
666 nestingMode = [
self _applicableNestingMode];
687 [
CPException raise:CPInvalidArgumentException
reason:@"Not supported CPRuleEditorNestingMode " + nestingMode];
703 - (void)insertRowAtIndex:(
int)rowIndex withType:(
unsigned int)rowType asSubrowOfRow:(CPInteger)parentRow animate:(BOOL)shouldAnimate
708 var newObject = [
self _insertNewRowAtIndex:rowIndex ofType:rowType withParentRow:parentRow];
712 var subrow = [
self _insertNewRowAtIndex:(rowIndex + 1) ofType:CPRuleEditorRowTypeSimple withParentRow:rowIndex];
722 - (void)removeRowAtIndex:(
int)rowIndex
726 if (rowIndex < 0 || rowIndex >= [
self numberOfRows])
739 - (void)removeRowsAtIndexes:(
CPIndexSet)rowIndexes includeSubrows:(BOOL)includeSubrows
741 if ([rowIndexes count] === 0)
744 if ([rowIndexes lastIndex] >= [
self numberOfRows])
752 if (parentRowIndex === -1)
753 subrows = [
self _rootRowsArray];
756 var parentRowObject = [[
self _rowCacheForIndex:parentRowIndex] rowObject];
757 subrows = [
self _subrowObjectsOfObject:parentRowObject];
762 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
763 relativeChildIndex = [[subrows _representedObject] indexOfObjectIdenticalTo:rowObject];
766 [childsIndexes addIndex:relativeChildIndex];
777 [subrows removeObjectsAtIndexes:childsIndexes];
789 - (CPPredicate)predicate
798 - (void)reloadPredicate
800 [
self _updatePredicate];
809 - (CPPredicate)predicateForRow:(CPInteger)aRow
811 var predicateParts = @{},
813 count = [items count],
817 for (i = 0; i < count; i++)
819 var item = [items objectAtIndex:i],
822 predpart = [
self _sendDelegateRuleEditorPredicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
825 [predicateParts addEntriesFromDictionary:predpart];
830 var compoundPredicate,
834 if ([subrowsIndexes count] === 0)
837 var current_index = [subrowsIndexes firstIndex];
841 if (subpredicate !== nil)
842 [subpredicates addObject:subpredicate];
844 current_index = [subrowsIndexes indexGreaterThanIndex:current_index];
847 var compoundType = [predicateParts objectForKey:CPRuleEditorPredicateCompoundType];
849 if ([subpredicates count] === 0)
855 compoundPredicate = [[
CPCompoundPredicate alloc ] initWithType:compoundType subpredicates:subpredicates];
859 CPLogConsole(
@"Compound predicate error: [%@]\npredicateType:%i", [error
description], compoundType);
860 compoundPredicate = nil;
864 return compoundPredicate;
870 var lhs = [predicateParts objectForKey:CPRuleEditorPredicateLeftExpression],
871 rhs = [predicateParts objectForKey:CPRuleEditorPredicateRightExpression],
872 operator = [predicateParts objectForKey:CPRuleEditorPredicateOperatorType],
873 options = [predicateParts objectForKey:CPRuleEditorPredicateOptions],
874 modifier = [predicateParts objectForKey:CPRuleEditorPredicateComparisonModifier],
879 CPLogConsole(
@"missing left expression in predicate parts dictionary");
885 CPLogConsole(
@"missing right expression in predicate parts dictionary");
889 if (selector === nil &&
operator === nil)
891 CPLogConsole(
@"missing operator and selector in predicate parts dictionary");
895 if (modifier === nil)
896 CPLogConsole(
@"missing modifier in predicate parts dictionary. Setting default: CPDirectPredicateModifier");
899 CPLogConsole(
@"missing options in predicate parts dictionary. Setting default: CPCaseInsensitivePredicateOption");
903 if (selector !== nil)
911 modifier:(modifier || CPDirectPredicateModifier)
913 options:(options || CPCaseInsensitivePredicateOption)
918 CPLogConsole(
@"Row predicate error: [" + [error
description] +
"] for row " + aRow);
946 - (void)setRowClass:(Class)rowClass
949 rowClass = [_CPRuleEditorRowObject class];
951 _rowClass = rowClass;
973 if (_typeKeyPath !== keyPath)
974 _typeKeyPath = keyPath;
986 return _subrowsArrayKeyPath;
996 if (_subrowsArrayKeyPath !== keyPath)
997 _subrowsArrayKeyPath = keyPath;
1009 return _itemsKeyPath;
1019 if (_itemsKeyPath !== keyPath)
1020 _itemsKeyPath = keyPath;
1032 return _valuesKeyPath;
1042 if (_valuesKeyPath !== keyPath)
1043 _valuesKeyPath = keyPath;
1057 return _currentAnimation;
1068 _currentAnimation = animation;
1069 [_currentAnimation setDelegate:self];
1117 - (BOOL)acceptsFirstResponder
1122 - (void)keyDown:(
CPEvent)event
1126 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeCompound];
1134 if (!_suppressKeyDownHandling)
1136 [_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeSimple];
1142 - (_CPRuleEditorViewSliceDropSeparator)_createSliceDropSeparator
1144 var view = [[_CPRuleEditorViewSliceDropSeparator alloc] initWithFrame:CGRectMake(0, -10, [
self frame].size.width, 2)];
1145 [view setAutoresizingMask:CPViewWidthSizable];
1149 - (BOOL)_suppressKeyDownHandling
1151 return _suppressKeyDownHandling;
1154 - (BOOL)_wantsRowAnimations
1156 return (_currentAnimation !== nil);
1159 - (void)_updateButtonVisibilities
1161 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1164 - (float)_alignmentGridWidth
1166 return _alignmentGridWidth;
1169 - (float)_minimumFrameHeight
1174 - (CPRuleEditorNestingMode)_applicableNestingMode
1176 if (!_nestingModeDidChange)
1177 return _nestingMode;
1183 return _nestingMode;
1188 - (BOOL)_shouldHideAddButtonForSlice:(
id)slice
1193 - (BOOL)_shouldHideSubtractButtonForSlice:(
id)slice
1198 if (!_disallowEmpty)
1202 rowIndex = [slice rowIndex],
1203 parentIndex = [
self parentRowForRow:rowIndex],
1204 subrowsIndexes = [
self subrowIndexesForRow:parentIndex],
1205 nestingMode = [
self _applicableNestingMode];
1207 switch (nestingMode)
1216 default: shouldHide = NO;
1222 #pragma mark Rows management 1224 - (id)_rowCacheForIndex:(
int)index
1226 return [_rowCache objectAtIndex:index];
1229 - (id)_searchCacheForRowObject:(
id)rowObject
1231 var count = [_rowCache count],
1234 for (i = 0; i < count; i++)
1236 var cache = _rowCache[i];
1237 if ([cache rowObject] === rowObject)
1244 - (int)_rowIndexForRowObject:(
id)rowobject
1246 if (rowobject === _boundArrayOwner)
1249 return [[
self _searchCacheForRowObject:rowobject] rowIndex];
1254 if (
object === _boundArrayOwner)
1255 return [
self _rootRowsArray];
1257 return [object mutableArrayValueForKey:_subrowsArrayKeyPath];
1260 - (
CPIndexSet)_childlessParentsIfSlicesWereDeletedAtIndexes:(
id)indexes
1263 current_index = [indexes firstIndex];
1267 var parentIndex = [
self parentRowForRow:current_index],
1268 subrowsIndexes = [
self subrowIndexesForRow:parentIndex];
1270 if ([subrowsIndexes count] === 1)
1272 if (parentIndex !== -1)
1276 [childlessParents addIndexes:childlessGranPa];
1279 current_index = [indexes indexGreaterThanIndex:current_index];
1282 return childlessParents;
1288 var subindexes = [indexes
copy],
1293 var sub = [
self subrowIndexesForRow:current_index];
1294 [subindexes addIndexes:[
self _includeSubslicesForSlicesAtIndexes:sub]];
1301 - (void)_deleteSlice:(
id)slice
1305 if (!_allowsEmptyCompoundRows)
1307 var childlessIndexes = [
self _childlessParentsIfSlicesWereDeletedAtIndexes:rowindexes];
1308 if ([childlessIndexes count] > 0)
1309 rowindexes = childlessIndexes;
1312 [
self removeRowsAtIndexes:rowindexes includeSubrows:YES];
1314 [
self _updatePredicate];
1315 [
self _sendRuleAction];
1316 [
self _postRuleOptionChangedNotification];
1317 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:rowindexes];
1320 - (CPArray)_rootRowsArray
1322 return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath];
1325 - (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(CPInteger)rowIndex forRowType:(
unsigned int)type
1327 var parentItem = [items lastObject],
1328 childrenCount = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
1331 if (childrenCount === 0)
1335 count = [
self numberOfRows],
1338 for (row = 0; row < count; row++)
1340 var aCriteria = [
self criteriaForRow:row],
1341 itemIndex = [items count];
1343 if ([
self rowTypeForRow:row] === type && itemIndex < [aCriteria count])
1345 var crit = [aCriteria objectAtIndex:itemIndex];
1346 [current_criterions addObject:crit];
1354 for (i = 0; i < childrenCount; i++)
1356 var child = [
self _queryChild:i ofItem:parentItem withRowType:type];
1357 if ([current_criterions indexOfObject:child] ===
CPNotFound)
1366 for (var k = 0; k < childrenCount; k++)
1368 var anobject = [
self _queryChild:k ofItem:parentItem withRowType:type],
1369 index = [buffer indexOfObject:anobject];
1371 [buffer removeObjectAtIndex:index];
1374 current_criterions = buffer;
1378 var foundItem = [
self _queryChild:foundIndex ofItem:parentItem withRowType:type],
1379 foundValue = [
self _queryValueForItem:foundItem inRow:rowIndex];
1381 [items addObject:foundItem];
1382 [values addObject:foundValue];
1387 - (
CPMutableArray)_getItemsAndValuesToAddForRow:(CPInteger)rowIndex ofType:(CPRuleEditorRowType)type
1399 unusedItems = [
self _nextUnusedItems:items andValues:values forRow:rowIndex forRowType:type];
1401 var count = [items count];
1403 for (var i = 0; i < count; i++)
1405 var item = [items objectAtIndex:i],
1406 value = [values objectAtIndex:i],
1412 [itemsAndValues addObject:itemAndValue];
1415 return itemsAndValues;
1418 - (void)_addOptionFromSlice:(
id)slice ofRowType:(
unsigned int)type
1422 var rowIndexEvent = [slice rowIndex],
1423 rowTypeEvent = [
self rowTypeForRow:rowIndexEvent],
1424 insertIndex = rowIndexEvent + 1,
1427 [
self insertRowAtIndex:insertIndex withType:type asSubrowOfRow:parentRowIndex animate:YES];
1430 - (id)_insertNewRowAtIndex:(
int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(CPInteger)parentRowIndex
1432 var row = [[[
self rowClass] alloc] init],
1433 itemsandvalues = [
self _getItemsAndValuesToAddForRow:insertIndex ofType:rowtype],
1434 newitems = [itemsandvalues valueForKey:@"item"],
1435 newvalues = [itemsandvalues valueForKey:@"value"];
1437 [row setValue:newitems forKey:_itemsKeyPath];
1438 [row setValue:newvalues forKey:_valuesKeyPath];
1439 [row setValue:rowtype forKey:_typeKeyPath];
1440 [row setValue:[
CPMutableArray array] forKey:_subrowsArrayKeyPath];
1444 subrowsObjects = [
self _rootRowsArray];
1447 var parentRowObject = [[
self _rowCacheForIndex:parentRowIndex] rowObject];
1448 subrowsObjects = [
self _subrowObjectsOfObject:parentRowObject];
1451 var relInsertIndex = insertIndex - parentRowIndex - 1;
1452 [subrowsObjects insertObject:row atIndex:relInsertIndex];
1454 [
self _updatePredicate];
1455 [
self _sendRuleAction];
1456 [
self _postRuleOptionChangedNotification];
1457 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:[
CPIndexSet indexSetWithIndex:insertIndex]];
1462 #pragma mark Key value observing 1464 - (void)_startObservingRowObjectsRecursively:(CPArray)rowObjects
1466 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
1468 var count = [rowObjects count];
1470 for (var i = 0; i < count; i++)
1472 var rowObject = [rowObjects objectAtIndex:i];
1474 [rowObject addObserver:self forKeyPath:_itemsKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:itemsContext];
1475 [rowObject addObserver:self forKeyPath:_valuesKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:valuesContext];
1476 [rowObject addObserver:self forKeyPath:_subrowsArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:subrowsContext];
1478 var subrows = [
self _subrowObjectsOfObject:rowObject];
1479 if ([subrows count] > 0)
1480 [
self _startObservingRowObjectsRecursively:subrows];
1485 - (void)_stopObservingRowObjectsRecursively:(CPArray)rowObjects
1487 [_boundArrayOwner removeObserver:self forKeyPath:_boundArrayKeyPath];
1489 var count = [rowObjects count];
1491 for (var i = 0; i < count; i++)
1493 var rowObject = [rowObjects objectAtIndex:i];
1494 [rowObject removeObserver:self forKeyPath:_itemsKeyPath];
1495 [rowObject removeObserver:self forKeyPath:_valuesKeyPath];
1496 [rowObject removeObserver:self forKeyPath:_subrowsArrayKeyPath];
1498 var subrows = [rowObject valueForKey:_subrowsArrayKeyPath];
1499 if ([subrows count] > 0)
1500 [
self _stopObservingRowObjectsRecursively:subrows];
1504 - (void)observeValueForKeyPath:(
CPString)keypath ofObject:(
id)object change:(
CPDictionary)change context:(
void)context
1506 var changeKind = [change
objectForKey:CPKeyValueChangeKindKey],
1507 changeNewValue = [change
objectForKey:CPKeyValueChangeNewKey],
1508 changeOldValue = [change
objectForKey:CPKeyValueChangeOldKey],
1516 newRows = changeNewValue;
1517 oldRows = changeOldValue;
1522 newRows = [
self _subrowObjectsOfObject:object];
1523 oldRows = [CPArray arrayWithArray:newRows];
1524 [oldRows removeObjectsInArray:changeNewValue];
1527 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:object];
1528 [
self _reconfigureSubviewsAnimate:[
self _wantsRowAnimations]];
1532 - (void)_changedItem:(
id)fromItem toItem:(
id)toItem inRow:(CPInteger)aRow atCriteriaIndex:(
int)fromItemIndex
1534 var criteria = [
self criteriaForRow:aRow],
1535 displayValues = [
self displayValuesForRow:aRow],
1536 rowType = [
self rowTypeForRow:aRow],
1539 items = [criteria subarrayWithRange:CPMakeRange(0, fromItemIndex)],
1540 values = [displayValues subarrayWithRange:CPMakeRange(0, fromItemIndex)];
1546 [items addObject:anItem];
1547 var value = [
self _queryValueForItem:anItem inRow:aRow];
1548 [values addObject:value];
1550 if (![
self _queryNumberOfChildrenOfItem:anItem withRowType:rowType])
1553 anItem = [
self _queryChild:0 ofItem:anItem withRowType:rowType];
1556 var
object = [[
self _rowCacheForIndex:aRow] rowObject];
1557 [object setValue:items forKey:_itemsKeyPath];
1558 [object setValue:values forKey:_valuesKeyPath];
1560 var slice = [_slices objectAtIndex:aRow];
1561 [slice _reconfigureSubviews];
1563 [
self _updatePredicate];
1564 [
self _sendRuleAction];
1565 [
self _postRuleOptionChangedNotification];
1568 - (void)_changedRowArray:(CPArray)newRows withOldRowArray:(CPArray)oldRows forParent:(
id)parentRowObject
1570 var newRowCount = [newRows count],
1571 oldRowCount = [oldRows count],
1572 deltaCount = newRowCount - oldRowCount,
1573 minusCount = MIN(newRowCount, oldRowCount),
1574 maxCount = MAX(newRowCount, oldRowCount),
1577 newCaches = [CPArray array],
1579 parentCacheIndentation,
1580 parentCacheIndex = [self _rowIndexForRowObject:parentRowObject],
1582 newRowCacheIndex = 0,
1583 changeStartIndex = 0;
1585 [
self _stopObservingRowObjectsRecursively:oldRows];
1586 [
self _startObservingRowObjectsRecursively:newRows];
1590 if (parentCacheIndex === -1)
1591 parentCacheIndentation = -1;
1593 parentCacheIndentation = [[
self _rowCacheForIndex:parentCacheIndex] indentation];
1595 for (; newRowCacheIndex < newRowCount; newRowCacheIndex++)
1597 var newCacheGlobalIndex = (parentCacheIndex + 1) + newRowCacheIndex,
1598 obj = [newRows objectAtIndex:newRowCacheIndex],
1599 newRowType = [obj valueForKey:_typeKeyPath],
1600 cache = [[_CPRuleEditorCache alloc] init];
1602 [cache setRowObject:obj];
1603 [cache setRowIndex:newCacheGlobalIndex];
1604 [cache setIndentation:parentCacheIndentation + 1];
1606 [insertCacheIndexes addIndex:newCacheGlobalIndex];
1607 [newCaches addObject:cache];
1611 [_rowCache removeObjectsInRange:CPMakeRange(parentCacheIndex + 1, [oldRows count])];
1612 [_rowCache insertObjects:newCaches atIndexes:insertCacheIndexes];
1614 for (; changeStartIndex < minusCount; changeStartIndex++)
1616 var oldrow = [oldRows objectAtIndex:changeStartIndex],
1617 newrow = [newRows objectAtIndex:changeStartIndex];
1619 if (newrow !== oldrow)
1623 var replaceCount = (deltaCount === 0) ? maxCount : maxCount - minusCount,
1624 startIndex = parentCacheIndex + changeStartIndex + 1;
1626 if (deltaCount <= 0)
1629 removeSlices = [_slices objectsAtIndexes:removeIndexes];
1631 [removeSlices makeObjectsPerformSelector:@selector(removeFromSuperview)];
1632 [_slices removeObjectsAtIndexes:removeIndexes];
1635 if (deltaCount >= 0)
1637 var newIndentation = parentCacheIndentation + 1,
1638 newIndex = startIndex;
1640 for (; newIndex < startIndex + replaceCount; newIndex++)
1642 var newslice = [
self _newSlice],
1643 rowType = [
self rowTypeForRow:newIndex];
1645 [newslice setRowIndex:newIndex];
1646 [newslice setIndentation:newIndentation];
1647 [newslice _setRowType:rowType];
1648 [newslice _configurePlusButtonByRowType:CPRuleEditorRowTypeSimple];
1650 [_slices insertObject:newslice atIndex:newIndex];
1654 var emptyArray = [CPArray array],
1655 count = [oldRows count],
1657 for (n = 0; n < count; n++)
1659 var oldRow = [oldRows objectAtIndex:n],
1660 subOldRows = [
self _subrowObjectsOfObject:oldRow];
1662 if ([subOldRows count] > 0)
1663 [
self _changedRowArray:emptyArray withOldRowArray:subOldRows forParent:oldRow];
1666 count = [newRows count];
1667 for (n = 0; n < count; n++)
1669 var newRow = [newRows objectAtIndex:n],
1670 subnewRows = [
self _subrowObjectsOfObject:newRow];
1672 if ([subnewRows count] > 0)
1673 [
self _changedRowArray:subnewRows withOldRowArray:emptyArray forParent:newRow];
1679 if ([aBinding isEqualToString:
@"rows"])
1681 [
self unbind:aBinding];
1682 [
self _setBoundDataSource:observableController withKeyPath:aKeyPath options:options];
1684 [_rowCache removeAllObjects];
1685 [_slices removeAllObjects];
1687 var newRows = [CPArray array],
1688 oldRows = [
self _rootRowsArray];
1690 [
self _changedRowArray:newRows withOldRowArray:oldRows forParent:_boundArrayOwner];
1693 [
super bind:aBinding toObject:observableController withKeyPath:aKeyPath options:options];
1698 _rowClass = [_CPRuleEditorRowObject class];
1699 [
super unbind:object];
1702 - (void)_setBoundDataSource:(
id)datasource withKeyPath:(
CPString)keyPath options:(
CPDictionary)options
1704 if ([datasource respondsToSelector:
@selector(objectClass)])
1705 _rowClass = [datasource objectClass];
1707 _boundArrayKeyPath = keyPath;
1708 _boundArrayOwner = datasource;
1712 [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
1718 - (void)_setPredicate:(CPPredicate)predicate
1720 if (_predicate !== predicate)
1721 _predicate = predicate;
1724 - (void)_updatePredicate
1726 if (_delegateWantsValidation)
1728 if (![
self _delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow])
1731 _delegateWantsValidation = NO;
1735 subindexes = [
self subrowIndexesForRow:-1],
1736 current_index = [subindexes firstIndex];
1740 var subpredicate = [
self predicateForRow:current_index];
1742 if (subpredicate !== nil)
1743 [subpredicates addObject:subpredicate];
1745 current_index = [subindexes indexGreaterThanIndex:current_index];
1748 var new_predicate = [[
CPCompoundPredicate alloc] initWithType:CPOrPredicateType subpredicates:subpredicates];
1750 [
self _setPredicate:new_predicate];
1753 - (_CPRuleEditorViewSliceRow)_newSlice
1755 var sliceRect = CGRectMake(0, 0, CGRectGetWidth([
self frame]), 0),
1756 slice = [
self _createNewSliceWithFrame:sliceRect ruleEditorView:self];
1761 - (_CPRuleEditorViewSliceRow)_createNewSliceWithFrame:(CGRect)frame ruleEditorView:(
CPRuleEditor)editor
1763 return [[_CPRuleEditorViewSliceRow alloc] initWithFrame:frame ruleEditorView:editor];
1766 - (void)_reconfigureSubviewsAnimate:(BOOL)animate
1770 count = [_slices count];
1772 [
self _updateSliceRows];
1774 if ([[
self superview] isKindOfClass:[
CPClipView class]])
1775 [
self setFrameSize:CGSizeMake(CGRectGetWidth([
self frame]), count * _sliceHeight)];
1777 for (var i = 0; i < count; i++)
1779 var aslice = [_slices objectAtIndex:i],
1780 targetRect = [aslice _animationTargetRect],
1781 startRect = [aslice frame],
1782 startIndex = [aslice rowIndex] - 1;
1784 if ([aslice superview] === nil)
1786 startRect = CGRectMake(0, startIndex * _sliceHeight, CGRectGetWidth(startRect), _sliceHeight);
1787 [aslice _reconfigureSubviews];
1788 [added_slices addObject:aslice];
1793 var animation = @{};
1794 [animation setObject:aslice forKey:CPViewAnimationTargetKey];
1795 [animation setObject:startRect forKey:CPViewAnimationStartFrameKey];
1796 [animation setObject:targetRect forKey:CPViewAnimationEndFrameKey];
1798 [viewAnimations insertObject:animation atIndex:0];
1801 [aslice setFrame:targetRect];
1804 var addcount = [added_slices count];
1805 for (var i = 0; i < addcount; i++)
1806 [_slicesHolder addSubview:added_slices[i] positioned:CPWindowBelow relativeTo:nil];
1810 [_currentAnimation setViewAnimations:viewAnimations];
1811 [_currentAnimation startAnimation];
1814 _lastRow = [
self numberOfRows] - 1;
1816 if (_lastRow === -1)
1817 _nestingModeDidChange = NO;
1819 [
self setNeedsDisplay:YES];
1820 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1831 - (void)_updateSliceRows
1833 var
width = [
self frame].size.width,
1834 count = [_slices count];
1836 for (var i = 0; i < count; i++)
1838 var slice = [_slices objectAtIndex:i],
1839 targetRect = CGRectMake(0, i * _sliceHeight,
width, _sliceHeight);
1841 [slice setRowIndex:i];
1842 [slice _setAnimationTargetRect:targetRect];
1846 - (CPArray)_backgroundColors
1848 return [
self valueForThemeAttribute:@"alternating-row-colors"];
1853 return [
self valueForThemeAttribute:@"selected-color"];
1856 - (
CPColor)_sliceTopBorderColor
1858 return [
self valueForThemeAttribute:@"slice-top-border-color"];
1861 - (
CPColor)_sliceBottomBorderColor
1863 return [
self valueForThemeAttribute:@"slice-bottom-border-color"];
1866 - (
CPColor)_sliceLastBottomBorderColor
1868 return [
self valueForThemeAttribute:@"slice-last-bottom-border-color"];
1873 return [
self valueForThemeAttribute:@"font"];
1878 return [
self valueForThemeAttribute:@"font-color"];
1883 return [
self valueForThemeAttribute:@"add-image" inState:CPThemeStateNormal];
1886 - (
CPImage)_imageAddHighlighted
1888 return [
self valueForThemeAttribute:@"add-image" inState:CPThemeStateHighlighted];
1893 return [
self valueForThemeAttribute:@"remove-image" inState:CPThemeStateNormal];
1896 - (
CPImage)_imageRemoveHighlighted
1898 return [
self valueForThemeAttribute:@"remove-image" inState:CPThemeStateHighlighted];
1901 - (CPVerticalTextAlignment)_verticalAlignment
1903 return [
self valueForThemeAttribute:@"vertical-alignment"];
1906 - (
CPString)_toolTipForAddCompoundRowButton
1908 return [_standardLocalizer localizedStringForString:@"Add compound row"];
1911 - (
CPString)_toolTipForAddSimpleRowButton
1913 return [_standardLocalizer localizedStringForString:@"Add row"];
1916 - (
CPString)_toolTipForDeleteRowButton
1918 return [_standardLocalizer localizedStringForString:@"Delete row"];
1921 - (void)_updateSliceIndentations
1923 [
self _updateSliceIndentationAtIndex:0 toIndentation:0 withIndexSet:[
self subrowIndexesForRow:0]];
1926 - (void)_updateSliceIndentationAtIndex:(
int)index toIndentation:(
int)indentation withIndexSet:(
id)indexes
1928 var current_index = [indexes firstIndex];
1932 var subindexes = [
self subrowIndexesForRow:index];
1933 [
self _updateSliceIndentationAtIndex:current_index toIndentation:indentation + 1 withIndexSet:subindexes];
1934 current_index = [indexes indexGreaterThanIndex:current_index];
1937 [[_slices objectAtIndex:index] setIndentation:indentation];
1940 - (CPArray)_selectedSlices
1943 count = [_slices count],
1946 for (i = 0; i < count; i++)
1948 var slice = _slices[i];
1949 if ([slice _isSelected])
1950 [_selectedSlices addObject:slice];
1953 return _selectedSlices;
1956 - (int)_lastSelectedSliceIndex
1959 count = [_slices count],
1962 for (i = 0; i < count; i++)
1964 var slice = _slices[i];
1965 if ([slice _isLastSelected])
1966 return [slice rowIndex];
1972 - (void)_mouseUpOnSlice:(
id)slice withEvent:(
CPEvent)event
1979 rowIndexes = [
CPIndexSet indexSetWithIndex:[slice rowIndex]];
1981 [
self selectRowIndexes:rowIndexes byExtendingSelection:extend];
1984 - (void)_mouseDownOnSlice:(
id)slice withEvent:(
CPEvent)event
1988 - (void)_rightMouseDownOnSlice:(_CPRuleEditorViewSlice)slice withEvent:(
CPEvent)event
1992 - (void)_performClickOnSlice:(
id)slice withEvent:(
CPEvent)event
1996 - (void)_setSuppressKeyDownHandling:(BOOL)flag
1998 _suppressKeyDownHandling = flag;
2001 - (void)selectAll:(
id)sender
2003 var count = [_slices count];
2007 var slice = _slices[count];
2008 [slice _setSelected:YES];
2009 [slice setNeedsDisplay:YES];
2013 - (void)_deselectAll
2015 var count = [_slices count];
2019 var slice = _slices[count];
2020 [slice _setSelected:NO];
2021 [slice _setLastSelected:NO];
2022 [slice setNeedsDisplay:YES];
2026 - (int)_queryNumberOfChildrenOfItem:(
id)item withRowType:(CPRuleEditorRowType)type
2028 return [_ruleDelegate ruleEditor:self numberOfChildrenForCriterion:item withRowType:type];
2031 - (id)_queryChild:(
int)childIndex ofItem:(
id)item withRowType:(CPRuleEditorRowType)type
2033 return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item withRowType:type];
2036 - (id)_queryValueForItem:(
id)item inRow:(CPInteger)row
2038 return [_ruleDelegate ruleEditor:self displayValueForCriterion:item inRow:row];
2046 - (int)_countOfRowsStartingAtObject:(
id)object
2048 var index = [
self _rowIndexForRowObject:object];
2049 return ([
self numberOfRows] - index);
2052 - (void)_setAlignmentGridWidth:(
float)width
2054 _alignmentGridWidth =
width;
2057 - (BOOL)_validateItem:(
id)item value:(
id)value inRow:(CPInteger)row
2059 return [
self _queryCanSelectItem:item displayValue:value inRow:row];
2062 - (BOOL)_queryCanSelectItem:(
id)item displayValue:(
id)value inRow:(CPInteger)row
2067 - (void)_windowChangedKeyState
2069 [
self setNeedsDisplay:YES];
2074 [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:) withObject:flag];
2075 [
super setNeedsDisplay:flag];
2078 - (void)setFrameSize:(CGSize)size
2080 [
self setNeedsDisplay:YES];
2082 if (CGRectGetWidth([
self frame]) !== size.width)
2083 [_slices makeObjectsPerformSelector:
@selector(setNeedsLayout)];
2085 [super setFrameSize:size];
2091 count = [_slices count],
2094 for (i = 0; i < count; i++)
2096 var slice = _slices[i];
2097 if ([slice _isSelected])
2098 [selectedIndices addIndex:[slice rowIndex]];
2101 return selectedIndices;
2104 - (void)mouseDragged:(
CPEvent)event
2110 view = [_slices objectAtIndex:FLOOR(MAX(0, point.y) / _sliceHeight)];
2112 if ([
self _dragShouldBeginFromMouseDown:view])
2113 [
self _performDragForSlice:view withEvent:event];
2116 - (BOOL)_dragShouldBeginFromMouseDown:(
CPView)view
2118 return (([
self nestingMode] ===
CPRuleEditorNestingModeList || [view rowIndex] !== 0) && _editable && [view isKindOfClass:[_CPRuleEditorViewSliceRow
class]] && _draggingRows === nil);
2121 - (BOOL)_performDragForSlice:(
id)slice withEvent:(
CPEvent)event
2124 mainRowIndex = [slice rowIndex],
2126 selected_indices = [
self _selectedSliceIndices],
2129 [pasteboard declareTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType, nil] owner: self];
2131 if ([selected_indices containsIndex:mainRowIndex])
2132 [draggingRows addIndexes:selected_indices];
2133 _draggingRows = [
self _includeSubslicesForSlicesAtIndexes:draggingRows];
2135 var firstIndex = [_draggingRows firstIndex],
2136 firstSlice = [_slices objectAtIndex:firstIndex],
2137 dragview = [[
CPView alloc] initWithFrame:[firstSlice frame]];
2140 var html = firstSlice._DOMElement.innerHTML;
2141 dragview._DOMElement.innerHTML = [html copy];
2143 [dragview setBackgroundColor:[firstSlice backgroundColor]];
2144 [dragview setAlphaValue:0.7];
2146 dragPoint = CGPointMake(0, firstIndex * _sliceHeight);
2148 [
self dragView:dragview
2150 offset:CGSizeMake(0, _sliceHeight)
2152 pasteboard:pasteboard
2159 - (CPDragOperation)draggingEntered:(
id )sender
2161 if ([sender draggingSource] ===
self)
2163 [
self _clearDropLine];
2170 - (void)draggingExited:(
id)sender
2172 [
self _clearDropLine];
2173 [
self setNeedsDisplay:YES];
2176 - (void)_clearDropLine
2178 [_dropLineView setAlphaValue:0];
2180 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < _lastRow)
2182 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2183 [previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2189 - (CPDragOperation)draggingUpdated:(
id )sender
2191 var point = [
self convertPoint:[sender draggingLocation] fromView:nil],
2192 y = point.y + _sliceHeight / 2,
2193 indexOfDropLine = FLOOR(y / _sliceHeight),
2194 numberOfRows = [self numberOfRows];
2196 if (indexOfDropLine <= 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
2198 if (_subviewIndexOfDropLine !==
CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
2199 [
self _clearDropLine];
2203 if (_subviewIndexOfDropLine !== indexOfDropLine)
2205 if (_subviewIndexOfDropLine !==
CPNotFound && _subviewIndexOfDropLine < numberOfRows)
2207 var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
2208 [previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
2211 if (indexOfDropLine <= _lastRow && indexOfDropLine < numberOfRows)
2213 var belowSlice = [_slices objectAtIndex:indexOfDropLine];
2214 [belowSlice setFrameOrigin:CGPointMake(0, [belowSlice rowIndex] * _sliceHeight + 2)];
2217 [_dropLineView setAlphaValue:1];
2218 [_dropLineView setFrameOrigin:CGPointMake(CGRectGetMinX([_dropLineView frame]), indexOfDropLine * _sliceHeight)];
2220 _subviewIndexOfDropLine = indexOfDropLine;
2226 - (BOOL)prepareForDragOperation:(
id )sender
2228 return (_subviewIndexOfDropLine !==
CPNotFound);
2231 - (BOOL)performDragOperation:(
id )info
2233 var aboveInsertIndexCount = 0,
2237 var rowObjects = [_rowCache valueForKey:@"rowObject"],
2238 index = [_draggingRows lastIndex];
2240 var parentRowIndex = [
self parentRowForRow:index],
2241 parentRowObject = (parentRowIndex === -1) ? _boundArrayOwner : [[self _rowCacheForIndex:parentRowIndex] rowObject],
2242 insertIndex = _subviewIndexOfDropLine;
2246 if (index >= insertIndex)
2248 removeIndex = index + aboveInsertIndexCount;
2249 aboveInsertIndexCount += 1;
2253 removeIndex = index;
2257 object = [rowObjects objectAtIndex:removeIndex];
2258 [
self removeRowAtIndex:removeIndex];
2259 [[
self _subrowObjectsOfObject:parentRowObject] insertObject:object atIndex:insertIndex - parentRowIndex - 1];
2261 index = [_draggingRows indexLessThanIndex:index];
2264 [
self _clearDropLine];
2265 _draggingRows = nil;
2274 - (void)draggedView:(
CPView)dragView endedAt:(CGPoint)aPoint operation:(CPDragOperation)operation
2276 _draggingRows = nil;
2278 [
self _updatePredicate];
2279 [
self _sendRuleAction];
2280 [
self _postRuleOptionChangedNotification];
2281 [
self _postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification indexes:nil];
2284 - (BOOL)wantsPeriodicDraggingUpdates
2289 - (void)pasteboard:(
CPPasteboard)pasteboard provideDataForType:(
int)type
2293 - (void)_setWindow:(
CPWindow)window
2295 [
super _setWindow:window];
2298 - (void)_windowUpdate:(
id)sender
2300 [
super _windowUpdate:sender];
2303 - (void)_postRuleOptionChangedNotification
2308 - (void)_postRowCountChangedNotificationOfType:(
CPString)notificationName indexes:indexes
2310 var userInfo = indexes === nil ? @{} : @{
"indexes": indexes };
2314 - (
CPIndexSet)_globalIndexesForSubrowIndexes:(
CPIndexSet)indexes ofParentObject:(
id)parentRowObject
2316 var _subrows = [
self _subrowObjectsOfObject:parentRowObject],
2317 parentRowIndex = [
self _rowIndexForRowObject:parentRowObject],
2321 numberOfChildrenOfPreviousBrother = 0;
2325 var globalChildIndex = current_index + parentRowIndex + 1 + numberOfChildrenOfPreviousBrother;
2326 [globalIndexes addIndex:globalChildIndex];
2330 var rowObject = [[
self _rowCacheForIndex:current_index] rowObject],
2331 subrows = [
self _subrowObjectsOfObject:rowObject],
2334 numberOfChildrenOfPreviousBrother = [subIndexes count];
2340 return globalIndexes;
2343 - (void)_sendRuleAction
2345 var action = [
self action],
2346 target = [
self target];
2348 [
self sendAction:action to:target];
2351 - (BOOL)_sendsActionOnIncompleteTextChange
2356 - (void)_getAllAvailableItems:(
id)items values:(
id)values asChildrenOfItem:(
id)parentItem inRow:(CPInteger)aRow
2365 var criterion = nil,
2369 type = [
self rowTypeForRow:aRow];
2370 numOfChildren = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type];
2372 var criteria = [
self criteriaForRow:aRow];
2373 indexofCriterion = [criteria indexOfObject:criterion];
2375 if (parentItem !== nil
2377 && indexofCriterion < [criteria count] - 1)
2379 var next = indexofCriterion + 1;
2381 criterion = [criteria objectAtIndex:next];
2382 var values = [
self displayValuesForRow:aRow];
2383 value = [values objectAtIndex:next];
2386 for (var i = 0; i < numOfChildren; ++i)
2388 var aChild = [
self _queryChild:i ofItem:parentItem withRowType:type],
2389 availChild = aChild,
2392 if (criterion !== aChild)
2393 availValue = [
self _queryValueForItem:aChild inRow:aRow];
2396 availValue = [
self _queryValueForItem:availChild inRow:aRow];
2398 [availItems addObject:availChild];
2399 [availValues addObject:availValue];
2402 [items addObjectsFromArray:availItems];
2403 [values addObjectsFromArray:availValues];
2409 @implementation CPRuleEditor (CPRuleEditorDelegate)
2415 - (BOOL)_delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow
2424 - (
CPDictionary)_sendDelegateRuleEditorPredicatePartsForCriterion:(
id)criterion withDisplayValue:(
id)value inRow:(CPInteger)row
2429 return [_ruleDelegate ruleEditor:self predicatePartsForCriterion:criterion withDisplayValue:value inRow:row];
2435 var CPRuleEditorAlignmentGridWidthKey =
@"CPRuleEditorAlignmentGridWidth",
2436 CPRuleEditorSliceHeightKey =
@"CPRuleEditorSliceHeight",
2437 CPRuleEditorStringsFilenameKey =
@"CPRuleEditorStringsFilename",
2438 CPRuleEditorEditableKey =
@"CPRuleEditorEditable",
2439 CPRuleEditorAllowsEmptyCompoundRowsKey =
@"CPRuleEditorAllowsEmptyCompoundRows",
2440 CPRuleEditorDisallowEmptyKey =
@"CPRuleEditorDisallowEmpty",
2441 CPRuleEditorNestingModeKey =
@"CPRuleEditorNestingMode",
2442 CPRuleEditorRowTypeKeyPathKey =
@"CPRuleEditorRowTypeKeyPath",
2443 CPRuleEditorItemsKeyPathKey =
@"CPRuleEditorItemsKeyPath",
2444 CPRuleEditorValuesKeyPathKey =
@"CPRuleEditorValuesKeyPath",
2445 CPRuleEditorSubrowsArrayKeyPathKey =
@"CPRuleEditorSubrowsArrayKeyPath",
2446 CPRuleEditorBoundArrayKeyPathKey =
@"CPRuleEditorBoundArrayKeyPath",
2447 CPRuleEditorRowClassKey =
@"CPRuleEditorRowClass",
2448 CPRuleEditorSlicesHolderKey =
@"CPRuleEditorSlicesHolder",
2449 CPRuleEditorSlicesKey =
@"CPRuleEditorSlices",
2450 CPRuleEditorDelegateKey =
@"CPRuleEditorDelegate",
2451 CPRuleEditorBoundArrayOwnerKey =
@"CPRuleEditorBoundArrayOwner";
2453 @implementation CPRuleEditor (CPCoding)
2455 - (id)initWithCoder:(
CPCoder)coder
2457 self = [
super initWithCoder:coder];
2460 [
self setFormattingStringsFilename:[coder decodeObjectForKey:CPRuleEditorStringsFilenameKey]];
2461 _alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey];
2462 _sliceHeight = [coder decodeDoubleForKey:CPRuleEditorSliceHeightKey];
2463 _editable = [coder decodeBoolForKey:CPRuleEditorEditableKey];
2464 _allowsEmptyCompoundRows = [coder decodeBoolForKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2465 _disallowEmpty = [coder decodeBoolForKey:CPRuleEditorDisallowEmptyKey];
2466 _nestingMode = [coder decodeIntForKey:CPRuleEditorNestingModeKey];
2467 _typeKeyPath = [coder decodeObjectForKey:CPRuleEditorRowTypeKeyPathKey];
2468 _itemsKeyPath = [coder decodeObjectForKey:CPRuleEditorItemsKeyPathKey];
2469 _valuesKeyPath = [coder decodeObjectForKey:CPRuleEditorValuesKeyPathKey];
2470 _subrowsArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorSubrowsArrayKeyPathKey];
2471 _boundArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorBoundArrayKeyPathKey];
2473 _slicesHolder = [[
self subviews] objectAtIndex:0];
2474 _boundArrayOwner = [coder decodeObjectForKey:CPRuleEditorBoundArrayOwnerKey];
2475 _slices = [coder decodeObjectForKey:CPRuleEditorSlicesKey];
2476 _ruleDelegate = [coder decodeObjectForKey:CPRuleEditorDelegateKey];
2478 [
self _initRuleEditorShared];
2484 - (void)encodeWithCoder:(
CPCoder)coder
2486 [
super encodeWithCoder:coder];
2488 [coder encodeBool:_editable forKey:CPRuleEditorEditableKey];
2489 [coder encodeBool:_allowsEmptyCompoundRows forKey:CPRuleEditorAllowsEmptyCompoundRowsKey];
2490 [coder encodeBool:_disallowEmpty forKey:CPRuleEditorDisallowEmptyKey];
2492 [coder encodeFloat:_alignmentGridWidth forKey:CPRuleEditorAlignmentGridWidthKey];
2493 [coder encodeDouble:_sliceHeight forKey:CPRuleEditorSliceHeightKey];
2494 [coder encodeInt:_nestingMode forKey:CPRuleEditorNestingModeKey];
2496 [coder encodeObject:_stringsFilename forKey:CPRuleEditorStringsFilenameKey];
2497 [coder encodeObject:_typeKeyPath forKey:CPRuleEditorRowTypeKeyPathKey];
2498 [coder encodeObject:_itemsKeyPath forKey:CPRuleEditorItemsKeyPathKey];
2499 [coder encodeObject:_valuesKeyPath forKey:CPRuleEditorValuesKeyPathKey];
2500 [coder encodeObject:_boundArrayKeyPath forKey:CPRuleEditorBoundArrayKeyPathKey];
2501 [coder encodeObject:_subrowsArrayKeyPath forKey:CPRuleEditorSubrowsArrayKeyPathKey];
2503 [coder encodeConditionalObject:_slicesHolder forKey:CPRuleEditorSlicesHolderKey];
2504 [coder encodeObject:_slices forKey:CPRuleEditorSlicesKey];
2505 [coder encodeObject:_boundArrayOwner forKey:CPRuleEditorBoundArrayOwnerKey];
2510 var CriteriaKey =
@"criteria",
2511 SubrowsKey =
@"subrows",
2512 DisplayValuesKey =
@"displayValues",
2513 RowTypeKey =
@"rowType";
2515 @implementation _CPRuleEditorRowObject :
CPObject 2519 CPArray displayValues;
2525 var copy = [[_CPRuleEditorRowObject alloc] init];
2526 [copy setSubrows:[[CPArray alloc] initWithArray:subrows copyItems:YES]];
2527 [copy setCriteria:[[CPArray alloc] initWithArray:criteria copyItems:YES]];
2528 [copy setDisplayValues:[[CPArray alloc] initWithArray:displayValues copyItems:YES]];
2529 [copy setRowType:rowType];
2536 return "<" + [self className] + ">\nsubrows = " + [subrows
description] + "\ncriteria = " + [criteria
description] + "\ndisplayValues = " + [displayValues
description];
2539 - (id)initWithCoder:(
CPCoder)coder
2541 self = [
super init];
2544 subrows = [coder decodeObjectForKey:SubrowsKey];
2545 criteria = [coder decodeObjectForKey:CriteriaKey];
2546 displayValues = [coder decodeObjectForKey:DisplayValuesKey];
2547 rowType = [coder decodeIntForKey:RowTypeKey];
2553 - (void)encodeWithCoder:(
CPCoder)coder
2555 [coder encodeObject:subrows forKey:SubrowsKey];
2556 [coder encodeObject:criteria forKey:CriteriaKey];
2557 [coder encodeObject:displayValues forKey:DisplayValuesKey];
2558 [coder encodeInt:rowType forKey:RowTypeKey];
2563 @implementation _CPRuleEditorCache :
CPObject 2567 CPInteger indentation;
2572 return [
CPString stringWithFormat:@"<%d object:%d rowIndex:%d indentation:%d>", [
self hash], [rowObject hash], rowIndex, indentation];
2577 var CPBoundArrayKey =
@"CPBoundArray";
2579 @implementation _CPRuleEditorViewUnboundRowHolder :
CPObject 2586 if (
self = [super
init])
2587 boundArray = [[CPArray alloc]
init];
2592 - (id)initWithCoder:(
CPCoder)coder
2594 if (
self = [super
init])
2595 boundArray = [coder decodeObjectForKey:CPBoundArrayKey];
2600 - (void)encodeWithCoder:(
CPCoder)coder
2602 [coder encodeObject:boundArray forKey:CPBoundArrayKey];
2606 @implementation _CPRuleEditorViewSliceHolder :
CPView 2611 - (void)addSubview:(
CPView)subview
2613 [
self setNeedsDisplay:YES];
2614 [
super addSubview:subview];
2620 @implementation _CPRuleEditorViewSliceDropSeparator :
CPView 2625 - (void)drawRect:(CGRect)rect
2634 @implementation CPObject (CPRuleEditorSliceRow)
2639 isString = [
self isKindOfClass:CPString];
2643 var isView = [
self isKindOfClass:CPView];
2648 var ismenuItem = [
self isKindOfClass:CPMenuItem];
2665 @implementation CPRuleEditor (CPSynthesizedAccessors)
2672 return _boundArrayKeyPath;
2678 - (void)setBoundArrayKeyPath:(
CPString)aValue
2680 _boundArrayKeyPath = aValue;
2686 - (_CPRuleEditorLocalizer)standardLocalizer
2688 return _standardLocalizer;
2694 - (void)setStandardLocalizer:(_CPRuleEditorLocalizer)aValue
2696 _standardLocalizer = aValue;
void insertRowAtIndex:withType:asSubrowOfRow:animate:(int rowIndex, [withType] unsigned int rowType, [asSubrowOfRow] CPInteger parentRow, [animate] BOOL shouldAnimate)
Adds a new row of a given type at a given location.
Used to implement exception handling (creating & raising).
CPKeyValueChangeInsertion
CPMutableArray displayValuesForRow:(CPInteger row)
Returns the chosen values for a given row.
CPRuleEditorPredicateCustomSelector
CPColor colorWithHexString:(string hex)
CPPredicate predicateForRow:(CPInteger aRow)
Returns the predicate for a given row.
int parentRowForRow:(CPInteger rowIndex)
Returns the index of the parent of a given row.
CPCaseInsensitivePredicateOption
CPRuleEditorNestingModeList
CPGraphicsContext currentContext()
void postNotificationName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
An object representation of nil.
CPFont systemFontOfSize:(CGSize aSize)
CPDragOperation CPDragOperationNone
CPRuleEditorRowType CPRuleEditorRowTypeSimple
var CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_
CGPoint locationInWindow()
CPRuleEditorNestingModeCompound
void removeRowsAtIndexes:includeSubrows:(CPIndexSet rowIndexes, [includeSubrows] BOOL includeSubrows)
Removes the rows at a given index.
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void raise:reason:(CPString aName, [reason] CPString aReason)
A collection of unique integers.
function CPSelectorFromString(aSelectorName)
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
CPRuleEditorNestingModeSingle
BOOL containsIndex:(CPInteger anIndex)
CPRuleEditorNestingModeSimple
CPCompoundPredicate is a subclass of CPPredicate used to represent logical “gate” operations (AND/O...
CPRuleEditorRowTypeCompound
CPString pathForResource:(CPString aFilename)
An immutable string (collection of characters).
id objectForKey:(id aKey)
CPInteger indexGreaterThanIndex:(CPInteger anIndex)
id initWithDuration:animationCurve:(float aDuration, [animationCurve] CPAnimationCurve anAnimationCurve)
function CGContextSetFillColor(aContext, aColor)
void reloadCriteria()
Instructs the receiver to refetch criteria from its delegate. You can use this method to indicate th...
var CPRuleEditorItemPBoardType
A notification that can be posted to a CPNotificationCenter.
A view for creating and configuring criteria.
CPPredicate predicateWithLeftExpression:rightExpression:customSelector:(CPExpression left, [rightExpression] CPExpression right, [customSelector] SEL selector)
int numberOfRows()
Returns the number of rows in the receiver.
Defines methods for use when archiving & restoring (enc/decoding).
CPIndexSet subrowIndexesForRow:(CPInteger rowIndex)
Returns the immediate subrows of a given row.
CPComparisonPredicate is a subclass of CPPredicate used to compare expressions.
Sends messages (CPNotification) between objects.
CPPredicate predicateWithLeftExpression:rightExpression:modifier:type:options:(CPExpression left, [rightExpression] CPExpression right, [modifier] CPComparisonPredicateModifier modifier, [type] int type, [options] unsigned options)
function CGContextFillRect(aContext, aRect)
id indexSetWithIndexesInRange:(CPRange aRange)
id criteriaForRow:(CPInteger row)
Returns the currently chosen items for a given row.
id URLWithString:(CPString URLString)
id indexSetWithIndex:(int anIndex)
CPDirectPredicateModifier
id pasteboardWithName:(CPString aName)
id stringWithFormat:(CPString format, [,] ...)
FrameUpdater prototype description