[ruleeditor commit] r95 - in branches: CPRuleEditor Issue16_Branch/Framework Issue16_Branch/TestApp TreeBranch/Framew...

0 views
Skip to first unread message

codesite...@google.com

unread,
Oct 8, 2008, 5:56:23 PM10/8/08
to psruleedit...@googlegroups.com
Author: caca...@gmail.com
Date: Wed Oct 8 14:54:24 2008
New Revision: 95

Added:
branches/CPRuleEditor/
branches/CPRuleEditor/AppController.j
branches/CPRuleEditor/CPComparisonPredicate.j
branches/CPRuleEditor/CPCompoundPredicate.j
branches/CPRuleEditor/CPExpression.j
branches/CPRuleEditor/CPExpression_aggregate.j
branches/CPRuleEditor/CPExpression_assignment.j
branches/CPRuleEditor/CPExpression_constant.j
branches/CPRuleEditor/CPExpression_function.j
branches/CPRuleEditor/CPExpression_keypath.j
branches/CPRuleEditor/CPExpression_operator.j
branches/CPRuleEditor/CPExpression_self.j
branches/CPRuleEditor/CPExpression_variable.j
branches/CPRuleEditor/CPImageNameAddTemplate.tiff (contents, props
changed)
branches/CPRuleEditor/CPImageNameRemoveTemplate.tiff (contents, props
changed)
branches/CPRuleEditor/CPPredicate.j
branches/CPRuleEditor/CPPredicateTests.j
branches/CPRuleEditor/CPRuleEditor.j
branches/CPRuleEditor/CPRuleEditorButtonCell.j
branches/CPRuleEditor/CPRuleEditorPopupButton.j
branches/CPRuleEditor/CPRuleEditorPopupButtonCell.j
branches/CPRuleEditor/CPRuleEditorTextField.j
branches/CPRuleEditor/CPRuleEditorViewSlice.j
branches/CPRuleEditor/CPRuleEditorViewSliceDropSeparator.j
branches/CPRuleEditor/CPRuleEditorViewSliceRow.j
branches/CPRuleEditor/Info.plist
branches/CPRuleEditor/RuleDelegate.j
branches/CPRuleEditor/RuleEditor.steam
branches/CPRuleEditor/_CPRuleEditorCache.j
branches/CPRuleEditor/_CPRuleEditorViewSliceHolder.j
branches/CPRuleEditor/_CPRuleEditorViewUnboundRowHolder.j
branches/CPRuleEditor/criteria.plist
branches/CPRuleEditor/index.html
branches/CPRuleEditor/main.j
Modified:
branches/Issue16_Branch/Framework/Criterion.m
branches/Issue16_Branch/Framework/PSPredicateEditor.m
branches/Issue16_Branch/Framework/PSPredicateEditorRowTemplate.m
branches/Issue16_Branch/Framework/PSRuleEditor_SelectDrag.m
branches/Issue16_Branch/TestApp/PEController.m
branches/TreeBranch/Framework/PSRuleEditor_SelectDrag.m
branches/TreeBranch/PSRuleEditor.xcodeproj/project.pbxproj

Log:
Created CPRuleEditor branch

Added: branches/CPRuleEditor/AppController.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/AppController.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,41 @@
+
+import <Foundation/CPObject.j>
+import "CPRuleEditor.j"
+import "RuleDelegate.j"
+
+@implementation CPObject (Additions)
+
+- (id)mutableArrayValueForKey:(CPString)key
+{
+ return [self valueForKey:key];
+}
+
+@end
+
+@implementation AppController : CPObject
+{
+}
+
+- (void)applicationDidFinishLaunching:(CPNotification)aNotification
+{
+ objj_backtrace_set_enable(true);
+ CPLogRegister(CPLogConsole);
+
+ var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
styleMask:CPBorderlessBridgeWindowMask],
+ contentView = [theWindow contentView];
+
+ var ruleeditor = [[RuleEditor alloc]
initWithFrame:CGRectMake(0,0,600,400)];
+ var datasource = [[RuleDelegate alloc] init];
+ [ruleeditor setDelegate:datasource];
+
+ [ruleeditor setBackgroundColor:[CPColor grayColor]];
+ [contentView addSubview:ruleeditor];
+
+ [ruleeditor addRow:self];
+ [theWindow orderFront:self];
+
+ // Uncomment the following line to turn on the standard menu bar.
+ //[CPMenu setMenuBarVisible:YES];
+}
+
+@end
\ No newline at end of file

Added: branches/CPRuleEditor/CPComparisonPredicate.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPComparisonPredicate.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,424 @@
+
+import <Foundation/CPArray.j>
+import <Foundation/CPEnumerator.j>
+import <Foundation/CPNull.j>
+import <Foundation/CPString.j>
+import "CPPredicate.j"
+import "CPExpression.j"
+import "CPExpression_operator.j"
+
+
+CPDirectPredicateModifier = 0;
+CPAllPredicateModifier = 1;
+CPAnyPredicateModifier = 2;
+
+CPLessThanPredicateOperatorType = 0;
+CPLessThanOrEqualToPredicateOperatorType = 1;
+CPGreaterThanPredicateOperatorType = 2;
+CPGreaterThanOrEqualToPredicateOperatorType = 3;
+CPEqualToPredicateOperatorType = 4;
+CPNotEqualToPredicateOperatorType = 5;
+CPMatchesPredicateOperatorType = 6;
+CPLikePredicateOperatorType = 7;
+CPBeginsWithPredicateOperatorType = 8;
+CPEndsWithPredicateOperatorType = 9;
+CPInPredicateOperatorType = 10;
+CPCustomSelectorPredicateOperatorType = 11;
+
+CPCaseInsensitivePredicateOption = 1;
+CPDiacriticInsensitivePredicateOption = 2;
+
+var CPComparisonPredicateModifier;
+var CPPredicateOperatorType;
+
+@implementation CPComparisonPredicate : CPPredicate
+{
+ CPExpression _left;
+ CPExpression _right;
+
+ var _modifier;
+ var _type;
+ var _options;
+ var _customSelector;
+
+}
+
+- (id)initWithLeftExpression:(CPExpression)left
rightExpression:(CPExpression)right
modifier:(CPComparisonPredicateModifier)modifier
type:(CPPredicateOperatorType)type options:(unsigned)options
+{
+ _left = left;
+ _right = right;
+ _modifier = modifier;
+ _type = type;
+
+ if(type == CPMatchesPredicateOperatorType
+ || type == CPLikePredicateOperatorType
+ || type == CPBeginsWithPredicateOperatorType
+ || type == CPEndsWithPredicateOperatorType
+ || type == CPInPredicateOperatorType)
+ _options = options;
+ else
+ _options = 0;
+
+ _customSelector = 0;
+ return self;
+}
+
+- (id)initWithLeftExpression:(CPExpression)left
rightExpression:(CPExpression)right customSelector:(SEL)selector
+{
+ _left = left;
+ _right = right;
+ _modifier = CPDirectPredicateModifier;
+ _type = CPCustomSelectorPredicateOperatorType;
+ _options = 0;
+ _customSelector = selector;
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ // UNIMPLEMENTED
+ return self;
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ // UNIMPLEMENTED
+}
+
++ (CPPredicate)predicateWithLeftExpression:(CPExpression)left
rightExpression:(CPExpression)right
modifier:(CPComparisonPredicateModifier)modifier type:(int)type
options:(unsigned)options
+{
+ return [[self alloc] initWithLeftExpression:left rightExpression:right
modifier:modifier type:type options:options];
+}
+
++ (CPPredicate)predicateWithLeftExpression:(CPExpression)left
rightExpression:(CPExpression)right customSelector:(SEL)selector
+{
+ return [[self alloc] initWithLeftExpression:left rightExpression:right
customSelector:selector];
+}
+
+- (CPString)predicateFormat
+{
+ var modifier;
+ var operator;
+ var options;
+
+ switch(_modifier)
+ {
+ case CPDirectPredicateModifier:
+ modifier = "";
+ break;
+
+ case CPAllPredicateModifier:
+ modifier = "ALL ";
+ break;
+
+ case CPAnyPredicateModifier:
+ modifier = "ANY ";
+ break;
+
+ default:
+ modifier = "";
+ break;
+ }
+
+ switch (_options)
+ {
+ case CPCaseInsensitivePredicateOption:
+ options = "[c]";
+ break;
+
+ case CPDiacriticInsensitivePredicateOption:
+ options = "[d]";
+ break;
+
+ case CPCaseInsensitivePredicateOption |
CPDiacriticInsensitivePredicateOption:
+ options = "[cd]";
+ break;
+
+ default:
+ options = "";
+ break;
+ }
+
+ switch(_type){
+
+ case CPLessThanPredicateOperatorType:
+ operator = "<";
+ break;
+
+ case CPLessThanOrEqualToPredicateOperatorType:
+ operator = "<=";
+ break;
+
+ case CPGreaterThanPredicateOperatorType:
+ operator = ">";
+ break;
+
+ case CPGreaterThanOrEqualToPredicateOperatorType:
+ operator = ">=";
+ break;
+
+ case CPEqualToPredicateOperatorType:
+ operator = "==";
+ break;
+
+ case CPNotEqualToPredicateOperatorType:
+ operator = "!=";
+ break;
+
+ case CPMatchesPredicateOperatorType:
+ operator = "MATCHES";
+ break;
+
+ case CPLikePredicateOperatorType:
+ operator = "LIKE";
+ break;
+
+ case CPBeginsWithPredicateOperatorType:
+ operator = "BEGINSWITH";
+ break;
+
+ case CPEndsWithPredicateOperatorType:
+ operator = "ENDSWITH";
+ break;
+
+ case CPInPredicateOperatorType:
+ operator = "IN";
+ break;
+
+ // FIX, not right
+ case CPCustomSelectorPredicateOperatorType:
+ operator = [CPString
stringWithFormat:@"%s",CPStringFromSelector(_customSelector)];
+ break;
+
+ }
+
+ return [CPString stringWithFormat:@"%s%s %s%s %s",modifier,[_left
description],operator,options,[_right description]];
+
+}
+
+- (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables
+{
+ var left = [_left _expressionWithSubstitutionVariables:variables];
+ var right = [_left _expressionWithSubstitutionVariables:variables];
+
+ if(_type != CPCustomSelectorPredicateOperatorType)
+ return [CPComparisonPredicate predicateWithLeftExpression:left
rightExpression:right modifier:_modifier type:_type options:_options];
+ else
+ return [CPComparisonPredicate predicateWithLeftExpression:left
rightExpression:right customSelector:_customSelector];
+}
+
+- (CPExpression)leftExpression
+{
+ return _left;
+}
+
+- (CPExpression)rightExpression
+{
+ return _right;
+}
+
+- (CPPredicateOperatorType)predicateOperatorType
+{
+ return _type;
+}
+
+- (CPComparisonPredicateModifier)comparisonPredicateModifier
+{
+ return _modifier;
+}
+
+- (unsigned)options
+{
+ return _options;
+}
+
+- (SEL)customSelector
+{
+ return _customSelector;
+}
+
+- (BOOL)_evaluateValue:leftResult rightValue:rightResult
+{
+ var leftIsNil = (leftResult == nil || [leftResult isEqual:[CPNull null]]);
+ var rightIsNil = (rightResult == nil || [rightResult isEqual:[CPNull
null]]);
+
+ if (leftIsNil || rightIsNil)
+ return ((leftIsNil == rightIsNil)
+ && (_type == CPEqualToPredicateOperatorType
+ || _type == CPLessThanOrEqualToPredicateOperatorType
+ || _type == CPGreaterThanOrEqualToPredicateOperatorType));
+
+ // left and right should be casted first [CAST()] following 10.5 rules.
+ switch(_type){
+
+ case CPLessThanPredicateOperatorType:
+ return ([leftResult compare:rightResult] == CPOrderedAscending);
+
+ case CPLessThanOrEqualToPredicateOperatorType:
+ return ([leftResult compare:rightResult] != CPOrderedDescending);
+
+ case CPGreaterThanPredicateOperatorType:
+ return ([leftResult compare:rightResult] == CPOrderedDescending);
+
+ case CPGreaterThanOrEqualToPredicateOperatorType:
+ return ([leftResult compare:rightResult] != CPOrderedAscending);
+
+ case CPEqualToPredicateOperatorType:
+ return [leftResult isEqual:rightResult];
+
+ case CPNotEqualToPredicateOperatorType:
+ return (![leftResult isEqual:rightResult]);
+
+ case CPMatchesPredicateOperatorType:
+ if(_options & CPDiacriticInsensitivePredicateOption)
+ {
+ leftResult = replace_diacritics(leftResult);
+ rightResult = replace_diacritics(rightResult);
+ }
+
+ var commut = (_options &
CPCaseInsensitivePredicateOption) ? "gi":"g";
+ var reg = new RegExp(rightResult,commut);
+ return reg.test(leftResult);
+
+ case CPLikePredicateOperatorType:
+
+ if(_options & CPDiacriticInsensitivePredicateOption)
+ {
+ leftResult = replace_diacritics(leftResult);
+ rightResult = replace_diacritics(rightResult);
+ }
+
+ var commut = (_options &
CPCaseInsensitivePredicateOption) ? "gi":"g";
+ var like_pattern = escape_regex(rightResult);
+ var reg = new RegExp(like_pattern,commut);
+ return reg.test(leftResult);
+
+ case CPBeginsWithPredicateOperatorType:
+ var range = CPMakeRange(0,[rightResult length]);
+ var string_compare_options = (_options &
CPCaseInsensitivePredicateOption) ? CPCaseInsensitiveSearch : 0;
+
+ if(_options & CPDiacriticInsensitivePredicateOption)
+ {
+ leftResult = replace_diacritics(leftResult);
+ rightResult = replace_diacritics(rightResult);
+ }
+
+ return ([leftResult compare:rightResult options:string_compare_options
range:range] == CPOrderedSame);
+
+ case CPEndsWithPredicateOperatorType:
+ var range = CPMakeRange([leftResult length] - [rightResult
length],[rightResult length]);
+ var string_compare_options = (_options &
CPCaseInsensitivePredicateOption) ? CPCaseInsensitiveSearch : 0;
+
+ if(_options & CPDiacriticInsensitivePredicateOption)
+ {
+ leftResult = replace_diacritics(leftResult);
+ rightResult = replace_diacritics(rightResult);
+ }
+
+ return ([leftResult compare:rightResult options:string_compare_options
range:range] == CPOrderedSame);
+
+ case CPInPredicateOperatorType: // UNTESTED
+ // Handle special case where rightResult is a collection and
leftResult an element of it.
+ if (![rightResult isKindOfClass: [CPString class]])
+ {
+ var e;
+ var value;
+
+ if (![rightResult respondsToSelector:
@selector(objectEnumerator)])
+ [CPException raise: CPInvalidArgumentException reason:
@"The right hand side for an IN operator must be a collection"];
+
+ e = [rightResult objectEnumerator];
+ while (value = [e nextObject])
+ {
+ if ([value isEqual:leftResult])
+ return YES;
+ }
+
+ return NO;
+ }
+
+ if(_options & CPDiacriticInsensitivePredicateOption)
+ {
+ leftResult = replace_diacritics(leftResult);
+ rightResult = replace_diacritics(rightResult);
+ }
+
+ return ([rightResult rangeOfString: leftResult options:
string_compare_options].location != CPNotFound);
+
+ case CPCustomSelectorPredicateOperatorType:
+ return [leftResult performSelector:_customSelector
withObject:rightResult];
+
+ default:
+ return NO;
+ }
+}
+
+- (BOOL)evaluateWithObject:(id)object
substitutionVariables:(CPDictionary)variables
+{
+ var p = [self predicateWithSubstitutionVariables:variables];
+ return [p evaluateWithObject:object];
+}
+
+- (BOOL)evaluateWithObject:(id)object
+{
+ var leftValue = [_left expressionValueWithObject:object context:nil];
+ var rightValue = [_right expressionValueWithObject:object context:nil];
+
+ if(_modifier == CPDirectPredicateModifier)
+ return [self _evaluateValue:leftValue rightValue:rightValue];
+ else
+{
+ var result = (_modifier == CPAllPredicateModifier);
+ var e;
+ var value;
+
+ if (![leftValue respondsToSelector: @selector(objectEnumerator)])
+ [CPException raise:CPInvalidArgumentException reason:@"The left hand
side for an ALL or ANY operator must be either an CPArray or an CPSet"];
+
+ e = [leftValue objectEnumerator];
+ while (value = [e nextObject])
+ {
+ var eval = [self _evaluateValue:leftValue rightValue:rightValue];
+ if (eval != result)
+ return eval;
+ }
+
+ return result;
+ }
+}
+
+@end
+
+function replace_diacritics(str)
+{
+ var diacritics = [
+ /[À-Æ]/g, /[à-é]/g, // A, a
+ /È-Ë/g, /[Ăš-Ă«]/g, // E, e
+ /[Ì-Ï]/g, /[ì-ï]/g, // I, i
+ /[Ò-Ö]/g, /[ĂČ-ö]/g, // O, o
+ /[Ù-Ü]/g, /[Ăč-ĂŒ]/g, // U, u
+ /Ñ/g, /ñ/g, // N, n
+ /Ç/g, /ç/g, // C, c
+ ];
+
+ var normalized =
['A','a','E','e','I','i','O','o','U','u','N','n','C','c'];
+
+ for (var i = 0; i < diacritics.length; i++)
+ str = str.replace(diacritics[i],normalized[i])
+
+return str;
+}
+
+function escape_regex(str)
+{
+
+ var regexchar = ['(',')','{','}','.','*','+','?','|','^','$'];
+ var replace = ['\(','\)','\{','\}','\.','.*','\+','.?','\|','\^','\$'];
+
+ for (var i = 0; i < regexchar.length; i++)
+ str = str.replace(regexchar[i], replace[i]);
+ CPLogConsole(str);
+ return str;
+}
+
+

Added: branches/CPRuleEditor/CPCompoundPredicate.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPCompoundPredicate.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,129 @@
+import "CPPredicate.j"
+import <Foundation/CPArray.j>
+import <Foundation/CPString.j>
+
+CPNotPredicateType = 0;
+CPAndPredicateType = 1;
+CPOrPredicateType = 2;
+
+var CPCompoundPredicateType;
+
+@implementation CPCompoundPredicate : CPPredicate
+{
+ CPCompoundPredicateType _type;
+ CPArray _predicates;
+
+}
+
+- (id)initWithType:(CPCompoundPredicateType)type
subpredicates:(CPArray)predicates
+{
+ _type=type;
+ _predicates = predicates;
+ return self;
+}
+
++ (CPPredicate)notPredicateWithSubpredicate:(CPPredicate)predicate
+{
+ return [[self alloc] initWithType:CPNotPredicateType
subpredicates:[CPArray arrayWithObject:predicate]];
+}
+
++ (CPPredicate)andPredicateWithSubpredicates:(CPArray *)predicates
+{
+ return [[self alloc] initWithType:CPAndPredicateType
subpredicates:predicates];
+}
+
++ (CPPredicate)orPredicateWithSubpredicates:(CPArray)predicates
+{
+ return [[self alloc] initWithType:CPOrPredicateType
subpredicates:predicates];
+}
+
+- (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables
+{
+ var subp = [CPArray array];
+ var i;
+ for (i =0; i < [subp count]; i++){
+ var p = [subp objectAtIndex:i];
+ var sp = [p predicateWithSubstitutionVariables:variables];
+ [subp addObject:sp];
+ }
+ return [[[CPCompoundPredicate alloc] initWithType:_type
subpredicates:subp] autorelease];
+}
+
+- (CPString)predicateFormat
+{
+ var result = [CPString string];
+ var args = [CPArray array];
+ var i,count = [_predicates count];
+
+ for(i = 0;i < count;i++)
+ {
+ var subpredicate = [_predicates objectAtIndex:i];
+ var precedence = [subpredicate predicateFormat];
+
+ if([subpredicate isKindOfClass:[CPCompoundPredicate class]])
+ if([subpredicate compoundPredicateType] != _type)
+ precedence = [CPString stringWithFormat:@"(%s)",precedence];
+
+ [args addObject:precedence];
+ }
+
+ switch(_type)
+ {
+ case CPNotPredicateType:
+ result = result + [CPString stringWithFormat:@"NOT %s",[args
objectAtIndex:0]];
+ break;
+
+ case CPAndPredicateType:
+ result = result + [CPString stringWithFormat:@"%s AND %s",[args
objectAtIndex:0],[args objectAtIndex:1]];
+ break;
+
+ case CPOrPredicateType:
+ result = result + [CPString stringWithFormat:@"%s OR %s",[args
objectAtIndex:0],[args objectAtIndex:1]];
+ break;
+ }
+
+ return result;
+}
+
+- (CPCompoundPredicateType)compoundPredicateType
+{
+ return _type;
+}
+
+- (CPArray)subpredicates
+{
+ return _predicates;
+}
+
+- (BOOL)evaluateWithObject:(id)object
+{
+ var result = NO;
+ var i,count = [_predicates count];
+
+ for(i = 0;i < count;i++)
+ {
+ var predicate = [_predicates objectAtIndex:i];
+
+ switch(_type)
+ {
+ case CPNotPredicateType:
+ return ![predicate evaluateWithObject:object];
+
+ case CPAndPredicateType:
+ if(i == 0)
+ result = [predicate evaluateWithObject:object];
+ else
+ result = result && [predicate evaluateWithObject:object];
+ break;
+
+ case CPOrPredicateType:
+ if([predicate evaluateWithObject:object])
+ return YES;
+ break;
+ }
+ }
+
+ return result;
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,137 @@
+
+import <Foundation/CPString.j>
+import <Foundation/CPArray.j>
+import <Foundation/CPKeyValueCoding.j>
+import <Foundation/CPDictionary.j>
+import <Foundation/CPCoder.j>
+
+CPConstantValueExpressionType = 0;
+CPEvaluatedObjectExpressionType = 1;
+CPVariableExpressionType = 2;
+CPKeyPathExpressionType = 3;
+CPFunctionExpressionType = 4;
+CPAggregateExpressionType = 5;
+
+@implementation CPExpression : CPObject
+{
+ int _type;
+}
+
+- (id)initWithExpressionType:(int)type
+{
+ _type = type;
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+// IMPLEMENTED BY CONCRETE SUBCLASSES
+ return self;
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+// IMPLEMENTED BY CONCRETE SUBCLASSES
+}
+
++ (CPExpression)expressionForConstantValue:(id)value
+{
+ return [[CPExpression_constant alloc] initWithValue:value];
+}
+
++ (CPExpression)expressionForEvaluatedObject
+{
+ return [[CPExpression_self alloc] init];
+}
+
++ (CPExpression)expressionForVariable:(CPString)string
+{
+ return [[CPExpression_variable alloc] initWithVariable:string];
+}
+
++ (CPExpression)expressionForKeyPath:(CPString)keyPath
+{
+ return [[CPExpression_keypath alloc] initWithKeyPath:keyPath];
+}
+
++ (CPExpression)expressionForFunction:(CPString)function_name
arguments:(CPArray)arguments
+{
+
+ var expression_function = [[CPExpression_function alloc]
initWithName:function_name arguments:arguments];
+
+ var selector = CPSelectorFromString(function_name);
+
+ if (![expression_function respondsToSelector:selector])
+ [CPException raise: CPInvalidArgumentException reason: [CPString
stringWithFormat:@"Unknown function implementation: %s", function_name]];
+
+ [expression_function setSelector:selector];
+
+ return expression_function;
+}
+
++ (CPExpression)expressionForAggregate:(CPArray)collection
+{
+ return [[CPExpression_aggregate alloc] initWithAggregate:collection];
+}
+
+- (int)expressionType
+{
+ return _type;
+}
+
+- (id)constantValue
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPConstantValueExpressionType"];
+ return nil;
+}
+
+- (CPString)variable
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPVariableExpressionType"];
+ return nil;
+}
+
+- (CPString)keyPath
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPKeyPathExpressionType"];
+ return nil;
+}
+
+- (CPString)function
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPFunctionExpressionType"];
+ return nil;
+}
+
+- (CPArray)arguments
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPFunctionExpressionType"];
+ return nil;
+}
+
+- (id)collection
+{
+ [CPException raise:CPInvalidArgumentException reason:@"self is not of
CPAggregateExpressionType"];
+ return nil;
+}
+
+- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
+{
+// IMPLEMENTED BY SUBCLASSES
+ return nil;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+// IMPLEMENTED BY SUBCLASSES
+ return self;
+}
+
+@end
+
+import "CPExpression_aggregate.j"
+import "CPExpression_constant.j"
+import "CPExpression_self.j"
+import "CPExpression_variable.j"
+import "CPExpression_keypath.j"
+import "CPExpression_function.j"

Added: branches/CPRuleEditor/CPExpression_aggregate.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_aggregate.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,95 @@
+
+import "CPExpression.j"
+import <Foundation/CPArray.j>
+import <Foundation/CPString.j>
+
+@implementation CPExpression_aggregate : CPExpression
+{
+ CPArray _aggregate;
+}
+
+- (id)initWithAggregate:(CPArray)collection
+{
+ [super initWithExpressionType:CPAggregateExpressionType];
+ _aggregate = collection;
+ return self;
+}
+
++ (CPExpression)expressionForAggregate:(CPArray)collection
+{
+ return [[self alloc] initWithAggregate:collection];
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ var aggregate = [coder decodeObjectForKey:@"CPExpressionAggregate"];
+ return [self initWithAggregate:aggregate];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ [coder encodeObject:_aggregate forKey:@"CPExpressionAggregate"]; //
subexpressions must be NSCoding compliant.
+}
+
+- (id)collection
+{
+ return _aggregate;
+}
+
+- (CPExpression)rightExpression
+{
+ if([_aggregate count] > 0)
+ return [_aggregate lastObject];
+
+ return nil;
+}
+
+- (CPExpression)leftExpression
+{
+ if([_aggregate count] > 0)
+ return [_aggregate objectAtIndex:0];
+
+ return nil;
+}
+
+- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
+{
+ var eval_array = [CPArray array];
+
+ var collection = [_aggregate objectEnumerator];
+ var exp;
+ while (exp = [collection nextObject]) {
+ var eval = [exp expressionValueWithObject:object context:context];
+ if(eval != nil)[eval_array addObject:eval];
+ }
+
+ return eval_array;
+}
+
+- (CPString)description
+{
+ var i,
+ count = [_aggregate count];
+
+ var result = "{";
+
+ for(i = 0;i < count;i++)
+ result = result + [CPString stringWithFormat:@"%s%s", [[_aggregate
objectAtIndex:i] description], (i + 1 < count) ? @", " : @""];
+
+ result = result + "}";
+ return result;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ var subst_array = [CPArray array];
+ var i,
+ count = [_aggregate count];
+
+ for(i = 0; i < count; i++)
+ [subst_array addObject:[[_aggregate objectAtIndex:i]
_expressionWithSubstitutionVariables:variables]];
+
+ return [CPExpression expressionForAggregate:subst_array];
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression_assignment.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_assignment.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,42 @@
+
+import "CPExpression.j"
+import "CPExpression_operator.j"
+import <Foundation/CPString.j>
+
+
+@implementation CPExpression_assignment: CPExpression
+{
+ CPExpression _variable;
+ CPExpression _expression;
+}
+
+- (id)initWithVariable:(CPExpression)variable
expression:(CPExpression)expression
+{
+ _variable = variable;
+ _expression = expression;
+ return self;
+}
+
++ (CPExpression)expressionWithVariable:(CPExpression)variable
expression:(CPExpression)expression
+{
+ return [[self alloc] initWithVariable:variable expression:expression];
+}
+
+- (CPString)description
+{
+ var pretty = [_expression description];
+
+ if ([_expression isKindOfClass:[CPExpression_operator class]])
+ pretty = [CPString stringWithFormat:@"(%@)", pretty];
+
+ return [CPString stringWithFormat:@"%@ := %@", _variable, pretty];
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+// FIX?
+ return self;
+}
+
+@end
+

Added: branches/CPRuleEditor/CPExpression_constant.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_constant.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,52 @@
+
+import "CPExpression.j"
+import <Foundation/CPDictionary.j>
+
+@implementation CPExpression_constant : CPExpression
+{
+ id _value;
+}
+
+- (id)initWithValue:(id)value
+{
+ [super initWithExpressionType:CPConstantValueExpressionType];
+ _value = value;
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ var value = [coder decodeObjectForKey:@"CPExpressionConstantValue"];
+ return [self initWithValue:value];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+if([_value respondsToSelector:@selector(encodeOject:forKey:)])
+ [coder encodeObject:_value forKey:@"CPExpressionConstantValue"];
+}
+
+- (id)constantValue
+{
+ return _value;
+}
+
+- (id)expressionValueWithObject:object context:(CPDictionary)context
+{
+ return _value;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ return self;
+}
+
+- (CPString)description
+{
+ if([_value isKindOfClass:[CPString class]])
+ return [CPString stringWithFormat:@"\"%s\"",_value];
+ else
+ return [_value description];
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression_function.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_function.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,314 @@
+import "CPExpression.j"
+import <Foundation/CPString.j>
+import <Foundation/CPArray.j>
+import <Foundation/CPDictionary.j>
+
+@implementation CPExpression_function : CPExpression
+{
+ CPString _name;
+ SEL _selector;
+ CPArray _arguments;
+ int _argc;
+}
+
+- (void)setSelector:(SEL)selector
+{
+ _selector = selector;
+}
+
+- (id)initWithName:(CPString)name arguments:(CPArray)arguments
+{
+ [super initWithExpressionType:CPFunctionExpressionType];
+
+ _name = name;
+ _arguments = arguments;
+ _argc = [_arguments count];
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ var name = [coder decodeObjectForKey:@"CPExpressionFunctionName"];
+ var arguments = [coder
decodeObjectForKey:@"CPExpressionFunctionArguments"];
+
+ return [self initWithName:name arguments:arguments];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ [coder encodeObject:_name forKey:@"CPExpressionFunctionName"];
+ [coder encodeObject:_arguments forKey:@"CPExpressionArguments"];
+}
+
+- (CPString)function
+{
+ return _name;
+}
+
+- (CPArray)arguments
+{
+ return _arguments;
+}
+
+- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
+{
+ var subst_args = [CPArray array];
+ var i;
+
+ for (i = 0; i < _argc; i++)
+ [subst_args addObject: [[_arguments objectAtIndex: i]
expressionValueWithObject:object context:context]];
+
+
+ return [self performSelector: _selector withObject: subst_args];
+
+}
+
+- (CPString)description
+{
+ var i;
+
+ var result = [CPString stringWithFormat:@"%s(", _name];
+
+ for(i = 0; i < _argc; i++){
+ result = result + [CPString stringWithFormat:@"%s%s", [_arguments
objectAtIndex:i] , (i+1<_argc) ? ", " : ""];
+ }
+
+ result = result + ")";
+
+ return result;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ var array = [CPArray array];
+ var i;
+
+ for(i = 0; i < _argc; i++)
+ [array addObject:[[_arguments objectAtIndex:i]
_expressionWithSubstitutionVariables:variables]];
+
+ return [CPExpression expressionForFunction:_name arguments:array];
+
+}
+/*
+10.5 documentation for expressionForFunction:arguments:
+
+ This method throws an exception immediately if the selector is unknown;
it throws at runtime if the parameters are incorrect.
+ Parameters
+ name
+ The name of the function to invoke.
+
+ parameters
+ An array containing NSExpression objects that will be used as parameters
during the invocation of selector.
+
+ For a selector taking no parameters, the array should be empty. For a
selector taking one or more parameters, the array should contain one
NSExpression object which will evaluate to an instance of the appropriate
type for each parameter.
+
+ If there is a mismatch between the number of parameters expected and the
number you provide during evaluation, an exception may be raised or missing
parameters may simply be replaced by nil (which occurs depends on how many
parameters are provided, and whether you have over- or underflow).
+
+ Return Value
+ A new expression that invokes the function name using the parameters in
parameters.
+*/
+
+// 10.4 Functions are sum, count, min, max, average
+
+
+- (CPNumber)average:(CPArray)parameters
+{
+ var i;
+ var sum = 0.0;
+
+ for (i = 0; i < _argc; i++)
+ {
+ sum += [[parameters objectAtIndex: i] doubleValue];
+ }
+ return [CPNumber numberWithDouble: sum / _argc];
+}
+
+- (CPNumber)sum:(CPArray)parameters
+{
+ var i;
+ var sum = 0.0;
+
+ for (i = 0; i < _argc; i++)
+ {
+ sum += [[parameters objectAtIndex: i] doubleValue];
+ }
+ return [CPNumber numberWithDouble: sum];
+}
+
+- (CPNumber)count:(CPArray)parameters
+{
+ if (_argc != 1) // raise
+ return CPNotFound;
+
+ return [CPNumber numberWithUnsignedInt: [[parameters objectAtIndex: 0]
count]];
+}
+
+- (CPNumber)min:(CPArray)parameters
+{
+ var i;
+ var min = 0.0;
+ var cur;
+
+ if (_argc > 0)
+ {
+ min = [[parameters objectAtIndex: 0] doubleValue];
+ }
+
+ for (i = 1; i < _argc; i++)
+ {
+ cur = [[parameters objectAtIndex: i] doubleValue];
+ if (min > cur)
+ {
+ min = cur;
+ }
+ }
+ return [CPNumber numberWithDouble: min];
+}
+
+- (CPNumber)max:(CPArray)parameters
+{
+ var i;
+ var max = 0.0;
+ var cur;
+
+ if (_argc > 0)
+ {
+ max = [[parameters objectAtIndex: 0] doubleValue];
+ }
+
+ for (i = 1; i < _argc; i++)
+ {
+ cur = [[parameters objectAtIndex: i] doubleValue];
+ if (max < cur)
+ {
+ max = cur;
+ }
+ }
+ return [CPNumber numberWithDouble: max];
+}
+/*
+- (CPNumber)median:(CPArray)parameters
+{
+}
+- (CPNumber)mode:(CPArray)parameters
+{
+}
+- (CPNumber)stddev:(CPArray)parameters
+{
+}
+- (CPNumber)add:to:(CPArray)parameters
+{
+ var left = [parameters objectAtIndex: 0];
+ var right = [parameters objectAtIndex: 1];
+
+ return [CPNumber numberWithDouble: [left doubleValue] + [right
doubleValue]];
+}
+
+- (CPNumber)from:subtract:(CPArray)parameters
+{
+ var left = [parameters objectAtIndex: 0];
+ var right = [parameters objectAtIndex: 1];
+
+ return [CPNumber numberWithDouble: [left doubleValue] - [right
doubleValue]];
+}
+
+- (CPNumber)multiply:by:(CPArray)parameters
+{
+ var left = [parameters objectAtIndex: 0];
+ var right = [parameters objectAtIndex: 1];
+
+ return [CPNumber numberWithDouble: [left doubleValue] * [right
doubleValue]];
+
+}
+
+- (CPNumber)divide:by:(CPArray)parameters
+{
+ var left = [parameters objectAtIndex: 0];
+ var right = [parameters objectAtIndex: 1];
+
+ return [CPNumber numberWithDouble: [left doubleValue] / [right
doubleValue]];
+}
+
+- (CPNumber)modulus:by:(CPArray)parameters
+{
+}
+- (CPNumber)sqrt:(CPArray)parameters
+{
+ var num = [[parameters objectAtIndex: 0] doubleValue];
+
+ return [CPNumber numberWithDouble: num * num];
+
+}
+
+- (CPNumber)log:(CPArray)parameters
+{
+}
+- (CPNumber)ln:(CPArray)parameters
+{
+}
+- (CPNumber)raise:to:(CPArray)parameters
+{
+}
+- (CPNumber)exp:(CPArray)parameters
+{
+}
+- (CPNumber)ceiling:(CPArray)parameters
+{
+}
+- (CPNumber)abs:(CPArray)parameters
+{
+ var num = [[parameters objectAtIndex: 0] doubleValue];
+ var abs = (num > 0) ? num : (-1) * num;
+
+ return [NSNumber numberWithDouble:abs];
+}
+
+- (CPNumber)trunc:(CPArray)parameters
+{
+}
+- (CPNumber)random
+{
+}
+- (CPNumber)random:(CPArray)parameters
+{
+}
+- (CPNumber)now
+{
+ return [CPDate date];
+}
+
+// These functions are generated when parsing
+
+- (id) first: (CPArray)parameters
+{
+ return [[parameters objectAtIndex: 0] objectAtIndex: 0];
+}
+
+- (id) last: (CPArray)parameters
+{
+ return [[parameters objectAtIndex: 0] lastObject];
+}
+
+- (CPNumber)chs:(CPArray)parameters
+{
+ return [CPNumber numberWithInt: -[[parameters objectAtIndex: 0]
intValue]];
+}
+
+- (id)index:(CPArray)parameters
+{
+ var left = [parameters objectAtIndex: 0];
+ var right = [parameters objectAtIndex: 1];
+
+ if ([left isKindOfClass: [CPDictionary class]])
+ {
+ return [left objectForKey: right];
+ }
+ else
+ {
+ // raises exception if invalid
+ return [left objectAtIndex: [right unsignedIntValue]];
+ }
+}
+*/
+
+@end

Added: branches/CPRuleEditor/CPExpression_keypath.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_keypath.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,49 @@
+
+import "CPExpression.j"
+import <Foundation/CPString.j>
+import <Foundation/CPKeyValueCoding.j>
+
+@implementation CPExpression_keypath : CPExpression
+{
+ CPString _keyPath;
+}
+
+- (id)initWithKeyPath:(CPString)keyPath
+{
+ [super initWithExpressionType:CPKeyPathExpressionType];
+ _keyPath = keyPath ;
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ var keyPath = [coder decodeObjectForKey:@"CPExpressionKeyPath"];
+ return [self initWithKeyPath:keyPath];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ [coder encodeObject:_keyPath forKey:@"CPExpressionKeyPath"];
+}
+
+- (CPString)keyPath
+{
+ return _keyPath;
+}
+
+- (id)expressionValueWithObject:object context:(CPDictionary)context
+{
+ return [object valueForKeyPath:_keyPath];
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ return self;
+}
+
+- (CPString)description
+{
+ return _keyPath;
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression_operator.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_operator.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,115 @@
+
+import "CPExpression.j"
+import <Foundation/CPArray.j>
+import <Foundation/CPString.j>
+import <Foundation/CPDictionary.j>
+
+ var CPExpressionOperatorNegate = "CPExpressionOperatorNegate";
+ var CPExpressionOperatorAdd = "CPExpressionOperatorAdd";
+ var CPExpressionOperatorSubtract = "CPExpressionOperatorSubtract";
+ var CPExpressionOperatorMultiply = "CPExpressionOperatorMultiply";
+ var CPExpressionOperatorDivide = "CPExpressionOperatorDivide";
+ var CPExpressionOperatorExp = "CPExpressionOperatorExp";
+ var CPExpressionOperatorAssign = "CPExpressionOperatorAssign";
+ var CPExpressionOperatorKeypath = "CPExpressionOperatorKeypath";
+ var CPExpressionOperatorIndex = "CPExpressionOperatorIndex";
+ var CPExpressionOperatorIndexFirst = "CPExpressionOperatorIndexFirst";
+ var CPExpressionOperatorIndexLast = "CPExpressionOperatorIndexLast";
+ var CPExpressionOperatorIndexSize = "CPExpressionOperatorIndexSize";
+
+@implementation CPExpression_operator : CPExpression
+{
+ int _operator;
+ CPArray _arguments;
+}
+
+- (id)initWithOperator:(int)operator arguments:(CPArray)arguments
+{
+ _operator = operator;
+ _arguments = arguments;
+ return self;
+}
+
++ (CPExpression)expressionForOperator:(CPExpressionOperator)operator
arguments:(CPArray)arguments
+{
+ return [self initWithOperator:operator arguments:arguments];
+}
+
+- (CPArray)arguments
+{
+ return _arguments;
+}
+
+- (CPString)description
+{
+ var result = [CPString string];
+ var args = [CPArray array];
+ var i,
+ count = [_arguments count];
+
+ for(i = 0; i < count; i++)
+ {
+ var check = [_arguments objectAtIndex:i];
+ var precedence = [check description];
+
+ if ([check isKindOfClass:[CPExpression_operator class]])
+ precedence = [CPString stringWithFormat:@"(%@)", precedence];
+
+ [args addObject:precedence];
+ }
+
+ switch(_operator)
+ {
+ case CPExpressionOperatorNegate : result = result + [CPString
stringWithFormat:@"-%@", [args objectAtIndex:0]];
+ break;
+
+ case CPExpressionOperatorAdd : result = result + [CPString
stringWithFormat:@"%@ + %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorSubtract : result = result + [CPString
stringWithFormat:@"%@ - %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorMultiply : result = result + [CPString
stringWithFormat:@"%@ * %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorDivide : result = result + [CPString
stringWithFormat:@"%@ / %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorExp : result = result + [CPString
stringWithFormat:@"%@ ** %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorAssign : result = result + [CPString
stringWithFormat:@"%@ := %@", [args objectAtIndex:0], [args
objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorKeypath : result = result + [CPString
stringWithFormat:@"%@.%@", [args objectAtIndex:0], [args objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorIndex : result = result + [CPString
stringWithFormat:@"%@[%@]", [args objectAtIndex:0], [args objectAtIndex:1]];
+ break;
+
+ case CPExpressionOperatorIndexFirst : result = result + [CPString
stringWithFormat:@"%@[FIRST]", [args objectAtIndex:0]];
+ break;
+
+ case CPExpressionOperatorIndexLast : result = result + [CPString
stringWithFormat:@"%@[LAST]", [args objectAtIndex:0]];
+ break;
+
+ case CPExpressionOperatorIndexSize : result = result + [CPString
stringWithFormat:@"%@[SIZE]", [args objectAtIndex:0]];
+ break;
+ }
+
+ return result;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ var array = [CPArray array];
+ var i,
+ count = [_arguments count];
+
+ for(i = 0; i < count; i++)
+ [array addObject:[[_arguments objectAtIndex:i]
_expressionWithSubstitutionVariables:variables]];
+
+ return [CPExpression_operator expressionForOperator:_operator
arguments:array];
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression_self.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_self.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,38 @@
+
+import "CPExpression.j"
+import <Foundation/CPString.j>
+import <Foundation/CPDictionary.j>
+import <Foundation/CPCoder.j>
+
+@implementation CPExpression_self : CPExpression{}
+
+- (id)init
+{
+ [super initWithExpressionType:CPEvaluatedObjectExpressionType];
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ return [self init];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+}
+- (id)expressionValueWithObject:object context:(CPDictionary)context
+{
+ return object;
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ return self;
+}
+
+- (CPString)description
+{
+ return @"SELF";
+}
+
+@end

Added: branches/CPRuleEditor/CPExpression_variable.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPExpression_variable.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,55 @@
+
+import "CPExpression.j"
+import <Foundation/CPString.j>
+import <Foundation/CPDictionary.j>
+
+@implementation CPExpression_variable : CPExpression
+{
+ CPString _variable;
+}
+
+- (id)initWithVariable:(CPString)variable
+{
+ [super initWithExpressionType:CPVariableExpressionType];
+ _variable = [variable copy];
+ return self;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ var variable = [coder decodeObjectForKey:@"CPExpressionVariable"];
+ return [self initWithVariable:variable];
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ [coder encodeObject:_variable forKey:@"CPExpressionVariable"];
+}
+
+- (CPString)variable
+{
+ return _variable;
+}
+
+- (id)expressionValueWithObject:object context:(CPDictionary)context
+{
+ return [context objectForKey: _variable];
+}
+
+- (CPString)description
+{
+ return [CPString stringWithFormat:@"$%s", _variable];
+}
+
+-
(CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
+{
+ var aconstant = [variables objectForKey:_variable];
+
+ if (aconstant != nil)
+ return [CPExpression expressionForConstantValue:aconstant];
+
+ return self;
+}
+
+
+@end

Added: branches/CPRuleEditor/CPImageNameAddTemplate.tiff
==============================================================================
Binary file. No diff available.

Added: branches/CPRuleEditor/CPImageNameRemoveTemplate.tiff
==============================================================================
Binary file. No diff available.

Added: branches/CPRuleEditor/CPPredicate.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPPredicate.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,113 @@
+
+import <Foundation/CPValue.j>
+import <Foundation/CPArray.j>
+import <Foundation/CPNull.j>
+
+@implementation CPPredicate : CPObject
+{
+}
+
+- (CPString)description
+{
+ return [self predicateFormat];
+}
+
++ (CPPredicate)predicateWithValue:(BOOL)value
+{
+ return [[CPPredicate_BOOL alloc] initWithBool:value];
+}
+
+- (BOOL) evaluateWithObject:(id)object
+{
+ // IMPLEMENTED BY SUBCLASSES
+}
+
+- (CPString) predicateFormat
+{
+ // IMPLEMENTED BY SUBCLASSES
+}
+
+- (CPPredicate) predicateWithSubstitutionVariables: (CPDictionary)variables
+{
+ // IMPLEMENTED BY SUBCLASSES
+}
+
++ (CPPredicate) predicateWithFormat: (CPString) format, ...
+{
+ // UNIMPLEMENTED
+}
+
++ (CPPredicate) predicateWithFormat: (CPString)format argumentArray:
(CPArray)args
+{
+ // UNIMPLEMENTED
+}
+
++ (CPPredicate) predicateWithFormat: (CPString)format arguments:
(va_list)args
+{
+ // UNIMPLEMENTED
+}
+
+@end
+
+@implementation CPPredicate_BOOL : CPPredicate
+{
+ BOOL _value;
+}
+
+- (id)initWithBool:(BOOL)value
+{
+ _value = value;
+ return self;
+}
+
+- (BOOL)evaluateObject:(id)object
+{
+ return _value;
+}
+
+- (CPString)predicateFormat
+{
+ return (_value) ? @"TRUEPREDICATE" : @"FALSEPREDICATE";
+}
+
+@end
+
+@implementation CPArray (CPPredicate)
+
+- (CPArray)filteredArrayUsingPredicate:(CPPredicate)predicate
+{
+ var i,count = [self count];
+ var result = [CPArray array];
+
+ for(i = 0;i < count;i++){
+ var object = [self objectAtIndex:i];
+
+ if([predicate evaluateWithObject:object])
+ [result addObject:object];
+ }
+
+ return result;
+}
+
+- (void)filterUsingPredicate:(CPPredicate)predicate
+{
+ var count = [self count];
+
+ while(--count >= 0){
+ var check=[self objectAtIndex:count];
+
+ if(![predicate evaluateWithObject:check])
+ [self removeObjectAtIndex:count];
+ }
+}
+
+@end
+
+
+import "CPCompoundPredicate.j"
+import "CPComparisonPredicate.j"
+import "CPExpression.j"
+
+import "CPExpression_operator.j"
+import "CPExpression_aggregate.j"
+import "CPExpression_assignment.j"

Added: branches/CPRuleEditor/CPPredicateTests.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPPredicateTests.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,56 @@
+//
+// main.j
+
+import <Foundation/Foundation.j>
+import <AppKit/AppKit.j>
+import "CPPredicate.j"
+
+@implementation CPString (Description)
+-(CPString)description
+{
+ return self;
+}
+@end
+
+function main(args, namedArgs)
+{
+ CPLogRegister(CPLogConsole);
+ var keyPathExp = [CPExpression expressionForKeyPath:@"name"];
+ CPLogConsole(keyPathExp);
+ var regexExp = [CPExpression expressionForConstantValue:@"j[a-z]an"];
+ CPLogConsole(regexExp);
+ var constantExpNum = [CPExpression
expressionForConstantValue:[CPNumber numberWithInt:20]];
+ CPLogConsole(constantExpNum);
+ var variableExp = [CPExpression expressionForVariable:@"variable"];
+ CPLogConsole(variableExp);
+ var functionExp = [CPExpression expressionForFunction:@"sum:"
arguments:[CPArray arrayWithObjects:constantExpNum,constantExpNum,nil]];
+ CPLogConsole(functionExp);
+ var evalExp = [CPExpression expressionForEvaluatedObject];
+ CPLogConsole(evalExp);
+ var aggregateExp = [CPExpression expressionForAggregate:[CPArray
arrayWithObjects:keyPathExp,regexExp,functionExp,nil]];
+ CPLogConsole(aggregateExp);
+
+ var entry1 = [CPDictionary dictionaryWithObject:@"Jean"
forKey:@"name"];
+ [entry1 setObject:[CPNumber numberWithInt:38] forKey:@"age"];
+
+ var entry2 = [CPDictionary dictionaryWithObject:@"Paul"
forKey:@"name"];
+ [entry2 setObject:[CPNumber numberWithInt:32] forKey:@"age"];
+
+ var array = [CPArray arrayWithObjects:entry1,entry2,nil];
+
+ var predicate1 = [[CPComparisonPredicate alloc]
initWithLeftExpression:[CPExpression expressionForKeyPath:@"name"]
rightExpression:regexExp modifier:CPDirectPredicateModifier
type:CPLikePredicateOperatorType options:1];
+ var predicate2 = [[CPComparisonPredicate alloc]
initWithLeftExpression:[CPExpression expressionForKeyPath:@"age"]
rightExpression:functionExp modifier:CPDirectPredicateModifier
type:CPLessThanPredicateOperatorType options:3];
+
+ var compound_predicate = [[CPCompoundPredicate alloc]
initWithType:CPAndPredicateType subpredicates:[CPArray
arrayWithObjects:predicate1,predicate2,nil]];
+ CPLogConsole([CPString
stringWithFormat:@"PREDICATE: %s",[compound_predicate description]]);
+
+ CPLogConsole([CPString stringWithFormat:@"UNFILTERED(%d): %s", [array
count], [array description]]);
+
+ var filtered = [array filteredArrayUsingPredicate:compound_predicate];
+
+ CPLogConsole([CPString stringWithFormat:@"FILTERED(%d): %s", [filtered
count], [filtered description]]);
+
+ var predicate = [[CPComparisonPredicate alloc]
initWithLeftExpression:[CPExpression expressionForConstantValue:@"abba"]
rightExpression:[CPExpression expressionForConstantValue:@"ab[f-g]*"]
modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType
options:2];
+
+ CPLogConsole(""+predicate+" --> "+[predicate evaluateWithObject:nil]);
+ }

Added: branches/CPRuleEditor/CPRuleEditor.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditor.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,1766 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+
+
+import "CPPredicate.j"
+import "_CPRuleEditorCache.j"
+import "_CPRuleEditorViewSliceHolder.j"
+import "_CPRuleEditorViewUnboundRowHolder.j"
+import "CPRuleEditorViewSliceDropSeparator.j"
+
+CPRuleEditorPredicateLeftExpression
= "CPRuleEditorPredicateLeftExpression";
+CPRuleEditorPredicateRightExpression
= "CPRuleEditorPredicateRightExpression";
+CPRuleEditorPredicateComparisonModifier
= "CPRuleEditorPredicateComparisonModifier";
+CPRuleEditorPredicateOptions = "CPRuleEditorPredicateOptions";
+CPRuleEditorPredicateOperatorType = "CPRuleEditorPredicateOperatorType";
+CPRuleEditorPredicateCustomSelector
= "CPRuleEditorPredicateCustomSelector";
+CPRuleEditorPredicateCompoundType = "CPRuleEditorPredicateCompoundType";
+
+CPRuleEditorRowsDidChangeNotification
= "CPRuleEditorRowsDidChangeNotification";
+CPRuleEditorRulesDidChangeNotification
= "CPRuleEditorRulesDidChangeNotification";
+
+CPRuleEditorNestingModeSingle = 0; // Only a single row is allowed.
Plus/minus buttons will not be shown
+CPRuleEditorNestingModeList = 1; // Allows a single list, with no
nesting and no compound rows
+CPRuleEditorNestingModeCompound = 2; // Unlimited nesting and compound
rows; this is the default
+CPRuleEditorNestingModeSimple = 3; // One compound row at the top with
subrows beneath it, and no further nesting allowed
+
+var CPRuleEditorNestingMode;
+
+CPRuleEditorRowTypeSimple = 0;
+CPRuleEditorRowTypeCompound = 1;
+
+var CPRuleEditorRowType;
+
+var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType";
+
+var itemsContext = @"items";
+var valuesContext = @"values";
+var subrowsContext = @"subrows_array";
+var boundArrayContext = @"bound_array";
+
+@implementation RuleEditor : CPView
+{
+
+ var elideUpdating = 1;
+ var lastAlternateKeyValue = 1;
+ var extendedDelegateCalls = 1;
+ var editable = 1;
+ var settingSize = 1;
+ var suppressKeyDown = 1;
+ var dropWasSuccessful = 1;
+ var delegateWantsValidation = 1;
+ var disallowEmpty = 1;
+ var lastDrewWithFRAppearance = 1;
+ var allowsEmptyCompoundRows = 1;
+ var dropChangedRowCount = 1;
+ var reserved = 20;
+
+ CALayer _rootLayer;
+ Class _rowClass;
+
+ CPIndexSet _draggingRows;
+ int _subviewIndexOfDropLine;
+ id _dropLineView;
+
+ CPMutableArray _rowCache;
+ CPMutableArray _slices;
+
+ CPPredicate _predicate;
+
+ CPString _boundArrayKeyPath;
+ CPString _itemsKeyPath;
+ CPString _subrowsArrayKeyPath;
+ CPString _typeKeyPath;
+ CPString _valuesKeyPath;
+
+ CPTimer _frameTimer;
+ CPView _slicesHolder;
+ CPViewAnimation _currentAnimation;
+
+ int _lastRow;
+ int _nestingMode;
+
+ float _alignmentGridWidth;
+ float _sliceHeight;
+
+ id _ruleDataSource;
+ id _ruleDelegate;
+ id _boundArrayOwner;
+
+ CPString _stringsFilename;
+ id _headerLocalizer;
+ id _standardLocalizer;
+
+ id _ruleReserved1;
+ id _ruleReserved2;
+}
+
++ (void)initialize
+{
+
+}
+
+- (void)windowWillClose:(CPNotification)window
+{
+ var observationInfo = [self observationInfo];
+ var binders = [observationInfo
valueForKeyPath:@"_observances._observer._observer"];
+ [binders
makeObjectsPerformSelector:@selector(releaseConnectionWithSynchronizePeerBinders:)
withObject:YES];
+}
+
+- (BOOL)isFlipped
+{
+ return YES;
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ self = [super initWithCoder:coder];
+ if (self != nil) {
+ // BOOL int float : we should nil check keys first.
+ _alignmentGridWidth = [coder
decodeDoubleForKey:@"CPRuleEditorAlignmentGridWidth"];
+ _sliceHeight = [coder decodeDoubleForKey:@"CPRuleEditorSliceHeight"];
+
+ editable = [coder decodeBoolForKey:@"CPRuleEditorEditable"];
+ allowsEmptyCompoundRows = [coder
decodeBoolForKey:@"CPRuleEditorAllowsEmptyCompoundRows"];
+ disallowEmpty = [coder decodeBoolForKey:@"CPRuleEditorDisallowEmpty"];
+
+ _nestingMode = [coder decodeIntForKey:@"CPRuleEditorNestingMode"];
+
+ _typeKeyPath = [[coder decodeObjectForKey:@"CPRuleEditorRowTypeKeyPath"]
retain];
+ _itemsKeyPath = [[coder decodeObjectForKey:@"CPRuleEditorItemsKeyPath"]
retain];
+ _valuesKeyPath = [[coder
decodeObjectForKey:@"CPRuleEditorValuesKeyPath"] retain];
+ _subrowsArrayKeyPath = [[coder
decodeObjectForKey:@"CPRuleEditorSubrowsArrayKeyPath"] retain];
+ _boundArrayKeyPath = [[coder
decodeObjectForKey:@"CPRuleEditorBoundArrayKeyPath"] retain];
+
+ _rowClass = CPClassFromString([coder
decodeObjectForKey:@"CPRuleEditorRowClass"]);
+ _boundArrayOwner = [coder
decodeObjectForKey:@"CPRuleEditorBoundArrayOwner"];
+
+ _slices = [[coder decodeObjectForKey:@"CPRuleEditorSlices"] retain];
+ // var dragTypes = [coder decodeObjectForKey:@"CPDragTypes"];
+
+ [self _initRuleEditorShared];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(id)coder
+{
+ [super encodeWithCoder:coder];
+
+ [coder encodeBool:editable forKey:@"CPRuleEditorEditable"];
+ [coder encodeBool:allowsEmptyCompoundRows
forKey:@"CPRuleEditorAllowsEmptyCompoundRows"];
+ [coder encodeBool:disallowEmpty forKey:@"CPRuleEditorDisallowEmpty"];
+
+ [coder encodeObject:_typeKeyPath forKey:@"CPRuleEditorRowTypeKeyPath"];
+ [coder encodeObject:_itemsKeyPath forKey:@"CPRuleEditorItemsKeyPath"];
+ [coder encodeObject:_valuesKeyPath forKey:@"CPRuleEditorValuesKeyPath"];
+ [coder encodeObject:_boundArrayKeyPath
forKey:@"CPRuleEditorBoundArrayKeyPath"];
+ [coder encodeObject:_subrowsArrayKeyPath
forKey:@"CPRuleEditorSubrowsArrayKeyPath"];
+ [coder encodeObject:CPStringFromClass(_rowClass)
forKey:@"CPRuleEditorRowClass"];
+
+ [coder encodeObject:_slices forKey:@"CPRuleEditorSlices"];
+ [coder encodeObject:_boundArrayOwner
forKey:@"CPRuleEditorBoundArrayOwner"];
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self != nil) {
+ _rootLayer = [CALayer layer];
+
+ [self setWantsLayer:YES];
+ [self setLayer:_rootLayer];
+ [_rootLayer setNeedsDisplay];
+
+ [self _initRuleEditorShared];
+ }
+ return self;
+}
+
+- (void)_initRuleEditorShared
+{
+// _currentAnimation = [[CPViewAnimation alloc] initWithDuration:0.
animationCurve:CPAnimationEaseInOut];
+// [_currentAnimation setAnimationBlockingMode:CPAnimationNonblocking];
+
+ _rowCache = [[CPMutableArray alloc] init];
+ _slices = [[CPMutableArray alloc] init];
+
+ _nestingMode = CPRuleEditorNestingModeSimple; // 10.5 default =
CPRuleEditorNestingModeCompound
+ _subviewIndexOfDropLine = -1;
+ _lastRow = 0;
+ editable = 1;
+ delegateWantsValidation = 1;
+
+ _rowClass = [CPDictionary class];
+ _itemsKeyPath = @"criteria";
+ _subrowsArrayKeyPath = @"subrows";
+ _typeKeyPath = @"rowType";
+ _valuesKeyPath = @"displayValues";
+ _boundArrayKeyPath = @"boundArray";
+
+ _dropLineView = [self _createSliceDropSeparator];
+
+ _slicesHolder = [[RuleEditorViewSliceHolder alloc] initWithFrame:[self
bounds]];
+ [_slicesHolder setAutoresizingMask:64];
+ // [_slicesHolder addSubview:_dropLineView];
+ [self addSubview:_slicesHolder];
+
+ _boundArrayOwner = [[RuleEditorViewUnboundRowHolder alloc] init];
+ [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath
options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew
context:boundArrayContext];
+ [self registerForDraggedTypes:[CPArray
arrayWithObjects:CPRuleEditorItemPBoardType,nil]];
+
+ var center = [CPNotificationCenter defaultCenter];
+ [center addObserver:self selector:@selector(windowWillClose:)
name:CPWindowWillCloseNotification object:nil];
+ [center addObserver:self selector:@selector(reloadPredicate)
name:CPRuleEditorRulesDidChangeNotification object:nil];
+}
+
+- (RuleEditorViewSliceDropSeparator)_createSliceDropSeparator
+{
+ var view = [[RuleEditorViewSliceDropSeparator alloc]
initWithFrame:CGRectMake(0,-5, [self frame].size.width, 2)];
+ [view setAutoresizingMask:CPViewWidthSizable];
+ return view;
+}
+
+- (BOOL)_suppressKeyDownHandling
+{
+ return suppressKeyDown;
+}
+
+- (BOOL)_wantsRowAnimations
+{
+ return YES;
+}
+
+- (BOOL)_allowsEmptyCompoundRows
+{
+ return allowsEmptyCompoundRows;
+}
+
+- (void)_setAllowsEmptyCompoundRows:(BOOL)value
+{
+ allowsEmptyCompoundRows = value;
+}
+
+- (BOOL)canRemoveAllRows
+{
+ return !disallowEmpty;
+}
+
+- (void)setCanRemoveAllRows:(BOOL)value
+{
+ disallowEmpty = !value;
+}
+
+- (BOOL)isEditable
+{
+ return editable;
+}
+
+- (void)setEditable:(BOOL)value
+{
+ editable = value;
+}
+
+ - (float)_alignmentGridWidth
+{
+ return _alignmentGridWidth;
+}
+
+- (float)_minimumFrameHeight
+{
+ return 25.;
+}
+
+- (Class)rowClass
+{
+ return _rowClass;
+}
+
+- (void)setRowClass:(Class)aclass
+{
+ _rowClass = aclass;
+}
+
+- (float)rowHeight
+{
+ return _sliceHeight;
+}
+
+- (void)setRowHeight:(float)height
+{
+ _sliceHeight = height;
+}
+
+- (void)setBoundArrayKeyPath:(CPString)value
+{
+ if (_boundArrayKeyPath != value)
+ _boundArrayKeyPath = value;
+}
+
+- (CPString)criteriaKeyPath
+{
+ return _itemsKeyPath;
+}
+
+- (void)setCriteriaKeyPath:(CPString)value
+{
+ if (_itemsKeyPath != value) {
+ _itemsKeyPath = value;
+ }
+}
+
+- (CPString)displayValuesKeyPath
+{
+ return _valuesKeyPath;
+}
+
+- (void)setDisplayValuesKeyPath:(CPString)value
+{
+ if (_valuesKeyPath != value) {
+ _valuesKeyPath = [value retain];
+ }
+}
+
+- (CPString)subrowsKeyPath
+{
+ return _subrowsArrayKeyPath;
+}
+
+- (void)setSubrowsKeyPath:(CPString)value
+{
+ if (_subrowsArrayKeyPath != value) {
+ _subrowsArrayKeyPath = [value retain];
+ }
+}
+
+- (CPString)rowTypeKeyPath
+{
+ return _typeKeyPath;
+}
+
+- (void)setRowTypeKeyPath:(CPString)value
+{
+ if (_typeKeyPath != value) {
+ _typeKeyPath = [value retain];
+ }
+}
+
+- (id)delegate
+{
+ return _ruleDelegate;
+}
+
+- (void)setDelegate:(id)newDelegate
+{
+ if(_ruleDelegate != newDelegate){
+
+ var nc = [CPNotificationCenter defaultCenter];
+
+ if (_ruleDelegate)[nc removeObserver:_ruleDelegate name:nil object:self];
+
+ _ruleDelegate = newDelegate;
+
+ if ([_ruleDelegate
respondsToSelector:@selector(ruleEditorRowsDidChange:)])
+ [nc addObserver:_ruleDelegate
selector:@selector(ruleEditorRowsDidChange:)
name:CPRuleEditorRowsDidChangeNotification object:self];
+ }
+}
+
+- (CPRuleEditorNestingMode)nestingMode
+{
+ return _nestingMode;
+}
+
+- (void)setNestingMode:(CPRuleEditorNestingMode)mode
+{
+ _nestingMode = mode;
+ // verif si des rows sont deja ajoutées
+}
+
+- (CPRuleEditorNestingMode)_applicableNestingMode
+{
+ return [self nestingMode];
+}
+
+- (BOOL)_shouldHideAddButtonForSlice:(id)slice
+{
+ return (_nestingMode == CPRuleEditorNestingModeSingle);
+}
+
+- (BOOL)_shouldHideSubtractButtonForSlice:(id)slice
+{
+ if (disallowEmpty == NO) return NO;
+
+ switch (_nestingMode)
+ {
+ case CPRuleEditorNestingModeCompound:
+ return NO; // UNIMPLEMENTED
+ case CPRuleEditorNestingModeSimple:
+ return ([slice rowIndex] == 0);
+ break;
+ case CPRuleEditorNestingModeList:
+ return ([self numberOfRows]==1);
+ break;
+ case CPRuleEditorNestingModeSingle:
+ return YES;
+ break;
+ default:
+ return NO;
+ }
+
+ return NO;
+}
+
+- (int)numberOfRows
+{
+ return [_slices count];
+}
+
+/* ROWS INSERT/REMOVE */
+
+- (id)_rowCacheForIndex:(int)index
+{
+ return [_rowCache objectAtIndex:index];
+}
+
+- (id)_searchCacheForRowObject:(id)rowObject
+{
+ for(var cache in _rowCache)
+ if([cache rowObject] == rowObject)
+ return cache;
+
+ return nil;
+}
+
+- (int)_rowIndexForRowObject:(id)rowobject
+{
+ if(rowobject == _boundArrayOwner) return -1;
+
+ return [[self _searchCacheForRowObject:rowobject] rowIndex]; // Pas bon
car le rowIndex du row cache n'est pas synchro avec la position dans
_rowCache.
+}
+
+- (int)parentRowForRow:(int)rowIndex
+{
+ if(rowIndex < 0 || rowIndex > [self numberOfRows])
+ [CPException raise:CPRangeException format:@"row %d is out of
range",rowIndex];
+
+
+ var targetObject = [[self _rowCacheForIndex:rowIndex] rowObject];
+
+ var current_index;
+ for (current_index = 0; current_index < rowIndex; current_index ++){
+ if([self rowTypeForRow:current_index] == CPRuleEditorRowTypeCompound){
+ var candidate = [[self _rowCacheForIndex:current_index] rowObject];
+ var subObjects = [self _subrowObjectsOfObject:candidate];
+
+ if([subObjects indexOfObjectIdenticalTo:targetObject] != CPNotFound)
+ return current_index;
+ }
+ }
+ return -1;
+}
+
+- (CPMutableArray)_subrowObjectsOfObject:(id)object
+{
+ if(object == _boundArrayOwner)
+ return [object mutableArrayValueForKey:_boundArrayKeyPath];
+ else
+ return [object mutableArrayValueForKey:_subrowsArrayKeyPath];
+
+}
+
+- (CPIndexSet)subrowIndexesForRow:(int)rowIndex
+{
+ var object;
+ if(rowIndex == -1)
+ object = _boundArrayOwner;
+ else if(rowIndex<[self numberOfRows])
+ object = [[self _rowCacheForIndex:rowIndex] rowObject];
+ else [CPException raise:CPRangeException format:@"row(%d) is greater than
the number of rows",rowIndex];
+
+ var subobjects = [self _subrowObjectsOfObject:object];
+ var objectsCount = [subobjects count];
+
+ var indexes = [CPMutableIndexSet indexSet];
+ var i;
+ for (i=rowIndex+1; i<[self numberOfRows]; i++) {
+ var candidate = [[self _rowCacheForIndex:i] rowObject];
+ var indexInSubrows = [subobjects indexOfObjectIdenticalTo:candidate];
+
+ if(indexInSubrows != CPNotFound){
+ [indexes addIndex:i];
+ objectsCount --;
+ // [buffer removeObjectAtIndex:indexInSubrows];
+ if([self rowTypeForRow:i]==CPRuleEditorRowTypeCompound)i+=[[self
subrowIndexesForRow:i] count];
+ }
+ if(objectsCount==0) break;
+ }
+ return indexes;
+}
+
+- (CPIndexSet)_childlessParentsIfSlicesWereDeletedAtIndexes:(id)indexes
+{
+ var childlessParents = [CPMutableIndexSet indexSet];
+
+ var current_index = [indexes firstIndex];
+
+ while (current_index != CPNotFound) {
+ var parentIndex = [self parentRowForRow:current_index];
+ var subrowsIndexes = [self subrowIndexesForRow:parentIndex];
+
+ if([subrowsIndexes count]==1 && [subrowsIndexes
firstIndex]==current_index)
+ {
+ [childlessParents addIndex:parentIndex];
+ var moreChildless = [self
_childlessParentsIfSlicesWereDeletedAtIndexes:[CPIndexSet
indexSetWithIndex:parentIndex]];
+ [childlessParents addIndexes:moreChildless];
+ }
+
+ current_index = [indexes indexGreaterThanIndex:current_index];
+ }
+
+ return childlessParents;
+ // (id)-[RuleEditor _includeSubslicesForSlicesAtIndexes:]
+}
+
+- (CPIndexSet)_includeSubslicesForSlicesAtIndexes:(CPIndexSet)indexes
+{
+ var subindexes = [CPMutableIndexSet indexSet];
+ [subindexes addIndexes:indexes];
+
+ var current_index = [indexes firstIndex];
+
+ while (current_index != CPNotFound) {
+ var sub = [self subrowIndexesForRow:current_index];
+ [subindexes addIndexes:[self _includeSubslicesForSlicesAtIndexes:sub]];
+ current_index = [indexes indexGreaterThanIndex:current_index];
+ }
+
+ return subindexes;
+
+}
+
+- (void)_deleteSlice:(id)slice
+{
+ // TO DO : remove compound row / remove childless parent row
+
+ // For compound row deletion
+ // (BOOL)-[RuleEditor _allowsEmptyCompoundRows]
+ // (id)-[RuleEditor _childlessParentsIfSlicesWereDeletedAtIndexes:]
+ // (void)-[RuleEditor removeRowsAtIndexes:includeSubrows:]
+ // (void)-[RuleEditor _updatePredicate]
+
+ var rowindex = [slice rowIndex];
+ [self removeRowsAtIndexes:[CPIndexSet indexSetWithIndex:rowindex]
includeSubrows:YES];
+
+// [self _postRuleOptionChangedNotification];
+ [self
_postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification
indexes:[CPIndexSet indexSetWithIndex:rowindex]]; // indexes should include
childs
+}
+
+- (void)removeRowAtIndex:(int)rowIndex
+{
+ // TO DO : remove compound row
+ [self removeRowsAtIndexes:[CPIndexSet indexSetWithIndex:rowIndex]
includeSubrows:NO];
+}
+
+- (void)removeRowsAtIndexes:(CPIndexSet)indexes
includeSubrows:(BOOL)include
+{
+ if([indexes count]==0) return;
+
+ var current_index = [indexes firstIndex];
+
+ var parentRowIndex = [self parentRowForRow:current_index];
+ var parentRowObject;
+
+ if(parentRowIndex == -1)
+ parentRowObject = _boundArrayOwner;
+ else
+ parentRowObject = [[self _rowCacheForIndex:parentRowIndex] rowObject];
+
+ var subrows = [self _subrowObjectsOfObject:parentRowObject];
+
+ var childsIndexes = [CPMutableIndexSet indexSet];
+
+ while (current_index != CPNotFound) {
+ var rowObject = [[self _rowCacheForIndex:current_index] rowObject];
+
+ var relativeChildIndex = [subrows indexOfObjectIdenticalTo:rowObject];
+ if(relativeChildIndex != CPNotFound)[childsIndexes
addIndex:relativeChildIndex];
+
+ if(include && [self rowTypeForRow:current_index] ==
CPRuleEditorRowTypeCompound)
+ {
+ var more_childs = [self subrowIndexesForRow:current_index];
+ [self removeRowsAtIndexes:more_childs includeSubrows:include];
+ }
+
+ current_index = [indexes indexGreaterThanIndex:current_index];
+ }
+
+ [subrows removeObjectsAtIndexes:childsIndexes];
+}
+
+/* KVO & UICHANGES */
+
+- (void)addObserver:(CPObject)anObserver forKeyPath:(CPString)keyPath
options:(CPKeyValueObservingOptions)options context:(void)context
+{
+ CPLogConsole(@"addObserver:" + anObserver +" keypath: " + keyPath + "
options:" + options);
+ [super addObserver:anObserver forKeyPath:keyPath options:options
context:context];
+}
+
+- (void)_setBoundDataSource:(id)datasource withKeyPath:(CPString)keyPath
options:(CPDictionary)options
+{
+ if(_boundArrayOwner)
+ {
+ [_boundArrayOwner removeObserver:self forKeyPath:_boundArrayKeyPath];
+ [_boundArrayOwner release];
+ }
+ [self setBoundArrayKeyPath:keyPath];
+
+ var boundRows = [CPArray arrayWithArray:[datasource valueForKey:keyPath]];
+
+ [[datasource valueForKey:keyPath] removeAllObjects];
+ _boundArrayOwner = [datasource retain];// retain or not retain the bound
object ?
+
+ [_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath
options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew
context:boundArrayContext];
+
+ if([boundRows count]>0)
+ [[self _subrowObjectsOfObject:_boundArrayOwner] insertObjects:boundRows
atIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [boundRows
count])]];
+
+}
+
+- (CPMutableArray)_getItemsAndValuesToAddForRow:(int)rowIndex
ofType:(CPRuleEditorRowType)type
+{
+ var itemsAndValues = [CPMutableArray array];
+
+ var item = nil;
+ var numItems;
+ var firstItemAdded = NO;
+
+ var relativeIndex = (type == CPRuleEditorRowTypeSimple) ? rowIndex :
rowIndex - [self parentRowForRow:rowIndex] -1;
+
+ while((numItems = [self _queryNumberOfChildrenOfItem:item
withRowType:type]) > 0){
+
+ var itemAndValue = [CPDictionary dictionary];
+
+ var childIndex = (firstItemAdded)?0:(relativeIndex % numItems);
+
+ var child = [self _queryChild:childIndex ofItem:item withRowType:type];
+ [itemAndValue setObject:child forKey:@"item"];
+
+ var value = [self _queryValueForItem:child inRow:rowIndex];
+ [itemAndValue setObject:value forKey:@"value"];
+
+ [itemsAndValues addObject:itemAndValue];
+ firstItemAdded = YES;
+ item = child;
+ }
+
+ return itemsAndValues;
+}
+
+- (void)_addOptionFromSlice:(id)slice ofRowType:(unsigned int)type
+{
+ // for CPRuleEditorNestingModeSimple only
+
+ var rowIndexEvent = [slice rowIndex];
+ var rowTypeEvent = [self rowTypeForRow:rowIndexEvent];
+
+ var parentRowIndex = (rowTypeEvent==CPRuleEditorRowTypeCompound)?
rowIndexEvent:[self parentRowForRow:rowIndexEvent];
+
+ [self insertRowAtIndex:rowIndexEvent + 1 withType:type
asSubrowOfRow:parentRowIndex animate:YES];
+ // [self _reconfigureSubviewsAnimate:YES];
+ // [self _updatePredicate];
+
+}
+
+- (void)addRow:(id)sender
+{
+ var parentRowIndex, rowtype;
+ var numberOfRows = [self numberOfRows];
+
+ switch (_nestingMode){
+ case CPRuleEditorNestingModeSimple:
+ rowtype =
(numberOfRows==0)?CPRuleEditorRowTypeCompound:CPRuleEditorRowTypeSimple;
+ parentRowIndex = (numberOfRows == 0) ? -1 : 0;
+ break;
+ case CPRuleEditorNestingModeList:
+ rowtype = CPRuleEditorRowTypeSimple;
+ parentRowIndex = -1;
+ break;
+ case CPRuleEditorNestingModeSingle:
+ if(numberOfRows > 0) return;
+ rowtype = CPRuleEditorRowTypeSimple;
+ parentRowIndex = -1;
+ break;
+ case CPRuleEditorNestingModeCompound:
+ rowtype = CPRuleEditorRowTypeCompound;
+ parentRowIndex = -1; // bon ou pas bon ?
+ break;
+ default:
+ [CPException raise:CPInvalidArgumentException format:@"Not supported
CPRuleEditorNestingMode %d",_nestingMode];
+ // Compound mode:
parentRowIndex=(lastRowType==CPRuleEditorRowTypeCompound)?lastRow :[self
parentRowForRow:lastRow]; break;
+ }
+
+ [self insertRowAtIndex:numberOfRows withType:rowtype
asSubrowOfRow:parentRowIndex animate:YES];
+}
+
+- (void)insertRowAtIndex:(int)insertIndex withType:(unsigned int)rowtype
asSubrowOfRow:(int)parentRowIndex animate:(BOOL)animate
+{
+
+ var rowObject = [self _insertNewRowAtIndex:insertIndex ofType:rowtype
withParentRow:parentRowIndex];
+
+ if(rowtype == CPRuleEditorRowTypeCompound && ![self
_allowsEmptyCompoundRows])
+ {
+ var subrow = [self _insertNewRowAtIndex:insertIndex+1
ofType:CPRuleEditorRowTypeSimple withParentRow:insertIndex];
+ [[rowObject valueForKey:_subrowsArrayKeyPath] insertObject:subrow
atIndex:0];
+ }
+
+ var subrowsObjects;
+ var parentRowObject = (parentRowIndex == -1)?_boundArrayOwner:[[self
_rowCacheForIndex:parentRowIndex] rowObject];
+
+ switch (_nestingMode)
+ {
+ case CPRuleEditorNestingModeSimple:
+ subrowsObjects = [self _subrowObjectsOfObject:parentRowObject];
+ break;
+ case CPRuleEditorNestingModeList:
+ subrowsObjects = [self _subrowObjectsOfObject:_boundArrayOwner];
+ break;
+ default:
+ subrowsObjects = [self _subrowObjectsOfObject:parentRowObject];
+ break;
+ }
+
+ [subrowsObjects insertObject:rowObject
atIndex:insertIndex-parentRowIndex-1];
+ CPLogConsole("subrowsObjects" + [subrowsObjects description]);
+}
+
+- (id)_insertNewRowAtIndex:(int)insertIndex
ofType:(CPRuleEditorRowType)rowtype withParentRow:(int)parentRowIndex
+{
+ // why parentRowIndex is not used here ?
+ var row = [[[[self rowClass] alloc] init] autorelease];
+ [row setValue:[CPMutableArray array] forKey:_itemsKeyPath];
+ [row setValue:[CPMutableArray array] forKey:_valuesKeyPath];
+ [row setValue:[CPNumber numberWithInt:rowtype] forKey:_typeKeyPath];
+ [row setValue:[CPMutableArray array] forKey:_subrowsArrayKeyPath];
+
+ return row;
+}
+
+- (void)_startObservingRowObjectsRecursively:(id)rowObjects
+{
+ for(var rowObject in rowObjects)
+ {
+ [rowObject addObserver:self forKeyPath:_itemsKeyPath
options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew
context:itemsContext];
+ [rowObject addObserver:self forKeyPath:_valuesKeyPath
options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew
context:valuesContext];
+ [rowObject addObserver:self forKeyPath:_subrowsArrayKeyPath
options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew
context:subrowsContext];
+
+ var subrows = [self _subrowObjectsOfObject:rowObject];
+ [self _startObservingRowObjectsRecursively:subrows];
+ }
+
+ // ORIG IMPL : calls +keyPathsForValuesAffectingValueForKey: for all keys
+}
+
+- (void)_stopObservingRowObjectsRecursively:(id)rowObjects
+{
+ for(var rowObject in rowObjects)
+ {
+ [rowObject removeObserver:self forKeyPath:_itemsKeyPath];
+ [rowObject removeObserver:self forKeyPath:_valuesKeyPath];
+ [rowObject removeObserver:self forKeyPath:_subrowsArrayKeyPath];
+
+ var subrows = [rowObject objectForKey:_subrowsArrayKeyPath];
+ [self _stopObservingRowObjectsRecursively:subrows];
+ }
+
+}
+
+- (void)observeValueForKeyPath:(CPString)keypath ofObject:(id)object
change:(CPDictionary)change context:(void)context
+{
+ CPLogConsole([CPString stringWithFormat:"KVO CHANGE %@ of %@ in
context %d Change:%d\nOld:%@\nNew:%@",keypath,[object
className],context,[[change objectForKey:CPKeyValueChangeKindKey]
intValue],[change objectForKey:CPKeyValueChangeOldKey],[change
objectForKey:CPKeyValueChangeNewKey]]);
+ var changeKind = [[change objectForKey:CPKeyValueChangeKindKey] intValue];
+ var changeNewValue = [change objectForKey:CPKeyValueChangeNewKey];
+ var changeOldValue = [change objectForKey:CPKeyValueChangeOldKey];
+ var newRows;
+ var oldRows;
+
+ if(context == boundArrayContext){
+
+ if(changeKind==CPKeyValueChangeSetting)
+ {
+ newRows = changeNewValue;
+ oldRows = changeOldValue;
+ }
+ else if(changeKind==CPKeyValueChangeInsertion)
+ {
+ newRows = [self _subrowObjectsOfObject:object];
+ oldRows = [CPMutableArray arrayWithArray:newRows];
+ var newInsert = changeNewValue;
+ [oldRows removeObjectsInArray:newInsert];
+ }
+ else if(changeKind==CPKeyValueChangeRemoval)
+ {
+ newRows = [self _subrowObjectsOfObject:object];
+ oldRows = [CPMutableArray arrayWithArray:newRows];
+ var delIndexes = [change objectForKey:CPKeyValueChangeIndexesKey];
+ var delObjects = changeOldValue;
+ [oldRows insertObjects:delObjects atIndexes:delIndexes]; // Pas sur que
ce soit bon
+ }
+
+ [self _changedRowArray:newRows withOldRowArray:oldRows forParent:object];
+
+ for(var newRow in newRows)
+ {
+ var subnewRows = [self _subrowObjectsOfObject:newRow];
+ if([subnewRows count]>0)[self _changedRowArray:subnewRows
withOldRowArray:[CPArray array] forParent:newRow];
+ }
+
+ [self _reconfigureSubviewsAnimate:NO];
+ [self reloadPredicate];
+
+ if([newRows count] != [oldRows count])
+ [self
_postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification
indexes:[change objectForKey:CPKeyValueChangeIndexesKey]];
+
+ }else if(context == subrowsContext){
+
+ if(changeKind==CPKeyValueChangeSetting)
+ {
+ newRows = changeNewValue;
+ oldRows = changeOldValue;
+ [self _changedRowArray:newRows withOldRowArray:oldRows
forParent:object];
+
+ [self _reconfigureSubviewsAnimate:NO];
+ [self reloadPredicate];
+
+ if([newRows count] != [oldRows count])
+ [self
_postRowCountChangedNotificationOfType:CPRuleEditorRowsDidChangeNotification
indexes:[change objectForKey:CPKeyValueChangeIndexesKey]];
+ }
+ }
+ else if(context == itemsContext){
+ }
+ else if(context == valuesContext){
+ }
+
+ // CPLogConsole("============================== END KVO CHANGE
======================================");
+
+}
+
+- (void)_changedItem:(id)oldItem toItem:(id)newItem inRow:(int)rowIndex
atCriteriaIndex:(int)indexInCriteria
+{
+ var criteria = [self criteriaForRow:rowIndex];
+ var values = [self displayValuesForRow:rowIndex];
+ var type = [self rowTypeForRow:rowIndex];
+
+ var itemToAdd = newItem;
+ var relativeIndexInCriteria = 0;
+ var num_childs = CPNotFound;
+
+ var remainingRange = CPMakeRange(0, indexInCriteria);
+ var finalCriteria = [CPMutableArray arrayWithArray:[criteria
subarrayWithRange:remainingRange]];
+ var finalValues = [CPMutableArray arrayWithArray:[values
subarrayWithRange:remainingRange]];
+
+ while(num_childs >0){
+
+ [finalCriteria addObject:itemToAdd];
+
+ var displayvalue = [self _queryValueForItem:itemToAdd inRow:rowIndex];
+ [finalValues addObject:displayvalue];
+
+ num_childs = [self _queryNumberOfChildrenOfItem:itemToAdd
withRowType:type];
+
+ if(num_childs >0)
+ itemToAdd = [self _queryChild:0 ofItem:itemToAdd withRowType:type];
+
+ relativeIndexInCriteria++;
+ }
+
+ var object = [[self _rowCacheForIndex:rowIndex] rowObject];
+ [object setValue:finalCriteria forKey:_itemsKeyPath];
+ [object setValue:finalValues forKey:_valuesKeyPath];
+
+ [[_slices objectAtIndex:rowIndex] _reconfigureSubviews];
+
+ [self _postRuleOptionChangedNotification];
+}
+
+- (void)_changedRowArray:(CPArray)newRows withOldRowArray:(CPArray)oldRows
forParent:(id)parentRowObject
+{
+ [self _stopObservingRowObjectsRecursively:oldRows];
+ [self _startObservingRowObjectsRecursively:newRows];
+
+ var parentCacheIndex = [self _rowIndexForRowObject:parentRowObject];
+ var newRowCount = [newRows count];
+ var oldRowCount = [oldRows count];
+
+ CPLogConsole("\nOldArray:" + oldRowCount + "\nNewArray:" + newRowCount);
+
+ var parentCacheindentation;
+ if(parentCacheIndex == -1) parentCacheindentation = -1;
+ else
+ parentCacheindentation = [[self _rowCacheForIndex:parentCacheIndex]
indentation];
+
+ [_rowCache removeObjectsInRange:CPMakeRange(parentCacheIndex+1,
oldRowCount)];
+ var newRowCacheindex;
+ for(newRowCacheindex = 0; newRowCacheindex < newRowCount;
newRowCacheindex++){
+ var newCacheIndex = parentCacheIndex+newRowCacheindex+1;
+ var obj = [newRows objectAtIndex:newRowCacheindex];
+ var newRowType = [[obj valueForKey:_typeKeyPath] intValue];
+
+ var cache = [RuleEditorCache new];
+ [cache setRowObject:obj];
+ [cache setRowIndex:newCacheIndex];
+ [cache setIndentation:parentCacheindentation + 1];
+ [_rowCache insertObject:cache atIndex:newCacheIndex];
+ [cache release];
+
+ if([[obj valueForKey:_itemsKeyPath] count]==0){
+ var itemsandvalues = [self
_getItemsAndValuesToAddForRow:newRowCacheindex ofType:newRowType];
+ var newitems = [itemsandvalues valueForKey:@"item"];
+ var newvalues = [itemsandvalues valueForKey:@"value"];
+
+ [obj setValue:[CPMutableArray arrayWithArray:newitems]
forKey:_itemsKeyPath];
+ [obj setValue:[CPMutableArray arrayWithArray:newvalues]
forKey:_valuesKeyPath];
+ }
+ }
+
+ var deltaCount = newRowCount - oldRowCount;
+ var minusCount = MIN(newRowCount,oldRowCount);
+
+ var n;
+ for (n=0; n<minusCount; n++) {
+ var oldrow = [oldRows objectAtIndex:n];
+ var newrow = [newRows objectAtIndex:n];
+ if(newrow != oldrow) break;
+
+ }
+
+ var changePoint = n;
+ var absDeltaCount = MAX(deltaCount,-deltaCount); // WTF is abs()
function ?
+
+ if(deltaCount>0)
+ {
+ var startIndex = parentCacheIndex + changePoint +1;
+ var newIndentation = parentCacheindentation + 1;
+
+ var newSliceRelativeIndex;
+ for(newSliceRelativeIndex = 0 ; newSliceRelativeIndex < absDeltaCount;
newSliceRelativeIndex++)
+ {
+ var newIndex = startIndex + newSliceRelativeIndex;
+
+ var newslice = [self _newSlice];
+
+ [newslice setRowIndex:newIndex];
+ [newslice setIndentation:newIndentation];
+ var rowType = [self rowTypeForRow:newIndex];
+ [newslice _setRowType:rowType];
+ [newslice _configurePlusButtonByRowType:rowType];
+ [_slices insertObject:newslice atIndex:newIndex];
+ }
+ }else
+ {
+ var removeIndexes = [CPIndexSet
indexSetWithIndexesInRange:CPMakeRange(parentCacheIndex + changePoint+1,
absDeltaCount)];
+
+ var removeSlices = [_slices objectsAtIndexes:removeIndexes];
+ [removeSlices makeObjectsPerformSelector:@selector(removeFromSuperview)];
+ [_slices removeObjectsAtIndexes:removeIndexes];
+ }
+
+ [_slices makeObjectsPerformSelector:@selector(_updateButtonVisibilities)];
+}
+
+- (RuleEditorViewSliceRow)_newSlice
+{
+ var sliceRect = CGRectMake(0, 0, [self frame].size.width, 1);
+ var slice = [self _createNewSliceWithFrame:sliceRect ruleEditorView:self];
+ CPLogConsole(@"editable" + editable);
+ [slice setEditable:editable];
+
+ return slice;
+}
+
+- (RuleEditorViewSliceRow)_createNewSliceWithFrame:(CGRect)frame
ruleEditorView:(RuleEditor)editor
+{
+ var newslice = [[[RuleEditorViewSliceRow alloc] initWithFrame:frame
ruleEditorView:editor] autorelease];
+ return newslice;
+}
+
+- (void)_reconfigureSubviewsAnimate:(BOOL)animate
+{
+
+ // [self _updateSliceIndentations];
+ [self _updateSliceRows];
+
+ var viewAnimations = [CPMutableArray array];
+ var added_slices = [CPMutableArray array];
+
+ for(var slice in _slices)
+ {
+ var targetRect = [slice _animationTargetRect];
+ if(! CPEqualRects([slice frame], targetRect))
+ {
+ if([slice superview] == nil){
+ var addFrame = CGRectMake(0, ([slice rowIndex])*_sliceHeight, [self
frame].size.width, _sliceHeight);
+ if(animate)addFrame.size.height = 1.;
+ [slice setFrame:addFrame];
+ [slice _reconfigureSubviews];
+ [added_slices addObject:slice];
+ }
+
+ var animation = [CPDictionary dictionary];
+ [animation setObject:slice forKey:CPViewAnimationTargetKey];
+ [animation setObject:[CPValue valueWithRect:targetRect]
forKey:CPViewAnimationEndFrameKey];
+
+ [viewAnimations insertObject:animation atIndex:0];
+ }
+ }
+
+ for(var added_slice in added_slices)
+ [_slicesHolder addSubview:added_slice positioned:CPWindowBelow
relativeTo:nil];
+
+ if(animate)
+ {
+
+ for (var anim in viewAnimations)
+ {
+ var endFrame = [[anim valueforKey:CPViewAnimationEndFrameKey] rectValue];
+ var target = [anim valueforKey:CPViewAnimationTargetKey];
+ [[target layer] setFrame:endFrame];
+
+ }
+
+ }
+/*
+ [[_slices objectAtIndex:_lastRow] setNeedsDisplay:YES];
+ _lastRow = [self numberOfRows] -1;
+*/
+}
+
+- (void)_updateSliceRows
+{
+ var width = [self frame].size.width;
+ var i;
+
+ for (i = 0; i < [self numberOfRows]; i++) {
+ var slice = [_slices objectAtIndex:i];
+ [slice setRowIndex:i];
+ var targetRect = CGRectMake(0., i*_sliceHeight, width, _sliceHeight);
+ [slice _setAnimationTargetRect:targetRect];
+ }
+}
+
+- (void)setCriteria:(CPArray)criteria andDisplayValues:(CPArray)values
forRowAtIndex:(int)index{ // Not tested
+ var rowObject = [[self _rowCacheForIndex:index] rowObject];
+
+ [rowObject setValue:criteria forKey:_itemsKeyPath]; // Ou bien: [[self
criteriaForRow:index] setValue:criteria] ???
+ [rowObject setValue:values forKey:_valuesKeyPath];
+}
+
+- (id)criteriaForRow:(int)index
+{
+ var rowcache = [self _rowCacheForIndex:index];
+
+ if(rowcache){
+ var values = [[rowcache rowObject]
mutableArrayValueForKey:_itemsKeyPath];
+ return values;
+ }
+
+ return nil;
+}
+
+- (CPMutableArray)displayValuesForRow:(int)index
+{
+ var rowcache = [self _rowCacheForIndex:index];
+
+ if(rowcache){
+ var values = [[rowcache rowObject]
mutableArrayValueForKey:_valuesKeyPath];
+ return values;
+ }
+
+ return nil;
+}
+
+- (CPRuleEditorRowType)rowTypeForRow:(int)index
+{
+ var rowcache = [self _rowCacheForIndex:index];
+
+ if(rowcache){
+ var rowobject = [rowcache rowObject];
+ return [[rowobject valueForKey:_typeKeyPath] intValue];
+ }
+
+ return CPNotFound;
+}
+
+// PREDICATE
+
+- (CPPredicate)predicate
+{
+ return _predicate;
+}
+
+- (void)setPredicate:(CPPredicate)value
+{
+ if (_predicate != value) {
+ [_predicate release];
+ _predicate = [value retain];
+ }
+}
+
+- (void)reloadPredicate
+{
+ var subpredicates = [CPMutableArray array];
+ var subindexes = [self subrowIndexesForRow:-1];
+
+ var current_index = [subindexes firstIndex];
+ while(current_index!=CPNotFound)
+ {
+ var subpredicate = [self predicateForRow:current_index];
+ if(subpredicate)[subpredicates addObject:subpredicate];
+ current_index = [subindexes indexGreaterThanIndex:current_index];
+ }
+
+ var new_predicate = [[[CPCompoundPredicate alloc]
initWithType:CPOrPredicateType subpredicates:subpredicates] autorelease];
+
+ //[self willChangeValueForKey:@"predicate"];
+ [self setPredicate:new_predicate];
+ //[self didChangeValueForKey:@"predicate"];
+ CPLogConsole(@"new Predicate:" + new_predicate);
+}
+
+- (void)_updatePredicate
+{
+ [self willChangeValueForKey:@"predicate"];
+ [self didChangeValueForKey:@"predicate"];
+}
+
+- (CPPredicate)predicateForRow:(int)row
+{
+ if(delegateWantsValidation)
+ {
+ var predicatePartsForCriterion =
@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
+ var displayValueForCriterion =
@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
+
+ if (![_ruleDelegate respondsToSelector:predicatePartsForCriterion])
+ { CPLogConsole(@"Delegate doesn't respond to " +
CPStringFromSelector(predicatePartsForCriterion));
+ return NULL;
+ }
+
+ if (![_ruleDelegate respondsToSelector:displayValueForCriterion])
+ { [CPException raise:CPInternalInconsistencyException
+ format:@"Delegate doesn't respond to " +
CPStringFromSelector(displayValueForCriterion)];
+ return NULL;
+ }
+ delegateWantsValidation = NO;
+ }
+
+ var predicateParts = [CPDictionary dictionary];
+ var items = [self criteriaForRow:row];
+
+ var i;
+ for (i = 0; i < [items count]; i++){
+ var item = [items objectAtIndex:i];
+ var displayValue = [self _queryValueForItem:item inRow:row]; // A voir.
On peut aussi prendre la valeur affichée dans le row cache.
+
+ var predpart = [_ruleDelegate ruleEditor:self
predicatePartsForCriterion:item withDisplayValue:displayValue inRow:row];
+ if(predpart)[predicateParts setValuesForKeysWithDictionary:predpart];
+ }
+
+ if([self rowTypeForRow:row] == CPRuleEditorRowTypeCompound)
+ {
+
+ var subpredicates = [CPMutableArray array];
+ var subrowsIndexes = [self subrowIndexesForRow:row];
+
+ if([subrowsIndexes count] == 0) return nil;
+
+ var current_index = [subrowsIndexes firstIndex];
+ while (current_index != CPNotFound) {
+ var subpredicate = [self predicateForRow:current_index];
+ if(subpredicate)[subpredicates addObject:subpredicate];
+ current_index = [subrowsIndexes indexGreaterThanIndex:current_index];
+ }
+
+ var compoundType = [[predicateParts
objectForKey:CPRuleEditorPredicateCompoundType] intValue];
+ var compoundPredicate;
+
+ if ([subpredicates count] == 0)
+ return nil;
+ else
+ {
+ compoundPredicate = [[[CPCompoundPredicate alloc ]
initWithType:compoundType subpredicates:subpredicates] autorelease];
+/*
+ CPLogConsole(@"Compound predicate error: [%@]\npredicateType:%i",[e
description],compoundType);
+ compoundPredicate = NULL;
+*/
+ return compoundPredicate;
+
+ }
+ }
+
+ var lhs = [predicateParts
objectForKey:CPRuleEditorPredicateLeftExpression];
+ var rhs = [predicateParts
objectForKey:CPRuleEditorPredicateRightExpression];
+ var operator = [predicateParts
objectForKey:CPRuleEditorPredicateOperatorType];
+ var options = [predicateParts objectForKey:CPRuleEditorPredicateOptions];
+ var modifier = [predicateParts
objectForKey:CPRuleEditorPredicateComparisonModifier];
+ var selector = CPSelectorFromString([predicateParts
objectForKey:"CPRuleEditorPredicateCustomSelector"]);
+
+ if (!lhs){ CPLogConsole(@"missing left expression in predicate parts
dictionary"); return NULL;}
+ if (!rhs){ CPLogConsole(@"missing right expression in predicate parts
dictionary"); return NULL;}
+ if (selector==0 && !operator){ CPLogConsole(@"missing operator type while
no selector in predicate parts dictionary"); return NULL;}
+
+ if (!modifier) CPLogConsole(@"missing modifier in predicate parts
dictionary. Setting default: CPDirectPredicateModifier");
+ if (!options) CPLogConsole(@"missing options in predicate parts
dictionary. Setting default: CPCaseInsensitivePredicateOption");
+
+ var predicate;
+ CPLogConsole(@"lhs: " + lhs + " operator:" + operator + " rhs:" + rhs + "
modifier:" + modifier + " options:" + options + " selector:" + selector);
+ // ADD A try directive here. It seems try nested inside statements is
buggy currently.
+ if(selector != 0)
+ predicate = [CPComparisonPredicate
+ predicateWithLeftExpression:lhs
+ rightExpression:rhs
+ customSelector:selector
+ ];
+ else
+ predicate = [CPComparisonPredicate
+ predicateWithLeftExpression:lhs // Expression
+ rightExpression:rhs // Expression
+ modifier:(modifier)?[modifier intValue]:CPDirectPredicateModifier
// CPNumber
+ type:[operator intValue] // CPNumber
+ options:(options) ? [options
intValue]:CPCaseInsensitivePredicateOption // CPNumber
+ ];
+/*
+ CPLogConsole(@"Row predicate error: ["+[e description]+"] For row "+row);
+ predicate = nil; // NULL ou FALSEPREDICATE ? That is the question a 2
balles.
+*/
+ return predicate;
+
+}
+
+/* SLICES */
+- (CPColor)_sliceTopBorderColor
+{
+ return [CPColor colorWithCalibratedWhite:1 alpha:1];
+}
+
+- (CPColor)_sliceBottomBorderColor
+{
+ return [CPColor colorWithCalibratedRed:0.729412 green:0.729412
blue:0.729412 alpha:1];
+}
+
+- (CPColor)_sliceLastBottomBorderColor
+{
+ return [CPColor controlShadowColor];
+}
+
+- (CPString)_toolTipForAddCompoundRowButton
+{
+ return nil;
+}
+
+- (CPString)_toolTipForAddSimpleRowButton
+{
+ return nil;
+}
+
+- (CPString)_toolTipForDeleteRowButton
+{
+ return nil;
+}
+
+- (void)_updateSliceIndentations
+{
+ [self _updateSliceIndentationAtIndex:0 toIndentation:0 withIndexSet:[self
subrowIndexesForRow:0]];
+}
+
+- (void)_updateSliceIndentationAtIndex:(int)index
toIndentation:(int)indentation withIndexSet:(id)indexes
+{
+ var current_index = [indexes firstIndex];
+
+ while(current_index !=CPNotFound){
+ var subindexes = [self subrowIndexesForRow:index];
+ [self _updateSliceIndentationAtIndex:current_index
toIndentation:indentation+1 withIndexSet:subindexes];
+ current_index = [indexes indexGreaterThanIndex:current_index];
+ }
+
+ [[_slices objectAtIndex:index] setIndentation:indentation];
+}
+
+- (CPColor)_selectedActiveRowColor
+{
+ return [CPColor controlColor];
+}
+
+- (CPColor)_selectedInactiveRowColor
+{
+ return [CPColor secondarySelectedControlColor];
+}
+
+- (CPArray)_selectedSlices
+{
+ var _selectedSlices = [CPMutableArray array];
+
+ for (slice in _slices)
+ if([slice _isSelected])[_selectedSlices addObject:slice];
+
+ return _selectedSlices;
+}
+
+- (int)_lastSelectedSliceIndex
+{
+ var lastIndex = -1;
+
+ for (var slice in _slices)
+ if([slice _isLastSelected])return [slice rowIndex];
+
+ return CPNotFound;
+}
+
+- (void)_deselectAll
+{
+ for (var slice in _slices){
+ [slice _setSelected:NO];
+ [slice _setLastSelected:NO];
+ }
+}
+
+- (void)_mouseDownOnSlice:(id)slice withEvent:(CPEvent)event
+{
+ var modifierFlags = [event modifierFlags];
+
+ if(modifierFlags & CPCommandKeyMask && [slice _rowType] ==
CPRuleEditorRowTypeSimple){
+ [slice _setSelected:![slice _isSelected]];
+ if(![slice _isSelected])[slice _setLastSelected:YES];
+ [slice setNeedsDisplay:YES];
+ }else{
+ [self _deselectAll];
+ [slice _setSelected:YES];
+ [slice _setLastSelected:YES];
+ [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:)
withObject:YES];
+ }
+}
+
+- (void)_setSuppressKeyDownHandling:(BOOL)flag
+{
+ suppressKeyDown = flag;
+}
+
+- (void)selectAll:(id)sender
+{
+ [_slices makeObjectsPerformSelector:@selector(_setSelected:)
withObject:YES];
+ [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:)
withObject:YES];
+}
+
+- (CPIndexSet)selectedRowIndexes
+{
+ var selectedRowIndexes = [CPMutableIndexSet indexSet];
+
+ for(var slice in _slices)
+ if([slice _isSelected])[selectedRowIndexes addIndex:[slice rowIndex]];
+
+ return selectedRowIndexes;
+}
+
+/* DELEGATE METHODS */
+- (int)_queryNumberOfChildrenOfItem:(id)item
withRowType:(CPRuleEditorRowType)type
+{
+ return [_ruleDelegate ruleEditor:self numberOfChildrenForCriterion:item
withRowType:type];
+}
+
+- (id)_queryChild:(int)childIndex ofItem:(id)item
withRowType:(CPRuleEditorRowType)type
+{
+ return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item
withRowType:type];
+}
+
+- (id)_queryValueForItem:(id)item inRow:(int)row
+{
+ return [_ruleDelegate ruleEditor:self displayValueForCriterion:item
inRow:row];
+}
+
+/* MISC */
+- (void)drawInContext:(CGContext)context
+{
+ CGContextSetFillColor(context, [CPColor grayColor]);
+ CGContextFillRect(context, [self bounds]);
+
+ [self _drawSliceBackgroundsWithClipRect:rect];
+}
+
+- (void)_drawSliceBackgroundsWithClipRect:rect
+{
+}
+
+- (int)_lastRow
+{
+ return _lastRow;
+}
+
+- (int)_countOfRowsStartingAtObject:(id)object
+{
+ var index = [self _rowIndexForRowObject:object];
+ return ([self numberOfRows] - index);
+}
+
+- (void)_setAlignmentGridWidth:(float)width
+{
+ _alignmentGridWidth = width;
+}
+
+- (void)_postRowCountChangedNotificationOfType:(CPString)notificationName
indexes:indexes
+{
+ [[CPNotificationCenter defaultCenter]
postNotificationName:notificationName object:indexes];
+}
+
+- (void)bind:(CPString)binding toObject:(id)observableController
withKeyPath:(CPString)keyPath options:(CPDictionary)options
+{
+ if([binding isEqualToString:@"rows"])
+ [self _setBoundDataSource:observableController withKeyPath:keyPath
options:options];
+}
+
+- (void)unbind:(id)object
+{
+ CPLogConsole("%s",SELNAME(_cmd));
+ [super unbind:object];
+}
+
+- (BOOL)_validateItem:(id)item value:(id)value inRow:(int)row
+{
+ return [self _queryCanSelectItem:item displayValue:value inRow:row];
+}
+
+- (BOOL)_queryCanSelectItem:(id)item displayValue:(id)value inRow:(int)row
+{
+ return YES;
+}
+
+- (void)_windowChangedKeyState
+{
+ [_slices makeObjectsPerformSelector:@selector(setNeedsDisplay:)
withObject:YES];
+}
+
+- (void)setFrameSize:(CPSize)size
+{
+ CPLogConsole(@"setFrameSize:%@",CPStringFromSize(size));
+ [super setFrameSize:size];
+}
+
+- (void)sizeToFit
+{
+ [super sizeToFit];
+}
+
+- (CPIndexSet)_selectedSliceIndices
+{
+ var selectedIndices = [CPMutableIndexSet indexSet];
+
+ for (var slice in _slices)
+ if([slice _isSelected])[selectedIndices addIndex:[slice rowIndex]];
+
+ return selectedIndices;
+}
+
+- (CPString)formattingStringsFilename
+{
+ return _stringsFilename;
+}
+
+- (void)setFormattingStringsFilename:(CPString)value
+{
+ if (_stringsFilename != value) {
+ [_stringsFilename release];
+ _stringsFilename = [value retain];
+ }
+}
+
+- (void)mouseDragged:(CPEvent)event
+{
+ var point = [self convertPoint:[event locationInWindow] fromView:nil];
+ var view = [self hitTest:point];
+ CPLogConsole(@"Drag from %@",CPStringFromPoint(point));
+ if([self _dragShouldBeginFromMouseDown:view])
+ [self _performDragForSlice:view withEvent:event];
+}
+
+- (BOOL)_dragShouldBeginFromMouseDown:(CPView)view
+{
+ return (editable
+ && [view isKindOfClass:[RuleEditorViewSliceRow class]]);
+}
+
+- (BOOL)_performDragForSlice:(id)slice withEvent:(CPEvent)event
+{
+ var size;
+ var dragPoint, pt;
+
+ var mainRowIndex = [slice rowIndex];
+ var draggingRows = [CPMutableIndexSet indexSetWithIndex:mainRowIndex];
+ var selected_indices = [self _selectedSliceIndices];
+ if([selected_indices containsIndex:mainRowIndex])[draggingRows
addIndexes:selected_indices];
+
+ _draggingRows = [self _includeSubslicesForSlicesAtIndexes:draggingRows];
+
+ var pasteboard = [CPPasteboard pasteboardWithName: CPDragPboard];
+ [pasteboard declareTypes: [CPArray arrayWithObjects:
CPRuleEditorItemPBoardType, nil] owner: self];
+
+
+ var dragImage = [self _dragImageForIndices:_draggingRows];
+
+ dragPoint = CPMakePoint(0, ([_draggingRows lastIndex] + 1) *
_sliceHeight);
+
+ [self dragImage: dragImage
+ at: dragPoint
+ offset: CPZeroSize
+ event: event
+ pasteboard: pasteboard
+ source: self
+ slideBack: YES];
+
+ return YES;
+}
+
+- (CPImage)_dragImageForIndices:(CPIndexSet)indices
+{
+ var firstIndex = [indices firstIndex];
+ var lastIndex = [indices lastIndex];
+
+ var theDraggedSliceFrame = CGRectMake(0, firstIndex *_sliceHeight, [self
frame].size.width, (lastIndex - firstIndex + 1) *_sliceHeight);
+
+ var pdfData = [self dataWithPDFInsideRect:theDraggedSliceFrame];
+ var pdfImage = [[[CPImage alloc] initWithData:pdfData] autorelease];
+ var dragImage = [[[CPImage alloc] initWithSize:theDraggedSliceFrame.size]
autorelease];
+
+ [dragImage lockFocus];
+ [pdfImage dissolveToPoint: CPMakePoint(0,0) fraction: .75];
+ [dragImage unlockFocus];
+
+ return dragImage;
+}
+
+- (void)_rightMouseDownOnSlice:(RuleEditorViewSlice)slice
withEvent:(CPEvent)event
+{
+}
+
+- (void)_performClickOnSlice:(id)slice withEvent:(CPEvent)event
+{
+}
+
+- (void)selectRowIndexes:(CPIndexSet)indexes
byExtendingSelection:(BOOL)flag
+{
+}
+
+- (CPDragOperation)draggingEntered:(id < CPDraggingInfo >)sender
+{
+ if ([sender draggingSource] == self){
+ [self _clearDropLine];
+ return CPDragOperationGeneric;
+ }
+
+ return CPDragOperationNone;
+}
+
+- (void)_clearDropLine
+{
+ var dropLineRect = [_dropLineView frame];
+ dropLineRect.origin.y = -5;
+ [_dropLineView setFrame:dropLineRect];
+}
+
+- (void)draggingExited:(id)sender
+{
+ [self _clearDropLine];
+ [self setNeedsDisplay:YES];
+}
+
+- (BOOL)performDragOperation:(id)sender
+{
+ CPLogConsole(@"ROW CACHE BEFORE %@", [_rowCache description]);
+
+ CPLogConsole(@"ROW CACHE AFTER%@", [_rowCache description]);
+ [self _clearDropLine];
+}
+
+- (CPIndexSet)_draggingTypes
+{
+ return [CPIndexSet indexSetWithIndex:CPDragOperationMove];
+}
+
+- (int)_dragOperationFromInfo:(id)info
+{
+}
+
+- (CPDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
+{
+ if(isLocal) return CPDragOperationMove;
+ return CPDragOperationNone;
+}
+
+- (CPDragOperation)draggingUpdated:(id <CPDraggingInfo>)sender
+{
+ var point = [self convertPoint:[sender draggingLocation] fromView:nil];
+ var y = point.y + _sliceHeight /2;
+ var indexOfDropLine = floor(y / _sliceHeight);
+
+ if(indexOfDropLine < 0 || indexOfDropLine > [self numberOfRows])
+ return CPDragOperationNone;
+
+ var current_index = [_draggingRows firstIndex];
+ while (current_index != CPNotFound) {
+
+ if(indexOfDropLine == 0 || indexOfDropLine == current_index ||
indexOfDropLine == current_index + 1)
+ {
+ [self _clearDropLine];
+ return CPDragOperationNone;
+ }
+ current_index = [_draggingRows indexGreaterThanIndex:current_index];
+ }
+
+ var dropLineRect = [_dropLineView frame];
+ dropLineRect.origin.y = indexOfDropLine * _sliceHeight;
+ [_dropLineView setFrame:dropLineRect];
+
+ return CPDragOperationMove;
+}
+
+- (int)_updateDragging:(id)fp8
+{
+ return (NO) ? CPDragOperationMove : CPDragOperationGeneric;
+}
+
+- (void)draggedImage:(CPImage)dragImage endedAt:(CPPoint)aPoint
operation:(CPDragOperation)operation
+{
+}
+
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+}
+
+- (id)_dragHandleColors
+{
+}
+
+- (void)_setWindow:(id)window
+{
+ [super _setWindow:window];
+}
+
+- (void)_windowUpdate:(id)sender
+{
+ [super _windowUpdate:sender];
+}
+
+- (void)_postRuleOptionChangedNotification
+{
+ [[CPNotificationCenter defaultCenter]
postNotificationName:@"CPRuleEditorRulesDidChangeNotification" object:self];
+}
+
+/* DRAGGING PROTOCOL
+ -namesOfPromisedFilesDroppedAtDestination:
+ -slideDraggedImageTo:
+ -draggingSequenceNumber
+ -draggingSource
+ -draggingPasteboard
+ -draggedImage
+ -draggedImageLocation
+ -draggingLocation
+ -draggingSourceOperationMask
+ -draggingDestinationWindow
+*/
+
+/*==========================================================================================================*/
+/* UNIMPLEMENTED */
+/*==========================================================================================================*/
+
+/*
+- (void)_removeSubrowsForRow:(int)rowIndex fromSet:(CPIndexSet)set
+{
+}
+- (CPArray)_backgroundColors
+{
+}
+- (BOOL)_isInDesignMode
+{
+}
+- (BOOL)_privateDelegateMethodsEnabled
+{
+}
+- (BOOL)_ruleViewHasFirstResponder
+{
+}
+- (BOOL)_wantsMinimalArchival
+{
+}
+- (int)rowForDisplayValue:(id)value
+{
+}
+- (id)_queryOrderLocalizedDictionaries:(id)dicts withParent:(id)fp12
+{
+}
+- (BOOL)_findRowObject:(id)object startingAtObject:(id)startObject
withIndex:(int)index
+{
+}
+- (BOOL)_nextUnusedItems:(id *)items andValues:(id *)fp12 forRow:(int)fp16
forRowType:(unsigned int)fp20
+{
+}
+- (id)_globalIndexesForSubrowIndexes:(id)indexes ofParentObject:(id)fp12
+{
+}
+- (id)_uniqueizeIndexSet:(id)set
+{
+}
+- (id)_extendItem:(id)item withRow:(int)fp12
+{
+}
+- (void)_fullCacheUpdate
+{
+}
+- (void)_fullCacheUpdateRecursive:(id)fp8 intoRow:(int)fp12
withIndentation:(int)fp16
+{
+}
+- (void)reloadCriteria
+{
+}
+- (id)_generateFormattingDictionaryStringsFile
+{
+}
+- (id)_localizerForSlice:(id)slice
+{
+}
+- (void)_setHeaderLocalizer:(id)loc
+{
+}
+- (void)_setStandardLocalizer:(id)loc
+{
+}
+- (void)setFormattingDictionary:(id)dict
+{
+}
+- (void)setFormattingStringsFileName:(id)name
+{
+}
+- (void)_recursiveGenerateFormattingDictionaryPlistForItem:(id)item
rowType:(unsigned int)type intoArray:(id)array
withPriorValues:(id)priorValues hasSiblings:(BOOL)hasSiblings
+{
+}
+- (id)_layoutOrdersForChoiceRootedAtItem:(id)item inRow:(int)fp12
+{
+}
+- (int)_layoutOrderForItem:(id)item inRow:(int)fp12
+{
+}
+- (void)_loadInitialRows
+{
+}
+- (void)_postRuleOptionChangedNotification
+{
+}
+- (void)_sendRuleAction
+{
+}
+- (void)_stopAnimationWithoutChangingFrames
+{
+}
+*/
+
+@end
+
+import "CPRuleEditorViewSliceRow.j"

Added: branches/CPRuleEditor/CPRuleEditorButtonCell.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorButtonCell.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,45 @@
+/*
+ * Generated by class-dump 3.1.2.
+ *
+ * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by
Steve Nygard.
+ */
+
+@implementation RuleEditorButtonCell : CPButton
+{
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil) {
+ [self setAlignment:CPCenterTextAlignment];
+ [self setImagePosition:CPNoImage];
+ [self setControlSize:CPSmallControlSize];
+ }
+ return self;
+}
+
+- (CGRect)drawTitle:(CPAttributedString)title withFrame:(CGRect)cellFrame
inView:(CPView)view
+{
+ return [super drawTitle:title withFrame:cellFrame inView:view];
+}
+
+- (CGRect)titleRectForBounds:(CGRect)rect
+{
+ return [super titleRectForBounds:rect];
+}
+
+- (void)drawInteriorWithFrame:(CGRect)cellFrame inView:(CPView)controlView
+{
+ cellFrame.origin.x -=2;
+ cellFrame.size.width +=4;
+ [super drawInteriorWithFrame:cellFrame inView:controlView];
+}
+
+- (unsigned int)bezelStyle
+{
+ return CPRoundRectBezelStyle;
+}
+
+@end
+

Added: branches/CPRuleEditor/CPRuleEditorPopupButton.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorPopupButton.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,30 @@
+/*
+ * Generated by class-dump 3.1.2.
+ *
+ * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by
Steve Nygard.
+ */
+
+
+@implementation RuleEditorPopupButton : CPPopUpButton
+{
+}
+
+/*
++ (void)initialize
+{
+}
+*/
+
++ (Class)cellClass
+{
+ return [RuleEditorPopupButtonCell class];
+}
+
+/*
+
+- (void)sizeToFit
+{
+}
+*/
+@end
+

Added: branches/CPRuleEditor/CPRuleEditorPopupButtonCell.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorPopupButtonCell.j Wed Oct 8 14:54:24
2008
@@ -0,0 +1,54 @@
+/*
+ * Generated by class-dump 3.1.2.
+ *
+ * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by
Steve Nygard.
+ */
+
+
+@implementation RuleEditorPopupButtonCell : CPPopUpButtonCell
+{
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil) {
+ [self setFont:[CPFont fontWithName:@"LucidaGrande" size:11]];
+ [self setBezelStyle:CPRoundRectBezelStyle];
+ [self setControlSize:CPRegularControlSize];
+ }
+ return self;
+}
+
+
+- (BOOL)sliceIsEditable
+{
+ var slice = [[self controlView] superview];
+ return [slice isEditable];
+}
+
+
+- (BOOL)trackMouse:(CPEvent)theEvent inRect:(CGRect)cellFrame
ofView:(CPView)controlView untilMouseUp:(BOOL)untilMouseUp
+{
+ var editable = [self sliceIsEditable];
+ if(!editable)
+ return NO;
+
+ return [super trackMouse:theEvent inRect:cellFrame ofView:controlView
untilMouseUp:untilMouseUp];
+}
+
+- (CGRect)drawingRectForBounds:(CGRect)theRect
+{
+ theRect.size.height -=5;
+ return theRect;
+}
+
+- (unsigned int)arrowPosition
+{
+ if ([self sliceIsEditable])
+ return CPPopUpArrowAtBottom;
+
+ return CPPopUpNoArrow;
+}
+
+@end

Added: branches/CPRuleEditor/CPRuleEditorTextField.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorTextField.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,34 @@
+//
+// CPRuleEditorTextField.m
+// CPRuleEditor
+//
+// Created by x on 01/10/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+@implementation RuleEditorTextField : CPTextField
+
+- (id) initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self != nil) {
+ [[self cell] setControlSize:CPMiniControlSize];
+ [[self cell] setBordered:NO];
+ [[self cell] setEditable:NO];
+ [[self cell] setDrawsBackground:NO];
+ [[self cell] setFont:[CPFont fontWithName:@"LuciaGrande"
size:11.]];
+
+ }
+ return self;
+}
+
+
+- (id)hitTest:(CPPoint)point
+{
+ if(!CPPointInRect(point, [self frame]))
+ return nil;
+
+ return [self superview];
+}
+
+@end

Added: branches/CPRuleEditor/CPRuleEditorViewSlice.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorViewSlice.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,156 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+
+@implementation RuleEditorViewSlice : CPView
+{
+ CALayer _rootLayer;
+ CPRuleEditor _ruleEditor;
+ CPColor _backgroundColor;
+ int _indentation;
+ CGRect _animationTargetRect;
+
+ struct {
+ unsigned int selected:1;
+ unsigned int lastSelected:1;
+ unsigned int hideNonPartDrawing:1;
+ unsigned int reserved:29;
+ } _flags;
+
+ int _rowIndex;
+
+}
+
+- (CPString)descriptionWithLocale:(id)locale
+{
+ return [CPString stringWithFormat:@"<%@ %p index:%d
indentation:%d>",[self className],self,[self rowIndex],[self indentation]];
+}
+
+- (id)initWithCoder:(CPCoder)coder
+{
+ self = [super initWithCoder:coder];
+ if (self != nil) {
+ [self setBackgroundColor:[CPColor blueColor]]
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(CPCoder)coder
+{
+ [super encodeWithCoder:coder];
+}
+
+- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
+{
+ if(self = [super initWithFrame:frame]){
+
+ _ruleEditor = editor;
+
+ _rootLayer = [CALayer layer];
+ [self setWantsLayer:YES];
+ [self setLayer:_rootLayer];
+ [_rootLayer setBounds:[self bounds]];
+ [_rootLayer setDelegate:self];
+ [_rootLayer setNeedsDisplay];
+ [_rootLayer setBackgroundColor:[CPColor redColor]];
+ }
+ return self;
+}
+
+- (void)_setHideNonPartDrawing:(BOOL)value
+{
+ _flags.hideNonPartDrawing = value;
+}
+
+- (void)_setLastSelected:(BOOL)value
+{
+ _flags.lastSelected = value;
+}
+
+- (BOOL)_isLastSelected
+{
+ return _flags.lastSelected;
+}
+
+- (void)_setSelected:(BOOL)value
+{
+ _flags.selected = value;
+}
+
+- (BOOL)_isSelected
+{
+ return _flags.selected;
+}
+
+- (CPColor)backgroundColor
+{
+ return _backgroundColor ;
+}
+
+- (void)setBackgroundColor:(CPColor)color
+{
+ if(_backgroundColor != color)
+ _backgroundColor = color;
+}
+
+- (int)indentation
+{
+ return _indentation;
+}
+
+- (void)setIndentation:(int)value
+{
+ _indentation = value;
+}
+
+- (int)rowIndex
+{
+ return _rowIndex;
+}
+
+- (void)setRowIndex:(int)value
+{
+ _rowIndex = value;
+}
+
+- (void)_setAnimationTargetRect:(CGRect)rect
+{
+ _animationTargetRect = rect;
+}
+
+- (CGRect)_animationTargetRect
+{
+ return _animationTargetRect;
+}
+
+-(void)drawRect:(CGRect)rect
+{
+ if([self _isSelected])
+ {
+ var isKey = [[self window] isKeyWindow];
+ [(isKey) ? [_ruleEditor _selectedActiveRowColor]:[_ruleEditor
_selectedInactiveRowColor] set];
+ CPRectFill(rect);
+ }
+
+ var drawrect = NSMakeRect(0, 0, [self frame].size.width, 1);
+ [(_rowIndex == [_ruleEditor numberOfRows]-1) ? [_ruleEditor
_sliceLastBottomBorderColor]:[_ruleEditor _sliceBottomBorderColor] set];
+ CPRectFill(drawrect);
+
+ drawrect.origin.y += [self frame].size.height -1;
+ [[_ruleEditor _sliceTopBorderColor] set];
+ CPRectFill(drawrect);
+}
+
+- (void)mouseDown:(CPEvent)theEvent
+{
+ [_ruleEditor _mouseDownOnSlice:self withEvent:theEvent];
+}
+/*
+- (void)rightMouseDown:(CPEvent)theEvent
+{
+ [_ruleEditor _rightMouseDownOnSlice:self withEvent:theEvent];
+}
+*/
+@end

Added: branches/CPRuleEditor/CPRuleEditorViewSliceDropSeparator.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorViewSliceDropSeparator.j Wed Oct 8
14:54:24 2008
@@ -0,0 +1,37 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+@implementation RuleEditorViewSliceDropSeparator : CPView
+{
+ CALayer _rootLayer;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self != nil) {
+ _rootLayer = [CALayer layer];
+
+ [self setWantsLayer:YES];
+ [self setLayer:_rootLayer];
+ [_rootLayer setNeedsDisplay];
+
+ }
+ return self;
+}
+
+ - (BOOL)isFlipped
+{
+ return YES;
+}
+
+- (void)drawInContext:(CGContext)context
+{
+ CGContextSetFillColor(context, [CPColor lightGrayColor]);
+ CGContextFillRect(context, [self bounds]);
+ }
+
+@end
+

Added: branches/CPRuleEditor/CPRuleEditorViewSliceRow.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/CPRuleEditorViewSliceRow.j Wed Oct 8 14:54:24
2008
@@ -0,0 +1,486 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+var CPImageNameAddTemplate = @"CPImageNameAddTemplate";
+var CPImageNameRemoveTemplate = @"CPImageNameRemoveTemplate";
+var CONTROL_HEIGHT = 18.;
+
+import "CPRuleEditorViewSlice.j"
+
+import "CPRuleEditor.j"
+import "CPRuleEditorButtonCell.j"
+import "CPRuleEditorPopupButton.j"
+import "CPRuleEditorTextField.j"
+
+@implementation RuleEditorViewSliceRow : RuleEditorViewSlice
+{
+
+ CPMutableArray _ruleOptionViews;
+ CPMutableArray _ruleOptionFrames;
+ CPMutableArray _correspondingRuleItems;
+ CPMutableArray _ruleOptionInitialViewFrames;
+ CPButton _addButton;
+ CPButton _subtractButton;
+ int _rowType;
+ int _plusButtonRowType;
+ struct {
+ unsigned int editable:1;
+ unsigned int reserved:31;
+ } _sliceRowFlags;
+ id _sliceRowReserved;
+
+}
+
+- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
+{
+ if(self = [super initWithFrame:frame ruleEditorView:editor])
+ {
+
+ [self _initShared];
+ }
+ return self;
+}
+
+- (void)_initShared
+{
+ _correspondingRuleItems = [[CPMutableArray alloc] init];
+ _ruleOptionFrames = [[CPMutableArray alloc] init];
+ _ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
+ _ruleOptionViews = [[CPMutableArray alloc] init];
+
+ _addButton = [self _createAddRowButton];
+ _subtractButton = [self _createDeleteRowButton];
+
+ [_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
+ [_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
+
+ var sliceFrame = [self frame];
+
+ var _buttonframe = CGRectMake(sliceFrame.size.width - CONTROL_HEIGHT -
[self _rowButtonsRightHorizontalPadding],([_ruleEditor rowHeight]
-CONTROL_HEIGHT)/2,CONTROL_HEIGHT,CONTROL_HEIGHT);
+ [_addButton setFrame:_buttonframe];
+ _buttonframe.origin.x -= CONTROL_HEIGHT + [self
_rowButtonsInterviewHorizontalPadding];
+ [_subtractButton setFrame:_buttonframe];
+
+ [self setAutoresizingMask:CPViewWidthSizable & CPViewMinXMargin];
+
+ if([_ruleEditor isEditable])
+ {
+ [self addSubview:_addButton];
+ [self addSubview:_subtractButton];
+ }
+}
+
+- (CPButton )_createAddRowButton
+{
+ var button = [[CPButton alloc] init];
+
+ var buttoncell = [[RuleEditorButtonCell alloc] init];
+ [button setCell:buttoncell];
+ [buttoncell release];
+
+ var plus_image = [CPImage imageNamed:CPImageNameAddTemplate];
+
+ [button setImage:plus_image];
+ [button setAction:@selector(_addOption:)];
+ [button setTarget:self];
+ [button setAutoresizingMask:CPViewMaxXMargin];
+
+ return button;
+}
+
+- (CPButton )_createDeleteRowButton
+{
+ var button = [[CPButton alloc] init];
+
+ var buttoncell = [[RuleEditorButtonCell alloc] init];
+ [button setCell:buttoncell];
+ [buttoncell release];
+
+ var minus_image = [CPImage imageNamed:CPImageNameRemoveTemplate];
+
+ [button setImage:minus_image];
+ [button setAction:@selector(_deleteOption:)];
+ [button setTarget:self];
+ [button setAutoresizingMask:CPViewMaxXMargin];
+
+ return button;
+}
+
+- (CPMenuItem )_createMenuItemWithTitle:(CPString )title
+{
+ var loc_title = CPLocalizedStringFromTable(title,[_ruleEditor
formattingStringsFilename],nil);
+ return [[[CPMenuItem alloc] initWithTitle:loc_title action:0
keyEquivalent:@""] autorelease];
+}
+
+- (CPPopUpButton )_createPopUpButtonWithItems:(CPArray )itemsArray
selectedItemIndex:(int)index
+{
+ // [RuleEditorViewSliceRow _minimumVerticalPopupPadding]
+ var item;
+
+ var popup = [[[RuleEditorPopupButton alloc] init] autorelease];
+
+ [popup setFrame:NSMakeRect(0, ([_ruleEditor rowHeight] - [popup
frame].size.height)/2, CONTROL_HEIGHT, 40)];
+ var menu = [[CPMenu alloc] init];
+
+ for (var item in itemsArray)
+ [menu addItem:item];
+
+ [popup setMenu:menu];
+ [popup selectItemAtIndex:index];
+ [popup sizeToFit];
+
+ [menu release];
+
+ return popup;
+}
+
+- (CPMenuItem )_createMenuSeparatorItem
+{
+ return [CPMenuItem separatorItem];
+}
+
+- (CPTextField )_createStaticTextFieldWithStringValue:(CPString )text
+{
+ var textField = [[RuleEditorTextField alloc] initWithFrame:NSMakeRect(0,
0, 0, CONTROL_HEIGHT)];
+ var loc_text = CPLocalizedStringFromTable(text,[_ruleEditor
formattingStringsFilename],nil);
+ [textField setStringValue:loc_text];
+ [textField sizeToFit];
+
+ return textField;
+}
+
+- (void)_addOption:(id)sender
+{
+ if([self rowIndex]==[_ruleEditor numberOfRows]-1) [self
setNeedsDisplay:YES];
+ [_ruleEditor _addOptionFromSlice:self ofRowType:_plusButtonRowType];
+}
+
+- (void)_deleteOption:(id)sender
+{
+ [_ruleEditor _deleteSlice:self];
+}
+
+- (void)_ruleOptionPopupChangedAction:(CPMenuItem )sender
+{
+ var layoutdict = [sender representedObject];
+ var newItem = [layoutdict objectForKey:@"item"];
+ var indexInCriteria = [[layoutdict objectForKey:@"indexInCriteria"]
intValue];
+
+ var oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
+
+ if(newItem != oldItem)
+ {
+ [_correspondingRuleItems replaceObjectAtIndex:indexInCriteria
withObject:newItem];
+ [_ruleEditor _changedItem:oldItem toItem:newItem inRow:[self rowIndex]
atCriteriaIndex:indexInCriteria];
+ }
+}
+
+- (BOOL)validateMenuItem:(CPMenuItem )menuItem
+{
+ return [_ruleEditor _validateItem:menuItem value:[[menuItem
representedObject] valueForKey:@"item"] inRow:[self rowIndex]];
+}
+
+- (void)_emptyRulePartSubviews
+{
+ var collection = [_ruleOptionViews objectEnumerator];
+ var view;
+ while (view = [collection nextObject])
+ [view removeFromSuperview];
+
+ [_ruleOptionViews removeAllObjects];
+ [_ruleOptionFrames removeAllObjects];
+ [_ruleOptionInitialViewFrames removeAllObjects];
+
+}
+
+- (void)_reconfigureSubviews
+{
+ var numItems;
+ var currentItem = nil;
+ var optionView = nil;
+ var indexInCriteria = 0;
+
+ var rowtype = [_ruleEditor rowTypeForRow:[self rowIndex]];
+ var displayValues = [_ruleEditor displayValuesForRow:[self rowIndex]];
+
+ [self _emptyRulePartSubviews];
+ [_correspondingRuleItems removeAllObjects];
+
+ while( (numItems = [_ruleEditor _queryNumberOfChildrenOfItem:currentItem
withRowType:rowtype]) >0){
+
+ var isCustomRightControl = NO;
+ var isStaticTextField = NO;
+ var isPopupMenu = NO;
+ var isMultiValue = numItems > 1;
+ var selectedMenuItemIndex =0;
+
+ var itemsArray = [CPMutableArray array];
+ var current_display_value = nil;
+ var display_value_cached = [displayValues objectAtIndex:indexInCriteria];
+ var selectedItem = nil;
+
+ var childIndex;
+ for (childIndex = 0; childIndex < numItems; childIndex++) {
+ var childItem = [_ruleEditor _queryChild:childIndex ofItem:currentItem
withRowType:rowtype];
+ current_display_value = [_ruleEditor _queryValueForItem:childItem
inRow:[self rowIndex]];
+
+ if(isMultiValue)
+ {
+ var menuItem;
+
+ if([current_display_value isKindOfClass:[CPString class]])
+ menuItem = [self _createMenuItemWithTitle:current_display_value];
+ else if([current_display_value isKindOfClass:[CPMenuItem class]])
+ menuItem = current_display_value;
+ else
+ [CPException raise:CPGenericException format:@"Display value must
be a string or a menu item"];
+
+ [menuItem setAction:@selector(_ruleOptionPopupChangedAction:)];
+ [menuItem setTarget:self];
+ var layoutDictionary = [CPDictionary dictionary];
+ [layoutDictionary setObject:childItem forKey:@"item"];
+ [layoutDictionary setObject:[CPNumber numberWithInt:indexInCriteria]
forKey:@"indexInCriteria"];
+ [menuItem setRepresentedObject:layoutDictionary];
+ [menuItem setTag:indexInCriteria];
+
+ [itemsArray addObject:menuItem];
+ isPopupMenu = YES;
+
+ if((childIndex == numItems - 1 && selectedItem == nil)
+ || ([current_display_value isEqual:display_value_cached])
+ || ([current_display_value isKindOfClass:[CPView class]]
+ && [[current_display_value objectValue]
isEqualTo:[display_value_cached objectValue]]))
+ {
+ selectedItem = childItem; selectedMenuItemIndex = childIndex;
+ }
+
+ }
+ else if([current_display_value isKindOfClass:[CPString class]])
+ {
+ isStaticTextField = YES;
+ selectedItem = childItem; selectedMenuItemIndex =0;
+ }
+ else if([current_display_value isKindOfClass:[CPControl class]])
+ {
+ isCustomRightControl = YES;
+ selectedItem = childItem; selectedMenuItemIndex =0;
+ } else
+ [CPException raise:CPGenericException format:@"Display value must be a
string or a custom control"];
+
+ }
+
+ if(isPopupMenu)
+ {
+ optionView = [self _createPopUpButtonWithItems:itemsArray
selectedItemIndex:selectedMenuItemIndex];
+ }
+ else if(isStaticTextField)
+ {
+ optionView = [self
_createStaticTextFieldWithStringValue:[current_display_value description]];
+ }
+ else if(isCustomRightControl)
+ {
+ optionView = display_value_cached;
+ [optionView setFrame:NSMakeRect(0, 0, 150, CONTROL_HEIGHT)];
+ if([optionView respondsToSelector:@selector(cell)])
+ [[optionView cell] setEditable:_sliceRowFlags.editable];
+ }
+
+ [_ruleOptionViews addObject:optionView];
+ var rectValue = [CPValue valueWithRect:[optionView frame]];
+
+ if(rectValue)
+ [_ruleOptionInitialViewFrames addObject:rectValue];
+
+ [_correspondingRuleItems addObject:selectedItem];
+ currentItem = selectedItem;
+ indexInCriteria++;
+ }
+
+ [self _relayoutSubviewsWidthChanged:NO];
+}
+
+- (void)_relayoutSubviewsWidthChanged:(BOOL)changedWidth
+{
+ if(changedWidth){
+ var _addButtonOrigin = [self frame].size.width - [_addButton
frame].size.width - [self _rowButtonsRightHorizontalPadding];
+ [_addButton setFrameOrigin:NSMakePoint(_addButtonOrigin, [_addButton
frame].origin.y)];
+
+ var _substractButtonOrigin = _addButtonOrigin - [_subtractButton
frame].size.width - [self _rowButtonsInterviewHorizontalPadding];
+ [_subtractButton setFrameOrigin:NSMakePoint(_substractButtonOrigin,
[_addButton frame].origin.y) ];
+ }
+
+ [_ruleOptionFrames removeAllObjects];
+
+ var optionViewOriginX = [self _leftmostViewFixedHorizontalPadding] +
[self _indentationHorizontalPadding]*[self indentation];
+
+ var collection = [_ruleOptionViews objectEnumerator];
+ var _ruleOptionView;
+ while (_ruleOptionView = [collection nextObject])
+ {
+ var shouldAddView = ([_ruleOptionView superview]==nil);
+ if(changedWidth || shouldAddView)
+ {
+ var optionFrame = [_ruleOptionView frame];
+ optionFrame.origin = NSMakePoint(optionViewOriginX, ([_ruleEditor
rowHeight] - optionFrame.size.height)/2);
+ var optionFrameEnd = MIN(optionFrame.origin.x +
optionFrame.size.width,[_subtractButton frame].origin.x - [self
_rowButtonsLeftHorizontalPadding]);
+ optionFrame.size.width = optionFrameEnd - optionFrame.origin.x;
+
+ [_ruleOptionView setFrame:optionFrame];
+ [_ruleOptionView setAutoresizingMask:CPViewMinYMargin &
CPViewMinXMargin ];
+
+ if(shouldAddView)[self addSubview:_ruleOptionView];
+
+ [_ruleOptionFrames addObject:[CPValue valueWithRect:optionFrame]];
+ optionViewOriginX += optionFrame.size.width + [self
_interviewHorizontalPadding];
+ }
+ }
+}
+
+- (void)_updateButtonVisibilities
+{
+ [_addButton setHidden:[_ruleEditor _shouldHideAddButtonForSlice:self]];
+ [_subtractButton setHidden:[_ruleEditor
_shouldHideSubtractButtonForSlice:self]];
+}
+
+- (void)_configurePlusButtonByRowType:(int)type
+{
+ var plusButtonType;
+
+ switch ([_ruleEditor nestingMode])
+ {
+ case CPRuleEditorNestingModeList:
+ plusButtonType = CPRuleEditorRowTypeSimple;
+ break;
+ case CPRuleEditorNestingModeSimple:
+ plusButtonType = CPRuleEditorRowTypeSimple;
+ break;
+ case CPRuleEditorNestingModeCompound:
+ plusButtonType = (type ==
CPRuleEditorRowTypeSimple)?CPRuleEditorRowTypeSimple:CPRuleEditorRowTypeCompound;
+ break;
+ default:
+ plusButtonType = CPRuleEditorRowTypeSimple;
+ break;
+ }
+ [self _setRowTypeToAddFromPlusButton:plusButtonType];
+}
+
+- (unsigned int)_rowType{
+ return _rowType;
+}
+
+- (void)_setRowType:(unsigned int)type
+{
+ _rowType = type;
+}
+
+- (BOOL)isEditable
+{
+ return _sliceRowFlags.editable;
+}
+
+- (void)setEditable:(BOOL)value
+{
+ _sliceRowFlags.editable = value;
+// [RuleEditorViewSliceRow _updateEnabledStateForSubviews];
+// [RuleEditorViewSliceRow _updateButtonVisibilities];
+
+}
+
+- (float)_alignmentGridWidth
+{
+ return 75.;
+}
+
+- (float)_indentationHorizontalPadding
+{
+ return 30.;
+}
+
+- (float)_interviewHorizontalPadding
+{
+ return 6.;
+}
+
+- (float)_leftmostViewFixedHorizontalPadding
+{
+ return 7.;
+}
+
+- (float)_minimumVerticalPopupPadding
+{
+ return 2.;
+}
+
+- (float)_rowButtonsInterviewHorizontalPadding
+{
+ return 2.;
+}
+
+- (float)_rowButtonsLeftHorizontalPadding
+{
+ return 10.;
+}
+
+- (float)_rowButtonsRightHorizontalPadding
+{
+ return 10.;
+}
+
+- (void)_setRowTypeToAddFromPlusButton:(int)type
+{
+ _plusButtonRowType = type;
+}
+
+- (void)setNeedsDisplay:(BOOL)flag
+{
+ [super setNeedsDisplay:flag];
+}
+
+- (BOOL)_nestingModeShouldHideAddButton
+{
+ return [_ruleEditor nestingMode] == CPRuleEditorNestingModeSingle;
+}
+
+- (BOOL)_nestingModeShouldHideSubtractButton
+{
+ return [_ruleEditor nestingMode] == CPRuleEditorNestingModeSingle;
+}
+
+- (BOOL)containsDisplayValue:(id)value
+{
+ return [[_ruleEditor displayValuesForRow:[self rowIndex]]
containsObject:value];
+ // Ou alors avec _correspondingRuleItems
+}
+
+/*
+- (BOOL)_dropsIndentWhenImmediatelyBelow
+{
+}
+- (double)_minWidthForPass:(int)pass forView:(id)view
withProposedMinWidth:(double)minWidth
+{
+}
+- (BOOL)_isRulePopup:(id)fp8
+{
+}
+- (BOOL)_isRuleStaticTextField:(id)fp8
+{
+}
+- (id)_sortOptionDictionariesByLayoutOrder:(id)fp8
+{
+}
+- (void)_setHideNonPartDrawing:(BOOL)value
+{
+}
+- (void)_tightenResizables:(id)fp8 intoGivenWidth:(double)fp12
+{
+}
+- (void)_updateEnabledStateForSubviews
+{
+}
+- (void)viewDidMoveToWindow
+{
+*/
+
+@end

Added: branches/CPRuleEditor/Info.plist
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/Info.plist Wed Oct 8 14:54:24 2008
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST
1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CPApplicationDelegateClass</key>
+ <string>AppController</string>
+ <key>CPBundleName</key>
+ <string>Hello World</string>
+ <key>CPPrincipalClass</key>
+ <string>CPApplication</string>
+</dict>
+</plist>

Added: branches/CPRuleEditor/RuleDelegate.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/RuleDelegate.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,157 @@
+
+import <Foundation/Foundation.j>
+ import "CPRuleEditor.j"
+
+var CPRuleEditorPredicateKeys = new
Array(CPRuleEditorPredicateLeftExpression,CPRuleEditorPredicateRightExpression,CPRuleEditorPredicateComparisonModifier,CPRuleEditorPredicateOptions,CPRuleEditorPredicateOperatorType,CPRuleEditorPredicateCustomSelector,CPRuleEditorPredicateCompoundType);
+
+@implementation CPDictionary (Additions)
+
++(id)dictionaryWithContentsOfURL:(CPURL)url
+{
+
+ var request = [CPURLRequest requestWithURL:url];
+ var data = [CPURLConnection sendSynchronousRequest:request
returningResponse:NULL error:NULL];
+ if(data)
+ {
+ var dict = [CPPropertyListSerialization propertyListFromData:data
format:CPPropertyListXMLFormat_v1_0 errorDescription:NULL];
+ return dict;
+ }
+
+ return nil;
+}
+
+@end
+
+@implementation RuleDelegate : CPObject
+{
+CPDictionary rows;
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil)
+ {
+ rows = [CPDictionary dictionaryWithContentsOfURL:"criteria.plist"];
+ CPLogConsole("ROWS = "+[rows description]);
+ }
+
+ return self;
+}
+
+/* When called, you should return the number of child items of the given
criterion. If criterion is nil, you should return the number of root
criteria for the given row type. Implementation of this method is required.
*/
+
+- (int)ruleEditor:(RuleEditor )editor
numberOfChildrenForCriterion:(id)criterion
withRowType:(CPRuleEditorRowType)rowType
+{
+ var childs;
+ if(criterion)
+ childs = [criterion objectForKey:@"criteria"];
+ else
+ childs = [rows valueForKeyPath:(rowType == CPRuleEditorRowTypeSimple) ?
@"rootChildren.subrows" : @"rootHeaders.subrows"];
+ return [childs count];
+}
+
+/* When called, you should return the child of the given item at the given
index. If criterion is nil, return the root criterion for the given row
type at the given index. Implementation of this method is required. */
+
+- (id)ruleEditor:(RuleEditor *)editor child:(int)index
forCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType
+{
+ var childs;
+
+ if(criterion)
+ childs = [criterion objectForKey:@"criteria"];
+ else
+ childs = [rows valueForKeyPath:(rowType == CPRuleEditorRowTypeSimple) ?
@"rootChildren.subrows" : @"rootHeaders.subrows"];
+
+ return [childs objectAtIndex:index];
+
+}
+
+/*
+ When called, you should return a value for the given criterion. The
value should be an instance of CPString, CPView, or CPMenuItem (1). If the
value is an CPView or CPMenuItem (1), you must ensure it is unique for
every invocation of this method; that is, do not return a particular
instance of CPView or CPMenuItem more than once. Implementation of this
method is required.
+ (1) CPMenuItem: not implemented yet.
+*/
+
+- (id)ruleEditor:(RuleEditor)editor displayValueForCriterion:(id)criterion
inRow:(int)row
+{
+
+ var custom_control_class = [criterion
objectForKey:@"CPRuleEditorCustomControlClass"];
+
+ if(custom_control_class != nil)
+ {
+ var viewkey = [CPString stringWithFormat:@"view_%d", row];
+
+ var view = [criterion objectForKey:viewkey];
+ if(view == nil)
+ {
+ var custom_class = CPClassFromString(custom_control_class);
+ view = [[[custom_class alloc] initWithFrame:CGZeroRect] autorelease];
+
+ [criterion setObject:view forKey:viewkey];
+ }
+ return view;
+ }
+
+ return [criterion objectForKey:@"valeur"];
+
+}
+
+- (CPDictionary)ruleEditor:(RuleEditor)editor
predicatePartsForCriterion:(id)criterion withDisplayValue:(id)value
inRow:(int)row
+{
+
+ var predicatePartsForCriterion = [CPDictionary dictionary];
+
+ if([editor rowTypeForRow:row] == CPRuleEditorRowTypeCompound)
+ {
+ var compound_type = [criterion
objectForKey:CPRuleEditorPredicateCompoundType];
+ if(compound_type)[predicatePartsForCriterion setObject:compound_type
forKey:CPRuleEditorPredicateCompoundType];
+ return predicatePartsForCriterion;
+ }
+
+ var i;
+ for (i=0 ;i< 7;i++){
+ var key = CPRuleEditorPredicateKeys[i];
+ var predicatePart = nil ;
+
+ if([key isEqualToString:CPRuleEditorPredicateLeftExpression])
+ {
+ var str = [criterion objectForKey:key];
+ if(str) predicatePart = [CPExpression expressionForKeyPath:str];
+ }
+ else if ([key isEqualToString:CPRuleEditorPredicateRightExpression])
+ {
+ var transformedValue;
+ if([criterion objectForKey:@"CPRuleEditorCustomControlClass"] != nil)
+ transformedValue = ([value isKindOfClass:[CPView class]]) ? [value
objectValue]:value;
+ else
+ transformedValue = [criterion objectForKey:key];
+ predicatePart = [CPExpression
expressionForCoCPtantValue:transformedValue];
+ }
+ else if ([key isEqualToString:CPRuleEditorPredicateOperatorType])
+ {
+ var operator = [criterion objectForKey:key];
+ if(operator) predicatePart = operator;
+ }
+ else if ([key isEqualToString:CPRuleEditorPredicateCustomSelector])
+ {
+ var selector = [criterion objectForKey:key];
+ if(selector) predicatePart = selector;
+ }
+ else if ([key isEqualToString:CPRuleEditorPredicateOptions])
+ {
+ var options = [criterion objectForKey:key];
+ if(options) predicatePart = options;
+ }
+ else continue;
+
+ if(predicatePart)[predicatePartsForCriterion setObject:predicatePart
forKey:key];
+ }
+ return predicatePartsForCriterion;
+}
+
+
+- (void)ruleEditorRowsDidChange:(CPNotification)notification
+{
+ // CPLog(@"ruleEditorRowsDidChange:%@",[notification description]);
+}
+
+@end

Added: branches/CPRuleEditor/RuleEditor.steam
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/RuleEditor.steam Wed Oct 8 14:54:24 2008
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST
1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Name</key>
+ <string>CPRuleEditorTest</string>
+ <key>Targets</key>
+ <array>
+ <dict>
+ <key>Name</key>
+ <string>CPRuleEditorTest</string>
+ </dict>
+ </array>
+ <key>Configurations</key>
+ <array>
+ <dict>
+ <key>Name</key>
+ <string>Debug</string>
+ <key>Settings</key>
+ <dict>
+ <key>PREPROCESS</key>
+ <true/>
+ <key>FLAGS</key>
+ <string>-DDEBUG</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Name</key>
+ <string>Release</string>
+ <key>Settings</key>
+ <dict>
+ <key>PREPROCESS</key>
+ <true/>
+ <key>PREINTERPRET</key>
+ <true/>
+ </dict>
+ </dict>
+ </array>
+</dict>
+</plist>

Added: branches/CPRuleEditor/_CPRuleEditorCache.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/_CPRuleEditorCache.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,54 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+
+@implementation RuleEditorCache : CPObject
+{
+ CPDictionary rowObject;
+ int rowIndex;
+ int indentation;
+}
+-(CPString)description
+{
+ return [CPString stringWithFormat:@"<%@ object:%p rowIndex:%d
indentation:%d>",[self className] , rowObject,rowIndex,indentation];
+}
+
+- (CPDictionary)rowObject
+{
+ return rowObject;
+}
+
+- (void)setRowObject:(CPDictionary)value
+{
+ if (rowObject != value)
+ rowObject = value;
+}
+
+- (int)rowIndex
+{
+ return rowIndex;
+}
+
+- (void)setRowIndex:(int)value
+{
+ if (rowIndex != value)
+ rowIndex = value;
+}
+
+- (int)indentation
+{
+ return indentation;
+}
+
+- (void)setIndentation:(int)value
+{
+ if (indentation != value)
+ indentation = value;
+}
+
+
+
+@end
+

Added: branches/CPRuleEditor/_CPRuleEditorViewSliceHolder.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/_CPRuleEditorViewSliceHolder.j Wed Oct 8
14:54:24 2008
@@ -0,0 +1,36 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+
+@implementation RuleEditorViewSliceHolder : CPView
+{
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self != nil) {
+ [self setBackgroundColor:[CPColor redColor]]
+}
+ return self;
+}
+
+- (void)addSubview:(CPView)subview
+{
+ [super addSubview:subview];
+}
+
+- (BOOL)isFlipped
+{
+ return YES;
+}
+
+- (void)drawRect:(CGRect)rect
+{
+ [[self superview] drawRect:rect];
+}
+
+@end
+

Added: branches/CPRuleEditor/_CPRuleEditorViewUnboundRowHolder.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/_CPRuleEditorViewUnboundRowHolder.j Wed Oct 8
14:54:24 2008
@@ -0,0 +1,34 @@
+/*
+ * Created by caca...@gmail.com.
+ * Copyright (c) 2008 Pear, Inc. All rights reserved.
+ */
+
+@implementation RuleEditorViewUnboundRowHolder : CPObject
+{
+ CPArray boundArray;
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil)
+ boundArray = [[CPArray alloc] init];
+ return self;
+}
+
+- (id)initWithCoder:(id)coder
+{
+ self = [super init];
+ if (self != nil)
+ boundArray = [coder decodeObjectForKey:@"CPBoundArray"];
+
+ return self;
+}
+
+- (void)encodeWithCoder:(id)coder
+{
+ [coder encodeObject:boundArray forKey:@"CPBoundArray"];
+}
+
+@end
+

Added: branches/CPRuleEditor/criteria.plist
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/criteria.plist Wed Oct 8 14:54:24 2008
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST
1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>rootHeaders</key>
+ <dict>
+ <key>subrows</key>
+ <array>
+ <dict>
+ <key>NSRuleEditorPredicateCompoundType</key>
+ <integer>1</integer>
+ <key>criteria</key>
+ <array>
+ <dict>
+ <key>valeur</key>
+ <string>of the following is true</string>
+ </dict>
+ </array>
+ <key>valeur</key>
+ <string>All</string>
+ </dict>
+ <dict>
+ <key>NSRuleEditorPredicateCompoundType</key>
+ <integer>2</integer>
+ <key>criteria</key>
+ <array>
+ <dict>
+ <key>valeur</key>
+ <string>of the following is true</string>
+ </dict>
+ </array>
+ <key>valeur</key>
+ <string>Any</string>
+ </dict>
+ </array>
+ </dict>
+ <key>rootChildren</key>
+ <dict>
+ <key>subrows</key>
+ <array>
+ <dict>
+ <key>NSRuleEditorPredicateLeftExpression</key>
+ <string>age</string>
+ <key>criteria</key>
+ <array>
+ <dict>
+ <key>NSRuleEditorPredicateComparisonModifier</key>
+ <integer>0</integer>
+ <key>NSRuleEditorPredicateOperatorType</key>
+ <integer>0</integer>
+ <key>NSRuleEditorPredicateOptions</key>
+ <integer>0</integer>
+ <key>criteria</key>
+ <array>
+ <dict>
+ <key>NSRuleEditorPredicateRightExpression</key>
+ <integer>45</integer>
+ <key>valeur</key>
+ <string>45 ans</string>
+ </dict>
+ </array>
+ <key>valeur</key>
+ <string>NSLessThanPredicateOperatorType</string>
+ </dict>
+ <dict>
+ <key>NSRuleEditorPredicateComparisonModifier</key>
+ <integer>0</integer>
+ <key>NSRuleEditorPredicateOperatorType</key>
+ <integer>1</integer>
+ <key>NSRuleEditorPredicateOptions</key>
+ <integer>0</integer>
+ <key>criteria</key>
+ <array>
+ <dict>
+ <key>NSRuleEditorPredicateRightExpression</key>
+ <integer>50</integer>
+ <key>valeur</key>
+ <string>50 ans</string>
+ </dict>
+ </array>
+ <key>valeur</key>
+ <string>NSLessThanOrEqualToPredicateOperatorType</string>
+ </dict>
+ </array>
+ <key>valeur</key>
+ <string>age</string>
+ </dict>
+ </array>
+ </dict>
+</dict>
+</plist>

Added: branches/CPRuleEditor/index.html
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/index.html Wed Oct 8 14:54:24 2008
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns = "http://www.w3.org/1999/xhtml" xml:lang = "en" lang = "en">
+<!--
+//
+// index.html
+// Viewer
+//
+// Created by Ross Boucher on 5/19/2008.
+// Copyright 2005 - 2008, 280 North, Inc. All rights reserved.
+//
+-->
+ <head>
+
+ <title>Hello World</title>
+
+ <script src = "Frameworks/Objective-J/Objective-J.js" type
= "text/javascript"></script>
+
+ <script type = "text/javascript">
+
+ objj_import("main.j", YES, function() { main();
});OBJJ_EXCEPTION_OUTPUT_STREAM = console.error;
+ </script>
+
+ </head>
+
+ <body>
+ <div style="position: absolute; left: 50%; top: 50%;">
+ <center>
+ <img src
= "Frameworks/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"
style="left: -32px; position: relative; top: -32px;" />
+ </center>
+ </div>
+ </body>
+
+</html>
\ No newline at end of file

Added: branches/CPRuleEditor/main.j
==============================================================================
--- (empty file)
+++ branches/CPRuleEditor/main.j Wed Oct 8 14:54:24 2008
@@ -0,0 +1,9 @@
+import <Foundation/Foundation.j>
+import <AppKit/AppKit.j>
+
+import "AppController.j"
+
+function main(args, namedArgs)
+{
+ CPApplicationMain(args, namedArgs);
+}

Modified: branches/Issue16_Branch/Framework/Criterion.m
==============================================================================
--- branches/Issue16_Branch/Framework/Criterion.m (original)
+++ branches/Issue16_Branch/Framework/Criterion.m Wed Oct 8 14:54:24 2008
@@ -10,11 +10,11 @@
+ (Criterion*)criterionWithObjectValue:(id)ov slice:(id)s
rowIndex:(int)index rowType:(PSRuleEditorRowType)rowType{
return [[[self alloc] initWithObjectValue:(id)ov slice:(id)s
rowIndex:(int)index rowType:(PSRuleEditorRowType)rowType] autorelease];
}
-
+/*
+ (Criterion*)criterionWithView:(NSView*)view{
return [[[self alloc] initWithView:view] autorelease];
}
-
+*/
- (id)initWithObjectValue:(id)ov slice:(id)s rowIndex:(int)rowindex
rowType:(PSRuleEditorRowType)rowType{
self = [super init];
if (self != nil){
@@ -27,7 +27,7 @@
return self;
}

-- (id)initWithView:(NSView*)aView{
+- (Criterion*)initWithView:(NSView*)aView{
self = [super init];
if (self != nil){
[self setView:aView];
@@ -160,12 +160,11 @@
id displayValue;
while (displayValue = [e nextObject]) {
NSMenuItem *item;
- if ([displayValue isKindOfClass:[NSString class]])
- {
+ if ([displayValue isKindOfClass:[NSString class]]){
NSString *fdisplayValue = [[self slice] formattedValue:displayValue];
item = [[[NSMenuItem alloc] initWithTitle: fdisplayValue action:NULL
keyEquivalent:@"" ] autorelease];
}
- else if ([displayValue isKindOfClass:[NSMenuItem class]])
+ else if ([displayValue isKindOfClass:[NSMenuItem class]]) // On donne
le menu item directement. Peut-ĂȘtre issu d'une template si predicate editor.
item = displayValue;
else
continue;

Modified: branches/Issue16_Branch/Framework/PSPredicateEditor.m
==============================================================================
--- branches/Issue16_Branch/Framework/PSPredicateEditor.m (original)
+++ branches/Issue16_Branch/Framework/PSPredicateEditor.m Wed Oct 8
14:54:24 2008
@@ -96,28 +96,29 @@
}

- (NSArray*)sharedLeftExpressions{
-
- return [self
valueForKeyPath:@"rowTemplates.@distinctUnionOfArrays.leftExpressions"];
+ return [_allTemplates
valueForKeyPath:@"@distinctUnionOfArrays.leftExpressions"];

}

-- (NSArray*)setupCriteriaTree{
+- (void)createCriteriaTree{
NSMutableArray *simpleTree = [NSMutableArray array];
- NSArray *lhsa = [self
valueForKeyPath:@"rowTemplates.@distinctUnionOfArrays.leftExpressions"];
+
+ NSArray *lhsa = [self sharedLeftExpressions];
+
NSEnumerator *lhse = [lhsa objectEnumerator];
NSExpression *lhs;
while (lhs= [lhse nextObject]) {
- NSPredicate * lhs_predicate = [NSPredicate predicateWithFormat:@"%@ IN
leftExpressions",lhs];
- NSArray *templates_by_lhs = [[self rowTemplates]
filteredArrayUsingPredicate:lhs_predicate];
+ NSPredicate * lhs_predicate = [NSPredicate predicateWithFormat:@"%@ IN
leftExpressions",lhs]; // TODO: make static
+ NSArray *templates_by_lhs = [_allTemplates
filteredArrayUsingPredicate:lhs_predicate];
NSArray *opa = [templates_by_lhs
valueForKeyPath:@"@distinctUnionOfArrays.operators"];
NSEnumerator *ope = [opa objectEnumerator];
NSNumber *op;
NSMutableArray *op_criteria = [NSMutableArray array];

while (op = [ope nextObject]) {
- NSPredicate * op_predicate = [NSPredicate predicateWithFormat:@"%@ IN
operators",op];
+ NSPredicate * op_predicate = [NSPredicate predicateWithFormat:@"%@ IN
operators",op]; // TODO: make static
NSArray *templates_by_operator = [templates_by_lhs
filteredArrayUsingPredicate:op_predicate];
- PSPredicateEditorRowTemplate *priority_template =
[templates_by_operator objectAtIndex:0]; // get template on top of priority
list
+ PSPredicateEditorRowTemplate *priority_template =
[templates_by_operator objectAtIndex:0]; // get template which is on top of
priority list

NSDictionary *op_dict;
NSMutableArray *rhsa = [NSMutableArray array];
@@ -144,25 +145,36 @@
while (rhs = [rhse nextObject]) {
NSDictionary *rhs_dict = [NSDictionary
dictionaryWithObjectsAndKeys:[NSNumber
numberWithInt:2],@"level",rhs ,@"value",[NSNumber
numberWithBool:isAttributeType],@"AttributeType",nil];
[rhs_criteria addObject:rhs_dict];
- }
+ }
+
op_dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber
numberWithInt:1],@"level",op,@"value",rhs_criteria,@"childs",nil];
[op_criteria addObject:op_dict];
}
- NSDictionary *lhs_dict = [NSDictionary
dictionaryWithObjectsAndKeys:[NSNumber
numberWithInt:0],@"level",lhs ,@"value",op_criteria,@"childs",nil];
+ NSMenuItem *lhsItem = [[[NSMenuItem alloc] initWithTitle:[lhs
description] action:NULL keyEquivalent:@""] autorelease];
+ id first_lhs_template = [templates_by_lhs objectAtIndex:0];
+ int index = [[first_lhs_template leftExpressions] indexOfObject:lhs];
+
+ NSDictionary *ref = [NSDictionary
dictionaryWithObjectsAndKeys:first_lhs_template,@"template",[NSNumber
numberWithInt:index],@"index",nil];
+ [lhsItem setRepresentedObject:ref];
+ NSDictionary *lhs_dict = [NSDictionary
dictionaryWithObjectsAndKeys:[NSNumber
numberWithInt:0],@"level",lhsItem ,@"value",op_criteria,@"childs",nil];
[simpleTree addObject:lhs_dict];
}

NSArray *cp = [_allTemplates
valueForKeyPath:@"@distinctUnionOfArrays.compoundTypes"];
- NSMutableArray *compoundTree = [NSMutableArray array]; int i;
+ NSMutableArray *compoundTree = [NSMutableArray array];
NSArray *childs = [NSArray arrayWithObject:[NSDictionary
dictionaryWithObjectsAndKeys:@"of the following is true",@"value",[NSNumber
numberWithInt:0],@"level",nil]];
-
+
+ int i;
+ NSArray * cp_strings = [NSArray
arrayWithObjects:@"All",@"Any",@"None",nil]; // TODO: make static
for (i=0; i<[cp count]; i++) {
NSNumber *n = [cp objectAtIndex:i];
- NSDictionary *d = [NSDictionary
dictionaryWithObjectsAndKeys:n,@"value",childs,@"childs",[NSNumber
numberWithInt:0],@"level",nil];
+ NSString *cp_string = [cp_strings objectAtIndex:[n intValue]];
+ NSDictionary *d = [NSDictionary
dictionaryWithObjectsAndKeys:cp_string,@"value",childs,@"childs",[NSNumber
numberWithInt:0],@"level",nil];
[compoundTree addObject:d];
}

NSDictionary *tree = [NSDictionary
dictionaryWithObjectsAndKeys:simpleTree,@"PSRuleEditorRowTypeSimple",compoundTree,@"PSRuleEditorRowTypeCompound",nil];
+ NSLog(@"tree :%@",tree);
[self setCriteriaTree:tree];
}

@@ -211,10 +223,10 @@
id value = [criterion objectForKey:@"value"];
id displayValue = nil;

- switch ([[criterion objectForKey:@"level"] intValue])
+ switch (level)
{
case 0:
- displayValue = [value description];
+ displayValue = [[value copy] autorelease];
break;
case 1:
displayValue = predicateOperatorType[[value intValue]];
@@ -240,7 +252,21 @@
return displayValue;
}

-// Creates a fresh template based on current templates in use by editor's
rows
+- (NSDictionary*)ruleEditor:(PSRuleEditor*)editor
predicatePartsForCriterion:(id)criterion withDisplayValue:(id)value
inRow:(int)row{
+
+ NSMutableDictionary *predicatePartsForCriterion = [NSMutableDictionary
dictionary];
+ int i;
+ for (i=0 ;i< 6;i++){
+ /*
+ NSString *key = predicatePartsKeys[i];
+ [predicatePartsForCriterion setObject:predicatePart forKey:key];
+ */
+ }
+ return predicatePartsForCriterion;
+}
+
+/*
+// Creates a fresh template based on current templates in use by editor's
rows // obsolete (Issue 16).
- (PSPredicateEditorRowTemplate*)nextTemplate{

NSEnumerator *te = [[self rowTemplates] objectEnumerator];
@@ -250,7 +276,7 @@

return t;
}
-
+*/
// Mark dirty nodes and refresh the view
- (void)_removeRow:(PSRuleEditorSlice*)slice{

@@ -656,8 +682,8 @@
if (rowTemplates != _allTemplates){
[_allTemplates release];
_allTemplates = [rowTemplates retain];
- if(formattingDictionary)
- [_allTemplates
makeObjectsPerformSelector:@selector(_setFormattingDictionary:)
withObject:formattingDictionary];
+ if(formattingDictionary)[_allTemplates
makeObjectsPerformSelector:@selector(_setFormattingDictionary:)
withObject:formattingDictionary];
+ if(_allTemplates) [self createCriteriaTree];
}
}


Modified: branches/Issue16_Branch/Framework/PSPredicateEditorRowTemplate.m
==============================================================================
--- branches/Issue16_Branch/Framework/PSPredicateEditorRowTemplate.m
(original)
+++ branches/Issue16_Branch/Framework/PSPredicateEditorRowTemplate.m Wed
Oct 8 14:54:24 2008
@@ -177,6 +177,7 @@
if (self != nil) {
_compoundTypes = [compoundTypes retain];
_templateType = 2;
+
}
return self;
}
@@ -267,7 +268,10 @@
- (NSArray *)displayableSubpredicatesOfPredicate:(NSPredicate *)predicate{

if([predicate isKindOfClass:[NSCompoundPredicate class]])
- return [(NSCompoundPredicate*)predicate subpredicates];
+ {
+ NSArray *subp = [(NSCompoundPredicate*)predicate subpredicates];
+ return ([subp count]>0)? subp:nil;
+ }
else
return nil;

@@ -311,7 +315,7 @@
- (void)_checkForValidOperators:(NSArray*)operators{
NSPredicate *validNumbers = [NSPredicate predicateWithFormat:@"(ALL
className == 'NSCFNumber') AND (ALL SELF < 12)"];
if(![validNumbers evaluateWithObject:operators])
- [NSException raise:NSInvalidArgumentException format:@"operators should
be NSNumber.\n%@",operators];
+ [NSException raise:NSInvalidArgumentException format:@"Operators should
be NSNumber.\n%@",operators];
}

- (void)_checkForValidExpressions:(NSArray*)expressions{

Modified: branches/Issue16_Branch/Framework/PSRuleEditor_SelectDrag.m
==============================================================================
--- branches/Issue16_Branch/Framework/PSRuleEditor_SelectDrag.m (original)
+++ branches/Issue16_Branch/Framework/PSRuleEditor_SelectDrag.m Wed Oct 8
14:54:24 2008
@@ -64,8 +64,7 @@
//===========================================================
// selectedSlices
//===========================================================
-- (NSMutableArray *)selectedSlices
-{
+- (NSMutableArray *)selectedSlices{
return selectedSlices;
}


Modified: branches/Issue16_Branch/TestApp/PEController.m
==============================================================================
--- branches/Issue16_Branch/TestApp/PEController.m (original)
+++ branches/Issue16_Branch/TestApp/PEController.m Wed Oct 8 14:54:24 2008
@@ -128,7 +128,7 @@

/* set the templates back on the predicate editor */
[predicateEditor setRowTemplates:templates];
- [predicateEditor setupCriteriaTree];
+

[predicateEditor bind:@"value" toObject:criteriaController
withKeyPath:@"selection.predicate" options:[NSDictionary
dictionaryWithObjectsAndKeys:[NSNumber
numberWithInt:1],NSValidatesImmediatelyBindingOption,[NSNumber
numberWithInt:1],NSContinuouslyUpdatesValueBindingOption,nil]];
}

Modified: branches/TreeBranch/Framework/PSRuleEditor_SelectDrag.m
==============================================================================
--- branches/TreeBranch/Framework/PSRuleEditor_SelectDrag.m (original)
+++ branches/TreeBranch/Framework/PSRuleEditor_SelectDrag.m Wed Oct 8
14:54:24 2008
@@ -134,7 +134,7 @@
[self setNeedsDisplay:YES];
}

- return ([downEvent modifierFlags] & NSAlternateKeyMask)?
NSDragOperationCopy:NSDragOperationAll;
+ return ([downEvent modifierFlags] & NSAlternateKeyMask)?
NSDragOperationCopy:NSDragOperationEvery;
}


/*****************************************************************************
@@ -222,7 +222,7 @@
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
if ([sender draggingSource] == self) {
[self clearDragDestinationMembers];
- return NSDragOperationAll;
+ return NSDragOperationEvery;
} else {
return NSDragOperationNone;
}
@@ -236,7 +236,7 @@

*****************************************************************************/
- (void)draggingExited:(id <NSDraggingInfo>)sender {
[self clearDragDestinationMembers];
- [self setNeedsDisplay:TRUE];
+ [self setNeedsDisplay:YES];
}


/*****************************************************************************

Modified: branches/TreeBranch/PSRuleEditor.xcodeproj/project.pbxproj
==============================================================================
Binary files. No diff available.
Reply all
Reply to author
Forward
0 new messages