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:)])
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];
285 - (void)setNestingMode:(CPRuleEditorNestingMode)mode
287 if (mode !== _nestingMode)
291 _nestingModeDidChange = YES;
302 return !_disallowEmpty;
310 - (void)setCanRemoveAllRows:(BOOL)canRemove
312 _disallowEmpty = !canRemove;
313 [
self _updateButtonVisibilities];
323 return _allowsEmptyCompoundRows;
331 - (void)setAllowsEmptyCompoundRows:(BOOL)allows
333 _allowsEmptyCompoundRows = allows;
334 [
self _updateButtonVisibilities];
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";
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."];
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
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
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],
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,
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
739 - (void)removeRowsAtIndexes:(
CPIndexSet)rowIndexes includeSubrows:(BOOL)includeSubrows
741 if ([rowIndexes count] === 0)
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];
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];
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;
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],
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
1270 if ([subrowsIndexes count] === 1)
1272 if (parentIndex !== -1)
1276 [childlessParents addIndexes:childlessGranPa];
1282 return childlessParents;
1288 var subindexes = [indexes
copy],
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;
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)
1338 for (row = 0; row < count; 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],
1424 insertIndex = rowIndexEvent + 1,
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
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],
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 1724 - (void)_updatePredicate
1726 if (_delegateWantsValidation)
1728 if (![
self _delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow])
1731 _delegateWantsValidation = NO;
1736 current_index = [subindexes firstIndex];
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];
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;
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];
1816 if (_lastRow === -1)
1817 _nestingModeDidChange = NO;
1820 [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
1831 - (void)_updateSliceRows
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
1933 [
self _updateSliceIndentationAtIndex:current_index toIndentation:indentation + 1 withIndexSet:subindexes];
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
1977 var modifierFlags = [event modifierFlags],
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];
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
2074 [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:) withObject:flag];
2078 - (void)setFrameSize:(CGSize)size
2082 if (CGRectGetWidth([
self frame]) !== size.width)
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
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);
2150 offset:CGSizeMake(0, _sliceHeight)
2159 - (CPDragOperation)draggingEntered:(
id )sender
2161 if ([sender draggingSource] ===
self)
2163 [
self _clearDropLine];
2170 - (void)draggingExited:(
id)sender
2172 [
self _clearDropLine];
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
2192 y = point.y + _sliceHeight / 2,
2193 indexOfDropLine = FLOOR(y / _sliceHeight),
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)
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];
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];
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
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
2351 - (BOOL)_sendsActionOnIncompleteTextChange
2356 - (void)_getAllAvailableItems:(
id)items values:(id)values asChildrenOfItem:(
id)parentItem inRow:(CPInteger)aRow
2365 var criterion = nil,
2370 numOfChildren = [
self _queryNumberOfChildrenOfItem:parentItem withRowType:type];
2373 indexofCriterion = [criteria indexOfObject:criterion];
2375 if (parentItem !== nil
2377 && indexofCriterion < [criteria count] - 1)
2379 var next = indexofCriterion + 1;
2381 criterion = [criteria objectAtIndex:next];
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
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
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
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).
CPInteger rowHeight()
Returns the row height for the receiver.
CPKeyValueChangeInsertion
CPMutableArray displayValuesForRow:(CPInteger row)
Returns the chosen values for a given row.
CPRuleEditorPredicateCustomSelector
void addSubview:(CPView aSubview)
void dragView:at:offset:event:pasteboard:source:slideBack:(CPView aView, [at] CGPoint aLocation, [offset] CGSize mouseOffset, [event] CPEvent anEvent, [pasteboard] CPPasteboard aPasteboard, [source] id aSourceObject, [slideBack] BOOL slideBack)
void reloadPredicate()
Instructs the receiver to regenerate its predicate by invoking the corresponding delegate method...
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
CPDictionary themeAttributes()
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_
void removeRowAtIndex:(int rowIndex)
Removes the row at a given index.
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)
id delegate()
Returns the receiver’s delegate.
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
CPRuleEditorNestingModeSingle
BOOL containsIndex:(CPInteger anIndex)
CPString criteriaKeyPath()
Returns the criteria key path.
CPRuleEditorNestingModeSimple
CPPredicate predicate()
Returns the predicate for the receiver.
CPCompoundPredicate is a subclass of CPPredicate used to represent logical “gate” operations (AND/O...
BOOL isEditable()
Returns a Boolean value that indicates whether the receiver is editable.
CPIndexSet selectedRowIndexes()
Returns the indexes of the receiver’s selected rows.
id animation()
Returns the current animation for the receiver.
CPString formattingStringsFilename()
Returns the name of the strings file for the receiver.
CPRuleEditorRowTypeCompound
CPString pathForResource:(CPString aFilename)
An immutable string (collection of characters).
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
CPInteger indexGreaterThanIndex:(CPInteger anIndex)
id initWithDuration:animationCurve:(float aDuration, [animationCurve] CPAnimationCurve anAnimationCurve)
BOOL sendAction:to:(SEL anAction, [to] id anObject)
void setFormattingStringsFilename:(CPString stringsFilename)
Sets the name of the strings file used for formatting.
id initWithCoder:(CPCoder aCoder)
Class rowClass()
Returns the class used to create a new row in the “rows” binding.
CPRuleEditorNestingMode nestingMode()
Returns the nesting mode for the receiver.
function CGContextSetFillColor(aContext, aColor)
CPRuleEditorRowType rowTypeForRow:(CPInteger rowIndex)
Returns the type of a given row.
void setNeedsDisplay:(BOOL aFlag)
CPString displayValuesKeyPath()
Returns the display values key path.
void selectRowIndexes:byExtendingSelection:(CPIndexSet indexes, [byExtendingSelection] BOOL extend)
Sets in the receiver the indexes of rows that are selected.
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)
CPDictionary formattingDictionary()
Returns the formatting dictionary for the receiver.
int numberOfRows()
Returns the number of rows in the receiver.
CPString rowTypeKeyPath()
Returns the key path for the row type.
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.
CPString subrowsKeyPath()
Returns the key path for the subrows.
BOOL canRemoveAllRows()
Returns a Boolean value that indicates whether all the rows can be removed.
CPPredicate predicateWithLeftExpression:rightExpression:modifier:type:options:(CPExpression left, [rightExpression] CPExpression right, [modifier] CPComparisonPredicateModifier modifier, [type] int type, [options] unsigned options)
void setFrameSize:(CGSize aSize)
function CGContextFillRect(aContext, aRect)
CPRuleEditorRowsDidChangeNotification
id indexSetWithIndexesInRange:(CPRange aRange)
id criteriaForRow:(CPInteger row)
Returns the currently chosen items for a given row.
id URLWithString:(CPString URLString)
BOOL allowsEmptyCompoundRows()
Returns a Boolean value that indicates whether compounds rows can be childless.
id indexSetWithIndex:(int anIndex)
void encodeWithCoder:(CPCoder aCoder)
CPDirectPredicateModifier
id pasteboardWithName:(CPString aName)
id stringWithFormat:(CPString format, [,] ...)
FrameUpdater prototype description