Merge branch 'master' of github.com:intalio/cappuccino

This commit is contained in:
Pascal Belloncle
2011-06-10 16:37:40 -07:00
165 changed files with 33026 additions and 1109 deletions
+6
View File
@@ -37,6 +37,7 @@
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@import "CPClipView.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@@ -59,6 +60,7 @@
@import "CPImage.j"
@import "CPImageView.j"
@import "CPKeyBinding.j"
@import "CPLevelIndicator.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
@import "CPOpenPanel.j"
@@ -66,9 +68,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"
@@ -89,6 +94,7 @@
@import "CPToolbarItem.j"
@import "_CPToolTip.j"
@import "CPTreeNode.j"
@import "CPUserDefaultsController.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@import "CPViewController.j"
+6 -2
View File
@@ -1292,8 +1292,12 @@ var _CPAppBootstrapperActions = nil,
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
{
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
var themeBlends = [CPApp themeBlends];
[themeBlends addObject:aThemeBlend];
if ([themeBlends count] === 1)
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
if (_CPAppThemeURLsToLoad.length === 0)
[self performActions];
+31 -11
View File
@@ -70,7 +70,8 @@
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
return [CPSet setWithObjects:"content", "filterPredicate", "sortDescriptors"];
// Also depends on "filterPredicate" but we'll handle that manually.
return [CPSet setWithObjects:"content", "sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
@@ -488,7 +489,14 @@
*/
- (void)setFilterPredicate:(CPPredicate)value
{
if (_filterPredicate === value)
return;
// __setFilterPredicate will call _rearrangeObjects without
// sending notifications, so we must send them instead.
[self willChangeValueForKey:@"arrangedObjects"];
[self __setFilterPredicate:value];
[self didChangeValueForKey:@"arrangedObjects"];
}
/*
@@ -501,8 +509,7 @@
return;
_filterPredicate = value;
// Use the non-notification version since arrangedObjects already depends
// on filterPredicate.
// Use the non-notification version.
[self _rearrangeObjects];
}
@@ -712,8 +719,12 @@
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
var willClearPredicate = NO;
if (_clearsFilterPredicateOnInsertion && _filterPredicate)
{
[self willChangeValueForKey:@"filterPredicate"];
willClearPredicate = YES;
}
[self willChangeValueForKey:@"content"];
@@ -728,11 +739,15 @@
[_contentObject addObject:object];
_disableSetContent = NO;
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
if (willClearPredicate)
{
// Full rearrange needed due to changed filter.
_filterPredicate = nil;
[self _rearrangeObjects];
}
else if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
// Insert directly into the array.
var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
// selectionIndexes change notification will be fired as a result of the
@@ -742,11 +757,16 @@
else
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
}
else
[self _rearrangeObjects];
/*
else if (_filterPredicate !== nil)
...
// Implies _filterPredicate && ![_filterPredicate evaluateWithObject:object], so the new object does
// not appear in arrangedObjects and we do not have to update at all.
*/
// This will also send notificaitons for arrangedObjects.
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
}
+66
View File
@@ -35,6 +35,12 @@ CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
/*!
@ingroup appkit
@class CPBox
A CPBox is a simple view which can display a border.
*/
@implementation CPBox : CPView
{
CPBoxType _boxType;
@@ -89,16 +95,46 @@ CPGrooveBorder = 3;
// Configuring Boxes
/*!
Returns the receiver's border rectangle.
@return the border rectangle of the box
*/
- (CPRect)borderRect
{
return [self bounds];
}
/*!
Returns the receiver's border type. Possible values are:
<pre>
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder
</pre>
@return the border type of the box
*/
- (CPBorderType)borderType
{
return _borderType;
}
/*!
Sets the receiver's border type. Valid values are:
<pre>
CPNoBorder
CPLineBorder
CPBezelBorder
CPGrooveBorder
</pre>
@param borderType the border type to use
*/
- (void)setBorderType:(CPBorderType)aBorderType
{
if (_borderType === aBorderType)
@@ -108,11 +144,41 @@ CPGrooveBorder = 3;
[self setNeedsDisplay:YES];
}
/*!
Returns the receiver's box type. Possible values are:
<pre>
CPBoxPrimary
CPBoxSecondary
CPBoxSeparator
CPBoxOldStyle
CPBoxCustom
</pre>
(In the current implementation, all values act the same except CPBoxSeparator.)
@return the box type of the box.
*/
- (CPBoxType)boxType
{
return _boxType;
}
/*!
Sets the receiver's box type. Valid values are:
<pre>
CPBoxPrimary
CPBoxSecondary
CPBoxSeparator
CPBoxOldStyle
CPBoxCustom
</pre>
(In the current implementation, all values act the same except CPBoxSeparator.)
@param aBoxType the box type of the box.
*/
- (void)setBoxType:(CPBoxType)aBoxType
{
if (_boxType === aBoxType)
+14 -9
View File
@@ -560,14 +560,9 @@ CPButtonImageOffset = 3.0;
return bounds;
}
/*!
Adjust the size of the button to fit the title and surrounding button image.
*/
- (void)sizeToFit
- (CGSize)_minimumFrameSize
{
[self layoutSubviews];
var size,
var size = CGSizeMakeZero(),
contentView = [self ephemeralSubviewNamed:@"content-view"];
if (contentView)
@@ -591,9 +586,19 @@ CPButtonImageOffset = 3.0;
if (maxSize.height >= 0.0)
size.height = MIN(size.height, maxSize.height);
[self setFrameSize:size];
return size;
}
if (contentView)
/*!
Adjust the size of the button to fit the title and surrounding button image.
*/
- (void)sizeToFit
{
[self layoutSubviews];
[self setFrameSize:[self _minimumFrameSize]];
if ([self ephemeralSubviewNamed:@"content-view"])
[self layoutSubviews];
}
+45 -2
View File
@@ -131,6 +131,49 @@
/*!
Sets the item prototype to \c anItem
The item prototype should implement the CPCoding protocol
because the item is copied by archiving and unarchiving the
prototypal view.
Example:
<pre>
@implement MyCustomView : CPCollectionViewItem
{
CPArray items @accessors;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
items = [];
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
items = [aCoder decodeObjectForKey:@"KEY"];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:items forKey:@"KEY"];
[super encodeWithCoder:aCoder];
}
@end
</pre>
This will allow the collection view to create multiple 'clean' copies
of the item prototype which will maintain the original values for item
and all of the properties archived by the super class.
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
@@ -343,7 +386,7 @@
_items = [];
if (!_itemPrototype || !_content)
if (!_itemPrototype)
return;
var index = 0;
@@ -369,7 +412,7 @@
{
var width = CGRectGetWidth([self bounds]);
if (![_content count] || width == _tileWidth)
if (width == _tileWidth)
return;
// We try to fit as many views per row as possible. Any remaining space is then
+1 -1
View File
@@ -50,7 +50,7 @@ var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
}
return nil;
return self;
}
- (BOOL)isEditing
+2 -2
View File
@@ -583,11 +583,11 @@ var _CPEventPeriodicEventPeriod = 0,
c === CPEnterCharacter ||
c === CPNewlineCharacter ||
c === CPCarriageReturnCharacter ||
c === CPEscapeFunctionKey ||
(!firstResponderIsText &&
(c === CPSpaceFunctionKey ||
c === CPDeleteCharacter ||
c === CPBackspaceCharacter ||
c === CPEscapeFunctionKey)))
c === CPBackspaceCharacter)))
{
return YES;
}
-4
View File
@@ -174,10 +174,6 @@ var CPBindingOperationAnd = 0,
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName,
valueTransformer,
placeholder;
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
+403
View File
@@ -0,0 +1,403 @@
/*
* CPLevelIndicator.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2011, WireLoad Inc.
*
* 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 "CPControl.j"
CPTickMarkBelow = 0;
CPTickMarkAbove = 1;
CPTickMarkLeft = CPTickMarkAbove;
CPTickMarkRight = CPTickMarkBelow;
CPRelevancyLevelIndicatorStyle = 0;
CPContinuousCapacityLevelIndicatorStyle = 1;
CPDiscreteCapacityLevelIndicatorStyle = 2;
CPRatingLevelIndicatorStyle = 3;
var _CPLevelIndicatorBezelColor = nil,
_CPLevelIndicatorSegmentEmptyColor = nil,
_CPLevelIndicatorSegmentNormalColor = nil,
_CPLevelIndicatorSegmentWarningColor = nil,
_CPLevelIndicatorSegmentCriticalColor = nil,
_CPLevelIndicatorSpacing = 1;
/*!
@ingroup appkit
@class CPLevelIndicator
CPLevelIndicator is a control which indicates a value visually on a scale.
*/
@implementation CPLevelIndicator : CPControl
{
CPLevelIndicator _levelIndicatorStyle @accessors(property=levelIndicatorStyle);
double _minValue @accessors(property=minValue);
double _maxValue @accessors(property=maxValue);
double _warningValue @accessors(property=warningValue);
double _criticalValue @accessors(property=criticalValue);
CPTickMarkPosition _tickMarkPosition @accessors(property=tickMarkPosition);
int _numberOfTickMarks @accessors(property=numberOfTickMarks);
int _numberOfMajorTickMarks @accessors(property=numberOfMajorTickMarks);
BOOL _isEditable;
BOOL _isTracking;
}
+ (void)initialize
{
var bundle = [CPBundle bundleForClass:CPLevelIndicator];
_CPLevelIndicatorBezelColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-left.png"] size:CGSizeMake(3.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-center.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-bezel-right.png"] size:CGSizeMake(3.0, 18.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentEmptyColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-empty-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentNormalColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-normal-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentWarningColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-warning-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
_CPLevelIndicatorSegmentCriticalColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-left.png"] size:CGSizeMake(3.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-center.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPLevelIndicator/level-indicator-segment-critical-right.png"] size:CGSizeMake(3.0, 17.0)]
]
isVertical:NO
]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_levelIndicatorStyle = CPDiscreteCapacityLevelIndicatorStyle;
_maxValue = 2;
_warningValue = 2;
_criticalValue = 2;
[self _init];
}
return self;
}
- (void)_init
{
}
- (void)layoutSubviews
{
var bezelView = [self layoutEphemeralSubviewNamed:"bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
// TODO Make themable.
[bezelView setBackgroundColor:_CPLevelIndicatorBezelColor];
var segmentCount = _maxValue - _minValue;
if (segmentCount <= 0)
return;
var filledColor = _CPLevelIndicatorSegmentNormalColor,
value = [self doubleValue];
if (value < _criticalValue)
filledColor = _CPLevelIndicatorSegmentCriticalColor;
else if (value < _warningValue)
filledColor = _CPLevelIndicatorSegmentWarningColor;
for (var i = 0; i < segmentCount; i++)
{
var segmentView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:bezelView];
[segmentView setBackgroundColor:(_minValue + i) < value ? filledColor : _CPLevelIndicatorSegmentEmptyColor];
}
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
{
// TODO Put into theme attributes.
var bezelHeight = 18,
segmentHeight = 17,
bounds = _CGRectCreateCopy([self bounds]);
if (aViewName == "bezel")
{
bounds.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.size.height = bezelHeight;
return bounds;
}
else if (aViewName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aViewName.substring("segment-bezel-".length), 10),
segmentCount = _maxValue - _minValue;
if (segment >= segmentCount)
return _CGRectMakeZero();
var basicSegmentWidth = bounds.size.width / segmentCount,
segmentFrame = CGRectCreateCopy([self bounds]);
segmentFrame.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.x = FLOOR(segment * basicSegmentWidth);
segmentFrame.size.width = (segment == segmentCount - 1) ? bounds.size.width - segmentFrame.origin.x : FLOOR(((segment + 1) * basicSegmentWidth)) - FLOOR((segment * basicSegmentWidth)) - _CPLevelIndicatorSpacing;
segmentFrame.size.height = segmentHeight;
return segmentFrame;
}
return _CGRectMakeZero();
}
/*!
Sets whether or not the receiver level indicator can be edited.
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
if (_isEditable === shouldBeEditable)
return;
_isEditable = shouldBeEditable;
}
/*!
Returns \c YES if the textfield is currently editable by the user.
*/
- (BOOL)isEditable
{
return _isEditable;
}
- (void)mouseDown:(CPEvent)anEvent
{
if (![self isEditable] || ![self isEnabled])
return;
[self _trackMouse:anEvent];
}
- (void)_trackMouse:(CPEvent)anEvent
{
var type = [anEvent type];
if (type == CPLeftMouseDown || type == CPLeftMouseDragged)
{
var segmentCount = _maxValue - _minValue;
if (segmentCount <= 0)
return;
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds],
oldValue = [self doubleValue];
newValue = oldValue;
// Moving the mouse outside of the widget to the left sets it
// to its minimum, and moving outside on the right sets it to
// its maximum.
if (type == CPLeftMouseDragged && location.x < 0)
{
newValue = _minValue;
}
else if (type == CPLeftMouseDragged && location.x > bounds.size.width)
{
newValue = _maxValue;
}
else
{
for (var i = 0; i < segmentCount; i++)
{
var rect = [self rectForEphemeralSubviewNamed:"segment-bezel-" + i];
// Once we're tracking the mouse, we only care about horizontal mouse movement.
if (location.x >= CGRectGetMinX(rect) && location.x < CGRectGetMaxX(rect))
{
newValue = (_minValue + i + 1);
break;
}
}
}
if (newValue != oldValue)
[self setDoubleValue:newValue];
// Track the mouse to support click and slide value editing.
_isTracking = YES;
[CPApp setTarget:self selector:@selector(_trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
if ([self isContinuous])
[self sendAction:[self action] to:[self target]];
}
else if (_isTracking)
{
_isTracking = NO;
[self sendAction:[self action] to:[self target]];
}
}
/*
- (CPLevelIndicatorStyle)style;
- (void)setLevelIndicatorStyle:(CPLevelIndicatorStyle)style;
*/
- (void)setMinValue:(double)minValue
{
if (_minValue === minValue)
return;
_minValue = minValue;
[self setNeedsLayout];
}
- (void)setMaxValue:(double)maxValue
{
if (_maxValue === maxValue)
return;
_maxValue = maxValue;
[self setNeedsLayout];
}
- (void)setWarningValue:(double)warningValue;
{
if (_warningValue === warningValue)
return;
_warningValue = warningValue;
[self setNeedsLayout];
}
- (void)setCriticalValue:(double)criticalValue;
{
if (_criticalValue === criticalValue)
return;
_criticalValue = criticalValue;
[self setNeedsLayout];
}
/*
- (CPTickMarkPosition)tickMarkPosition;
- (void)setTickMarkPosition:(CPTickMarkPosition)position;
- (int)numberOfTickMarks;
- (void)setNumberOfTickMarks:(int)count;
- (int)numberOfMajorTickMarks;
- (void)setNumberOfMajorTickMarks:(int)count;
- (double)tickMarkValueAtIndex:(int)index;
- (CGRect)rectOfTickMarkAtIndex:(int)index;
*/
@end
var CPLevelIndicatorStyleKey = "CPLevelIndicatorStyleKey",
CPLevelIndicatorMinValueKey = "CPLevelIndicatorMinValueKey",
CPLevelIndicatorMaxValueKey = "CPLevelIndicatorMaxValueKey",
CPLevelIndicatorWarningValueKey = "CPLevelIndicatorWarningValueKey",
CPLevelIndicatorCriticalValueKey = "CPLevelIndicatorCriticalValueKey",
CPLevelIndicatorTickMarkPositionKey = "CPLevelIndicatorTickMarkPositionKey",
CPLevelIndicatorNumberOfTickMarksKey = "CPLevelIndicatorNumberOfTickMarksKey",
CPLevelIndicatorNumberOfMajorTickMarksKey = "CPLevelIndicatorNumberOfMajorTickMarksKey",
CPLevelIndicatorIsEditableKey = "CPLevelIndicatorIsEditableKey";
@implementation CPLevelIndicator (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_levelIndicatorStyle = [aCoder decodeIntForKey:CPLevelIndicatorStyleKey];
_minValue = [aCoder decodeDoubleForKey:CPLevelIndicatorMinValueKey];
_maxValue = [aCoder decodeDoubleForKey:CPLevelIndicatorMaxValueKey];
_warningValue = [aCoder decodeDoubleForKey:CPLevelIndicatorWarningValueKey];
_criticalValue = [aCoder decodeDoubleForKey:CPLevelIndicatorCriticalValueKey];
_tickMarkPosition = [aCoder decodeIntForKey:CPLevelIndicatorTickMarkPositionKey];
_numberOfTickMarks = [aCoder decodeIntForKey:CPLevelIndicatorNumberOfTickMarksKey];
_numberOfMajorTickMarks = [aCoder decodeIntForKey:CPLevelIndicatorNumberOfMajorTickMarksKey];
_isEditable = [aCoder decodeBoolForKey:CPLevelIndicatorIsEditableKey];
[self _init];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_levelIndicatorStyle forKey:CPLevelIndicatorStyleKey];
[aCoder encodeDouble:_minValue forKey:CPLevelIndicatorMinValueKey];
[aCoder encodeDouble:_maxValue forKey:CPLevelIndicatorMaxValueKey];
[aCoder encodeDouble:_warningValue forKey:CPLevelIndicatorWarningValueKey];
[aCoder encodeDouble:_criticalValue forKey:CPLevelIndicatorCriticalValueKey];
[aCoder encodeInt:_tickMarkPosition forKey:CPLevelIndicatorTickMarkPositionKey];
[aCoder encodeInt:_numberOfTickMarks forKey:CPLevelIndicatorNumberOfTickMarksKey];
[aCoder encodeInt:_numberOfMajorTickMarks forKey:CPLevelIndicatorNumberOfMajorTickMarksKey];
[aCoder encodeBool:_isEditable forKey:CPLevelIndicatorIsEditableKey];
}
@end
+504
View File
@@ -0,0 +1,504 @@
/*
* 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("CPPredicateEditor 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];
[node applyTemplate:aTemplate withViews:templateViews forOriginalTemplate:originalTemplate];
[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],
rowType = [rowItem valueForKey:_typeKeyPath];
if (rowType == CPRuleEditorRowTypeCompound)
{
var subrows = [rowItem valueForKey:_subrowsArrayKeyPath],
count = [subrows count];
for (var i = 0; i < count; i++)
{
var subrow = [subrows objectAtIndex:i];
var predicate = [self _predicateFromRowItem:subrow];
[subpredicates addObject:predicate];
}
}
var criteria = [rowItem valueForKey:_itemsKeyPath],
displayValues = [rowItem valueForKey:_valuesKeyPath],
count = [criteria count],
lastItem = [criteria lastObject],
template = [lastItem templateForRow],
templateViews = [template templateViews];
for (var j = 0; j < count; j++)
{
var view = [templateViews objectAtIndex:j],
value = [displayValues objectAtIndex:j];
[[criteria objectAtIndex:j] setTemplateViews:templateViews];
if ([view isKindOfClass:[CPPopUpButton class]])
[view selectItemWithTitle:value];
else if ([view respondsToSelector:@selector(setObjectValue:)])
[view setObjectValue:[value objectValue]];
}
return [template predicateWithSubpredicates:subpredicates];
}
- (CPCompoundPredicateType)_compoundPredicateTypeForRootRows
{
return CPAndPredicateType;
}
#pragma mark Control delegate
- (void)_sendRuleAction
{
[self _updatePredicate];
[super _sendRuleAction];
}
- (BOOL)_sendsActionOnIncompleteTextChange
{
return NO;
}
/*
- (void)_setDefaultTargetAndActionOnView:(CPView)view
{
if ([view isKindOfClass:[CPControl class]])
{
[view setTarget:self];
[view setAction:@selector(_templateControlValueDidChange:)];
}
}
- (void)_templateControlValueDidChange:(id)sender
{
}
- (void)controlTextDidBeginEditing:(CPNotification)notification
{
}
- (void)controlTextDidEndEditing:(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)childIndex ofItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
var trees = (type == CPRuleEditorRowTypeSimple) ? _rootTrees : _rootHeaderTrees;
return [_CPPredicateEditorRowNode rowNodeFromTree:trees[childIndex]];
}
return [[rowItem children] objectAtIndex:childIndex];
}
- (id)_queryValueForItem:(id)rowItem inRow:(int)rowIndex
{
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,788 @@
/*
* 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
{
return [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:self]];
}
+ (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];
// In Xcode 4, when the menu item title == template's expression keypath, representedObject is empty.
// So we need to regenerate expressions from titles.
if (_templateType == 1 && _leftIsWildcard == NO)
{
var itemArray = [_views[0] itemArray],
count = [itemArray count];
for (var i = 0; i < count; i++)
{
var item = itemArray[i];
if ([item representedObject] == nil)
{
var exp = [CPExpression expressionForKeyPath:[item title]];
[item setRepresentedObject:exp];
}
}
}
}
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,132 @@
/*
* 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);
}
+ (id)rowNodeFromTree:(id)aTree
{
var mapTable = {};
return [_CPPredicateEditorRowNode _rowNodeFromTree:aTree withTemplateTable:mapTable];
}
+ (id)_rowNodeFromTree:(id)aTree withTemplateTable:(id)templateTable
{
var node,
views,
copiedContainer;
node = [[_CPPredicateEditorRowNode alloc] init];
node.tree = aTree;
var template = [aTree template],
uuid = [template UID];
var cachedNode = templateTable[uuid];
if (cachedNode == nil)
{
views = [CPMutableArray array];
copiedContainer = [CPMutableArray array];
templateTable[uuid] = node;
}
else
{
views = [cachedNode templateViews];
copiedContainer = [cachedNode copiedTemplateContainer];
}
node.templateViews = views;
node.copiedTemplateContainer = copiedContainer;
var nodeChildren = [CPMutableArray array],
treeChildren = [aTree children],
count = [treeChildren count];
for (var i = 0; i < count; i++)
{
var treeChild = treeChildren[i],
child = [_CPPredicateEditorRowNode _rowNodeFromTree:treeChild withTemplateTable:templateTable];
[nodeChildren addObject:child];
}
[node setChildren:nodeChildren];
return node;
}
- (BOOL)applyTemplate:(id)template withViews:(id)views forOriginalTemplate:(id)originalTemplate
{
var t = [tree template];
if (t !== template)
{
[templateViews setArray:views];
[copiedTemplateContainer removeAllObjects];
[copiedTemplateContainer addObject:template];
}
var count = [children count];
for (var i; i < count; i++)
[children[i] applyTemplate:template withViews:views forOriginalTemplate:originalTemplate];
}
- (BOOL)isEqual:(id)node
{
if (![node isKindOfClass:[_CPPredicateEditorRowNode class]])
return NO;
return (tree === [node tree]);
}
- (void)copyTemplateIfNecessary
{
if ([copiedTemplateContainer count] == 0)
{
CPLogConsole("COPYING TEMPLATE");
var copy = [[tree template] copy];
[copiedTemplateContainer addObject:copy];
[templateViews addObjectsFromArray:[copy templateViews]];
}
}
- (CPView)templateView
{
[self copyTemplateIfNecessary];
return [templateViews objectAtIndex:[tree indexIntoTemplate]];
}
- (id)templateForRow
{
[self copyTemplateIfNecessary];
return [copiedTemplateContainer lastObject];
}
- (CPString)title
{
return [tree title];
}
- (id)displayValue
{
var title = [self title];
if (title != nil)
return title;
return [self templateView];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<%@ %@ %@ tree:%@ tviews:%@", [self className],[self UID], [self title], [tree UID], [templateViews description]];
}
@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,512 @@
/*
* 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];
var mItem = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
return mItem;
}
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
{
var title = [[itemsArray objectAtIndex:index] title];
var font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 20,
rect = CGRectMake(0, 0, (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"],
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
if (![newItem isEqual: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 ruleItems,
criteria,
repObject,
menuItem,
ruleView,
criterion,
parent,
numberOfCriteria,
numberOfChildren,
firstResponderIndex;
var ruleItems = [CPMutableArray array];
[self _emptyRulePartSubviews];
criteria = [_ruleEditor criteriaForRow:_rowIndex];
numberOfCriteria = [criteria count];
firstResponderIndex = numberOfCriteria - 1;
var responder = [[self window] firstResponder];
if (responder)
firstResponderIndex = [_ruleOptionViews indexOfObjectIdenticalTo:responder];
for (var i = 0; i < numberOfCriteria; i++)
{
ruleView = nil;
parent = nil;
criterion = [criteria objectAtIndex:i];
if (i > 0)
parent = [criteria objectAtIndex:i - 1];
var childItems = [],
childValues = [];
[_ruleEditor _getAllAvailableItems:childItems values:childValues asChildrenOfItem:parent inRow:_rowIndex];
numberOfChildren = [childItems count];
if (numberOfChildren > 1)
{
var menuItems = [CPMutableArray arrayWithCapacity:numberOfChildren];
var selectedIndex = [childItems indexOfObject:criterion];
if (selectedIndex == CPNotFound)
break;
for (var j = 0; j < numberOfChildren; ++j)
{
var childItem = [childItems objectAtIndex:j];
var childValue = [childValues objectAtIndex:j];
if ([childValue isKindOfClass:[CPMenuItem class]])
{
[[childValue menu] removeItem:childValue];
menuItem = childValue;
}
else
{
if ([childValue isEqualToString:@""])
menuItem = [self _createMenuSeparatorItem];
else
{
menuItem = [self _createMenuItemWithTitle:childValue];
[menuItem setTarget:self];
[menuItem setAction:@selector(_ruleOptionPopupChangedAction:)];
}
}
repObject = [CPDictionary dictionaryWithObjectsAndKeys:childItem, @"item", childValue, @"value", i, @"indexInCriteria"];
[menuItem setRepresentedObject:repObject];
[menuItems addObject:menuItem];
}
ruleView = [self _createPopUpButtonWithItems:menuItems selectedItemIndex:selectedIndex];
}
else
{
var value = [childValues objectAtIndex:0];
var type = [value valueType];
if (type === 0)
ruleView = [self _createStaticTextFieldWithStringValue:value];
else
{
if (type !== 1)
{
[CPException raise:CPInternalInconsistencyException reason:@"Display value must be a string or a menu item"];
continue;
}
ruleView = value;
[ruleView setTarget:self];
[ruleView setAction:@selector(_sendRuleAction:)];
if ([ruleView respondsToSelector:@selector(setDelegate:)])
[ruleView setDelegate:self];
}
}
if (ruleView != nil)
{
[_ruleOptionViews addObject:ruleView];
var frame = [ruleView frame];
[_ruleOptionInitialViewFrames addObject:frame];
[_ruleOptionFrames addObject:frame];
if (!criterion)
criterion = [CPNull null];
[ruleItems addObject:criterion];
}
}
[_correspondingRuleItems setArray:ruleItems];
if (!editable)
[self _updateEnabledStateForSubviews];
[self _relayoutSubviewsWidthChanged:YES];
if (firstResponderIndex != CPNotFound)
{
var aView = [_ruleOptionViews objectAtIndex:firstResponderIndex];
[[self window] makeFirstResponder:aView]; // This is not working. bug in CPPopUpButton firstResponder ?
}
//[self setNeedsDisplay:YES];
}
- (void)_updateEnabledStateForSubviews
{
[_ruleOptionViews makeObjectsPerformSelector:@selector(setEnabled:) withObject:NO];
}
- (void)layoutSubviews
{
// CPLogConsole(_cmd);
[self _relayoutSubviewsWidthChanged:YES];
}
- (void)_relayoutSubviewsWidthChanged:(BOOL)widthChanged
{
var optionViewOriginX,
leftHorizontalPadding,
leftButtonMinX,
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame];
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];
if (widthChanged)
{
optionViewOriginX = [self _leftmostViewFixedHorizontalPadding] + [self _indentationHorizontalPadding] * _indentation;
leftHorizontalPadding = [self _rowButtonsLeftHorizontalPadding];
leftButtonMinX = CGRectGetMinX(buttonFrame);
}
for (var i = 0; i < count; i++)
{
var ruleOptionView = _ruleOptionViews[i],
optionFrame = _ruleOptionFrames[i];
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame))/2 - 2;
if (widthChanged)
{
optionFrame.origin.x = optionViewOriginX;
if (i == count - 1 && ![self _isRulePopup:ruleOptionView])
{
var initialFrame = _ruleOptionInitialViewFrames[i];
optionFrame.size.width = MIN(CGRectGetWidth(initialFrame), leftButtonMinX - leftHorizontalPadding - optionViewOriginX);
}
}
[ruleOptionView setFrame:optionFrame];
[self addSubview:ruleOptionView];
if (widthChanged)
optionViewOriginX += CGRectGetWidth(optionFrame) + [self _interviewHorizontalPadding];
}
}
- (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 _sendsActionOnIncompleteTextChange])
[_ruleEditor _sendRuleAction];
}
@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
+4 -4
View File
@@ -428,7 +428,7 @@ CPTableColumnUserResizingMask = 1 << 1;
var x = [self tableView]._cachedDataViews[dataViewUID];
if (x && x.length)
return x.pop();
return x.pop();
// if we haven't cached an archive of the data view, do it now
if (!_dataViewData[dataViewUID])
@@ -738,9 +738,9 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
{
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
[aCoder encodeObject:_width forKey:CPTableColumnWidthKey];
[aCoder encodeObject:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeObject:_maxWidth forKey:CPTableColumnMaxWidthKey];
[aCoder encodeFloat:_width forKey:CPTableColumnWidthKey];
[aCoder encodeFloat:_minWidth forKey:CPTableColumnMinWidthKey];
[aCoder encodeFloat:_maxWidth forKey:CPTableColumnMaxWidthKey];
[aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
+8 -11
View File
@@ -212,7 +212,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
- (CGRect)headerRectOfColumn:(int)aColumnIndex
{
var headerRect = [self bounds],
var headerRect = CGRectMakeCopy([self bounds]),
columnRect = [_tableView rectOfColumn:aColumnIndex];
headerRect.origin.x = _CGRectGetMinX(columnRect);
@@ -592,16 +592,13 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
for (var i = 0; i < count; i++)
{
var column = [tableColumns objectAtIndex:i],
headerView = [column headerView];
var frame = [self headerRectOfColumn:i];
headerView = [column headerView],
frame = [self headerRectOfColumn:i];
// Make space for the gridline on the right.
frame.origin.x -= 0.5;
frame.size.width -= 1.0;
frame.size.height -= 0.5;
if (i > 0)
{
frame.origin.x += 0.5;
frame.size.width -= 1;
}
// Note: we're not adding in intercell spacing here. This setting only affects the regular
// table cell data views, not the header. Verified in Cocoa on March 29th, 2011.
@@ -645,8 +642,8 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
columnMaxX = _CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
}
CGContextClosePath(context);
CGContextStrokePath(context);
+3 -10
View File
@@ -323,6 +323,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
{
_tableViewFlags = 0;
_lastSelectedRow = -1;
_clickedRow = -1;
_selectedColumnIndexes = [CPIndexSet indexSet];
_selectedRowIndexes = [CPIndexSet indexSet];
@@ -662,13 +663,6 @@ NOT YET IMPLEMENTED
[self reloadData];
}
/*!
@ignore
*/
- (void)setThemeState:(int)aState
{
}
/*!
Returns the intercell spacing in a CGSize object.
*/
@@ -1544,7 +1538,6 @@ NOT YET IMPLEMENTED
_numberOfHiddenColumns += 1;
_tableColumnRanges[index] = CPMakeRange(x, 0.0);
}
else
{
var width = [_tableColumns[index] width] + _intercellSpacing.width;
@@ -1843,7 +1836,7 @@ NOT YET IMPLEMENTED
leftInset = FLOOR(_intercellSpacing.width / 2.0),
topInset = FLOOR(_intercellSpacing.height / 2.0);
return _CGRectMake(tableColumnRange.location + leftInset, _CGRectGetMinY(rectOfRow) + topInset, tableColumnRange.length - _intercellSpacing.width, _CGRectGetHeight(rectOfRow) - _intercellSpacing.height);
return _CGRectMake(tableColumnRange.location + leftInset, _CGRectGetMinY(rectOfRow) + topInset, tableColumnRange.length - _intercellSpacing.width, _CGRectGetHeight(rectOfRow) - _intercellSpacing.height);
}
/*!
@@ -3643,7 +3636,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
for (; columnArrayIndex < columnArrayCount; ++columnArrayIndex)
{
var columnRect = [self rectOfColumn:columnsArray[columnArrayIndex]],
columnX = _CGRectGetMaxX(columnRect) + 0.5;
columnX = _CGRectGetMaxX(columnRect) - 0.5;
CGContextMoveToPoint(context, columnX, minY);
CGContextAddLineToPoint(context, columnX, maxY);
+267
View File
@@ -0,0 +1,267 @@
/*
* CPUserDefaultsController.j
* AppKit
*
* Portions based on NSUserDefaultsController.m (2009-06-04) in Cocotron (http://www.cocotron.org/)
* Copyright (c) 2006-2007 Christopher J. W. Lloyd
*
* Created by Alexander Ljungberg.
* Copyright 2011, WireLoad Inc.
*
* 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 <Foundation/CPString.j>
@import <AppKit/CPController.j>
var SharedUserDefaultsController = nil;
@implementation CPUserDefaultsController : CPController
{
CPUserDefaults _defaults @accessors(readonly, property=defaults);
CPDictionary _initialValues @accessors(property=initialValues);
BOOL _appliesImmediately @accessors(property=appliesImmediately);
}
+ (id)sharedUserDefaultsController
{
if (!SharedUserDefaultsController)
SharedUserDefaultsController = [[CPUserDefaultsController alloc] initWithDefaults:nil initialValues:nil];
return SharedUserDefaultsController;
}
- (id)initWithDefaults:(CPUserDefaults)someDefaults initialValues:(CPDictionary)initialValues
{
if (self = [super init])
{
if (!someDefaults)
someDefaults = [CPUserDefaults standardUserDefaults];
_defaults = someDefaults;
_initialValues = [initialValues copy];
_appliesImmediately = YES;
_valueProxy = [[_CPUserDefaultsControllerProxy alloc] initWithController:self];
}
return self;
}
- (id)values
{
return _valueProxy;
}
- (BOOL)hasUnappliedChanges
{
return [_valueProxy hasUnappliedChanges];
}
- (void)save:(id)sender
{
[_valueProxy save];
}
- (void)revert:(id)sender
{
[_valueProxy revert];
}
- (void)revertToInitialValues:(id)sender
{
[_valueProxy revertToInitialValues];
}
@end
var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
@implementation CPUserDefaultsController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if ([aCoder decodeBoolForKey:CPUserDefaultsControllerSharedKey])
return [CPUserDefaultsController sharedUserDefaultsController];
self = [super initWithCoder:aCoder];
if (self)
{
[CPException raise:CPUnsupportedMethodException reason:@"decoding of non-shared CPUserDefaultsController not implemented"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
if (self === SharedUserDefaultsController)
{
[aCoder encodeBool:YES forKey:CPUserDefaultsControllerSharedKey];
return;
}
[CPException raise:CPUnsupportedMethodException reason:@"encoding of non-shared CPUserDefaultsController not implemented"];
}
@end
@implementation _CPUserDefaultsControllerProxy : CPObject
{
CPUserDefaultsController _controller;
// TODO Could be optimised with a JS dict.
CPMutableDictionary _cachedValues;
}
- (id)initWithController:(CPUserDefaultsController)aController
{
if (self = [super init])
{
_controller = aController;
_cachedValues = [CPMutableDictionary dictionary];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:CPUserDefaultsDidChangeNotification object:[_controller defaults]];
}
return self;
}
- (void)dealloc
{
// FIXME No dealloc in Cappuccino.
[[CPNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id)valueForKey:(CPString)aKey
{
var value = [_cachedValues objectForKey:aKey];
if (value === nil)
{
value = [[_controller defaults] objectForKey:aKey];
if (value === nil)
value = [[_controller initialValues] objectForKey:aKey];
if (value !== nil)
[_cachedValues setObject:value forKey:aKey];
}
return value;
}
- (void)setValue:(id)aValue forKey:(CPString)aKey
{
[self willChangeValueForKey:aKey];
[_cachedValues setObject:aValue forKey:aKey];
if ([_controller appliesImmediately])
[[_controller defaults] setObject:aValue forKey:aKey];
[self didChangeValueForKey:aKey];
}
- (void)revert
{
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
[_cachedValues removeObjectForKey:key];
[self didChangeValueForKey:key];
}
}
- (void)save
{
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
{
var key = keys[keysCount];
[[_controller defaults] setObject:[_cachedValues objectForKey:key] forKey:key];
}
}
- (void)revertToInitialValues
{
var initial = [_controller initialValues],
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
var initialValue = [initial objectForKey:key];
if (initialValue !== nil)
[_cachedValues setObject:initialValue forKey:key];
else
[_cachedValues removeObjectForKey:key];
[self didChangeValueForKey:key];
}
}
- (void)userDefaultsDidChange:(CPNotification)aNotification
{
var defaults = [_controller defaults],
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
newValue = [defaults objectForKey:key];
if (![value isEqual:newValue])
{
[self willChangeValueForKey:key];
[_cachedValues setObject:newValue forKey:key];
[self didChangeValueForKey:key];
}
}
}
- (BOOL)hasUnappliedChanges
{
var defaults = [_controller defaults],
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
newValue = [defaults objectForKey:key];
if (![value isEqual:newValue])
return YES;
}
return NO;
}
@end
+1 -1
View File
@@ -2695,7 +2695,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[self setupViewFlags];
_theme = [CPTheme defaultTheme];
_theme = [CPTheme themeForView:self];
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
_themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
_themeAttributes = {};
@@ -0,0 +1,64 @@
/*
* CPCibRuntimeAttributesConnector.j
* AppKit
*
* Created by Aparajita Fishman.
* Copyright 2011, 280 North, Inc.
*
* 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 "CPCibConnector.j"
var CPCibRuntimeAttributesConnectorObjectKey = @"CPCibRuntimeAttributesConnectorObjectKey",
CPCibRuntimeAttributesConnectorKeyPathsKey = @"CPCibRuntimeAttributesConnectorKeyPathsKey",
CPCibRuntimeAttributesConnectorValuesKey = @"CPCibRuntimeAttributesConnectorValuesKey";
@implementation CPCibRuntimeAttributesConnector : CPCibConnector
{
id _keyPaths;
id _values;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_source = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorObjectKey];
_keyPaths = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
_values = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorValuesKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_source forKey:CPCibRuntimeAttributesConnectorObjectKey];
[aCoder encodeObject:_keyPaths forKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
[aCoder encodeObject:_values forKey:CPCibRuntimeAttributesConnectorValuesKey];
}
- (void)establishConnection
{
var count = [_keyPaths count];
while (count--)
[_source setValue:_values[count] forKeyPath:_keyPaths[count]];
}
@end
+2 -2
View File
@@ -61,14 +61,14 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
if (!object)
{
CPLog.error("Unable to find class " + theClassName + " in cib file.");
CPLog.error("Unable to find class " + theClassName + " referenced in cib file.");
object = [self allocObjectWithCoder:aCoder className:[aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]];
}
}
if (!object)
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."];
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " referenced in cib file."];
return object;
}
+24 -1
View File
@@ -43,6 +43,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObject:aSize forKey:@"size"]];
}
+ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize bundleClass:(CPString)aBundleClass
{
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObjects:[aSize, aBundleClass] forKeys:[@"size", @"bundleClass"]]];
}
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
{
self = [super init];
@@ -83,7 +88,25 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
if ([aCoder respondsToSelector:@selector(bundle)] &&
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
if (_className === @"CPImage")
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
{
if (_resourceName == "CPAddTemplate")
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
else if (_resourceName == "CPRemoveTemplate")
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
var bundleClass = _properties.valueForKey(@"bundleClass"),
bundle = nil;
if (bundleClass)
{
bundleClass = CPClassFromString(bundleClass);
if (bundleClass)
bundle = [CPBundle bundleForClass:bundleClass];
}
return [[CPImage alloc] initWithContentsOfFile:[(bundle || [aCoder bundle]) pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
}
return self;
}
+21 -2
View File
@@ -29,6 +29,7 @@
@import "CPCibControlConnector.j"
@import "CPCibOutletConnector.j"
@import "CPCibBindingConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@implementation _CPCibObjectData : CPObject
@@ -257,11 +258,29 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
_replacementObjects[[_fileOwner UID]] = anOwner;
var index = 0,
count = _connections.length;
count = _connections.length,
runtimeAttributeConnectors = [],
connection = nil;
for (; index < count; ++index)
{
var connection = _connections[index];
connection = _connections[index];
if ([connection isKindOfClass:[CPCibRuntimeAttributesConnector class]])
// Defer runtime attribute connections until after all other connections are made
runtimeAttributeConnectors.push(connection);
else
{
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
}
}
count = runtimeAttributeConnectors.length;
for (index = 0; index < count; ++index)
{
connection = runtimeAttributeConnectors[index];
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Platform.j
* Platform.h
* AppKit
*
* Created by Francisco Tolmasky.
Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

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
+1 -1
View File
@@ -127,7 +127,7 @@
_removeManySEL = sel_getName(@"remove" + capitalizedKey + "AtIndexes:");
if ([_proxyObject respondsToSelector:_removeManySEL])
_remove = [_proxyObject methodForSelector:_removeManySEL];
_removeMany = [_proxyObject methodForSelector:_removeManySEL];
_replaceManySEL = sel_getName(@"replace" + capitalizedKey + "AtIndexes:with" + capitalizedKey + ":");
if ([_proxyObject respondsToSelector:_replaceManySEL])
+11
View File
@@ -397,6 +397,17 @@
@end
@implementation CPArray (CPMutableCopying)
- (id)mutableCopy
{
var r = [CPMutableArray new];
[r addObjectsFromArray:self];
return r;
}
@end
var selectorCompare = function selectorCompare(object1, object2, selector)
{
return [object1 performSelector:selector withObject:object2];
+2 -3
View File
@@ -201,11 +201,10 @@ var _CPKeyedArchiverStringClass = Nil,
for (; i < _objects.length; ++i)
{
var object = _objects[i],
theClass = [object classForKeyedArchiver];
var object = _objects[i];
// Do whatever with the class, yo.
// We call willEncodeObject previously.
// We called willEncodeObject previously.
_plistObject = _plistObjects[[_UIDs objectForKey:[object UID]]];
[object encodeWithCoder:self];
+6 -41
View File
@@ -329,6 +329,11 @@ CPLog(@"Got some class: %@", inst);
return objj_msgSend(self, aSelector, anObject, anotherObject);
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return nil;
}
// Forwarding Messages
/*!
Subclasses can override this method to forward message to
@@ -341,36 +346,6 @@ CPLog(@"Got some class: %@", inst);
[self doesNotRecognizeSelector:[anInvocation selector]];
}
/*!
Used for forwarding of messages to other objects.
@ignore
*/
// FIXME: This should be moved to the runtime?
- (void)forward:(SEL)aSelector :(marg_list)args
{
var signature = [self methodSignatureForSelector:aSelector];
if (signature)
{
var invocation = [CPInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:aSelector];
var index = 2,
count = args.length;
for (; index < count; ++index)
[invocation setArgument:args[index] atIndex:index];
[self forwardInvocation:invocation];
return [invocation returnValue];
}
[self doesNotRecognizeSelector:aSelector];
}
// Error Handling
/*!
Called by the Objective-J runtime when an object can't respond to
@@ -381,7 +356,7 @@ CPLog(@"Got some class: %@", inst);
{
[CPException raise:CPInvalidArgumentException reason:
(class_isMetaClass(isa) ? "+" : "-") + " [" + [self className] + " " + aSelector + "] unrecognized selector sent to " +
(class_isMetaClass(isa) ? "class" : "instance") + " 0x" + [CPString stringWithHash:[self UID]]];
(class_isMetaClass(isa) ? "class " + class_getName(isa) : "instance 0x" + [CPString stringWithHash:[self UID]])];
}
// Archiving
@@ -542,13 +517,3 @@ CPLog(@"Got some class: %@", inst);
}
@end
// override toString on Objective-J objects so we get the actual description of the object
// when coerced to a string, instead of "[Object object]"
objj_class.prototype.toString = objj_object.prototype.toString = function()
{
if (this.isa && class_getInstanceMethod(this.isa, "description") != NULL)
return [this description];
else
return String(this) + " (-description not implemented)";
}
+10 -6
View File
@@ -438,14 +438,18 @@ var CPComparisonPredicateModifier,
reg = new RegExp(rhs.escapeForRegExp(),commut);
return reg.test(lhs);
case CPBeginsWithPredicateOperatorType: var range = CPMakeRange(0,[rhs length]);
if (_options & CPCaseInsensitivePredicateOption) string_compare_options |= CPCaseInsensitiveSearch;
if (_options & CPDiacriticInsensitivePredicateOption) string_compare_options |= CPDiacriticInsensitiveSearch;
case CPBeginsWithPredicateOperatorType: var range = CPMakeRange(0, MIN([lhs length], [rhs length]));
if (_options & CPCaseInsensitivePredicateOption)
string_compare_options |= CPCaseInsensitiveSearch;
if (_options & CPDiacriticInsensitivePredicateOption)
string_compare_options |= CPDiacriticInsensitiveSearch;
return ([lhs compare:rhs options:string_compare_options range:range] == CPOrderedSame);
case CPEndsWithPredicateOperatorType: var range = CPMakeRange([lhs length] - [rhs length],[rhs length]);
if (_options & CPCaseInsensitivePredicateOption) string_compare_options |= CPCaseInsensitiveSearch;
if (_options & CPDiacriticInsensitivePredicateOption) string_compare_options |= CPDiacriticInsensitiveSearch;
case CPEndsWithPredicateOperatorType: var range = CPMakeRange(MAX([lhs length] - [rhs length], 0), MIN([lhs length], [rhs length]));
if (_options & CPCaseInsensitivePredicateOption)
string_compare_options |= CPCaseInsensitiveSearch;
if (_options & CPDiacriticInsensitivePredicateOption)
string_compare_options |= CPDiacriticInsensitiveSearch;
return ([lhs compare:rhs options:string_compare_options range:range] == CPOrderedSame);
case CPCustomSelectorPredicateOperatorType: return [lhs performSelector:_customSelector withObject:rhs];
+1 -1
View File
@@ -42,7 +42,7 @@ foundationTask = framework ("Foundation", function(foundationTask)
foundationTask.setInfoPlistPath("Info.plist");
foundationTask.setEnvironments(require("objective-j/jake/environment").ObjJ);
var INCLUDES = "--include \"../AppKit/Platform/Platform.h\"";
var INCLUDES = "--include \"../AppKit/Platform/Platform.h\" --include \"Ref.h\"";
if ($CONFIGURATION === "Release")
foundationTask.setCompilerFlags("-O " + INCLUDES);
+30
View File
@@ -0,0 +1,30 @@
/*
* Ref.h
* Foundation
*
* Created by Alexander Ljungberg.
* Copyright 2011, WireLoad Inc.
*
* 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
*/
/*
Temporary macros to substitute for @ref and @deref functionality in a future version of Objective-J. Since these are C macros rather than a part of Preprocessor.js they can only be used within Cappuccino itself.
*/
// @ref
#define AT_REF(x) function(__input) { if (arguments.length) return x = __input; return x; }
// @deref (kind of)
#define AT_DEREF(x, ...) x(##__VA_ARGS__)
+50 -44
View File
@@ -120,7 +120,12 @@ function serializePropertyList(/*CFPropertyList*/ aPropertyList, /*Object*/ seri
else if (type === "number")
{
if (FLOOR(aPropertyList) === aPropertyList)
// A number like 3.4028234663852885e+54 should not be written as an integer, even that it is
// an integer - it'd be awfully long if written by expanding it. Worse, if written as an
// integer with scientific notation the parseInt() used to read it back will parse it as
// just 3, thereby wasting many hours of sanity when you're trying to nib2cib a table and
// columns are mysteriously showing up 3 pixels wide.
if (FLOOR(aPropertyList) === aPropertyList && ("" + aPropertyList).indexOf('e') == -1)
type = "integer";
else
type = "real";
@@ -240,14 +245,14 @@ CFPropertyListSerializers[CFPropertyList.Format280North_v1_0] =
"integer": function(/*Integer*/ anInteger)
{
var string = "" + anInteger;
return INTEGER_MARKER + ';' + string.length + ';' + string;
},
"real": function(/*Float*/ aFloat)
{
var string = "" + aFloat;
return FLOAT_MARKER + ';' + string.length + ';' + string;
},
@@ -259,7 +264,7 @@ CFPropertyListSerializers[CFPropertyList.Format280North_v1_0] =
for (; index < count; ++index)
string += serializePropertyList(anArray[index], serializers);
return string + END_MARKER + ';';
},
@@ -340,57 +345,57 @@ var textContent = function(nodes)
var _plist_traverseNextNode = function(anXMLNode, stayWithin, stack)
{
var node = anXMLNode;
PLIST_FIRST_CHILD(node);
// If this element has a child, traverse to it.
if (node)
return node;
// If not, first check if it is a container class (as opposed to a designated leaf).
// If it is, then we have to pop this container off the stack, since it is empty.
if (NODE_NAME(anXMLNode) === PLIST_ARRAY || NODE_NAME(anXMLNode) === PLIST_DICTIONARY)
stack.pop();
// If not, next check whether it has a sibling.
else
{
if (node === stayWithin)
return NULL;
node = anXMLNode;
PLIST_NEXT_SIBLING(node);
if (node)
return node;
return node;
}
// If it doesn't, start working our way back up the node tree.
node = anXMLNode;
// While we have a node and it doesn't have a sibling (and we're within our stayWithin),
// keep moving up.
while (node)
{
var next = node;
PLIST_NEXT_SIBLING(next);
// If we have a next sibling, just go to it.
if (next)
return next;
var node = PARENT_NODE(node);
// If we are being asked to move up, and our parent is the stay within, then just
// If we are being asked to move up, and our parent is the stay within, then just
if (stayWithin && node === stayWithin)
return NULL;
// Pop the stack if we have officially "moved up"
stack.pop();
}
return NULL;
}
@@ -428,13 +433,13 @@ var ARRAY_MARKER = "A",
function propertyListFrom280NorthString(/*String*/ aString)
{
var stream = new MarkedStream(aString),
marker = NULL,
key = "",
object = NULL,
plistObject = NULL,
containers = [],
currentContainer = NULL;
@@ -445,12 +450,12 @@ function propertyListFrom280NorthString(/*String*/ aString)
containers.pop();
continue;
}
var count = containers.length;
if (count)
currentContainer = containers[count - 1];
if (marker === KEY_MARKER)
{
key = stream.getString();
@@ -465,26 +470,27 @@ function propertyListFrom280NorthString(/*String*/ aString)
case DICTIONARY_MARKER: object = new CFMutableDictionary();
containers.push(object);
break;
case FLOAT_MARKER: object = parseFloat(stream.getString());
break;
case INTEGER_MARKER: object = parseInt(stream.getString(), 10);
break;
case STRING_MARKER: object = stream.getString();
break;
case TRUE_MARKER: object = YES;
break;
case FALSE_MARKER: object = NO;
break;
default: throw new Error("*** " + marker + " marker not recognized in Plist.");
}
if (!plistObject)
plistObject = object;
else if (currentContainer)
// If the container is an array...
if (currentContainer.slice)
@@ -492,7 +498,7 @@ function propertyListFrom280NorthString(/*String*/ aString)
else
currentContainer.setValueForKey(key, object);
}
return plistObject;
}
@@ -539,7 +545,7 @@ CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLN
// Skip over DOCTYPE and so forth.
while (IS_OF_TYPE(XMLNode, XML_DOCUMENT) || IS_OF_TYPE(XMLNode, XML_XML))
PLIST_FIRST_CHILD(XMLNode);
// Skip over the DOCTYPE... see a pattern?
if (IS_DOCUMENTTYPE(XMLNode))
PLIST_NEXT_SIBLING(XMLNode);
@@ -551,19 +557,19 @@ CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLN
var key = "",
object = NULL,
plistObject = NULL,
plistNode = XMLNode,
containers = [],
currentContainer = NULL;
while (XMLNode = _plist_traverseNextNode(XMLNode, plistNode, containers))
{
var count = containers.length;
if (count)
currentContainer = containers[count - 1];
if (NODE_NAME(XMLNode) === PLIST_KEY)
{
key = TEXT_CONTENT(XMLNode);
@@ -590,22 +596,22 @@ CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLN
object = decodeHTMLComponent(FIRST_CHILD(XMLNode) ? TEXT_CONTENT(XMLNode) : "");
break;
case PLIST_BOOLEAN_TRUE: object = YES;
break;
case PLIST_BOOLEAN_FALSE: object = NO;
break;
case PLIST_DATA: object = new CFMutableData();
object.bytes = FIRST_CHILD(XMLNode) ? CFData.decodeBase64ToArray(TEXT_CONTENT(XMLNode), YES) : [];
break;
default: throw new Error("*** " + NODE_NAME(XMLNode) + " tag not recognized in Plist.");
}
if (!plistObject)
plistObject = object;
else if (currentContainer)
// If the container is an array...
if (currentContainer.slice)
@@ -613,7 +619,7 @@ CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLN
else
currentContainer.setValueForKey(key, object);
}
return plistObject;
}
@@ -51,6 +51,7 @@ function BundleTask(aName, anApplication)
this._compilerFlags = null;
this._flattensSources = false;
this._includesNibsAndXibs = false;
this._preventsNib2Cib = false;
this._productName = this.name();
@@ -204,6 +205,16 @@ BundleTask.prototype.includesNibsAndXibs = function()
return this._includesNibsAndXibs;
}
BundleTask.prototype.setPreventsNib2Cib = function(shouldPreventNib2Cib)
{
this._preventsNib2Cib = shouldPreventNib2Cib;
}
BundleTask.prototype.preventsNib2Cib = function()
{
return this._preventsNib2Cib;
}
BundleTask.prototype.setProductName = function(aProductName)
{
this._productName = aProductName;
@@ -486,9 +497,9 @@ BundleTask.prototype.defineResourceTask = function(aResourcePath, aDestinationPa
var extension = FILE.extension(aResourcePath),
extensionless = aResourcePath.substr(0, aResourcePath.length - extension.length);
// NOT:
// (extname === ".cib" && (FILE.exists(extensionless + '.xib') || FILE.exists(extensionless + '.nib')) ||
// (extname === ".cib" && (FILE.exists(extensionless + '.xib') || FILE.exists(extensionless + '.nib') && !this._preventsNib2Cib) ||
// (extname === ".xib" || extname === ".nib") && !this.shouldIncludeNibsAndXibs())
if ((extension !== ".cib" || !FILE.exists(extensionless + ".xib") && !FILE.exists(extensionless + ".nib")) &&
if ((extension !== ".cib" || !FILE.exists(extensionless + ".xib") && !FILE.exists(extensionless + ".nib") || this._preventsNib2Cib) &&
((extension !== ".xib" && extension !== ".nib") || this.includesNibsAndXibs()))
{
filedir (aDestinationPath, [aResourcePath], function()
@@ -505,7 +516,7 @@ BundleTask.prototype.defineResourceTask = function(aResourcePath, aDestinationPa
this.enhance([aDestinationPath]);
}
if (extension === ".xib" || extension === ".nib")
if ((extension === ".xib" || extension === ".nib") && !this._preventsNib2Cib)
{
var cibDestinationPath = FILE.join(FILE.dirname(aDestinationPath), FILE.basename(aDestinationPath, extension)) + ".cib";
+80 -8
View File
@@ -71,7 +71,7 @@ GLOBAL(objj_class) = function(displayName)
this.method_dtable = this.method_store.prototype;
#if DEBUG
// naming the allocator allows the WebKit heap snapshot tool to display object class names correctly
// Naming the allocator allows the WebKit heap snapshot tool to display object class names correctly
// HACK: displayName property is not respected so we must eval a function to name it
eval("this.allocator = function " + (displayName || "OBJJ_OBJECT").replace(/\W/g, "_") + "() { }");
#else
@@ -342,10 +342,61 @@ var _class_initialize = function(/*Class*/ aClass)
}
}
var _objj_forward = new objj_method("forward", function(self, _cmd)
var _objj_forward = function(self, _cmd)
{
return objj_msgSend(self, "forward::", _cmd, arguments);
});
var isa = self.isa,
implementation = isa.method_dtable[SEL_forwardingTargetForSelector_];
if (implementation)
{
var target = implementation.method_imp.call(this, self, SEL_forwardingTargetForSelector_, _cmd);
if (target && target !== self)
{
arguments[0] = target;
return objj_msgSend.apply(this, arguments);
}
}
implementation = isa.method_dtable[SEL_methodSignatureForSelector_];
if (implementation)
{
var forwardInvocationImplementation = isa.method_dtable[SEL_forwardInvocation_];
if (forwardInvocationImplementation)
{
var signature = implementation.method_imp.call(this, self, SEL_methodSignatureForSelector_, _cmd);
if (signature)
{
var invocationClass = objj_lookUpClass("CPInvocation");
if (invocationClass)
{
var invocation = objj_msgSend(invocationClass, SEL_invocationWithMethodSignature_, signature),
index = 0,
count = arguments.length;
for (; index < count; ++index)
objj_msgSend(invocation, SEL_setArgument_atIndex_, arguments[index], index);
forwardInvocationImplementation.method_imp.call(this, self, SEL_forwardInvocation_, invocation);
return objj_msgSend(invocation, SEL_returnValue);
}
}
}
}
implementation = isa.method_dtable[SEL_doesNotRecognizeSelector_];
if (implementation)
return implementation.method_imp.call(this, self, SEL_doesNotRecognizeSelector_, _cmd);
throw class_getName(isa) + " does not implement doesNotRecognizeSelector:. Did you forget a superclass for " + class_getName(isa) + "?";
};
// I think this forward:: may need to be a common method, instead of defined in CPObject.
#define CLASS_GET_METHOD_IMPLEMENTATION(aMethodImplementation, aClass, aSelector)\
@@ -354,10 +405,7 @@ var _objj_forward = new objj_method("forward", function(self, _cmd)
\
var method = aClass.method_dtable[aSelector];\
\
if (!method)\
method = _objj_forward;\
\
aMethodImplementation = method.method_imp;
aMethodImplementation = method ? method.method_imp : _objj_forward;
GLOBAL(class_getMethodImplementation) = function(/*Class*/ aClass, /*SEL*/ aSelector)
{
@@ -657,3 +705,27 @@ GLOBAL(sel_registerName) = function(/*String*/ aName)
}
DISPLAY_NAME(sel_registerName);
objj_class.prototype.toString = objj_object.prototype.toString = function()
{
var isa = this.isa;
if (class_getInstanceMethod(isa, SEL_description))
return objj_msgSend(this, SEL_description);
if (class_isMetaClass(isa))
return this.name;
return "[" + isa.name + " Object](-description not implemented)";
}
var SEL_description = sel_getUid("description"),
SEL_forwardingTargetForSelector_ = sel_getUid("forwardingTargetForSelector:"),
SEL_methodSignatureForSelector_ = sel_getUid("methodSignatureForSelector:"),
SEL_forwardInvocation_ = sel_getUid("forwardInvocation:"),
SEL_doesNotRecognizeSelector_ = sel_getUid("doesNotRecognizeSelector:"),
SEL_invocationWithMethodSignature_ = sel_getUid("invocationWithMethodSignature:"),
SEL_setTarget_ = sel_getUid("setTarget:"),
SEL_setSelector_ = sel_getUid("setSelector:"),
SEL_setArgument_atIndex_ = sel_getUid("setArgument:atIndex:"),
SEL_returnValue = sel_getUid("returnValue");
+10 -1
View File
@@ -8,12 +8,18 @@
/*
Ensure that we have no canvas nor vml support.
*/
[self assert:YES equals:!CPFeatureIsCompatible(CPHTMLCanvasFeature)];
if (system.engine !== "jsc")
{
[self assert:YES equals:!CPFeatureIsCompatible(CPHTMLCanvasFeature)];
}
[self assert:YES equals:!CPFeatureIsCompatible(CPVMLFeature)];
}
- (void)testGStateCreate
{
if (CPFeatureIsCompatible(CPHTMLCanvasFeature))
return;
var gstate = CGGStateCreate(),
testdata = { alpha: 1.0,
strokeStyle: "#000",
@@ -41,6 +47,9 @@
- (void)testGStateCreateCopy
{
if (CPFeatureIsCompatible(CPHTMLCanvasFeature))
return;
var gstate = CGGStateCreate(),
gstatecopy = CGGStateCreateCopy(gstate),
testdata = { alpha: 1.0,
+85 -14
View File
@@ -2,16 +2,17 @@
@import <Foundation/CPPredicate.j>
@import <AppKit/CPArrayController.j>
var ELEMENTS = 200,
REPEATS = 25;
@implementation CPArrayControllerPerformance : OJTestCase
- (void)testRearrangeObjects
- (CPArrayController)setupWithElements:(int)aCount
{
var ELEMENTS = 200,
REPEATS = 25,
ac = [CPArrayController new],
var ac = [CPArrayController new],
array = [];
for (var i = 0; i < ELEMENTS; i++)
for (var i = 0; i < aCount; i++)
{
var s = [Sortable new];
[s setA:i];
@@ -19,15 +20,17 @@
array.push(s);
}
var descriptors = [
[CPSortDescriptor sortDescriptorWithKey:"a" ascending:NO],
];
[ac setContent:array];
[ac setFilterPredicate:[CPPredicate predicateWithFormat:@"(b != %@)", 0]];
return ac;
}
- (void)testRearrangeObjects
{
var ac = [self setupWithElements:ELEMENTS];
// Filter alone
var start = (new Date).getTime();
for (var i = 0; i < REPEATS; i++)
@@ -41,7 +44,7 @@
for (var j = 0, count = [sorted count]; j < count; j++)
{
if (sorted[j].b == 0)
[self fail:"b == 0 should be filtered out (position: "+j+")"];
[self fail:"b == 0 should be filtered out (position: " + j + ")"];
last = sorted[j];
}
}
@@ -49,7 +52,9 @@
CPLog.warn("testRearrangeObjects, filter: "+(end-start)+"ms");
[ac setSortDescriptors:descriptors];
[ac setSortDescriptors:[
[CPSortDescriptor sortDescriptorWithKey:"a" ascending:NO],
]];
// Filter and sort.
start = (new Date).getTime();
@@ -64,9 +69,9 @@
for (var j = 0, count = [sorted count]; j < count; j++)
{
if (sorted[j].b == 0)
[self fail:"b == 0 should be filtered out (position: "+j+")"];
[self fail:"b == 0 should be filtered out (position: " + j + ")"];
if (sorted[j].a >= last)
[self fail:"array values should be descending (position: "+j+")"];
[self fail:"array values should be descending (position: " + j + ")"];
last = sorted[j];
}
}
@@ -75,6 +80,64 @@
CPLog.warn("testRearrangeObjects, filter and sort: "+(end-start)+"ms");
}
- (void)testAddObject_
{
var ac = [self setupWithElements:ELEMENTS],
predicate = [ac filterPredicate],
content = [[ac content] copy];
// Add object while clearing the predicate.
[ac setClearsFilterPredicateOnInsertion:YES];
[ac setSortDescriptors:[
[CPSortDescriptor sortDescriptorWithKey:"a" ascending:NO],
]];
var start = (new Date).getTime();
for (var i = 0; i < REPEATS / 2; i++)
{
[ac setFilterPredicate:predicate];
[ac addObject:[Sortable sortableWithA:i B:i * 2]];
var sorted = [ac arrangedObjects],
last = ELEMENTS;
// Verify that all is well.
for (var j = 0, count = [sorted count]; j < count; j++)
{
if (sorted[j].a >= last)
[self fail:"array values should be descending (position: " + j + ")"];
last = sorted[j];
}
}
var end = (new Date).getTime();
CPLog.warn("testAddObject_, sorted, clear filter on insert: " + (end - start) + "ms");
[ac setClearsFilterPredicateOnInsertion:NO];
[ac setFilterPredicate:predicate];
var start = (new Date).getTime();
for (var i = 0; i < REPEATS; i++)
{
[ac addObject:[Sortable sortableWithA:i B:i % 3]];
var sorted = [ac arrangedObjects],
last = ELEMENTS;
// Verify that all is well.
for (var j = 0, count = [sorted count]; j < count; j++)
{
if (sorted[j].b == 0)
[self fail:"b == 0 should be filtered out (position: " + j + ")"];
if (sorted[j].a >= last)
[self fail:"array values should be descending (position: " + j + ")"];
last = sorted[j];
}
}
var end = (new Date).getTime();
CPLog.warn("testAddObject_, sorted, filtered: " + (end - start) + "ms");
}
@end
@implementation Sortable : CPObject
@@ -83,4 +146,12 @@
int b @accessors;
}
+ (id)sortableWithA:(int)anA B:(int)aB
{
var r = [Sortable new];
r.a = anA;
r.b = aB;
return r;
}
@end
+26
View File
@@ -412,6 +412,32 @@
[self assert:newSelection equals:[arrayController selectionIndexes] message:@"selection was not set properly"];
}
- (void)testObservationDuringAddObject_
{
var arrayController = [self arrayController];
[arrayController addObserver:self forKeyPath:@"arrangedObjects" options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:nil];
// Add something to clear.
[arrayController setFilterPredicate:[CPPredicate predicateWithFormat:@"(name != %@)", "Francisco"]];
observations = [];
var aPerson = [Employee employeeWithName:@"Alexander" department:[Department departmentWithName:@"Cosmic Path Finding"]];
[arrayController setClearsFilterPredicateOnInsertion:NO];
[self assert:0 equals:[observations count] message:@"no observations before addObject test"];
[arrayController addObject:aPerson];
[self assert:1 equals:[observations count] message:@"exactly 1 notification for addObject (clearsFilterPredicate NO)"];
observations = [];
// Even that this is on, adding an object should only result in one notification.
[arrayController setClearsFilterPredicateOnInsertion:YES];
[self assert:0 equals:[observations count] message:@"no observations before addObject test"];
[arrayController addObject:aPerson];
[self assert:1 equals:[observations count] message:@"exactly 1 notification for addObject (clearsFilterPredicate YES)"];
}
- (void)testCompoundKeyPaths
{
var departmentNameField = [[CPTextField alloc] init];
@@ -43,7 +43,7 @@ var CPMenuValidatedUserInterfaceItemTestValidatedItems = [];
var parentItem = [[self menu] itemWithTitle:@"parent"];
[self assertTrue:[parentItem isEnabled] message:@"Parent items should never be disabled"];
[self assertFalse:[[[self menuTarget] validatedItems] containsObject:parent] message:@"Parent items should never be validated"];
[self assertFalse:[[[self menuTarget] validatedItems] containsObject:parentItem] message:@"Parent items should never be validated"];
}
@end
+13 -1
View File
@@ -2,7 +2,6 @@
@import <Foundation/Foundation.j>
@import "CPArrayTest.j"
@implementation CPMutableArrayTest : CPArrayTest
+ (Class)arrayClass
@@ -448,6 +447,19 @@
[self assert:[5, 4, 4, 3, 2, 2, 1, 1, 1, 1] equals:target];
}
- (void)testMutableCopy
{
var normalArray = [CPArray array];
[self assertThrows:function () { [array addObject:[CPNull null]] }];
var mutableArray = [normalArray mutableCopy];
[mutableArray addObject:[CPNull null]];
[self assert:1 equals:[mutableArray count] message:"mutable copy should have content"];
}
@end
@implementation CPPrettyObject : CPObject
+22
View File
@@ -189,6 +189,28 @@
[self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"];
}
- (void)testBeginsWithEndsWithPredicate
{
// This always worked
var data = ["To", "Tom", "Tomb", "Tomboy"],
pred = [CPPredicate predicateWithFormat:@"SELF beginsWith 'To'"],
result = [data filteredArrayUsingPredicate:pred];
[self assertTrue:result.length === 4 message:"'" + [pred description] + "' should return [\"To\", \"Tom\", \"Tomb\", \"Tomboy\"]"];
// Make sure beginsWith comparison string longer than source strings works
pred = [CPPredicate predicateWithFormat:@"SELF beginsWith 'Tomb'"];
result = [data filteredArrayUsingPredicate:pred];
[self assertTrue:[result isEqual:["Tomb", "Tomboy"]] message:"'" + [pred description] + "' should return [\"Tomb\", \"Tomboy\"]"];
// Make sure endsWith comparison string longer than source strings works
pred = [CPPredicate predicateWithFormat:@"SELF endsWith 'boy'"];
result = [data filteredArrayUsingPredicate:pred];
[self assertTrue:[result isEqual:["Tomboy"]] message:"'" + [pred description] + "' should return [\"Tomboy\"]"];
}
- (void)testNilComparisons
{
// Custom Selector Predicate
@@ -0,0 +1,30 @@
/*
* AppController.j
* CPLevelIndicator
*
* Created by Alexander Ljungberg on May 28, 2011.
* Copyright 2011, WireLoad All rights reserved.
*/
@import <Foundation/CPObject.j>
@implementation AppController : CPObject
{
CPWindow theWindow; //this "outlet" is connected automatically by the Cib
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
}
- (void)awakeFromCib
{
// This is called when the cib is done loading.
// You can implement this method on any object instantiated from a Cib.
// It's a useful hook for setting up current UI values, and other things.
}
@end
+10
View File
@@ -0,0 +1,10 @@
<?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>CPLevelIndicator</string>
</dict>
</plist>
+94
View File
@@ -0,0 +1,94 @@
/*
* Jakefile
* CPLevelIndicator
*
* Created by Alexander Ljungberg on May 28, 2011.
* Copyright 2011, WireLoad 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 ("CPLevelIndicator", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "CPLevelIndicator.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPLevelIndicator");
task.setIdentifier("com.yourcompany.CPLevelIndicator");
task.setVersion("1.0");
task.setAuthor("WireLoad");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPLevelIndicator");
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", ["CPLevelIndicator"], 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", "CPLevelIndicator", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "CPLevelIndicator", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "CPLevelIndicator"));
OS.system(["press", "-f", FILE.join("Build", "Release", "CPLevelIndicator"), FILE.join("Build", "Deployment", "CPLevelIndicator")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "CPLevelIndicator"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPLevelIndicator"), FILE.join("Build", "Desktop", "CPLevelIndicator", "CPLevelIndicator.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "CPLevelIndicator", "CPLevelIndicator.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPLevelIndicator"));
print("----------------------------");
}
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.8 KiB

@@ -0,0 +1,103 @@
<!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
CPLevelIndicator
Created by Alexander Ljungberg on May 28, 2011.
Copyright 2011, WireLoad All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, 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>CPLevelIndicator</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 CPLevelIndicator...</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>
+77
View File
@@ -0,0 +1,77 @@
<!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
CPLevelIndicator
Created by Alexander Ljungberg on May 28, 2011.
Copyright 2011, WireLoad All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, 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>CPLevelIndicator</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 CPLevelIndicator...</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
* CPLevelIndicator
*
* Created by Alexander Ljungberg on May 28, 2011.
* Copyright 2011, WireLoad All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
@@ -0,0 +1,193 @@
/*
* 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;
CPPredicateEditor 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];
[predicateEditor setAction:@selector(predicateEditorAction:)];
[predicateEditor setTarget:self];
[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
{
// CPLogConsole(_cmd + [predicateEditor displayValuesForRow:1]);
[predicateField setStringValue:[[predicateEditor objectValue] predicateFormat]];
}
- (void)ruleEditorRowsDidChange:(CPNotification)notification
{
}
// 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,32 @@
/*
* AppController.j
* CPUserDefaultsControllerTest
*
* Created by Alexander Ljungberg on May 30, 2011.
* Copyright 2011, WireLoad All rights reserved.
*/
@import <Foundation/CPObject.j>
@implementation AppController : CPObject
{
CPWindow theWindow; //this "outlet" is connected automatically by the Cib
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
}
- (void)awakeFromCib
{
// This is called when the cib is done loading.
// You can implement this method on any object instantiated from a Cib.
// It's a useful hook for setting up current UI values, and other things.
// In this case, we want the window from Cib to become our full browser window
[theWindow setFullPlatformWindow:YES];
}
@end
@@ -0,0 +1,10 @@
<?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>CPUserDefaultsControllerTest</string>
</dict>
</plist>
@@ -0,0 +1,94 @@
/*
* Jakefile
* CPUserDefaultsControllerTest
*
* Created by Alexander Ljungberg on May 30, 2011.
* Copyright 2011, WireLoad 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 ("CPUserDefaultsControllerTest", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "CPUserDefaultsControllerTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPUserDefaultsControllerTest");
task.setIdentifier("com.yourcompany.CPUserDefaultsControllerTest");
task.setVersion("1.0");
task.setAuthor("WireLoad");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPUserDefaultsControllerTest");
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", ["CPUserDefaultsControllerTest"], 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", "CPUserDefaultsControllerTest", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "CPUserDefaultsControllerTest", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "CPUserDefaultsControllerTest"));
OS.system(["press", "-f", FILE.join("Build", "Release", "CPUserDefaultsControllerTest"), FILE.join("Build", "Deployment", "CPUserDefaultsControllerTest")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "CPUserDefaultsControllerTest"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPUserDefaultsControllerTest"), FILE.join("Build", "Desktop", "CPUserDefaultsControllerTest", "CPUserDefaultsControllerTest.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "CPUserDefaultsControllerTest", "CPUserDefaultsControllerTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPUserDefaultsControllerTest"));
print("----------------------------");
}
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More