CPRuleEditor & CPPredicateEditor & CPPredicateEditorRowtemplate implementations with theming, nib2cib support.

Tests: CPRuleEditorCibTest, CPPredicateEditorCibTest, SmartFoldersDemo: a real world usage of CPPredicateEditor.
Documentation for these 3 new classes.
This commit is contained in:
cacaodev
2011-05-23 10:59:43 +02:00
committed by Klaas Pieter Annema
parent 6c6ac4bd2e
commit ca1a1b43f1
58 changed files with 19860 additions and 1 deletions
+3
View File
@@ -66,9 +66,12 @@
@import "CPPanel.j"
@import "CPPasteboard.j"
@import "CPPopUpButton.j"
@import "CPPredicateEditor.j"
@import "CPPredicateEditorRowTemplate.j"
@import "CPProgressIndicator.j"
@import "CPRadio.j"
@import "CPResponder.j"
@import "CPRuleEditor.j"
@import "CPScroller.j"
@import "CPScrollView.j"
@import "CPSearchField.j"
+490
View File
@@ -0,0 +1,490 @@
/*
* CPPredicateEditor.j
* AppKit
*
* Created by cacaodev.
* Copyright 2011, cacaodev.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPRuleEditor.j"
@import "_CPPredicateEditorTree.j"
@import "_CPPredicateEditorRowNode.j"
@import "CPPredicateEditorRowTemplate.j"
@implementation CPPredicateEditor : CPRuleEditor
{
CPArray _allTemplates;
CPArray _rootTrees;
CPArray _rootHeaderTrees;
id _predicateTarget @accessors(property=target);
SEL _predicateAction @accessors(property=action);
}
#pragma mark public methods
/*!
@ingroup appkit
@class CPPredicateEditor
@brief CPPredicateEditor is a subclass of CPRuleEditor that is specialized for editing CPPredicate objects.
CPPredicateEditor provides a CPPredicate property—objectValue (inherited from CPControl)—that you can get and set directly, and that you can bind using bindings (you typically configure a predicate editor in Interface Builder). CPPredicateEditor depends on another class, CPPredicateEditorRowTemplate, that describes the available predicates and how to display them.
Unlike CPRuleEditor, CPPredicateEditor does not depend on its delegate to populate its rows (and does not call the populating delegate methods). Instead, its rows are populated from its objectValue property (an instance of CPPredicate). CPPredicateEditor relies on instances CPPredicateEditorRowTemplate, which are responsible for mapping back and forth between the displayed view values and various predicates.
CPPredicateEditor exposes one property, rowTemplates, which is an array of CPPredicateEditorRowTemplate objects.
*/
/*!
@brief Returns the row templates for the receiver.
@return The row templates for the receiver.
@discussion Until otherwise set, this contains a single compound CPPredicateEditorRowTemplate object.
@see setRowTemplates:
*/
- (CPArray)rowTemplates
{
return _allTemplates;
}
/*!
@brief Sets the row templates for the receiver.
@param rowTemplates An array of CPPredicateEditorRowTemplate objects.
@see rowTemplates
*/
- (void)setRowTemplates:(id)rowTemplates
{
if (_allTemplates == rowTemplates)
return;
_allTemplates = rowTemplates;
[self _updateItemsByCompoundTemplates];
[self _updateItemsBySimpleTemplates];
if ([self numberOfRows] > 0)
{
var predicate = [super predicate];
[self _reflectPredicate:predicate];
}
}
/*! @cond */
- (void)_initRuleEditorShared
{
[super _initRuleEditorShared];
_rootTrees = [CPArray array];
_rootHeaderTrees = [CPArray array];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self != nil)
{
var initialTemplate = [[CPPredicateEditorRowTemplate alloc] initWithCompoundTypes:[CPAndPredicateType, CPOrPredicateType]];
_allTemplates = [CPArray arrayWithObject:initialTemplate];
}
return self;
}
- (id)objectValue
{
return [super predicate];
}
- (void)_updateItemsBySimpleTemplates
{
var templates = [CPMutableArray array],
count = [_allTemplates count],
t;
while (count--)
{
var t = _allTemplates[count];
if ([t _rowType] == CPRuleEditorRowTypeSimple)
[templates insertObject:t atIndex:0];
}
var trees = [self _constructTreesForTemplates:templates];
if ([trees count] > 0)
_rootTrees = [self _mergeTree:trees];
}
- (void)_updateItemsByCompoundTemplates
{
var templates = [CPMutableArray array],
count = [_allTemplates count],
t;
while (count--)
{
var t = _allTemplates[count];
if ([t _rowType] == CPRuleEditorRowTypeCompound)
[templates insertObject:t atIndex:0];
}
var trees = [self _constructTreesForTemplates:templates];
if ([trees count] > 0)
_rootHeaderTrees = [self _mergeTree:trees];
}
- (CPArray)_constructTreesForTemplates:(id)templates
{
var trees = [CPMutableArray array],
count = [templates count];
for (var i = 0; i < count; i++)
{
var tree = [self _constructTreeForTemplate:templates[i]];
[trees addObjectsFromArray:tree];
}
return trees;
}
- (id)_mergeTree:(id)tree
{
var merged = [CPMutableArray array],
titles = [CPMutableArray array],
count = [tree count];
for (var i = 0; i < count; i++)
{
var t = tree[i],
title = [CPString stringWithString:[t title]];
if ([titles containsObject:title])
{
CPLogConsole("CPPredicate does not support templates merging yet. Ignoring duplicate template: " + [t description]);
continue;
}
[merged addObject:t];
[titles addObject:title];
}
return merged;
}
- (id)_constructTreeForTemplate:(CPPredicateEditorRowTemplate)aTemplate
{
var tree = [CPArray array],
templateViews = [aTemplate templateViews],
count = [templateViews count];
while (count--)
{
var children = [CPArray array],
itemsCount = 0,
menuIndex = -1,
itemsArray,
templateView = [templateViews objectAtIndex:count],
isPopup = [templateView isKindOfClass:[CPPopUpButton class]];
if (isPopup)
{
itemArray = [[templateView itemArray] valueForKey:@"title"];
itemsCount = [itemArray count],
menuIndex = 0;
}
for (; menuIndex < itemsCount; menuIndex++)
{
var item = [_CPPredicateEditorTree new];
[item setIndexIntoTemplate:count];
[item setTemplate:aTemplate];
[item setMenuItemIndex:menuIndex];
if (isPopup)
[item setTitle:[itemArray objectAtIndex:menuIndex]];
[children addObject:item];
}
[children makeObjectsPerformSelector:@selector(setChildren:) withObject:tree];
tree = children;
}
return tree;
}
#pragma mark Set the Predicate
- (void)setObjectValue:(id)objectValue
{
if (![[objectValue predicateFormat] isEqualToString:[[super predicate] predicateFormat]]) // ??
[self _reflectPredicate:objectValue];
}
- (void)_reflectPredicate:(id)predicate
{
var animation = _currentAnimation;
_currentAnimation = nil;
if (predicate != nil)
{
if ((_nestingMode == CPRuleEditorNestingModeSimple || _nestingMode == CPRuleEditorNestingModeCompound)
&& [predicate isKindOfClass:[CPComparisonPredicate class]])
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:[CPArray arrayWithObject:predicate]];
var row = [self _rowObjectFromPredicate:predicate];
if (row != nil)
[_boundArrayOwner setValue:[CPArray arrayWithObject:row] forKey:_boundArrayKeyPath];
}
[self setAnimation:animation];
}
- (id)_rowObjectFromPredicate:(CPPredicate)predicate
{
var quality, // TODO: We should use this ref somewhere !
type,
matchedTemplate = [CPPredicateEditorRowTemplate _bestMatchForPredicate:predicate inTemplates:[self rowTemplates] quality:quality];
if (matchedTemplate == nil)
return nil;
var copyTemplate = [matchedTemplate copy],
subpredicates = [matchedTemplate displayableSubpredicatesOfPredicate:predicate];
if (subpredicates == nil)
{
[copyTemplate _setComparisonPredicate:predicate];
type = CPRuleEditorRowTypeSimple;
}
else
{
[copyTemplate _setCompoundPredicate:predicate];
type = CPRuleEditorRowTypeCompound;
}
var row = [self _rowFromTemplate:copyTemplate originalTemplate:matchedTemplate withRowType:type];
if (subpredicates == nil)
return row;
var count = [subpredicates count],
subrows = [CPMutableArray array];
for (var i = 0; i < count; i++)
{
var subrow = [self _rowObjectFromPredicate:subpredicates[i]];
if (subrow != nil)
[subrows addObject:subrow];
}
[row setValue:subrows forKey:[super subrowsKeyPath]];
return row;
}
- (id)_rowFromTemplate:(CPPredicateEditorRowTemplate)aTemplate originalTemplate:(CPPredicateEditorRowTemplate)originalTemplate withRowType:(CPRuleEditorRowType)rowType
{
var criteria = [CPArray array],
values = [CPArray array],
templateViews = [aTemplate templateViews],
rootItems,
count;
rootItems = (rowType == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
while ((count = [rootItems count]) > 0)
{
var treeChild;
for (var i = 0; i < count; i++)
{
treeChild = [rootItems objectAtIndex:i];
var currentView = [templateViews objectAtIndex:[treeChild indexIntoTemplate]],
menuItemIndex = [treeChild menuItemIndex];
if (menuItemIndex == -1 || [[treeChild title] isEqual:[currentView titleOfSelectedItem]])
{
var node = [_CPPredicateEditorRowNode _rowNodeFromTree:treeChild withTemplate:aTemplate];
[criteria addObject:node];
[values addObject:[node displayValue]];
break;
}
}
rootItems = [treeChild children];
}
var row = [CPDictionary dictionaryWithObjectsAndKeys:criteria, @"criteria", values, @"displayValues", rowType, @"rowType"];
return row;
}
#pragma mark Get the predicate
- (void)_updatePredicate
{
//[self willChangeValueForKey:@"objectValue"];
[self _updatePredicateFromRows];
//[self didChangeValueForKey:@"objectValue"];
}
- (void)_updatePredicateFromRows
{
var rootRowsArray = [super _rootRowsArray],
subpredicates = [CPMutableArray array],
count = count2 = [rootRowsArray count],
predicate;
while (count--)
{
var item = [rootRowsArray objectAtIndex:count],
subpredicate = [self _predicateFromRowItem:item];
if (subpredicate != nil)
[subpredicates insertObject:subpredicate atIndex:0];
}
if (_nestingMode != CPRuleEditorNestingModeList && count2 == 1)
predicate = [subpredicates lastObject];
else
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:subpredicates];
[super _setPredicate:predicate];
}
- (id)_predicateFromRowItem:(id)rowItem
{
var subpredicates = [CPArray array],
subrows = [rowItem valueForKey:[super subrowsKeyPath]],
count = [subrows count];
for (var i = 0; i < count; i++)
{
var predicate = [self _predicateFromRowItem:subrows[i]];
[subpredicates addObject:predicate];
}
var criteria = [rowItem valueForKey:[super criteriaKeyPath]],
displayValues = [rowItem valueForKey:[super displayValuesKeyPath]],
leftNode = [criteria objectAtIndex:0],
templateViews = [leftNode templateViews],
count = [criteria count];
for (var j = 0; j < count; j++)
{
var view = [templateViews objectAtIndex:j],
value = [displayValues objectAtIndex:j];
if ([view respondsToSelector:@selector(selectItemWithTitle:)])
[view selectItemWithTitle:value];
else
[view setObjectValue:[value objectValue]];
}
return [[leftNode templateForRow] predicateWithSubpredicates:subpredicates];
}
- (CPCompoundPredicateType)_compoundPredicateTypeForRootRows
{
return CPAndPredicateType;
}
#pragma mark Control delegate
- (void)_setDefaultTargetAndActionOnView:(CPView)view
{
if ([view isKindOfClass:[CPControl class]])
{
[view setAction:@selector(_templateControlValueDidChange:)];
[view setTarget:self];
}
}
- (void)controlTextDidEndEditing:(CPNotification)notification
{
[self _updatePredicate];
}
- (void)_templateControlValueDidChange:(id)sender
{
//[self _updatePredicate];
}
- (void)controlTextDidBeginEditing:(CPNotification)notification
{
}
- (void)controlTextDidChange:(CPNotification)notification
{
}
#pragma mark RuleEditor delegate methods
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
var trees = (type == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
return [trees count];
}
return [[rowItem children] count];
}
- (id)_queryChild:(int)index ofItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
var trees = (type == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
return [_CPPredicateEditorRowNode rowNodeFromTree:trees[index]];
}
return [[rowItem children] objectAtIndex:index];
}
- (id)_queryValueForItem:(id)rowItem inRow:(int)rowIndex
{
[rowItem copyTemplateIfNecessary];
return [rowItem displayValue];
}
@end
var CPPredicateTemplatesKey = @"CPPredicateTemplates";
@implementation CPPredicateEditor (CPCoding)
- (id)initWithCoder:(id)aCoder
{
self = [super initWithCoder:aCoder];
if (self != nil)
{
var nibTemplates = [aCoder decodeObjectForKey:CPPredicateTemplatesKey];
if (nibTemplates != nil)
[self setRowTemplates:nibTemplates];
}
return self;
}
- (void)encodeWithCoder:(id)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_allTemplates forKey:CPPredicateTemplatesKey];
}
@end
/*! @endcond */
@@ -0,0 +1,806 @@
/*
* CPPredicateEditorRowTemplate.j
* AppKit
*
* Created by cacaodev.
* Copyright 2011, cacaodev.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CPUndefinedAttributeType = 0,
CPInteger16AttributeType = 100,
CPInteger32AttributeType = 200,
CPInteger64AttributeType = 300,
CPDecimalAttributeType = 400,
CPDoubleAttributeType = 500,
CPFloatAttributeType = 600,
CPStringAttributeType = 700,
CPBooleanAttributeType = 800,
CPDateAttributeType = 900,
CPBinaryDataAttributeType = 1000,
CPTransformableAttributeType = 1800;
@implementation CPPredicateEditorRowTemplate : CPObject
{
int _templateType @accessors(readwrite, getter=_templateType, setter=_setTemplateType:);
unsigned _predicateOptions @accessors(readwrite, setter=_setOptions:);
unsigned _predicateModifier @accessors(readwrite, setter=_setModifier:);
unsigned _leftAttributeType @accessors(readwrite, getter=leftAttributeType, setter=_setLeftAttributeType:);
unsigned _rightAttributeType @accessors(readwrite, getter=rightAttributeType, setter=_setRightAttributeType:);
BOOL _leftIsWildcard @accessors(property=leftIsWildcard);
BOOL _rightIsWildcard @accessors(property=rightIsWildcard);
CPArray _views @accessors(setter=setTemplateViews:);
}
/*!
@ingroup appkit
@class CPPredicateEditorRowTemplate
@brief CPPredicateEditorRowTemplate describes available predicates and how to display them.
You can create instances of CPPredicateEditorRowTemplate programmatically or in Interface Builder. By default, a non-compound row template has three views: a popup (or static text field) on the left, a popup or static text field for operators, and either a popup or other view on the right. You can subclass CPPredicateEditorRowTemplate to create a row template with different numbers or types of views.
CPPredicateEditorRowTemplate is a concrete class, but it has five primitive methods which are called by CPPredicateEditor: -#templateViews, -#matchForPredicate:, -#setPredicate:, -#displayableSubpredicatesOfPredicate:, and -#predicateWithSubpredicates:. CPPredicateEditorRowTemplate implements all of them, but you can override them for custom templates. The primitive methods are used by an instance of CPPredicateEditor as follows.
First, an instance of CPPredicateEditor is created, and some row templates are set on it—either through a nib file or programmatically. The first thing predicate editor does is ask each of the templates for their views, using templateViews.
After setting up the predicate editor, you typically send it a CPPredicateEditor#setObjectValue: message to restore a saved predicate. CPPredicateEditor needs to determine which of its templates should display each predicate in the predicate tree. It does this by sending each of its row templates a matchForPredicate: message and choosing the one that returns the highest value.
After finding the best match for a predicate, CPPredicateEditor copies that template to get fresh views, inserts them into the proper row, and then sets the predicate on the template using setPredicate:. Within that method, the CPPredicateEditorRowTemplate object must set its views' values to represent that predicate.
CPPredicateEditorRowTemplate next asks the template for the “displayable sub-predicates” of the predicate by sending a -#displayableSubpredicatesOfPredicate: message. If a template represents a predicate in its entirety, or if the predicate has no subpredicates, it can return nil for this. Otherwise, it should return a list of predicates to be made into sub-rows of that template's row. The whole process repeats for each sub-predicate.
At this point, the user sees the predicate that was saved. If the user then makes some changes to the views of the templates, this causes CPPredicateEditor to recompute its predicate by asking each of the templates to return the predicate represented by the new view values, passing in the subpredicates represented by the sub-rows (an empty array if there are none, or nil if they aren't supported by that predicate type).
*/
/*!
@name Initializing a Template
*/
/*!
@brief Initializes and returns a “pop-up-pop-up-pop-up”-style row template.
@param leftExpressions An array of CPExpression objects that represent the left hand side of a predicate.
@param rightExpressions An array of CPExpression objects that represent the right hand side of a predicate.
@param modifier A modifier for the predicate (see @c CPComparisonPredicateModifier for possible values).
@param operators An array of CPNumber objects specifying the operator type (see @c CPPredicateOperatorType for possible values).
@param options Options for the predicate (see @c CPComparisonPredicateOptions for possible values).
@return A row template of the “pop-up-pop-up-pop-up”-form, with the left and right popups representing the left and right expression arrays -#leftExpressions and -#rightExpressions, and the center popup representing the operators.
*/
- (id)initWithLeftExpressions:(CPArray)leftExpressions rightExpressions:(CPArray)rightExpressions modifier:(int)modifier operators:(CPArray)operators options:(int)options
{
self = [super init];
if (self != nil)
{
_templateType = 1;
_leftIsWildcard = NO;
_rightIsWildcard = NO;
_leftAttributeType = 0;
_rightAttributeType = 0;
_predicateModifier = modifier;
_predicateOptions = options;
var leftView = [self _viewFromExpressions:leftExpressions],
rightView = [self _viewFromExpressions:rightExpressions],
middleView = [self _viewFromOperatorTypes:operators];
_views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
}
return self;
}
/*!
@brief Initializes and returns a “pop-up-pop-up-view”-style row template.
@param leftExpressions An array of CPExpression objects that represent the left hand side of a predicate.
@param attributeType An attribute type for the right hand side of a predicate. This value dictates the type of view created, and how the controls object value is coerced before putting it into a predicate.
@param modifier A modifier for the predicate (see @c CPComparisonPredicateModifier for possible values).
@param operators An array of CPNumber objects specifying the operator type (see @c CPPredicateOperatorType for possible values).
@param options Options for the predicate (see CPComparisonPredicateOptions for possible values).
@return A row template initialized using the given arguments.
*/
- (id)initWithLeftExpressions:(CPArray )leftExpressions rightExpressionAttributeType:(CPAttributeType)attributeType modifier:(CPComparisonPredicateModifier)modifier operators:(CPArray )operators options:(int)options
{
self = [super init];
if (self != nil)
{
var leftView = [self _viewFromExpressions:leftExpressions],
middleView = [self _viewFromOperatorTypes:operators],
rightView = [self _viewFromAttributeType:attributeType];
_templateType = 1;
_leftIsWildcard = NO;
_rightIsWildcard = YES;
_leftAttributeType = 0;
_rightAttributeType = attributeType;
_predicateModifier = modifier;
_predicateOptions = options;
_views = [[CPArray alloc] initWithObjects:leftView, middleView, rightView];
}
return self;
}
/*!
@brief Initializes and returns a row template suitable for displaying compound predicates.
@param compoundTypes An array of CPNumber objects specifying compound predicate types. See @c CPCompoundPredicateTypes for possible values.
@return A row template initialized for displaying compound predicates of the types specified by @a compoundTypes.
@discussion CPPredicateEditor contains such a template by default.
*/
- (id)initWithCompoundTypes:(CPArray )compoundTypes
{
self = [super init];
if (self != nil)
{
var leftView = [self _viewFromCompoundTypes:compoundTypes],
rightView = [[CPPopUpButton alloc] init];
[rightView addItemWithTitle:@"of the following are true"];
_templateType = 2;
_leftIsWildcard = NO;
_rightIsWildcard = NO;
_rightAttributeType = 0;
_views = [[CPArray alloc] initWithObjects:leftView, rightView];
}
return self;
}
/*!
@name Primitive Methods
*/
/*!
@brief Returns a positive number if the receiver can represent a given predicate, and 0 if it cannot.
@return A positive number if the template can represent predicate, and @c 0 if it cannot.
@discussion By default, returns values in the range @c 0 to @c 1.
The highest match among all the templates determines which template is responsible for displaying the predicate. You can override this to determine which predicates your custom template handles.
*/
- (double)matchForPredicate:(CPPredicate)predicate
{
// How exactly this value (float 0-1) is computed ?
if ([self _templateType] == 2 && [predicate isKindOfClass:[CPCompoundPredicate class]])
{
if ([[self compoundTypes] containsObject:[predicate compoundPredicateType]])
return 1;
}
else if ([self _templateType] == 1 && [predicate isKindOfClass:[CPComparisonPredicate class]])
{
if (!_leftIsWildcard && ![[self leftExpressions] containsObject:[predicate leftExpression]])
return 0;
if (![[self operators] containsObject:[predicate predicateOperatorType]])
return 0;
if (!_rightIsWildcard && ![[self rightExpressions] containsObject:[predicate rightExpression]]) return 0;
return 1;
}
return 0;
}
/*!
@brief Returns the views for the receiver.
@return The views for the receiver.
@discussion Instances of CPPopUpButton are treated specially by CPPredicateEditor; their menu items are merged into a single popup button, and matching menu item titles are combined. In this way, a single tree is built from the separate templates.
*/
- (CPArray)templateViews
{
return _views;
}
/*!
@brief Sets the value of the views according to the given predicate.
@param predicate The predicate value for the receiver.
@discussion This method is only called if -#matchForPredicate: returned a positive value for the receiver.
You can override this to set the values of custom views.
*/
- (void)setPredicate:(CPPredicate)predicate
{
if (_templateType == 2)
[self _setCompoundPredicate:predicate];
else
[self _setComparisonPredicate:predicate];
}
/*!
@brief Returns the subpredicates that should be made sub-rows of a given predicate.
@param predicate A predicate object.
@return The subpredicates that should be made sub-rows of @a predicate. For compound predicates (instances of CPCompoundPredicate), the array of subpredicates; for other types of predicate, returns @c nil. If a template represents a predicate in its entirety, or if the predicate has no subpredicates, returns @c nil.
@discussion You can override this method to create custom templates that handle complicated compound predicates.
*/
- (CPArray)displayableSubpredicatesOfPredicate:(CPPredicate)predicate
{
if ([predicate isKindOfClass:[CPCompoundPredicate class]])
{
var subpredicates = [predicate subpredicates];
if ([subpredicates count] == 0)
return nil;
return subpredicates;
}
return nil;
}
/*!
@brief Returns the predicate represented by the receivers views' values and the given sub-predicates.
@param subpredicates An array of predicates.
@return The predicate represented by the values of the template's views and the given @a subpredicates. You can override this method to return the predicate represented by your custom views.
@discussion This method is only called if -#matchForPredicate: returned a positive value for the receiver.
You can override this method to return the predicate represented by a custom view.
*/
- (CPPredicate)predicateWithSubpredicates:(CPArray)subpredicates
{
if (_templateType == 2)
{
var type = [[_views[0] selectedItem] representedObject];
return [[CPCompoundPredicate alloc] initWithType:type subpredicates:subpredicates];
}
if (_templateType == 1)
{
var lhs = [self _leftExpression],
rhs = [self _rightExpression],
operator = [[_views[1] selectedItem] representedObject];
return [CPComparisonPredicate predicateWithLeftExpression:lhs
rightExpression:rhs
modifier:[self modifier]
type:operator
options:[self options]];
}
return nil;
}
/*!
@name Information About a Row Template
*/
/*!
@brief Returns the left hand expressions for the receiver.
@return The left hand expressions for the receiver.
*/
- (CPArray)leftExpressions
{
if (_templateType ==1 && !_leftIsWildcard)
{
var view = [_views objectAtIndex:0];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the right hand expressions for the receiver.
@return The right hand expressions for the receiver.
*/
- (CPArray)rightExpressions
{
if (_templateType == 1 && !_rightIsWildcard)
{
var view = [_views objectAtIndex:2];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the compound predicate types for the receiver.
@return An array of CPNumber objects specifying compound predicate types. See @c CompoundPredicateTypes for possible values.
*/
- (CPArray)compoundTypes
{
if (_templateType == 2)
{
var view = [_views objectAtIndex:0];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the comparison predicate modifier for the receiver.
@return The comparison predicate modifier for the receiver.
*/
- (CPComparisonPredicateModifier)modifier
{
if (_templateType == 1)
return _predicateModifier;
return nil;
}
/*!
@brief Returns Returns the array of operators for the receiver.
@return The array of operators for the receiver.
*/
- (CPArray)operators
{
if (_templateType == 1)
{
var view = [_views objectAtIndex:1];
return [[view itemArray] valueForKey:@"representedObject"];
}
return nil;
}
/*!
@brief Returns the comparison predicate options for the receiver.
@return The comparison predicate options for the receiver. See @c CPComparisonPredicateOptions for possible values. Returns @c 0 if this does not apply (for example, for a compound template initialized with -#initWithCompoundTypes:).
*/
- (int)options
{
if (_templateType == 1)
return _predicateOptions;
return nil;
}
/*!
@brief Returns the attribute type of the receivers right expression.
@return The attribute type of the receivers right expression.
*/
- (CPAttributeType)rightExpressionAttributeType
{
return _rightAttributeType;
}
/*!
@brief Returns the attribute type of the receivers left expression.
@return The attribute type of the receivers left expression.
*/
- (CPAttributeType)leftExpressionAttributeType
{
return _leftAttributeType;
}
/*! @cond */
+ (id)_bestMatchForPredicate:(CPPredicate)predicate inTemplates:(CPArray)templates quality:(double)quality
{
var count = [templates count],
match_value = 0,
templateIndex = CPNotFound,
i;
for (i = 0; i < count; i++)
{
var template = [templates objectAtIndex:i],
amatch = [template matchForPredicate:predicate];
if (amatch > match_value)
{
templateIndex = i;
match_value = amatch;
}
}
if (templateIndex == CPNotFound)
{
[CPException raise:CPRangeException reason:@"Unable to find template matching predicate: " + [predicate predicateFormat]];
return nil;
}
return [templates objectAtIndex:templateIndex];
}
- (void)_setCompoundPredicate:(CPCompoundPredicate)predicate
{
var left = [_views objectAtIndex:0],
type = [predicate compoundPredicateType],
index = [left indexOfItemWithRepresentedObject:type];
[left selectItemAtIndex:index];
}
- (void)_setComparisonPredicate:(CPComparisonPredicate)predicate
{
var left = [_views objectAtIndex:0],
middle = [_views objectAtIndex:1],
right = [_views objectAtIndex:2],
leftExpression = [predicate leftExpression],
rightExpression = [predicate rightExpression],
operator = [predicate predicateOperatorType];
if (_leftIsWildcard)
[left setObjectValue:[leftExpression constantValue]];
else
{
var index = [left indexOfItemWithRepresentedObject:leftExpression];
[left selectItemAtIndex:index];
}
var op_index = [middle indexOfItemWithRepresentedObject:operator];
[middle selectItemAtIndex:op_index];
if (_rightIsWildcard)
[right setObjectValue:[rightExpression constantValue]];
else
{
var index = [right indexOfItemWithRepresentedObject:rightExpression];
[right selectItemAtIndex:index];
}
}
- (CPExpression)_leftExpression
{
return [self _expressionFromView:_views[0] forAttributeType:_leftAttributeType];
}
- (CPExpression)_rightExpression
{
return [self _expressionFromView:_views[2] forAttributeType:_rightAttributeType];
}
- (CPExpression)_expressionFromView:(CPView)aView forAttributeType:(CPAttributeType)attributeType
{
if (attributeType == 0)
return [[aView selectedItem] representedObject];
var value;
if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
value = [aView intValue];
else if (attributeType == CPBooleanAttributeType)
value = [aView state];
else
value = [aView stringValue];
return [CPExpression expressionForConstantValue:value];
}
- (int)_rowType
{
return (_templateType - 1);
}
- (id)copy
{
var t = [[CPPredicateEditorRowTemplate alloc] init],
views;
[t _setTemplateType:_templateType];
[t _setOptions:_predicateOptions];
[t _setModifier:_predicateModifier];
[t _setLeftAttributeType:_leftAttributeType];
[t _setRightAttributeType:_rightAttributeType];
[t setLeftIsWildcard:_leftIsWildcard];
[t setRightIsWildcard:_rightIsWildcard];
if (_templateType == 2)
{
var left = [self _viewFromCompoundTypes:[self compoundTypes]],
right = [_views objectAtIndex:1];
views = [CPArray arrayWithObjects:left,right];
}
else if (_templateType == 1)
{
var left = [self _viewFromExpressions:[self leftExpressions]],
middle = [self _viewFromOperatorTypes:[self operators]],
right;
if (_rightIsWildcard == YES)
right = [self _viewFromAttributeType:_rightAttributeType];
else
right = [self _viewFromExpressions:[self rightExpressions]];
views = [CPArray arrayWithObjects:left,middle,right];
}
var count = [views count];
while (count--)
[views[count] setObjectValue:[_views[count] objectValue]];
[t setTemplateViews:views];
return t;
}
+ (id)_operatorsForAttributeType:(CPAttributeType)attributeType
{
var operators_array = [CPMutableArray array];
switch (attributeType)
{
case CPInteger16AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPInteger32AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPInteger64AttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPDecimalAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPDoubleAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPFloatAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
case CPStringAttributeType : [operators_array addObjects:99,4,5,8,9];
break;
case CPBooleanAttributeType : [operators_array addObjects:4,5];
break;
case CPDateAttributeType : [operators_array addObjects:4,5,0,2,1,3];
break;
default : CPLogConsole("Cannot create operators for an CPAttributeType " + attributeType);
break;
}
return operators_array;
}
- (int)_templateType
{
return _templateType;
}
- (id)_displayValueForPredicateOperator:(int)operator
{
var value;
switch (operator)
{
case CPLessThanPredicateOperatorType : value = @"is less than";
break;
case CPLessThanOrEqualToPredicateOperatorType : value = @"is less than or equal to";
break;
case CPGreaterThanPredicateOperatorType : value = @"is greater than";
break;
case CPGreaterThanOrEqualToPredicateOperatorType : value = @"is greater than or equal to";
break;
case CPEqualToPredicateOperatorType : value = @"is";
break;
case CPNotEqualToPredicateOperatorType : value = @"is not";
break;
case CPMatchesPredicateOperatorType : value = @"matches";
break;
case CPLikePredicateOperatorType : value = @"is like";
break;
case CPBeginsWithPredicateOperatorType : value = @"begins with";
break;
case CPEndsWithPredicateOperatorType : value = @"ends with";
break;
case CPInPredicateOperatorType : value = @"in";
break;
case CPContainsPredicateOperatorType : value = @"contains";
break;
case CPBetweenPredicateOperatorType : value = @"between";
break;
default : CPLogConsole(@"unknown predicate operator %d" + operator);
}
return value;
}
- (id)_displayValueForCompoundPredicateType:(unsigned int)predicateType
{
var value;
switch (predicateType)
{
case CPNotPredicateType: value = @"None";
break;
case CPAndPredicateType: value = @"All";
break;
case CPOrPredicateType: value = @"Any";
break;
default : value = [CPString stringWithFormat:@"unknown compound predicate type %d",predicateType];
}
return value;
}
- (id)_displayValueForConstantValue:(id)value
{
return [value description]; // number, date, string, ... localize
}
- (id)_displayValueForKeyPath:(CPString)keyPath
{
return keyPath; // localize
}
- (CPPopUpButton)_viewFromExpressions:(CPArray)expressions
{
var popup = [[CPPopUpButton alloc] initWithFrame:CPMakeRect(0, 0, 100, 18)],
count = [expressions count];
for (var i = 0; i < count; i++)
{
var exp = expressions[i],
type = [exp expressionType],
title;
switch (type)
{
case CPKeyPathExpressionType: title = [self _displayValueForKeyPath:[exp keyPath]];
break;
case CPConstantValueExpressionType: title = [self _displayValueForConstantValue:[exp constantValue]];
break;
default: [CPException raise:CPInvalidArgumentException reason:@"Invalid Expression type " + type];
break;
}
var item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:exp];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPPopUpButton)_viewFromOperatorTypes:(CPArray)operators
{
var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
count = [operators count];
for (var i = 0; i < count; i++)
{
var op = operators[i],
title = [self _displayValueForPredicateOperator:op],
item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:op];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPView)_viewFromCompoundTypes:(CPArray)compoundTypes
{
var popup = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)],
count = [compoundTypes count];
for (var i = 0; i < count; i++)
{
var type = compoundTypes[i],
title = [self _displayValueForCompoundPredicateType:type],
item = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
[item setRepresentedObject:type];
[popup addItem:item];
}
[popup sizeToFit];
return popup;
}
- (CPView)_viewFromAttributeType:(CPAttributeType)attributeType
{
var view;
if (attributeType >= CPInteger16AttributeType && attributeType <= CPFloatAttributeType)
{
view = [self _textFieldWithFrame:CGRectMake(0,0,50,26)];
}
else if (attributeType == CPStringAttributeType)
{
view = [self _textFieldWithFrame:CGRectMake(0,0,150,26)];
}
else if (attributeType == CPBooleanAttributeType)
{
view = [[CPCheckBox alloc] initWithFrame:CGRectMake(0,0,50,26)];
}
else if (attributeType == CPDateAttributeType)
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0,0,150,26)];
else
return nil;
[view setTag:attributeType];
return view;
}
- (CPTextField)_textFieldWithFrame:(CGRect)frame
{
var textField = [[CPTextField alloc] initWithFrame:frame];
[textField setBezeled:YES];
[textField setBezelStyle:CPTextFieldSquareBezel];
[textField setBordered:YES];
[textField setEditable:YES];
[textField setFont:[CPFont systemFontOfSize:10]];
return textField;
}
- (void)_setOptions:(unsigned int)options
{
_predicateOptions = options;
}
- (void)_setModifier:(unsigned int)modifier
{
_predicateModifier = modifier;
}
- (CPString)description
{
if (_templateType == 2)
return [CPString stringWithFormat:@"<%@ %p %@>",[self className],self,[[self compoundTypes] componentsJoinedByString:@", "]];
else if (_templateType == 1 && _rightIsWildcard)
return [CPString stringWithFormat:@"<%@ %p [%@] [%@] %d>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[self rightExpressionAttributeType]];
else
return [CPString stringWithFormat:@"<%@ %p [%@] [%@] [%@]>",[self className],self,[[self leftExpressions] componentsJoinedByString:@", "],[[self operators] componentsJoinedByString:@", "],[[self rightExpressions] componentsJoinedByString:@", "]];
}
/*
- (void)_setLeftExpressionObject:(id)object
{
}
- (void)_setRightExpressionObject:(id)object
{
}
- (BOOL)_predicateIsNoneAreTrue:(id)predicate
{
}
- (id)_viewFromExpressionObject:(id)object
{
}
*/
@end
var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
CPPredicateTemplateOptionsKey = @"CPPredicateTemplateOptions",
CPPredicateTemplateModifierKey = @"CPPredicateTemplateModifier",
CPPredicateTemplateLeftAttributeTypeKey = @"CPPredicateTemplateLeftAttributeType",
CPPredicateTemplateRightAttributeTypeKey = @"CPPredicateTemplateRightAttributeType",
CPPredicateTemplateLeftIsWildcardKey = @"CPPredicateTemplateLeftIsWildcard",
CPPredicateTemplateRightIsWildcardKey = @"CPPredicateTemplateRightIsWildcard",
CPPredicateTemplateViewsKey = @"CPPredicateTemplateViews";
@implementation CPPredicateEditorRowTemplate (CPCoding)
- (id)initWithCoder:(CPCoder)coder
{
self = [super init];
if (self != nil)
{
_templateType = [coder decodeIntForKey:CPPredicateTemplateTypeKey];
_predicateOptions = [coder decodeIntForKey:CPPredicateTemplateOptionsKey];
_predicateModifier = [coder decodeIntForKey:CPPredicateTemplateModifierKey];
_leftAttributeType = [coder decodeIntForKey:CPPredicateTemplateLeftAttributeTypeKey];
_rightAttributeType = [coder decodeIntForKey:CPPredicateTemplateRightAttributeTypeKey];
_leftIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateLeftIsWildcardKey];
_rightIsWildcard = [coder decodeBoolForKey:CPPredicateTemplateRightIsWildcardKey];
_views = [coder decodeObjectForKey:CPPredicateTemplateViewsKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeInt:_templateType forKey:CPPredicateTemplateTypeKey];
[coder encodeInt:_predicateOptions forKey:CPPredicateTemplateOptionsKey];
[coder encodeInt:_predicateModifier forKey:CPPredicateTemplateModifierKey];
[coder encodeInt:_leftAttributeType forKey:CPPredicateTemplateLeftAttributeTypeKey];
[coder encodeInt:_rightAttributeType forKey:CPPredicateTemplateRightAttributeTypeKey];
[coder encodeBool:_leftIsWildcard forKey:CPPredicateTemplateLeftIsWildcardKey];
[coder encodeBool:_rightIsWildcard forKey:CPPredicateTemplateRightIsWildcardKey];
[coder encodeObject:_views forKey:CPPredicateTemplateViewsKey];
}
@end
/*! @endcond */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,91 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@class _CPPredicateEditorTree;
@implementation _CPPredicateEditorRowNode : CPObject
{
_CPPredicateEditorTree tree @accessors;
CPMutableArray templateViews @accessors;
CPMutableArray copiedTemplateContainer @accessors;
CPArray children @accessors(copy);
}
- (BOOL)applyTemplate:(id)template withViews:(id)views forOriginalTemplate:(id)arg3
{
return YES; // not in use
}
+ (id)rowNodeFromTree:(id)aTree
{
return [_CPPredicateEditorRowNode _rowNodeFromTree:aTree withTemplate:[aTree template]];
}
+ (id)_rowNodeFromTree:(id)aTree withTemplate:(id)template
{
var nodeChildren = [CPArray array],
treeChildren = [aTree children],
count = [treeChildren count];
for (var i = 0; i < count; i++)
{
var childnode = [self _rowNodeFromTree:treeChildren[i] withTemplate:template];
[nodeChildren addObject:childnode];
}
var node = [_CPPredicateEditorRowNode new];
[node setTree:aTree];
[node setCopiedTemplateContainer:[CPMutableArray arrayWithObject:template]];
[node setTemplateViews:[template templateViews]];
[node setChildren:nodeChildren];
return node;
}
- (BOOL)isEqual:(id)node
{
return (self === node || tree === [node tree]);
}
- (void)copyTemplateIfNecessary
{
if ([[self templateForRow] rightIsWildcard])
{
var copy = [[tree template] copy];
[self setCopiedTemplateContainer:[CPMutableArray arrayWithObject:copy]];
[self setTemplateViews:[copy templateViews]];
}
}
- (CPView)templateView
{
return [templateViews objectAtIndex:[tree indexIntoTemplate]];
}
- (id)templateForRow
{
return [copiedTemplateContainer lastObject];
}
- (CPString)title
{
return [tree title];
}
- (id)displayValue
{
var title = [self title];
if (title == nil)
return [self templateView];
return title;
}
- (CPString)description
{
return [CPString stringWithFormat:@"<%@ %@ %@ %p>", [self className], [self title], [self displayValue], self];
}
@end
@@ -0,0 +1,33 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@implementation _CPPredicateEditorTree : CPObject
{
CPPredicateEditorRowTemplate template @accessors;
CPString title @accessors(copy);
CPArray children @accessors(copy);
CPInteger indexIntoTemplate @accessors;
CPInteger menuItemIndex @accessors;
}
- (id)copy
{
var tree = [[_CPPredicateEditorTree alloc] init];
[tree setTemplate:template];
[tree setTitle:title];
[tree setMenuItemIndex:menuItemIndex];
[tree setIndexIntoTemplate:indexIntoTemplate];
[tree setChildren:children];
return tree;
}
- (CPString)description
{
return [CPString stringWithFormat:@"<%@: %p (%@) [%d-%d] T:%p at:%d> [\r%@\r]", [self className], self, title, indexIntoTemplate, menuItemIndex, template, [template rightExpressionAttributeType], children];
}
@end
@@ -0,0 +1,75 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPString.j>
var regex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+)?");
@implementation _CPRuleEditorLocalizer : CPObject
{
CPDictionary _dictionary @accessors(property=dictionary);
CPURLConnection connection;
CPURLRequest resquest;
}
- (void)loadContentOfURL:(CPURL)aURL
{
request = [CPURLRequest requestWithURL:aURL];
connection = [CPURLConnection connectionWithRequest:request delegate:self];
}
- (void)reloadIfNeeded
{
if (connection != nil) // Connection waiting
{
connection = nil;
var data = [CPURLConnection sendSynchronousRequest:request returningResponse:NULL];
[self loadContent:[data rawString]];
}
}
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)rawString
{
if (connection != nil && rawString != nil)
[self loadContent:rawString];
connection = nil;
}
- (void)loadContent:(CPString)aContent
{
var dict = [CPDictionary dictionary],
lines = [aContent componentsSeparatedByString:"\n"],
count = [lines count];
for (var i = 0 ; i < count ; i++)
{
var line = [lines objectAtIndex:i];
if (line.length > 1)
{
var match = regex.exec(line);
if (match.length >= 3)
[dict setObject:match[2] forKey:match[1]];
}
}
_dictionary = [CPDictionary dictionaryWithDictionary:dict];
}
- (CPString)localizedStringForString:(CPString)aString
{
[self reloadIfNeeded];
if (_dictionary != nil && aString != nil)
{
var localized = [_dictionary objectForKey:aString];
if (localized != nil)
return localized;
}
return aString;
}
@@ -0,0 +1,157 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
var GRADIENT_NORMAL,
GRADIENT_HIGHLIGHTED,
IE_FILTER = "progid:DXImageTransform.Microsoft.gradient(startColorstr='#fcfcfc', endColorstr='#dfdfdf')";
@implementation _CPRuleEditorPopUpButton : CPPopUpButton
{
CPInteger radius;
}
+ (void)initialize
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
{
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)))",
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(rgb(223, 223, 223)), to(rgb(252, 252, 252)))";
}
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
{
GRADIENT_NORMAL = "-moz-linear-gradient(top, rgb(252, 252, 252), rgb(223, 223, 223))",
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, rgb(223, 223, 223), rgb(252, 252, 252))";
}
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
var style = _DOMElement.style;
style.backgroundImage = GRADIENT_NORMAL;
style.border = "1px solid rgb(189, 189, 189)";
style.filter = IE_FILTER;
[self setTextColor:[CPColor colorWithWhite:101/255 alpha:1]];
[self setBordered:NO];
}
return self;
}
- (id)hitTest:(CPPoint)point
{
var slice = [self superview];
if (!CPRectContainsPoint([self frame], point) || ![self sliceIsEditable])
return nil;
return self;
}
- (void)setHighlighted:(BOOL)shouldHighlight
{
_DOMElement.style.backgroundImage = (shouldHighlight) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
}
- (BOOL)sliceIsEditable
{
return [[self superview] isEditable];
}
- (BOOL)trackMouse:(CPEvent)theEvent
{
if (![self sliceIsEditable])
return NO;
return [super trackMouse:theEvent];
}
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentRect = [super contentRectForBounds:bounds];
contentRect.origin.x += radius;
contentRect.size.width -= 2 * radius;
return contentRect;
}
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
//style.webkitBorderRadius = radiusCSS;
//style.mozBorderRadius = radiusCSS;
style.borderRadius = radiusCSS;
[super layoutSubviews];
}
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
var arrow_width = FLOOR(CGRectGetHeight(bounds)/3.5);
CGContextTranslateCTM(context, CGRectGetWidth(bounds) - radius - arrow_width, CGRectGetHeight(bounds) / 2);
var arrowsPath = [CPBezierPath bezierPath];
[arrowsPath moveToPoint:CGPointMake(0, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width/2, arrow_width + 1)];
[arrowsPath closePath];
CGContextSetFillColor(context, [CPColor colorWithWhite:101/255 alpha:1]);
[arrowsPath fill];
CGContextScaleCTM(context, 1 , -1);
[arrowsPath fill];
}
@end
@implementation _CPRuleEditorButton : CPButton
{
CPInteger radius;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
[self setFont:[CPFont boldFontWithName:@"Apple Symbol" size:12.0]];
[self setTextColor:[CPColor colorWithWhite:150/255 alpha:1]];
[self setAlignment:CPCenterTextAlignment];
[self setAutoresizingMask:CPViewMinXMargin];
[self setImagePosition:CPImageOnly];
[self setBordered:NO];
var style = _DOMElement.style;
style.border = "1px solid rgb(189, 189, 189)";
style.filter = IE_FILTER;
}
return self;
}
- (void)layoutSubviews
{
radius = FLOOR(CGRectGetHeight([self bounds])/2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
style.borderRadius = radiusCSS;
style.backgroundImage = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
[super layoutSubviews];
}
@end
@@ -0,0 +1,109 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@implementation _CPRuleEditorViewSlice : CPView
{
CPRuleEditor _ruleEditor;
int _indentation @accessors(property=indentation);
int _rowIndex @accessors(property=rowIndex);
CPRect _animationTargetRect @accessors(property=_animationTargetRect);
BOOL _selected @accessors(getter=_isSelected, setter=_setSelected:);
BOOL _lastSelected @accessors(getter=_isLastSelected, setter=_setLastSelected:);
CPColor _backgroundColor @accessors(property=backgroundColor);
}
- (void)removeFromSuperview
{
[super removeFromSuperview];
}
- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
{
if (self = [super initWithFrame:frame])
{
_ruleEditor = editor;
_selected = NO;
_lastSelected = NO;
}
return self;
}
- (void)_setSelected:(BOOL)select
{
if (select == _selected)
return;
var selector = select ? @"setThemeState:" : @"unsetThemeState:";
[[self subviews] makeObjectsPerformSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView];
_selected = select;
}
- (void)drawRect:(CPRect)rect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
maxX = CGRectGetWidth(bounds) - 2,
maxY = CGRectGetHeight(bounds);
// Draw background
if ([self _isSelected])
_backgroundColor = [_ruleEditor _selectedRowColor];
else
{
var colors = [_ruleEditor _backgroundColors],
count = [colors count];
_backgroundColor = [colors objectAtIndex:(_rowIndex % count)];
}
CGContextSetFillColor(context, _backgroundColor);
CGContextFillRect(context, rect);
// Draw Top Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, 0);
CGContextAddLineToPoint(context, maxX, 0);
CGContextClosePath(context);
CGContextSetStrokeColor(context, [_ruleEditor _sliceTopBorderColor]);
CGContextStrokePath(context);
// Draw Bottom Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, maxY - 0.5);
CGContextAddLineToPoint(context, maxX, maxY - 0.5);
CGContextClosePath(context);
var bottomColor = (_rowIndex == [_ruleEditor _lastRow]) ? [_ruleEditor _sliceLastBottomBorderColor] : [_ruleEditor _sliceBottomBorderColor];
CGContextSetStrokeColor(context, bottomColor);
CGContextStrokePath(context);
}
- (void)mouseDown:(CPEvent)theEvent
{
if (editable)
[_ruleEditor _mouseDownOnSlice:self withEvent:theEvent];
}
- (void)mouseUp:(CPEvent)theEvent
{
if (editable)
[_ruleEditor _mouseUpOnSlice:self withEvent:theEvent];
}
/*
- (void)rightMouseDown:(CPEvent)theEvent
{
[_ruleEditor _rightMouseDownOnSlice:self withEvent:theEvent];
}
*/
// =========
// ! DEBUG
// =========
- (CPString)description
{
return [CPString stringWithFormat:@"<%@ %p index:%d indentation:%d>",[self className],self,[self rowIndex],[self indentation]];
}
@end
@@ -0,0 +1,493 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*/
@import "_CPRuleEditorViewSlice.j"
@import "_CPRuleEditorPopUpButton.j"
@import "CPRuleEditor.j"
var CONTROL_HEIGHT = 16.,
BUTTON_HEIGHT = 16.;
@implementation _CPRuleEditorViewSliceRow : _CPRuleEditorViewSlice
{
CPMutableArray _ruleOptionViews;
CPMutableArray _ruleOptionFrames;
CPMutableArray _correspondingRuleItems;
CPMutableArray _ruleOptionInitialViewFrames;
CPButton _addButton;
CPButton _subtractButton;
BOOL editable;
CPRuleEditorRowType _rowType @accessors;
CPRuleEditorRowType _plusButtonRowType;
}
- (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];
editable = [_ruleEditor isEditable];
_addButton = [self _createAddRowButton];
_subtractButton = [self _createDeleteRowButton];
[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[_addButton setHidden:!editable];
[_subtractButton setHidden:!editable];
[self addSubview:_addButton];
[self addSubview:_subtractButton];
[self setAutoresizingMask:CPViewWidthSizable];
var center = [CPNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
}
- (CPButton)_createAddRowButton
{
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setImage:[_ruleEditor _addImage]];
[button setAction:@selector(_addOption:)];
[button setTarget:self];
[button setAutoresizingMask:CPViewMinXMargin];
return button;
}
- (CPButton)_createDeleteRowButton
{
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setImage:[_ruleEditor _removeImage]];
[button setAction:@selector(_deleteOption:)];
[button setTarget:self];
[button setAutoresizingMask:CPViewMinXMargin];
return button;
}
- (CPMenuItem)_createMenuItemWithTitle:(CPString )title
{
title = [[_ruleEditor standardLocalizer] localizedStringForString:title];
return [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
}
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
{
var title = [[itemsArray objectAtIndex:index] title],
font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 20,
rect = CGRectMake(0, ([_ruleEditor rowHeight] - CONTROL_HEIGHT)/2, (width - width % 40) + 80, CONTROL_HEIGHT);
var popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
[popup setValue:font forThemeAttribute:@"font"];
var count = [itemsArray count];
for (var i = 0; i < count; i++)
[popup addItem:[itemsArray objectAtIndex:i]];
[popup selectItemAtIndex:index];
return popup;
}
- (CPMenuItem)_createMenuSeparatorItem
{
return [CPMenuItem separatorItem];
}
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString )text
{
text = [[_ruleEditor standardLocalizer] localizedStringForString:text];
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CPMakeRect(0, 0, 200, CONTROL_HEIGHT)];
var font = [_ruleEditor font];
font = [CPFont fontWithName:font._name size:font._size + 2];
[textField setValue:font forThemeAttribute:@"font"];
[textField setStringValue:text];
[textField sizeToFit];
return textField;
}
- (void)_addOption:(id)sender
{
if (_rowIndex == [_ruleEditor numberOfRows] - 1)
[self setNeedsDisplay:YES];
var type = _plusButtonRowType;
if ([_ruleEditor nestingMode] == CPRuleEditorNestingModeCompound && ([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask))
type = CPRuleEditorRowTypeCompound;
[_ruleEditor _addOptionFromSlice:self ofRowType:type];
}
- (void)_deleteOption:(id)sender
{
[_ruleEditor _deleteSlice:self];
}
- (void)_ruleOptionPopupChangedAction:(CPMenuItem )sender
{
var layoutdict = [sender representedObject],
newItem = [layoutdict objectForKey:@"item"],
indexInCriteria = [[layoutdict objectForKey:@"indexInCriteria"] intValue],
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
if (newItem != oldItem)
{
[_correspondingRuleItems replaceObjectAtIndex:indexInCriteria withObject:newItem];
[_ruleEditor _changedItem:oldItem toItem:newItem inRow:_rowIndex atCriteriaIndex:indexInCriteria];
}
}
- (BOOL)validateMenuItem:(CPMenuItem )menuItem
{
return [_ruleEditor _validateItem:menuItem value:[[menuItem representedObject] valueForKey:@"item"] inRow:_rowIndex];
}
- (void)_emptyRulePartSubviews
{
var count = [_ruleOptionViews count];
while (count--)
[_ruleOptionViews[count] removeFromSuperview];
[_ruleOptionViews removeAllObjects];
[_ruleOptionFrames removeAllObjects];
[_ruleOptionInitialViewFrames removeAllObjects];
}
- (void)_reconfigureSubviews
{
var numItems;
currentItem = nil,
optionView = nil,
indexInCriteria = 0,
rowtype = [_ruleEditor rowTypeForRow:_rowIndex],
displayValues = [_ruleEditor displayValuesForRow:_rowIndex];
[self _emptyRulePartSubviews];
[_correspondingRuleItems removeAllObjects];
while ((numItems = [_ruleEditor _queryNumberOfChildrenOfItem:currentItem withRowType:rowtype]) > 0)
{
var isCustomRightControl = NO;
isStaticTextField = NO,
isPopupMenu = NO,
isMultiValue = numItems > 1,
selectedMenuItemIndex = 0,
selectedItem = nil,
current_display_value = nil,
itemsArray = [CPMutableArray array],
display_value_cached = [displayValues objectAtIndex:indexInCriteria];
for (var childIndex = 0; childIndex < numItems; childIndex++)
{
var childItem = [_ruleEditor _queryChild:childIndex ofItem:currentItem withRowType:rowtype];
current_display_value = [_ruleEditor _queryValueForItem:childItem inRow:_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:CPInternalInconsistencyException reason:@"Display value must be a string or a menu item"];
var layoutDictionary = [CPDictionary dictionaryWithObjectsAndKeys:childItem, @"item", indexInCriteria, @"indexInCriteria"];
[menuItem setAction:@selector(_ruleOptionPopupChangedAction:)];
[menuItem setTarget:self];
[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:[CPView class]])
{
isCustomRightControl = YES;
selectedItem = childItem;
selectedMenuItemIndex = 0;
} else
[CPException raise:CPInternalInconsistencyException reason:@"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; //display_value_cached
[optionView setTarget:self];
[optionView setAction:@selector(_sendRuleAction:)];
if ([optionView respondsToSelector:@selector(setEditable:)])
[optionView setEditable:editable];
}
if (optionView)
{
[_ruleOptionViews addObject:optionView];
[_ruleOptionInitialViewFrames addObject:[optionView frame]];
[_ruleOptionFrames addObject:[optionView frame]];
}
[_correspondingRuleItems addObject:selectedItem];
currentItem = selectedItem;
indexInCriteria++;
}
[self _relayoutSubviewsWidthChanged:(CGRectGetWidth([self frame]) != [_ruleEditor rowHeight])];
}
- (void)layoutSubviews
{
[self _relayoutSubviewsWidthChanged:YES];
}
- (void)_relayoutSubviewsWidthChanged:(BOOL)widthChanged
{
var optionViewOriginX,
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame];
if (widthChanged)
optionViewOriginX = [self _leftmostViewFixedHorizontalPadding] + [self _indentationHorizontalPadding]*[self indentation];
for (var i = 0; i < count; i++)
{
var ruleOptionView = _ruleOptionViews[i],
optionFrame = _ruleOptionFrames[i],
initialFrame = _ruleOptionInitialViewFrames[i];
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame))/2 - 2;
if (widthChanged)
{
optionFrame.origin.x = optionViewOriginX;
optionFrame.size.width = MIN(CGRectGetMinX(optionFrame) + CGRectGetWidth(initialFrame), CGRectGetMinX([_subtractButton frame]) - [self _rowButtonsLeftHorizontalPadding]) - CGRectGetMinX(optionFrame);
}
[ruleOptionView setFrame:optionFrame];
[self addSubview:ruleOptionView];
if (widthChanged)
optionViewOriginX += CGRectGetWidth(optionFrame) + [self _interviewHorizontalPadding];
}
var buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - BUTTON_HEIGHT - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - BUTTON_HEIGHT)/2 - 2, BUTTON_HEIGHT, BUTTON_HEIGHT);
[_addButton setFrame:buttonFrame];
buttonFrame.origin.x -= BUTTON_HEIGHT + [self _rowButtonsInterviewHorizontalPadding];
[_subtractButton setFrame:buttonFrame];
}
- (void)_updateButtonVisibilities
{
[_addButton setHidden:[_ruleEditor _shouldHideAddButtonForSlice:self]];
[_subtractButton setHidden:[_ruleEditor _shouldHideSubtractButtonForSlice:self]];
}
- (void)_configurePlusButtonByRowType:(CPRuleEditorRowType)type
{
[self _setRowTypeToAddFromPlusButton:type];
}
- (BOOL)isEditable
{
return editable;
}
- (void)setEditable:(BOOL)value
{
editable = value;
// [self _updateEnabledStateForSubviews];
[self _updateButtonVisibilities];
}
- (float)_alignmentGridWidth
{
return [_ruleEditor _alignmentGridWidth];
}
- (float)_indentationHorizontalPadding
{
return 30.;
}
- (float)_interviewHorizontalPadding
{
return 6.;
}
- (float)_leftmostViewFixedHorizontalPadding
{
return 7.;
}
- (float)_minimumVerticalPopupPadding
{
return 2.;
}
- (float)_rowButtonsInterviewHorizontalPadding
{
return 6.;
}
- (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 _applicableNestingMode] == CPRuleEditorNestingModeSingle;
}
- (BOOL)_nestingModeShouldHideSubtractButton
{
return [_ruleEditor _applicableNestingMode] == CPRuleEditorNestingModeSingle;
}
- (BOOL)containsDisplayValue:(id)value
{
return [[_ruleEditor displayValuesForRow:_rowIndex] containsObject:value];
// Ou alors avec _correspondingRuleItems
}
- (void)viewDidMoveToWindow
{
[self layoutSubviews];
}
- (void)drawRect:(CPRect)rect
{
[super drawRect:rect];
}
- (BOOL)_isRulePopup:(CPView)view
{
if ([view isKindOfClass:[_CPRuleEditorPopUpButton class]])
return YES;
return NO;
}
- (BOOL)_isRuleStaticTextField:(CPView)view
{
if ([view isKindOfClass:[_CPRuleEditorTextField class]])
return YES;
return NO;
}
- (void)_sendRuleAction:(id)sender
{
[_ruleEditor _sendRuleAction];
}
- (void)_textDidChange:(CPNotification)aNotif
{
if ([[aNotif object] superview] == self)
[_ruleEditor _sendRuleAction];
}
/*
- (BOOL)_dropsIndentWhenImmediatelyBelow
{
}
- (double)_minWidthForPass:(int)pass forView:(id)view withProposedMinWidth:(double)minWidth
{
}
- (id)_sortOptionDictionariesByLayoutOrder:(id)fp8
{
}
- (void)_setHideNonPartDrawing:(BOOL)value
{
}
- (void)_tightenResizables:(id)fp8 intoGivenWidth:(double)fp12
{
}
- (void)_updateEnabledStateForSubviews
{
}
*/
@end
@implementation _CPRuleEditorTextField : CPTextField
{
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
[self setBordered:NO];
[self setEditable:NO];
[self setDrawsBackground:NO];
}
return self;
}
- (id)hitTest:(CPPoint)point
{
if (!CPRectContainsPoint([self frame], point))
return nil;
return [self superview];
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

+32 -1
View File
@@ -326,7 +326,7 @@ var themedButtonValues = nil,
+ (CPArray)themeShowcaseExcludes
{
return ["alert", "cornerview", "columnHeader", "tableView", "tableHeaderRow", "tableDataView"];
return ["alert", "cornerview", "columnHeader", "tableView", "tableHeaderRow", "tableDataView", @"ruleeditor"];
}
+ (CPButton)makeButton
@@ -1633,6 +1633,37 @@ var themedButtonValues = nil,
return stepper;
}
+ (CPRuleEditor)themedRuleEditor
{
var ruleEditor = [[CPRuleEditor alloc] initWithFrame:CGRectMake(0, 0, 400, 300)];
var backgroundColors = [[CPColor whiteColor], [CPColor colorWithRed:235/255 green:239/255 blue:252/255 alpha:1]],
selectedActiveRowColor = [CPColor colorWithHexString:@"5f83b9"],
selectedInactiveRowColor = [CPColor colorWithWhite:0.83 alpha:1],
sliceTopBorderColor = [CPColor colorWithWhite:0.9 alpha:1],
sliceBottomBorderColor = [CPColor colorWithWhite:0.729412 alpha:1],
sliceLastBottomBorderColor = [CPColor colorWithWhite:0.6 alpha:1],
addImage = PatternImage(@"rule-editor-add.png", 8.0, 8.0),
removeImage = PatternImage(@"rule-editor-remove.png", 8.0, 8.0);
var ruleEditorThemedValues =
[
[@"alternating-row-colors", backgroundColors],
[@"selected-color", selectedActiveRowColor, CPThemeStateNormal],
[@"selected-color", selectedInactiveRowColor, CPThemeStateDisabled],
[@"slice-top-border-color", sliceTopBorderColor],
[@"slice-bottom-border-color", sliceBottomBorderColor],
[@"slice-last-bottom-border-color", sliceLastBottomBorderColor],
[@"font", [CPFont systemFontOfSize:10.0]],
[@"add-image", addImage],
[@"remove-image", removeImage]
];
[self registerThemeValues:ruleEditorThemedValues forView:ruleEditor];
return ruleEditor;
}
@end
@implementation AristoHUDThemeDescriptor : BKThemeDescriptor
@@ -0,0 +1,190 @@
/*
* AppController.j
* CPPredicateEditorCibTest
*
* Created by cacaodev on November 25, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import <AppKit/CPScrollView.j>
@implementation AppController : CPObject
{
CPWindow window;
CPRuleEditor predicateEditor;
CPTextField predicateField;
CPTableView leftTable;
CPTableView rightTable;
CPPopUpButton rightExpressionsType;
CPButton addTemplate;
CPBox templateBox;
CPMutableArray operators;
CPMutableArray leftKeyPaths;
CPMutableArray rightConstants;
}
- (void)awakeFromCib
{
operators = [CPMutableArray new];
leftKeyPaths = [CPMutableArray new];
rightConstants = [CPMutableArray new];
[templateBox setCornerRadius:10];
[self updateAddTemplateButton];
[window setBackgroundColor:[CPColor colorWithHexString:@"f3f4f5"]];
[window setFullBridge:YES];
}
- (IBAction)displayPredicate:(id)sender
{
var pred = [CPPredicate predicateWithFormat:[sender stringValue]];
if (pred)
[predicateEditor setObjectValue:pred];
}
- (IBAction)predicateEditorAction:(id)sender
{
[predicateEditor reloadPredicate];
[predicateField setStringValue:[[predicateEditor objectValue] predicateFormat]];
}
- (void)ruleEditorRowsDidChange:(CPNotification)notification
{
CPLogConsole(_cmd);
}
// Templates maker
- (IBAction)updateOperators:(id)sender
{
var op = [CPNumber numberWithInt:[sender tag]];
if ([sender state] == CPOnState)
{
if (![operators containsObject:op])
[operators addObject:op];
}
else if ([sender state] == CPOffState)
[operators removeObject:op];
[self updateAddTemplateButton];
}
- (IBAction)selectRightAttributeType:(id)sender
{
[self updateAddTemplateButton];
}
- (IBAction)addLeftKeyPath:(id)sender
{
[self addUniqueValue:@"keypath" toArray:leftKeyPaths];
[leftTable reloadData];
[self updateAddTemplateButton];
}
- (IBAction)addRightConstant:(id)sender
{
if ([rightExpressionsType indexOfSelectedItem] != 2)
return;
[self addUniqueValue:@"constant" toArray:rightConstants];
[rightTable reloadData];
[self updateAddTemplateButton];
}
- (IBAction)addTemplate:(id)sender
{
var template;
var leftExpressions = [CPMutableArray array],
count = [leftKeyPaths count];
while (count--)
{
var exp = [CPExpression expressionForKeyPath:leftKeyPaths[count]];
[leftExpressions insertObject:exp atIndex:0];
}
var type = [rightExpressionsType indexOfSelectedItem];
if (type == 0)
template = [[CPPredicateEditorRowTemplate alloc] initWithLeftExpressions:leftExpressions rightExpressionAttributeType:CPStringAttributeType modifier:0 operators:operators options:0];
else if (type == 1)
template = [[CPPredicateEditorRowTemplate alloc] initWithLeftExpressions:leftExpressions rightExpressionAttributeType:CPInteger16AttributeType modifier:0 operators:operators options:0];
else if (type ==2)
{
var rightExpressions = [CPMutableArray array],
count = [rightConstants count];
while (count--)
{
var exp = [CPExpression expressionForConstantValue:rightConstants[count]];
[rightExpressions insertObject:exp atIndex:0];
}
template = [[CPPredicateEditorRowTemplate alloc] initWithLeftExpressions:leftExpressions rightExpressions:rightExpressions modifier:0 operators:operators options:0];
}
var templates = [[predicateEditor rowTemplates] arrayByAddingObject:template];
[predicateEditor setRowTemplates:templates];
[self cleanAll];
}
- (void)cleanAll
{
var subviews = [[templateBox contentView] subviews],
count = [subviews count];
while (count--)
{
var view = subviews[count];
if ([view isKindOfClass:[CPCheckBox class]])
[view setState:CPOffState];
}
[leftKeyPaths removeAllObjects];
[operators removeAllObjects];
[rightConstants removeAllObjects];
[leftTable reloadData];
[rightTable reloadData];
[self updateAddTemplateButton];
}
- (void)updateAddTemplateButton
{
var enabled = ([leftKeyPaths count] > 0 && [operators count] > 0 && ([rightExpressionsType indexOfSelectedItem] != 2 || [rightConstants count] > 0));
[addTemplate setEnabled:enabled];
}
- (void)addUniqueValue:(CPString)value toArray:(CPMutableArray)array
{
var i = 0,
count = [array count];
while (count--)
if ([array[count] hasPrefix:value])
i++;
[array addObject:(i==0)?value:[CPString stringWithFormat:@"%@%d", value, i]];
}
- (CPArray)arrayForTable:(CPTableView)tableView
{
return (tableView == leftTable) ? leftKeyPaths : rightConstants;
}
- (id)tableView:(CPTableView)tableView objectValueForTableColumn:(CPTableColumn)tableColumn row:(CPInteger)row
{
return [[self arrayForTable:tableView] objectAtIndex:row];
}
- (void)tableView:(CPTableView)tableView setObjectValue:(id)object forTableColumn:(CPTableColumn)tableColumn row:(CPInteger)row
{
[[self arrayForTable:tableView] replaceObjectAtIndex:row withObject:object];
}
- (int)numberOfRowsInTableView:(CPTableView)tableView
{
return [[self arrayForTable:tableView] count];
}
@end
@@ -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>Main cib file base name</key>
<string>MainMenu.cib</string>
<key>CPBundleName</key>
<string>CPPredicateEditorTest</string>
<key>CPPrincipalClass</key>
<string>CPApplication</string>
</dict>
</plist>
@@ -0,0 +1,93 @@
/*
* Jakefile
* CPPredicateEditorTest
*
* Created by You on May 7, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
app ("CPPredicateEditorTest", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "CPPredicateEditorTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPPredicateEditorTest");
task.setIdentifier("com.yourcompany.CPPredicateEditorTest");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPPredicateEditorTest");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
task ("default", ["CPPredicateEditorTest"], function()
{
printResults(configuration);
});
task ("build", ["default"]);
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", "CPPredicateEditorTest", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "CPPredicateEditorTest", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "CPPredicateEditorTest"));
OS.system(["press", "-f", FILE.join("Build", "Release", "CPPredicateEditorTest"), FILE.join("Build", "Deployment", "CPPredicateEditorTest")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "CPPredicateEditorTest"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPPredicateEditorTest"), FILE.join("Build", "Desktop", "CPPredicateEditorTest", "CPPredicateEditorTest.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "CPPredicateEditorTest", "CPPredicateEditorTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPPredicateEditorTest"));
print("----------------------------");
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
"string" = "loc string";
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,101 @@
<!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-debug.html
CPPredicateEditorTest
Created by You on May 7, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>CPPredicateEditorTest</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
</script>
<script src="Frameworks/Debug/Objective-J/Objective-J.js" type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
</script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading CPPredicateEditorTest...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
@@ -0,0 +1,79 @@
<!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
CPPredicateEditorTest
Created by You on May 7, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>CPPredicateEditorTest</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading CPPredicateEditorTest...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
@@ -0,0 +1,18 @@
/*
* main.j
* CPPredicateEditorTest
*
* Created by You on May 7, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
@@ -0,0 +1,111 @@
/*
* AppController.j
* CPRuleEditorCibTest
*
* Created by cacaodev on September 3, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import "RuleDelegate.j"
@import "CPViewAnimationTransition.j"
var THEME_ATTRIBUTES = [@"slice-top-border-color", @"slice-bottom-border-color",@"slice-last-bottom-border-color", @"selected-color"];
@implementation AppController : CPObject
{
CPWindow theWindow; //this "outlet" is connected automatically by the Cib
CPRuleEditor ruleEditor @accessors;
CPTextField predicateField;
id animation;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
}
- (void)awakeFromCib
{
var contentView = [theWindow contentView];
[theWindow setFullBridge:YES];
[contentView setBackgroundColor:[CPColor colorWithHexString:@"f3f4f5"]];
var animationClass = (CPBrowserIsEngine(CPWebKitBrowserEngine)) ? [CPViewAnimationTransition class] : [CPViewAnimation class];
animation = [[animationClass alloc] initWithDuration:0.4 animationCurve:CPAnimationEaseInOut];
//[ruleEditor setAnimation:animation];
for (var i = 0; i < 4; i++)
{
var view = [[theWindow contentView] viewWithTag:(1001 + i)];
[view setColor:[ruleEditor valueForThemeAttribute:THEME_ATTRIBUTES[i]]];
}
var colors = [ruleEditor valueForThemeAttribute:@"alternating-row-colors"];
[[contentView viewWithTag:1005] setColor:colors[0]];
[[contentView viewWithTag:1006] setColor:colors[1]];
}
- (void)ruleEditorAction:(id)sender
{
[ruleEditor reloadPredicate];
[predicateField setStringValue:[[ruleEditor predicate] predicateFormat]];
}
- (void)setAnimate:(id)sender
{
var anim = ([sender state]) ? animation : nil;
[ruleEditor setAnimation:anim];
}
- (void)setEditable:(id)sender
{
[ruleEditor setEditable:[sender state]];
}
- (void)setCanRemoveAllRows:(id)sender
{
[ruleEditor setCanRemoveAllRows:[sender state]];
}
- (void)setAllowsEmptyCompoundRows:(id)sender
{
[ruleEditor setAllowsEmptyCompoundRows:[sender state]];
}
- (void)setNestingMode:(id)sender
{
[ruleEditor setNestingMode:[sender indexOfSelectedItem]];
}
- (void)setFormattingStringsFilename:(id)sender
{
[ruleEditor setFormattingStringsFilename:[sender stringValue]];
}
- (void)setRowHeight:(id)sender
{
[ruleEditor setRowHeight:[sender value]];
}
- (void)setAttributeValue:(id)sender
{
var tag = [sender tag],
value,
attribute;
if (tag == 1005 || tag == 1006)
{
var colorIndex = tag - 1005,
attribute = @"alternating-row-colors",
value = [ruleEditor valueForThemeAttribute:attribute];
value[colorIndex] = [sender color];
}
else
{
value = [sender color];
attribute = THEME_ATTRIBUTES[tag - 1001];
}
[ruleEditor setValue:value forThemeAttribute:attribute];
[ruleEditor setNeedsDisplay:YES];
}
@@ -0,0 +1,231 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2008 Pear, Inc. All rights reserved.
*/
@import <AppKit/CPView.j>
@import <AppKit/CPAnimation.j>
CPViewAnimationStartFrameKey = "CPViewAnimationStartFrameKey";
CPViewAnimationEndFrameKey = "CPViewAnimationEndFrameKey";
CPViewAnimationTargetKey = "CPViewAnimationTargetKey";
CPViewAnimationEffectKey = "CPViewAnimationEffectKey";
CPViewAnimationFadeInEffect = "CPViewAnimationFadeInEffect";
CPViewAnimationFadeOutEffect = "CPViewAnimationFadeOutEffect";
@implementation CPViewAnimationTransition : CPAnimation
{
CPArray _viewAnimations;
Function endListener;
BOOL _isAnimating;
}
// INSTANCE METHODS
- (id)initWithViewAnimations:(CPArray)animations
{
self = [super initWithDuration:0.5 animationCurve:CPAnimationEaseInOut];
if (self)
{
[self setViewAnimations:animations];
_isAnimating = NO;
}
return self;
}
- (id)initWithDuration:(CPInteger)duration animationCurve:(id)curve
{
self = [super initWithDuration:duration animationCurve:curve];
if (self)
{
_isAnimating = NO;
}
return self;
}
- (CPArray)viewAnimations
{
return _viewAnimations;
}
- (void)setViewAnimations:(CPArray)animations
{
_viewAnimations = animations;
var count = [_viewAnimations count];
for (var i = 0; i < count; i++)
{
var animation = [_viewAnimations objectAtIndex:i],
target = [animation objectForKey:CPViewAnimationTargetKey];
[self _updateAnimationCurve:[self animationCurve] forView:target];
[self _updateAnimationDuration:[self duration] forView:target];
}
endListener = function(event){[self _animationDidEnd:_viewAnimations]};
}
- (void)_updateTransitionPropertiesForView:(CPView)target
{
target._DOMElement.style.webkitTransitionProperty = "left, top, width, height, opacity";
}
// SUBCLASSING
- (BOOL)isAnimating
{
return _isAnimating;
}
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
var i,
count = [_viewAnimations count];
for (i = 0; i < count; i++)
{
var animation = [_viewAnimations objectAtIndex:i],
target = [animation objectForKey:CPViewAnimationTargetKey];
[self _updateAnimationCurve:anAnimationCurve forView:target];
}
[super setAnimationCurve:anAnimationCurve];
}
- (void)setAnimationDuration:(int)duration
{
var i,
count = [_viewAnimations count];
for (i = 0; i < count; i++)
{
var animation = [_viewAnimations objectAtIndex:i],
target = [animation objectForKey:CPViewAnimationTargetKey];
[self _updateAnimationDuration:duration forView:target];
}
[super setAnimationDuration:duration];
}
- (void)startAnimation
{
if (![self _animationShouldStart])
return;
var count = [_viewAnimations count];
if (count > 0)
{
_isAnimating = YES;
document.addEventListener("webkitTransitionEnd", endListener, false);
}
for (var i = 0; i < count; i++)
{
var animation = [_viewAnimations objectAtIndex:i],
target = [animation objectForKey:CPViewAnimationTargetKey],
startFrame = [animation objectForKey:CPViewAnimationStartFrameKey],
endFrame = [animation objectForKey:CPViewAnimationEndFrameKey],
effect;
[target setFrame:startFrame];
[self _updateTransitionPropertiesForView:target];
if (effect = [animation objectForKey:CPViewAnimationEffectKey])
{
var opacity;
switch (effect)
{
case CPViewAnimationFadeInEffect: opacity = 1;
break;
case CPViewAnimationFadeOutEffect: opacity = 0;
break;
default : opacity = 1;
}
[target setAlphaValue:opacity];
}
[target setFrame:endFrame];
}
}
// PRIVATE METHODS
- (void)_updateAnimationCurve:(CPAnimationCurve)anAnimationCurve forView:(CPView)view
{
var webkitTimingFunction;
switch (anAnimationCurve)
{
case CPAnimationEaseInOut: webkitTimingFunction = "ease-in-out";
break;
case CPAnimationEaseIn: webkitTimingFunction = "ease-in";
break;
case CPAnimationEaseOut: webkitTimingFunction = "ease-out";
break;
case CPAnimationLinear: webkitTimingFunction = "linear";
break;
default: [CPException raise:CPInvalidArgumentException
reason:"Invalid value provided for animation curve"];
break;
}
view._DOMElement.style.webkitTransitionTimingFunction = webkitTimingFunction;
}
- (void)_updateAnimationDuration:(int)duration forView:(CPView)view
{
view._DOMElement.style.webkitTransitionDuration = duration + "s";
}
- (BOOL)_animationShouldStart
{
if (_delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)])
return [_delegate animationShouldStart:self];
return YES;
}
- (void)_animationDidEnd:(CPArray)viewAnimations
{
var count = [viewAnimations count];
if (this.counter == null)
this.counter = count;
this.counter--;
if (this.counter == 0)
{
document.removeEventListener("webkitTransitionEnd", endListener, false);
this.counter = null;
_isAnimating = NO;
while(count--)
{
var target = [viewAnimations[count] objectForKey:CPViewAnimationTargetKey];
target._DOMElement.style.removeProperty("-webkit-transition");
}
if (_delegate && [_delegate respondsToSelector:@selector(animationDidEnd:)])
[_delegate animationDidEnd:self];
}
}
- (void)_stopAnimation:(int)value
{
}
- (void)setCurrentProgress:(float)progress
{
}
@end
@@ -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>Main cib file base name</key>
<string>MainMenu.cib</string>
<key>CPBundleName</key>
<string>CPRuleEditorCibTest</string>
<key>CPPrincipalClass</key>
<string>CPApplication</string>
</dict>
</plist>
+94
View File
@@ -0,0 +1,94 @@
/*
* Jakefile
* CPRuleEditorCibTest
*
* Created by You on September 3, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
app ("CPRuleEditorCibTest", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "CPRuleEditorCibTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPRuleEditorCibTest");
task.setIdentifier("com.yourcompany.CPRuleEditorCibTest");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPRuleEditorCibTest");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
task.setNib2CibFlags("-R Resources/");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
task ("default", ["CPRuleEditorCibTest"], function()
{
printResults(configuration);
});
task ("build", ["default"]);
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", "CPRuleEditorCibTest", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "CPRuleEditorCibTest", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "CPRuleEditorCibTest"));
OS.system(["press", "-f", FILE.join("Build", "Release", "CPRuleEditorCibTest"), FILE.join("Build", "Deployment", "CPRuleEditorCibTest")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "CPRuleEditorCibTest"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPRuleEditorCibTest"), FILE.join("Build", "Desktop", "CPRuleEditorCibTest", "CPRuleEditorCibTest.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "CPRuleEditorCibTest", "CPRuleEditorCibTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPRuleEditorCibTest"));
print("----------------------------");
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,192 @@
<?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>CPRuleEditorPredicateCompoundType</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>
<dict>
<key>CPRuleEditorPredicateCompoundType</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>
</array>
</dict>
<key>rootChildren</key>
<dict>
<key>subrows</key>
<array>
<dict>
<key>CPRuleEditorPredicateLeftExpression</key>
<string>firstName</string>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>8</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>3</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleTextField</string>
</dict>
</array>
<key>valeur</key>
<string>CPBeginsWithPredicateOperatorType</string>
</dict>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>7</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>3</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleTextField</string>
</dict>
</array>
<key>valeur</key>
<string>CPLikePredicateOperatorType</string>
</dict>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>6</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>0</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleTextField</string>
</dict>
</array>
<key>valeur</key>
<string>CPMatchesPredicateOperatorType</string>
</dict>
</array>
<key>valeur</key>
<string>firstName</string>
</dict>
<dict>
<key>CPRuleEditorPredicateLeftExpression</key>
<string>lastName</string>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>8</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>0</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleTextField</string>
</dict>
</array>
<key>valeur</key>
<string>CPBeginsWithPredicateOperatorType</string>
</dict>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>9</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>0</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleTextField</string>
</dict>
</array>
<key>valeur</key>
<string>CPEndsWithPredicateOperatorType</string>
</dict>
</array>
<key>valeur</key>
<string>lastName</string>
</dict>
<dict>
<key>CPRuleEditorPredicateLeftExpression</key>
<string>age</string>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>0</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorCustomControlClass</key>
<string>RuleSlider</string>
</dict>
</array>
<key>valeur</key>
<string>CPLessThanPredicateOperatorType</string>
</dict>
<dict>
<key>CPRuleEditorPredicateComparisonModifier</key>
<integer>0</integer>
<key>CPRuleEditorPredicateOperatorType</key>
<integer>3</integer>
<key>CPRuleEditorPredicateOptions</key>
<integer>0</integer>
<key>criteria</key>
<array>
<dict>
<key>CPRuleEditorPredicateRightExpression</key>
<integer>50</integer>
<key>valeur</key>
<string>50 ans</string>
</dict>
</array>
<key>valeur</key>
<string>CPGreaterThanOrEqualToPredicateOperatorType</string>
</dict>
</array>
<key>valeur</key>
<string>age</string>
</dict>
</array>
</dict>
</dict>
</plist>
@@ -0,0 +1,18 @@
"CPLessThanPredicateOperatorType" = "is less than"; //0
"CPLessThanOrEqualToPredicateOperatorType" = "is less than or equal to"; //1
"CPGreaterThanPredicateOperatorType" = "is greater than"; //2
"CPGreaterThanOrEqualToPredicateOperatorType" = "is greater than or equal to"; //3
"CPEqualToPredicateOperatorType" = "is equal to"; //4
"CPNotEqualToPredicateOperatorType" = "is not equal"; //5
"CPMatchesPredicateOperatorType" = "matches"; //6
"CPLikePredicateOperatorType" = "is like"; //7
"CPBeginsWithPredicateOperatorType" = "begins with"; //8
"CPEndsWithPredicateOperatorType" = "ends with"; //9
"CPInPredicateOperatorType" = "is in"; //10
"CPCustomSelectorPredicateOperatorType" = "function"; //11
"CPContainsPredicateOperatorType" = "contains"; //99
"CPBetweenPredicateOperatorType" = "is between"; //100
"firstName" = "First Name";
"lastName" = "Last Name";
"age" = "Age";
"birthDate" = "Birth Date";
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,76 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2008 Pear, Inc. All rights reserved.
*/
@implementation RuleTextField : CPTextField
{
}
- (id)initWithFrame:(CPRect)frame
{
self = [super initWithFrame:CGRectMake(0, 0, 500, 24)];
if (self != nil)
{
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldSquareBezel];
[self setBordered:YES];
[self setEditable:YES];
[self setFont:[CPFont systemFontOfSize:11]];
}
return self;
}
- (BOOL)isEqual:(id)object
{
if ([object class] == [RuleTextField class] &&
[[object objectValue] isEqual:[self objectValue]])
return YES;
return YES;
}
- (id)copy
{
var copy = [[RuleTextField alloc] initWithFrame:CGRectMakeZero()];
[copy setObjectValue:[self objectValue]];
return copy;
}
@end
@implementation RuleSlider : CPSlider
{
}
- (id) initWithFrame:(CPRect)frame
{
self = [super initWithFrame:CGRectMake(0, 0, 500, 18)];
if (self != nil)
{
[self setMinValue:0];
[self setMaxValue:60];
[self setContinuous:YES];
}
return self;
}
- (id)objectValue
{
return ROUND([self doubleValue]);
}
- (id)copy
{
var copy = [[RuleSlider alloc] initWithFrame:CGRectMakeZero()];
[copy setObjectValue:[self objectValue]];
return copy;
}
@end
@@ -0,0 +1,147 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2008 Pear, Inc. All rights reserved.
*/
@import <AppKit/CPRuleEditor.j>
@import "RuleControls.j"
var CPRuleEditorPredicateKeys = [
CPRuleEditorPredicateLeftExpression,
CPRuleEditorPredicateRightExpression,
CPRuleEditorPredicateComparisonModifier,
CPRuleEditorPredicateOptions,
CPRuleEditorPredicateOperatorType,
CPRuleEditorPredicateCustomSelector,
CPRuleEditorPredicateCompoundType
];
var CPRuleEditorCustomControlClass = @"CPRuleEditorCustomControlClass";
@implementation RuleDelegate : CPObject
{
CPDictionary criteria;
}
- (id)init
{
self = [super init];
if (self != nil)
{
var path = [[CPBundle mainBundle] pathForResource:@"criteria.plist"],
request = [CPURLRequest requestWithURL:path],
connection = [CPURLConnection connectionWithRequest:request delegate:self];
}
return self;
}
- (void)connection:(CPURLConnection)connection didReceiveData:(CPString)dataString
{
if (!dataString)
return;
var data = [[CPData alloc] initWithRawString:dataString];
criteria = [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0];
}
/* 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:(CPRuleEditor)editor numberOfChildrenForCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType
{
var childs;
if (criterion)
childs = [criterion objectForKey:@"criteria"];
else
childs = [criteria valueForKeyPath:(rowType == CPRuleEditorRowTypeSimple) ? @"rootChildren.subrows" : @"rootHeaders.subrows"];
return (childs == NULL) ? 0 : [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:(CPRuleEditor)editor child:(int)index forCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType
{
var childs;
if (criterion)
childs = [criterion objectForKey:@"criteria"];
else
childs = [criteria 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:(CPRuleEditor)editor displayValueForCriterion:(id)criterion inRow:(int)row
{
var custom_control_class = [criterion objectForKey:CPRuleEditorCustomControlClass];
if (custom_control_class != nil)
{
var custom_class = CPClassFromString(custom_control_class);
return [[custom_class alloc] initWithFrame:CGRectMake(0, 0, 100, 18)];
}
return [criterion objectForKey:@"valeur"];
}
- (CPDictionary)ruleEditor:(CPRuleEditor)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 != nil)
[predicatePartsForCriterion setObject:compound_type forKey:CPRuleEditorPredicateCompoundType];
return predicatePartsForCriterion;
}
var count = CPRuleEditorPredicateKeys.length;
for (var i = 0 ;i<count ;i++)
{
var key = CPRuleEditorPredicateKeys[i],
predicatePart = nil ;
if ([key isEqualToString:CPRuleEditorPredicateLeftExpression])
{
var str = [criterion objectForKey:key];
if (str != nil) 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 expressionForConstantValue:transformedValue];
}
else if ([key isEqualToString:CPRuleEditorPredicateOperatorType] ||
[key isEqualToString:CPRuleEditorPredicateCustomSelector] ||
[key isEqualToString:CPRuleEditorPredicateOptions])
{
var value = [criterion objectForKey:key];
if (value != nil) predicatePart = value;
}
else
continue;
if (predicatePart != nil)[predicatePartsForCriterion setObject:predicatePart forKey:key];
}
return predicatePartsForCriterion;
}
- (void)ruleEditorRowsDidChange:(CPNotification)notification
{
}
@end
@@ -0,0 +1,104 @@
<!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-debug.html
CPRuleEditorCibTest
Created by You on September 3, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>CPRuleEditorCibTest</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
</script>
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
</script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading CPRuleEditorCibTest...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
@@ -0,0 +1,78 @@
<!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
CPRuleEditorCibTest
Created by You on September 3, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>CPRuleEditorCibTest</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading CPRuleEditorCibTest...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
/*
* AppController.j
* CPRuleEditorCibTest
*
* Created by You on September 3, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
@@ -0,0 +1,319 @@
/*
* AppController.j
* Smart Folders Demo
*
* Created by cacaodev on November 25, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import "BadgedOutlineView.j"
@import "ImageAndTextView.j"
@import <AppKit/CPScrollView.j>
var rootItems = [CPArray arrayWithObject:[CPDictionary dictionaryWithObjectsAndKeys:@"SMART FOLDERS", @"name", YES, @"isContainer"]],
smartFolderImage = [[CPImage alloc] initWithContentsOfFile:@"Resources/SmartFolder.png" size:CGSizeMake(24, 24)],
newFolder = [CPDictionary dictionaryWithObjectsAndKeys:@"Smart Folder", @"name", [CPPredicate predicateWithFormat:@"firstName BEGINSWITH ''"], @"predicate"];
@implementation AppController : CPObject
{
// Outlets in MainMenu.cib
@outlet CPWindow theWindow;
@outlet CPView searchBar;
@outlet CPSearchField searchField;
@outlet CPOutlineView smartOutlineView;
@outlet CPTableView table;
@outlet CPArrayController tableController;
// Outlets in PredicateEditor.cib
@outlet CPPredicateEditor predicateEditor;
@outlet CPTextField folderNameField;
@outlet CPWindow predicateSheet;
//Model
CPArray smartFolders;
CPString searchCategory;
CPArray tableArray @accessors;
CPPredicate filterPredicate @accessors;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
var path = [[CPBundle mainBundle] pathForResource:@"tableArray.plist"],
request = [CPURLRequest requestWithURL:path],
connection = [CPURLConnection connectionWithRequest:request delegate:self];
smartFolders = [CPArray array];
// restore saved folders if they exist
var saved = [[CPUserDefaults standardUserDefaults] objectForKey:@"SmartFolders"];
if (saved)
{
[smartFolders addObjectsFromArray:saved];
[smartOutlineView reloadData];
}
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
}
// Save folders into defaults
- (void)saveSmartFolders
{
[CPTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(_saveSmartFolders) userInfo:nil repeats:NO];
}
- (void)_saveSmartFolders
{
var defaults = [CPUserDefaults standardUserDefaults];
[defaults setObject:smartFolders forKey:@"SmartFolders"];
}
- (void)awakeFromCib
{
// Search Bar
var color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:@"Resources/searchBarBlue.png" size:CGSizeMake(1.0, 34.0)]];
[searchBar setBackgroundColor:color];
// Smart Outline View
var dataView = [[ImageAndTextView alloc] initWithFrame:CGRectMakeZero()],
column = [[smartOutlineView tableColumns] objectAtIndex:0];
[column setDataView:dataView];
[smartOutlineView setBackgroundColor:[CPColor colorWithRed:212.0 / 255.0 green:221.0 / 255.0 blue:230.0 / 255.0 alpha:1.0]];
[smartOutlineView setDoubleAction:@selector(editFolderAction:)];
[smartOutlineView setAction:@selector(outlineViewAction:)];
[smartOutlineView setSourceListDataSource:self];
[smartOutlineView setRowHeight:26];
[smartOutlineView expandItem:[smartOutlineView itemAtRow:0]];
// Search Field
[searchField setSearchMenuTemplate:[searchField defaultSearchMenuTemplate]];
[searchField setRecentsAutosaveName:"autosave"];
// Button Bar
var plusButton = [CPButtonBar plusButton],
minusButton = [CPButtonBar minusButton],
superView = [[smartOutlineView enclosingScrollView] contentView],
buttonBar = [[CPButtonBar alloc] initWithFrame:CGRectMake(0.0, CGRectGetHeight([superView frame]) - 26, CGRectGetWidth([superView frame]), 26)];
[plusButton setTarget:self];
[minusButton setTarget:self];
[plusButton setAction:@selector(createNewFolder:)];
[minusButton setAction:@selector(removeFolder:)];
[buttonBar setHasResizeControl:YES];
[buttonBar setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
[buttonBar setButtons:[CPArray arrayWithObjects:plusButton, minusButton]];
[superView addSubview:buttonBar];
[theWindow setFullBridge:YES];
}
// Get the table data
- (void)connection:(CPURLConnection)connection didReceiveData:(CPString)dataString
{
if (!dataString)
return;
var data = [[CPData alloc] initWithRawString:dataString],
array = [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0];
var count = [array count];
while (count--)
{
var record = array[count],
string = [record objectForKey:@"birthDate"],
date = [[CPDate alloc] initWithString:string];
[record setObject:date forKey:@"birthDate"];
}
[self setTableArray:array];
}
// =======================
// ! Search field action
// =======================
- (IBAction)searchFieldFilter:(id)sender
{
var searchString = [searchField stringValue],
predicate = [CPPredicate predicateWithFormat:@"(%K CONTAINS[cd] %@) OR (%K CONTAINS[cd] %@)", "firstName", searchString, "lastName", searchString];
[self setFilterPredicate:predicate];
}
// ========================
// ! Manage smart folders
// ========================
// Simple click: just filter
- (IBAction)outlineViewAction:(id)sender
{
var folder = [self selectedFolder],
predicate = [folder objectForKey:@"predicate"];
[self setFilterPredicate:predicate];
[CPTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(setPredicateEditorValue:) userInfo:predicate repeats:NO];
}
- (void)setPredicateEditorValue:(CPTimer)timer
{
[predicateEditor setObjectValue:[timer userInfo]];
}
// Double click: edit folder
- (IBAction)editFolderAction:(id)sender
{
var folder = [self selectedFolder];
[self displaySheetWithFolder:folder];
}
- (IBAction)createNewFolder:(id)sender
{
var folder = [newFolder copy];
[smartFolders addObject:folder];
[smartOutlineView reloadData];
[smartOutlineView selectRowIndexes:[CPIndexSet indexSetWithIndex:[smartFolders count]] byExtendingSelection:NO];
[self displaySheetWithFolder:folder];
}
- (IBAction)removeFolder:(id)sender
{
var selectionIndexes = [smartOutlineView selectedRowIndexes];
if ([selectionIndexes count] == 0)
return;
[smartFolders removeObjectAtIndex:[selectionIndexes firstIndex] - 1];
[smartOutlineView reloadData];
[smartOutlineView selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO];
[self saveSmartFolders];
}
- (void)displaySheetWithFolder:(id)folder
{
if (predicateSheet == nil)
[CPBundle loadCibNamed:@"PredicateEditor" owner:self];
[folderNameField setStringValue:[folder objectForKey:@"name"]];
[predicateEditor setObjectValue:[folder objectForKey:@"predicate"]]; // nil is ok
[predicateSheet makeFirstResponder:folderNameField];
[CPApp beginSheet:predicateSheet modalForWindow:theWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:folder:) contextInfo:folder];
}
- (IBAction)closeSheet:(id)sender
{
if ([sender tag] == CPOKButton)
[predicateEditor reloadPredicate];
[CPApp endSheet:predicateSheet returnCode:[sender tag]];
}
- (void)sheetDidEnd:(CPWindow)aSheet returnCode:(int)returnCode folder:(id)folder
{
var name = [folderNameField stringValue];
if (returnCode == CPOKButton && [name length] > 0)
{
var predicate = [predicateEditor objectValue];
[self setFilterPredicate:predicate];
[folder setObject:predicate forKey:@"predicate"];
[folder setObject:name forKey:@"name"];
[folder setObject:[[tableController arrangedObjects] count] forKey:@"count"];
[smartOutlineView reloadData];
[self saveSmartFolders];
}
}
// convenience method
- (id)selectedFolder
{
var selectionIndexes = [smartOutlineView selectedRowIndexes];
if ([selectionIndexes count] > 0)
{
return [smartFolders objectAtIndex:[selectionIndexes firstIndex] - 1]; // O is not selectable
}
return nil;
}
// ================================================================
// Badged Outline View data source & delegate methods.
// ================================================================
- (CPArray)childrenForItem:(id)item
{
if (item == nil)
return rootItems;
return smartFolders;
}
- (id)outlineView:(CPOutlineView)theOutlineView child:(CPInteger)index ofItem:(id)item
{
var children = [self childrenForItem:item];
return [children objectAtIndex:index];
}
- (CPInteger)outlineView:(CPOutlineView)theOutlineView numberOfChildrenOfItem:(id)item
{
var children = [self childrenForItem:item];
return [[self childrenForItem:item] count];
}
- (id)outlineView:(CPOutlineView)theOutlineView objectValueForTableColumn:(CPTableColumn)tableColumn byItem:(id)item
{
return " " + [item objectForKey:@"name"];
}
- (void)outlineView:(CPOutlineView)theOutlineView willDisplayView:(CPView)aView forTableColumn:(CPTableColumn)tableColumn item:(id)item
{
if (![aView isKindOfClass:[ImageAndTextView class]])
return;
var isContainer = !![item objectForKey:@"isContainer"];
if (isContainer)
{
[aView setFont:[CPFont boldSystemFontOfSize:11.0]];
[aView setTextColor:[CPColor colorWithWhite:100.0 / 255.0 alpha:0.9]];
[aView setImagePosition:CPNoImage];
}
else
{
[aView setImagePosition:CPImageLeft];
[aView setImage:smartFolderImage];
}
}
- (BOOL)outlineView:(CPOutlineView)theOutlineView shouldSelectItem:(id)item
{
return ![item objectForKey:@"isContainer"];
}
- (BOOL)outlineView:(CPOutlineView)theOutlineView isItemExpandable:(id)item
{
return !![item objectForKey:@"isContainer"];
}
// Badged outline data source methods
- (BOOL)sourceList:(CPOutlineView)aSourceList itemHasBadge:(id)item
{
return ([item objectForKey:@"count"] != nil);
}
- (CPInteger)sourceList:(CPOutlineView)aSourceList badgeValueForItem:(id)item
{
return [item objectForKey:@"count"];
}
// Resize the sheet if needed
- (void)ruleEditorRowsDidChange:(CPNotification)notif
{
var frame = [predicateSheet frame],
newHeight = [predicateEditor numberOfRows] * [predicateEditor rowHeight] + 103;
frame.size.height = MAX([predicateSheet minSize].height, newHeight);
[predicateSheet setFrame:frame display:[predicateSheet isSheet] animate:[predicateSheet isSheet]];
}
@end
@@ -0,0 +1,264 @@
/*
* BadgedOutlineView.j
*
* Created by cacaodev on February 22, 2010.
* Copyright 2010, All rights reserved.
*
* Based on PXSourceList
* Created by Alex Rozanski on 05/09/2009.
* Copyright 2009-10 Alex Rozanski http://perspx.com
*/
@import "AppController.j"
var MIN_BADGE_WIDTH = 22.0, //The minimum badge width for each item (default 22.0)
BADGE_HEIGHT = 14.0, //The badge height for each item (default 14.0)
BADGE_MARGIN = 5.0, //The spacing between the badge and the cell for that row
ROW_RIGHT_MARGIN = 5.0, //The spacing between the right edge of the badge and the edge of the table column
BADGE_BACKGROUND_COLOR = [CPColor colorWithCalibratedRed:(152/255.0) green:(168/255.0) blue:(202/255.0) alpha:1],
BADGE_HIDDEN_BACKGROUND_COLOR = [CPColor colorWithWhite:(180/255.0) alpha:1],
BADGE_SELECTED_TEXT_COLOR = [CPColor colorWithCalibratedRed:(75/255.0) green:(137/255.0) blue:(208/255.0) alpha:1],
BADGE_SELECTED_UNFOCUSED_TEXT_COLOR = [CPColor colorWithCalibratedRed:(153/255.0) green:(169/255.0) blue:(203/255.0) alpha:1],
BADGE_SELECTED_HIDDEN_TEXT_COLOR = [CPColor colorWithCalibratedWhite:(170/255.0) alpha:1],
BADGE_FONT = [CPFont boldSystemFontOfSize:11];
var CPSourceListDataSource_sourceList_itemHasBadge_ = 1 << 1,
CPSourceListDataSource_sourceList_badgeValueForItem_ = 1 << 2,
CPSourceListDataSource_sourceList_badgeBackgroundColorForItem_ = 1 << 3,
CPSourceListDataSource_sourceList_badgeTextColorForItem_ = 1 << 4;
@implementation BadgedOutlineView : CPOutlineView
{
id _sourceListDataSource @accessors(property=sourceListDataSource);
int _implementedSourceListDataSourceMethods;
}
- (void)setSourceListDataSource:(id)aDataSource
{
_sourceListDataSource = aDataSource;
implementedSourceListDataSourceMethods = 0;
if ([_sourceListDataSource respondsToSelector:@selector(sourceList:itemHasBadge:)])
implementedSourceListDataSourceMethods |= CPSourceListDataSource_sourceList_itemHasBadge_;
if ([_sourceListDataSource respondsToSelector:@selector(sourceList:badgeValueForItem:)])
implementedSourceListDataSourceMethods |= CPSourceListDataSource_sourceList_badgeValueForItem_;
if ([_sourceListDataSource respondsToSelector:@selector(sourceList:badgeBackgroundColorForItem:)])
implementedSourceListDataSourceMethods |= CPSourceListDataSource_sourceList_badgeBackgroundColorForItem_;
if ([_sourceListDataSource respondsToSelector:@selector(sourceList:badgeTextColorForItem:)])
implementedSourceListDataSourceMethods |= CPSourceListDataSource_sourceList_badgeTextColorForItem_;
}
- (BOOL)itemHasBadge:(id)item
{
if (implementedSourceListDataSourceMethods & CPSourceListDataSource_sourceList_itemHasBadge_)
return [_sourceListDataSource sourceList:self itemHasBadge:item];
return NO;
}
- (CPInteger)badgeValueForItem:(id)item
{
if ([self itemHasBadge:item] && implementedSourceListDataSourceMethods & CPSourceListDataSource_sourceList_badgeValueForItem_)
return [_sourceListDataSource sourceList:self badgeValueForItem:item];
return CPNotFound;
}
//This method calculates and returns the size of the badge for the row index passed to the method. If the
//row for the row index passed to the method does not have a badge, then NSZeroSize is returned.
- (CGSize)sizeOfBadgeAtRow:(CPInteger)rowIndex
{
var rowItem = [self itemAtRow:rowIndex];
//Make sure that the item has a badge
if (![self itemHasBadge:rowItem])
return CGSizeZero();
var badgeString = [CPString stringWithFormat:@"%d", [self badgeValueForItem:rowItem]];
var stringSize = [badgeString sizeWithFont:BADGE_FONT];
//Calculate the width needed to display the text or the minimum width if it's smaller
var width = MAX(MIN_BADGE_WIDTH, stringSize.width + 2 * BADGE_MARGIN);
return CGSizeMake(width, BADGE_HEIGHT);
}
- (void)drawRow:(CPInteger)rowIndex clipRect:(CGRect)clipRect
{
var item = [self itemAtRow:rowIndex];
//Draw the badge if the item has one
if ([self itemHasBadge:item])
{
var columnIndex = [_tableColumns indexOfObjectIdenticalTo:[self outlineTableColumn]],
viewRect = [self frameOfDataViewAtColumn:columnIndex row:rowIndex],
badgeSize = [self sizeOfBadgeAtRow:rowIndex],
badgeFrame = CGRectMake(CGRectGetMaxX(viewRect) - badgeSize.width - ROW_RIGHT_MARGIN,
CGRectGetMidY(viewRect) - (badgeSize.height/2.0),
badgeSize.width,
badgeSize.height);
[self drawBadgeForRow:rowIndex inRect:badgeFrame];
}
}
- (void)drawBadgeForRow:(CPInteger)rowIndex inRect:(CGRect)badgeFrame
{
var rowItem = [self itemAtRow:rowIndex],
badgePath = [CPBezierPath bezierPath];
[badgePath appendBezierPathWithRoundedRect:badgeFrame xRadius:(BADGE_HEIGHT/2.0) yRadius:(BADGE_HEIGHT/2.0)];
//Get window and control state to determine colours used
var isFocused = [[[self window] firstResponder] isEqual:self],
rowBeingEdited = -1 // uninplemented [self editedRow];
//Set the attributes based on the row state
var backgroundColor,
textColor;
if ([[self selectedRowIndexes] containsIndex:rowIndex])
{
backgroundColor = [CPColor whiteColor];
//Set the text color based on window and control state
if (isFocused || rowBeingEdited == rowIndex)
textColor = BADGE_SELECTED_TEXT_COLOR;
else if (!isFocused)
textColor = BADGE_SELECTED_UNFOCUSED_TEXT_COLOR;
else
textColor = BADGE_SELECTED_HIDDEN_TEXT_COLOR;
}
else
{
//Set the text colour based on window and control state
textColor = [CPColor whiteColor];
//If the data source returns a custom colour..
if (implementedSourceListDataSourceMethods & CPSourceListDataSource_sourceList_badgeBackgroundColorForItem_)
{
backgroundColor = [_sourceListDataSource sourceList:self badgeBackgroundColorForItem:rowItem];
if (backgroundColor == nil)
backgroundColor = BADGE_BACKGROUND_COLOR;
}
else //Otherwise use the default (purple-blue colour)
backgroundColor = BADGE_BACKGROUND_COLOR;
//If the delegate wants a custom badge text colour..
if (implementedSourceListDataSourceMethods & CPSourceListDataSource_sourceList_badgeTextColorForItem_)
{
textColor = [_sourceListDataSource sourceList:self badgeTextColorForItem:rowItem];
if (textColor == nil)
textColor = [CPColor whiteColor];
}
}
[backgroundColor set];
[badgePath fill];
//Draw the badge text
var badgeString = [CPString stringWithFormat:@"%d", [self badgeValueForItem:rowItem]],
stringSize = [badgeString sizeWithFont:BADGE_FONT],
badgeTextPoint = CGPointMake(CGRectGetMidX(badgeFrame) - (stringSize.width/2.0), //Center in the badge frame
CGRectGetMidY(badgeFrame) + (stringSize.height/4.0)); //Center in the badge frame
[textColor setFill];
[badgeString drawAtPoint:badgeTextPoint withFont:BADGE_FONT];
}
/* This CPOutlineView subclass is necessary only if you want to delete items by dragging them to the trash. In order to support drags to the trash, you need to implement draggedImage:endedAt:operation: and handle the CPDragOperationDelete operation. For any other operation, pass the message to the superclass
*/
- (void)draggedImage:(CPImage)image endedAt:(CPPoint)screenPoint operation:(CPDragOperation)operation
{
if (operation == CPDragOperationDelete)
{
// Tell all of the dragged nodes to remove themselves from the model.
var selection = [[self dataSource] draggedNodes],
count = [selection count];
while (count--)
{
var node = selection[count];
[[[node parentNode] mutableChildNodes] removeObject:node];
}
[self reloadData];
[self deselectAll:nil];
}
else
{
[super draggedImage:image endedAt:screenPoint operation:operation];
}
}
@end
@implementation CPOutlineView (MyExtensions)
- (CPView)preparedViewAtColumn:(int)column row:(int)row
{
return [self _newDataViewForRow:row tableColumn:_tableColumns[column]];
}
- (CPArray)selectedItems
{
var items = [CPArray array],
selectedRows = [self selectedRowIndexes],
row = [selectedRows firstIndex];
if (selectedRows != nil)
{
while (row != CPNotFound)
{
[items addObject:[self itemAtRow:row]];
row = [selectedRows indexGreaterThanIndex:row];
}
}
return items;
}
- (void)setSelectedItems:(CPArray)items
{
// If we are extending the selection, we start with the existing selection; otherwise, we create a new blank set of the indexes.
var newSelection = [CPIndexSet indexSet],
count = [items count];
for (var i = 0; i < count; i++)
{
var row = [self rowForItem:[items objectAtIndex:i]];
if (row != CPNotFound)
[newSelection addIndex:row];
}
[self selectRowIndexes:newSelection byExtendingSelection:NO];
}
@end
@implementation CPString (DrawingAdditions)
- (CGSize)drawAtPoint:(CGPoint)point withFont:(CPFont)font
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ctx);
CGContextSetFont(ctx, font);
CGContextShowTextAtPoint(ctx, point.x, point.y + 1, self, 0);
CGContextRestoreGState(ctx);
return [self sizeWithFont:font];
}
@end
function CGContextShowTextAtPoint(aContext, x, y, aString,/* unused */ aStringLength)
{
aContext.fillText(aString, x, y);
}
function CGContextSetFont(aContext, aFont)
{
aContext.font = [aFont cssString];
}
@@ -0,0 +1,69 @@
@implementation ImageAndTextView : _CPImageAndTextView
{
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
[self _initShared];
}
return self;
}
- (void)_initShared
{
//[self setLineBreakMode:CPLineBreakByTruncatingTail];
[self setImagePosition:CPImageLeft];
[self setAlignment:CPLeftTextAlignment];
[self setVerticalAlignment:CPCenterVerticalTextAlignment];
}
- (id)initWithCoder:(CPCoder)coder
{
self = [super initWithCoder:coder];
[self _initShared];
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
{
[super encodeWithCoder:coder];
}
- (id)objectValue
{
return [self text];
}
- (void)setObjectValue:(id)value
{
[self setText:value];
}
- (void)setThemeState:(CPThemeState)state
{
if (state === CPThemeStateSelectedDataView)
{
[self setTextColor:[CPColor whiteColor]];
[self setFont:[CPFont boldSystemFontOfSize:13]];
}
[super setThemeState:state];
}
- (void)unsetThemeState:(CPThemeState)state
{
if (state === CPThemeStateSelectedDataView)
{
[self setTextColor:[CPColor colorWithWhite:0.3 alpha:1]];
[self setFont:[CPFont systemFontOfSize:13]];
}
[super unsetThemeState:state];
}
@end
+12
View File
@@ -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>Main cib file base name</key>
<string>MainMenu.cib</string>
<key>CPBundleName</key>
<string>SmartFoldersDemo</string>
<key>CPPrincipalClass</key>
<string>CPApplication</string>
</dict>
</plist>
+94
View File
@@ -0,0 +1,94 @@
/*
* Jakefile
* SmartFoldersDemo
*
* Created by You on November 25, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
app ("SmartFoldersDemo", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "SmartFoldersDemo.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("SmartFoldersDemo");
task.setIdentifier("com.yourcompany.");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("SmartFoldersDemo");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
task.setNib2CibFlags("-R Resources/");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
task ("default", ["SmartFoldersDemo"], function()
{
printResults(configuration);
});
task ("build", ["default"]);
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", "SmartFoldersDemo", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "SmartFoldersDemo", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "SmartFoldersDemo"));
OS.system(["press", "-f", FILE.join("Build", "Release", "SmartFoldersDemo"), FILE.join("Build", "Deployment", "SmartFoldersDemo")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "SmartFoldersDemo"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "SmartFoldersDemo"), FILE.join("Build", "Desktop", "SmartFoldersDemo", "SmartFoldersDemo.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "SmartFoldersDemo", "SmartFoldersDemo.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "SmartFoldersDemo"));
print("----------------------------");
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,96 @@
<?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">
<array>
<dict>
<key>birthDate</key>
<string>2010-05-16 10:40:55 +0000</string>
<key>firstName</key>
<string>Jimmy</string>
<key>lastName</key>
<string>McNulty</string>
<key>age</key>
<integer>46</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2010-05-12 10:40:55 +0000</string>
<key>firstName</key>
<string>Kima</string>
<key>lastName</key>
<string>Georges</string>
<key>age</key>
<integer>41</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2010-04-31 10:40:55 +0000</string>
<key>firstName</key>
<string>Lester</string>
<key>lastName</key>
<string>Freamon</string>
<key>age</key>
<integer>57</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2010-02-16 10:40:55 +0000</string>
<key>firstName</key>
<string>kevin</string>
<key>lastName</key>
<string>Russel</string>
<key>age</key>
<integer>37</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2010-01-16 10:40:55 +0000</string>
<key>firstName</key>
<string>William</string>
<key>lastName</key>
<string>Moreland</string>
<key>age</key>
<integer>53</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2007-12-16 10:40:55 +0000</string>
<key>firstName</key>
<string>Cedric</string>
<key>lastName</key>
<string>Daniels</string>
<key>age</key>
<integer>47</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2008-11-16 10:40:55 +0000</string>
<key>firstName</key>
<string>Roland</string>
<key>lastName</key>
<string>Prysbylewski</string>
<key>age</key>
<integer>27</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2007-10-16 10:40:55 +0000</string>
<key>firstName</key>
<string>Omar</string>
<key>lastName</key>
<string>Little</string>
<key>age</key>
<integer>29</integer>
</dict>
<dict>
<key>birthDate</key>
<string>2008-09-16 10:40:55 +0000</string>
<key>firstName</key>
<string>Avon</string>
<key>lastName</key>
<string>Barkstale</string>
<key>age</key>
<integer>36</integer>
</dict>
</array>
</plist>
@@ -0,0 +1,104 @@
<!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-debug.html
SmartFoldersDemo
Created by You on November 25, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>SmartFoldersDemo</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
</script>
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
</script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading SmartFoldersDemo...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
+78
View File
@@ -0,0 +1,78 @@
<!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
SmartFoldersDemo
Created by You on November 25, 2010.
Copyright 2010, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>SmartFoldersDemo</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading SmartFoldersDemo...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
/*
* AppController.j
* null
*
* Created by You on November 25, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
+2
View File
@@ -47,7 +47,9 @@
@import "NSObjectController.j"
@import "NSOutlineView.j"
@import "NSPopUpButton.j"
@import "NSPredicateEditor.j"
@import "NSResponder.j"
@import "NSRuleEditor.j"
@import "NSScrollView.j"
@import "NSScroller.j"
@import "NSSearchField.j"
+199
View File
@@ -0,0 +1,199 @@
@import <Foundation/CPExpression.j>
@implementation NSKeyPathExpression : CPExpression_keypath
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_keypath class];
}
@end
@implementation CPKeyPathSpecifierExpression : CPExpression_constant
{
}
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var keyPath = [aCoder decodeObjectForKey:@"NSKeyPath"];
self = [super initWithValue:keyPath];
return self;
}
@end
@implementation NSKeyPathSpecifierExpression : CPKeyPathSpecifierExpression
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_constant class];
}
@end
@implementation CPExpression_constant (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var value = [aCoder decodeObjectForKey:@"NSConstantValue"];
return [self initWithValue:value];
}
@end
@implementation NSConstantValueExpression : CPExpression_constant
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_constant class];
}
@end
@implementation CPExpression_function (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var type = [aCoder decodeIntForKey:@"NSExpressionType"],
operand = [aCoder decodeObjectForKey:@"NSOperand"],
selector = CPSelectorFromString([aCoder decodeObjectForKey:@"NSSelectorName"]),
args = [aCoder decodeObjectForKey:@"NSArguments"];
return [self initWithTarget:operand selector:selector arguments:args type:type];
}
@end
@implementation NSFunctionExpression : CPExpression_function
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_function class];
}
@end
@implementation CPExpression_set (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var type = [aCoder decodeIntForKey:@"NSExpressionType"],
left = [aCoder decodeObjectForKey:@"NSLeftExpression"],
right = [aCoder decodeObjectForKey:@"NSRightExpression"];
return [self initWithType:type left:left right:right];
}
@end
@implementation NSSetExpression : CPExpression_set
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_set class];
}
@end
@implementation NSSelfExpression : CPExpression_self
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [super init];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_self class];
}
@end
@implementation CPExpression_variable (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var variable = [aCoder decodeObjectForKey:@"NSVariable"];
return [self initWithVariable:variable];
}
@end
@implementation NSVariableExpression : CPExpression_variable
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_variable class];
}
@end
@implementation CPExpression_aggregate (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
var collection = [aCoder decodeObjectForKey:@"NSCollection"];
return [self initWithAggregate:collection];
}
@end
@implementation NSAggregateExpression : CPExpression_aggregate
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPExpression_aggregate class];
}
@end
+1
View File
@@ -21,6 +21,7 @@
*/
@import "NSArray.j"
@import "NSExpression.j"
@import "NSDictionary.j"
@import "NSMutableString.j"
@import "NSSet.j"
+94
View File
@@ -0,0 +1,94 @@
/*
* NSPredicateEditor.j
* nib2cib
*
* Created by cacaodev.
* Copyright 2010.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPPredicateEditor.j>
@implementation CPPredicateEditor (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
self = [super NS_initWithCoder:aCoder];
if (self)
{
_allTemplates = [aCoder decodeObjectForKey:@"NSPredicateTemplates"];
}
return self;
}
@end
@implementation NSPredicateEditor : CPPredicateEditor
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPPredicateEditor class];
}
@end
@implementation CPPredicateEditorRowTemplate (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_templateType = [aCoder decodeIntForKey:@"NSPredicateTemplateType"];
_predicateOptions = [aCoder decodeIntForKey:@"NSPredicateTemplateOptions"];
_predicateModifier = [aCoder decodeIntForKey:@"NSPredicateTemplateModifier"];
_leftAttributeType = [aCoder decodeIntForKey:@"NSPredicateTemplateLeftAttributeType"];
_rightAttributeType = [aCoder decodeIntForKey:@"NSPredicateTemplateRightAttributeType"];
_leftIsWildcard = [aCoder decodeBoolForKey:@"NSPredicateTemplateLeftIsWildcard"];
_rightIsWildcard = [aCoder decodeBoolForKey:@"NSPredicateTemplateRightIsWildcard"];
_views = [aCoder decodeObjectForKey:@"NSPredicateTemplateViews"];
}
return self;
}
@end
@implementation NSPredicateEditorRowTemplate : CPPredicateEditorRowTemplate
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPPredicateEditorRowTemplate class];
}
@end
+111
View File
@@ -0,0 +1,111 @@
/*
* NSRuleEditor.j
* nib2cib
*
* Created by cacaodev.
* Copyright 2010.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <AppKit/CPRuleEditor.j>
@import <AppKit/CPTextField.j>
@import "NSCell.j"
@import "NSControl.j"
@implementation CPRuleEditor (NSCoding)
- (id)NS_initWithCoder:(CPCoder)aCoder
{
self = [super NS_initWithCoder:aCoder];
if (self)
{
_alignmentGridWidth = [aCoder decodeFloatForKey:@"NSRuleEditorAlignmentGridWidth"];
_sliceHeight = [aCoder decodeDoubleForKey:@"NSRuleEditorSliceHeight"];
_stringsFilename = [aCoder decodeObjectForKey:@"NSRuleEditorStringsFileName"];
_editable = [aCoder decodeBoolForKey:@"NSRuleEditorEditable"];
_allowsEmptyCompoundRows = [aCoder decodeBoolForKey:@"NSRuleEditorAllowsEmptyCompoundRows"];
_disallowEmpty = [aCoder decodeBoolForKey:@"NSRuleEditorDisallowEmpty"];
_nestingMode = [aCoder decodeIntForKey:@"NSRuleEditorNestingMode"];
_typeKeyPath = [aCoder decodeObjectForKey:@"NSRuleEditorRowTypeKeyPath"];
_itemsKeyPath = [aCoder decodeObjectForKey:@"NSRuleEditorItemsKeyPath"];
_valuesKeyPath = [aCoder decodeObjectForKey:@"NSRuleEditorValuesKeyPath"];
_subrowsArrayKeyPath = [aCoder decodeObjectForKey:@"NSRuleEditorSubrowsArrayKeyPath"];
_boundArrayKeyPath = [aCoder decodeObjectForKey:@"NSRuleEditorBoundArrayKeyPath"];
//_slicesHolder = [aCoder decodeObjectForKey:@"NSRuleEditorViewSliceHolder"];
_boundArrayOwner = [aCoder decodeObjectForKey:@"NSRuleEditorBoundArrayOwner"];
_slices = [aCoder decodeObjectForKey:@"NSRuleEditorSlices"];
_ruleDelegate = [aCoder decodeObjectForKey:@"NSRuleEditorDelegate"];
}
return self;
}
@end
@implementation NSRuleEditor : CPRuleEditor
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [CPRuleEditor class];
}
@end
@implementation _NSRuleEditorViewSliceHolder : _CPRuleEditorViewSliceHolder
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
return [self NS_initWithCoder:aCoder];
}
- (Class)classForKeyedArchiver
{
return [_CPRuleEditorViewSliceHolder class];
}
@end
@implementation _NSRuleEditorViewUnboundRowHolder : _CPRuleEditorViewUnboundRowHolder
{
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super init])
boundArray = [aCoder decodeObjectForKey:@"NSBoundArray"];
return self;
}
- (Class)classForKeyedArchiver
{
return [_CPRuleEditorViewUnboundRowHolder class];
}
@end