mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
Merge branch 'master' of github.com:280north/cappuccino into eventualbuddha-CPTokenField-sendAction-fix
Conflicts: AppKit/CPTokenField.j
This commit is contained in:
@@ -394,7 +394,8 @@
|
||||
|
||||
// Push back the new selection to the model for selectionIndexes if we have one.
|
||||
// There won't be an infinite loop because of the equality check above.
|
||||
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
|
||||
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+4
-1
@@ -203,7 +203,7 @@ CPButtonImageOffset = 3.0;
|
||||
else if (![anObjectValue isKindOfClass:[CPNumber class]])
|
||||
anObjectValue = CPOnState;
|
||||
|
||||
else if (anObjectValue > CPOnState)
|
||||
else if (anObjectValue >= CPOnState)
|
||||
anObjectValue = CPOnState
|
||||
|
||||
else if (anObjectValue < CPOffState)
|
||||
@@ -255,6 +255,9 @@ CPButtonImageOffset = 3.0;
|
||||
*/
|
||||
- (void)setNextState
|
||||
{
|
||||
if ([self infoForBinding:CPValueBinding])
|
||||
[self setAllowsMixedState:NO];
|
||||
|
||||
[self setState:[self nextState]];
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,14 @@ CPCheckBoxImageOffset = 4.0;
|
||||
return @"check-box";
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
if (theBinding === CPValueBinding)
|
||||
return [_CPCheckBoxValueBinder class];
|
||||
|
||||
return [super _binderClassForBinding:theBinding];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
@@ -87,3 +95,53 @@ CPCheckBoxImageOffset = 4.0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPCheckBoxValueBinder : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)theBinding
|
||||
{
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [destination valueForKeyPath:keyPath],
|
||||
isPlaceholder = CPIsControllerMarker(newValue);
|
||||
|
||||
if (isPlaceholder)
|
||||
{
|
||||
switch (newValue)
|
||||
{
|
||||
case CPMultipleValuesMarker:
|
||||
newValue = CPMixedState;
|
||||
break;
|
||||
|
||||
case CPNoSelectionMarker:
|
||||
newValue = CPOffState;
|
||||
break;
|
||||
|
||||
case CPNotApplicableMarker:
|
||||
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
|
||||
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
|
||||
|
||||
newValue = CPOffState;
|
||||
break;
|
||||
}
|
||||
|
||||
if (newValue === CPMixedState)
|
||||
{
|
||||
[_source setAllowsMixedState:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cocoa will always set allowsMixedState to NO
|
||||
// This behavior will be fine for Cappuccino as well if we (like Cocoa)
|
||||
// default the CPConditionallySetsEnabledBindingOption to YES
|
||||
[_source setAllowsMixedState:NO];
|
||||
}
|
||||
}
|
||||
|
||||
[_source setState:newValue];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -312,7 +312,8 @@
|
||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||
[_items[index] setSelected:YES];
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
|
||||
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
||||
[_delegate collectionViewDidChangeSelection:self];
|
||||
|
||||
+9
-7
@@ -141,18 +141,20 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
if (theBinding === CPValueBinding)
|
||||
return [_CPValueBinder class];
|
||||
|
||||
return [super _binderClassForBinding:theBinding];
|
||||
}
|
||||
|
||||
- (void)_replacementKeyPathForBinding:(CPString)aBinding
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
if (aBinding === @"value")
|
||||
return @"objectValue";
|
||||
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
|
||||
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
|
||||
|
||||
return [super _replacementKeyPathForBinding:aBinding];
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
|
||||
+42
-40
@@ -35,7 +35,7 @@ var exposedBindingsMap = [CPDictionary new],
|
||||
var CPBindingOperationAnd = 0,
|
||||
CPBindingOperationOr = 1;
|
||||
|
||||
@implementation CPKeyValueBinding : CPObject
|
||||
@implementation CPBinder : CPObject
|
||||
{
|
||||
CPDictionary _info;
|
||||
id _source;
|
||||
@@ -59,7 +59,7 @@ var CPBindingOperationAnd = 0,
|
||||
return [[exposedBindingsMap objectForKey:[aClass UID]] copy];
|
||||
}
|
||||
|
||||
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
|
||||
+ (CPBinder)getBinding:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
return [[bindingsMap objectForKey:[anObject UID]] objectForKey:aBinding];
|
||||
}
|
||||
@@ -147,39 +147,10 @@ var CPBindingOperationAnd = 0,
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [destination valueForKeyPath:keyPath],
|
||||
isPlaceholder = CPIsControllerMarker(newValue);
|
||||
|
||||
if (isPlaceholder)
|
||||
{
|
||||
switch (newValue)
|
||||
{
|
||||
case CPMultipleValuesMarker:
|
||||
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
|
||||
break;
|
||||
|
||||
case CPNoSelectionMarker:
|
||||
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
|
||||
break;
|
||||
|
||||
case CPNotApplicableMarker:
|
||||
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
|
||||
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
|
||||
|
||||
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only transform the value if the current value is not a placeholder
|
||||
newValue = [self transformValue:newValue withOptions:options];
|
||||
}
|
||||
newValue = [destination valueForKeyPath:keyPath];
|
||||
|
||||
newValue = [self transformValue:newValue withOptions:options];
|
||||
[_source setValue:newValue forKey:aBinding];
|
||||
|
||||
if (aBinding === @"objectValue" && [_source respondsToSelector:@selector(_setCurrentValueIsPlaceholder:)])
|
||||
[_source _setCurrentValueIsPlaceholder:isPlaceholder];
|
||||
}
|
||||
|
||||
- (void)reverseSetValueFor:(CPString)aBinding
|
||||
@@ -259,7 +230,13 @@ var CPBindingOperationAnd = 0,
|
||||
|
||||
+ (void)exposeBinding:(CPString)aBinding
|
||||
{
|
||||
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
|
||||
[CPBinder exposeBinding:aBinding forClass:[self class]];
|
||||
}
|
||||
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
return [CPBinder class];
|
||||
}
|
||||
|
||||
- (CPArray)exposedBindings
|
||||
@@ -269,7 +246,7 @@ var CPBindingOperationAnd = 0,
|
||||
|
||||
while (theClass)
|
||||
{
|
||||
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
|
||||
var temp = [CPBinder exposedBindingsForClass:theClass];
|
||||
|
||||
if (temp)
|
||||
[exposedBindings addObjectsFromArray:temp];
|
||||
@@ -293,18 +270,21 @@ var CPBindingOperationAnd = 0,
|
||||
//if (![[self exposedBindings] containsObject:aBinding])
|
||||
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
|
||||
|
||||
var binderClass = [[self class] _binderClassForBinding:aBinding];
|
||||
|
||||
[self unbind:aBinding];
|
||||
[[CPKeyValueBinding alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
|
||||
[[binderClass alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
|
||||
}
|
||||
|
||||
- (CPDictionary)infoForBinding:(CPString)aBinding
|
||||
{
|
||||
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
|
||||
return [CPBinder infoForBinding:aBinding forObject:self];
|
||||
}
|
||||
|
||||
- (void)unbind:(CPString)aBinding
|
||||
{
|
||||
[CPKeyValueBinding unbind:aBinding forObject:self];
|
||||
var binderClass = [[self class] _binderClassForBinding:aBinding];
|
||||
[binderClass unbind:aBinding forObject:self];
|
||||
}
|
||||
|
||||
- (id)_replacementKeyPathForBinding:(CPString)binding
|
||||
@@ -314,7 +294,29 @@ var CPBindingOperationAnd = 0,
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
|
||||
/*!
|
||||
@ignore
|
||||
Provides stub implementations that simply call super for the "objectValue" binding
|
||||
This class should not be necessary but assures backwards compliance with our old way of doing bindings
|
||||
Every class with a value binding should implement a subclass to handle it's specific value binding logic
|
||||
*/
|
||||
@implementation _CPValueBinder : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)theBinding
|
||||
{
|
||||
[super setValueFor:@"objectValue"];
|
||||
}
|
||||
|
||||
- (void)reverseSetValueFor:(CPString)theBinding
|
||||
{
|
||||
[super reverseSetValueFor:@"objectValue"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPKeyValueOrBinding : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
@@ -335,7 +337,7 @@ var CPBindingOperationAnd = 0,
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
|
||||
@implementation _CPKeyValueAndBinding : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,8 @@
|
||||
{
|
||||
[self setContent:anObject];
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
var binderClass = [[self class] _binderClassForBinding:@"contentObject"];
|
||||
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
- (void)removeObject:(id)anObject
|
||||
@@ -145,7 +146,8 @@
|
||||
if ([self content] === anObject)
|
||||
[self setContent:nil];
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
var binderClass = [[self class] _binderClassForBinding:@"contentObject"];
|
||||
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
- (void)add:(id)aSender
|
||||
|
||||
@@ -62,6 +62,11 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
return [CPBinder class];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
@@ -507,7 +512,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
|
||||
{
|
||||
var bindingsDictionary = [CPKeyValueBinding allBindingsForObject:self],
|
||||
var bindingsDictionary = [CPBinder allBindingsForObject:self],
|
||||
keys = [bindingsDictionary allKeys];
|
||||
|
||||
for (var i = 0, count = [keys count]; i < count; i++)
|
||||
@@ -547,9 +552,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
value = [binding transformValue:value withOptions:[bindingInfo objectForKey:CPOptionsKey]];
|
||||
|
||||
// console.log(bindingName+" : "+keyPath+" : "+aRow+" : "+[[destination valueForKeyPath:keyPath] objectAtIndex:aRow]);
|
||||
[aDataView setValue:value forKey:bindingPath];
|
||||
[aDataView setValue:value forKey:@"objectValue"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-9
@@ -1078,7 +1078,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self setNeedsDisplay:YES]; // FIXME: should be setNeedsDisplayInRect:enclosing rect of new (de)selected rows
|
||||
// but currently -drawRect: is not implemented here
|
||||
|
||||
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectedRowIndexes"];
|
||||
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
|
||||
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectedRowIndexes"];
|
||||
|
||||
[self _noteSelectionDidChange];
|
||||
}
|
||||
@@ -2053,18 +2054,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
if (!(_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_))
|
||||
var height = (_rowHeight + _intercellSpacing.height) * _numberOfRows;
|
||||
else if ([self numberOfRows] === 0)
|
||||
var height = 0;
|
||||
else
|
||||
{
|
||||
// if this is the fist run we need to populate the cache
|
||||
if ([self numberOfRows] !== _cachedRowHeights.length)
|
||||
[self noteHeightOfRowsWithIndexesChanged:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfRows])]];
|
||||
|
||||
var heightObject = _cachedRowHeights[_cachedRowHeights.length - 1];
|
||||
|
||||
if (heightObject)
|
||||
var heightObject = _cachedRowHeights[_cachedRowHeights.length - 1],
|
||||
height = heightObject.heightAboveRow + heightObject.height + _intercellSpacing.height;
|
||||
else
|
||||
height = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2082,6 +2082,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Scrolls the receiver vertically in an enclosing CPClipView so the row specified by rowIndex is visible.
|
||||
|
||||
@@ -2089,7 +2090,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)scrollRowToVisible:(int)rowIndex
|
||||
{
|
||||
[self scrollRectToVisible:[self rectOfRow:rowIndex]];
|
||||
var visible = [self visibleRect],
|
||||
rowRect = [self rectOfRow:rowIndex];
|
||||
|
||||
visible.origin.y = rowRect.origin.y;
|
||||
visible.size.height = rowRect.size.height;
|
||||
|
||||
[self scrollRectToVisible:visible];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2099,8 +2106,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)scrollColumnToVisible:(int)columnIndex
|
||||
{
|
||||
[self scrollRectToVisible:[self rectOfColumn:columnIndex]];
|
||||
/*FIX ME: tableview header isn't rendered until you click the horizontal scroller (or scroll)*/
|
||||
var visible = [self visibleRect],
|
||||
colRect = [self rectOfColumn:columnIndex];
|
||||
|
||||
visible.origin.x = colRect.origin.x;
|
||||
visible.size.width = colRect.size.width;
|
||||
|
||||
[self scrollRectToVisible:visible];
|
||||
[_headerView scrollRectToVisible:colRect];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
+54
-26
@@ -84,7 +84,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
CPColor _textFieldBackgroundColor;
|
||||
|
||||
id _placeholderString;
|
||||
id _originalPlaceholderString;
|
||||
BOOL _currentValueIsPlaceholder;
|
||||
|
||||
id _delegate;
|
||||
@@ -160,6 +159,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return "textfield";
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
if (theBinding === CPValueBinding)
|
||||
return [_CPTextFieldValueBinder class];
|
||||
|
||||
return [super _binderClassForBinding:theBinding];
|
||||
}
|
||||
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), [CPNull null]]
|
||||
@@ -733,6 +740,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Sets the internal string value without updating the value in the input element
|
||||
*/
|
||||
- (void)_setStringValue:(id)aValue
|
||||
{
|
||||
@@ -792,30 +800,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return _placeholderString;
|
||||
}
|
||||
|
||||
- (void)_setCurrentValueIsPlaceholder:(BOOL)isPlaceholder
|
||||
{
|
||||
if (isPlaceholder)
|
||||
{
|
||||
// Save the original placeholder value so we can restore it later
|
||||
// Only do this if the placeholder is not already overridden because the bindings logic might call this method
|
||||
// several times and we don't want the bindings placeholder to ever become the original placeholder
|
||||
if (!_currentValueIsPlaceholder)
|
||||
_originalPlaceholderString = [self placeholderString];
|
||||
|
||||
// Set the current string value as the current placeholder and clear the string value
|
||||
[self setPlaceholderString:[self stringValue]];
|
||||
[self setStringValue:@""];
|
||||
}
|
||||
else if (_originalPlaceholderString)
|
||||
{
|
||||
// Restore the original placeholder, the actual textfield value is already correct
|
||||
// because it was set using setValue:forKey:
|
||||
[self setPlaceholderString:_originalPlaceholderString];
|
||||
}
|
||||
|
||||
_currentValueIsPlaceholder = isPlaceholder;
|
||||
}
|
||||
|
||||
/*!
|
||||
For non-bezeled text fields (typically a label), sizeToFit has two behaviors, depending
|
||||
on the line break mode of the receiver.
|
||||
@@ -1270,7 +1254,6 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
[self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
|
||||
|
||||
[self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1299,3 +1282,48 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPTextFieldValueBinder : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)theBinding
|
||||
{
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [destination valueForKeyPath:keyPath],
|
||||
isPlaceholder = CPIsControllerMarker(newValue);
|
||||
|
||||
if (isPlaceholder)
|
||||
{
|
||||
switch (newValue)
|
||||
{
|
||||
case CPMultipleValuesMarker:
|
||||
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
|
||||
break;
|
||||
|
||||
case CPNoSelectionMarker:
|
||||
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
|
||||
break;
|
||||
|
||||
case CPNotApplicableMarker:
|
||||
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
|
||||
[CPException raise:CPGenericException
|
||||
reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
|
||||
|
||||
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
|
||||
break;
|
||||
}
|
||||
|
||||
[_source setPlaceholderString:newValue];
|
||||
[_source setObjectValue:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = [self transformValue:newValue withOptions:options];
|
||||
[_source setObjectValue:newValue];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -264,7 +264,8 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
- (void)_controlTextDidChange
|
||||
{
|
||||
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
|
||||
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
|
||||
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
|
||||
|
||||
if (theBinding)
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
@import "CPMutableArray.j"
|
||||
|
||||
|
||||
var indexOf = Array.prototype.indexOf,
|
||||
join = Array.prototype.join,
|
||||
pop = Array.prototype.pop,
|
||||
push = Array.prototype.push,
|
||||
slice = Array.prototype.slice,
|
||||
splice = Array.prototype.splice;
|
||||
|
||||
@implementation _CPJavaScriptArray : CPMutableArray
|
||||
{
|
||||
}
|
||||
@@ -28,13 +35,13 @@
|
||||
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
return anArray.slice(0);
|
||||
return slice.call(anArray, 0);
|
||||
}
|
||||
|
||||
- (id)initWithArray:(CPArray)anArray copyItems:(BOOL)shouldCopyItems
|
||||
{
|
||||
if (!shouldCopyItems)
|
||||
return anArray.slice(0);
|
||||
return slice.call(anArray, 0);
|
||||
|
||||
self = [super init];
|
||||
|
||||
@@ -76,19 +83,19 @@
|
||||
if (arguments[index] === nil)
|
||||
break;
|
||||
|
||||
return Array.prototype.slice.call(arguments, 2, index);
|
||||
return slice.call(arguments, 2, index);
|
||||
}
|
||||
|
||||
- (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
|
||||
{
|
||||
if (objects.isa === _CPJavaScriptArray)
|
||||
return objects.slice(0);
|
||||
return slice.call(objects, 0);
|
||||
|
||||
var array = [],
|
||||
index = 0;
|
||||
|
||||
for (; index < aCount; ++index)
|
||||
array.push([objects objectAtIndex:index]);
|
||||
push.call(array, [objects objectAtIndex:index]);
|
||||
|
||||
return array;
|
||||
}
|
||||
@@ -106,11 +113,6 @@
|
||||
return self[anIndex];
|
||||
}
|
||||
|
||||
- (CPUInteger)indexOfObject:(id)anObject
|
||||
{
|
||||
return [self indexOfObject:anObject inRange:nil];
|
||||
}
|
||||
|
||||
- (CPUInteger)indexOfObject:(id)anObject inRange:(CPRange)aRange
|
||||
{
|
||||
// Only use isEqual: if our object is a CPObject.
|
||||
@@ -129,15 +131,10 @@
|
||||
return [self indexOfObjectIdenticalTo:anObject inRange:aRange];
|
||||
}
|
||||
|
||||
- (CPUInteger)indexOfObjectIdenticalTo:(id)anObject
|
||||
{
|
||||
return [self indexOfObjectIdenticalTo:anObject inRange:nil];
|
||||
}
|
||||
|
||||
- (CPUInteger)indexOfObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange
|
||||
{
|
||||
if (self.indexOf)
|
||||
return self.indexOf(anObject);
|
||||
if (indexOf && !aRange)
|
||||
return indexOf.call(self, anObject);
|
||||
|
||||
var index = aRange ? aRange.location : 0,
|
||||
count = aRange ? CPMaxRange(aRange) : self.length;
|
||||
@@ -179,32 +176,32 @@
|
||||
if (aRange.location < 0 || CPMaxRange(aRange) > self.length)
|
||||
[CPException raise:CPRangeException reason:"subarrayWithRange: aRange out of bounds"];
|
||||
|
||||
return self.slice(aRange.location, CPMaxRange(aRange));
|
||||
return slice.call(self, aRange.location, CPMaxRange(aRange));
|
||||
}
|
||||
|
||||
- (CPString)componentsJoinedByString:(CPString)aString
|
||||
{
|
||||
return self.join(aString);
|
||||
return join.call(self, aString);
|
||||
}
|
||||
|
||||
- (void)insertObject:(id)anObject atIndex:(CPUInteger)anIndex
|
||||
{
|
||||
self.splice(anIndex, 0, anObject);
|
||||
splice.call(self, anIndex, 0, anObject);
|
||||
}
|
||||
|
||||
- (void)removeObjectAtIndex:(CPUInteger)anIndex
|
||||
{
|
||||
self.splice(anIndex, 1);
|
||||
splice.call(self, anIndex, 1);
|
||||
}
|
||||
|
||||
- (void)addObject:(id)anObject
|
||||
{
|
||||
self.push(anObject);
|
||||
push.call(self, anObject);
|
||||
}
|
||||
|
||||
- (void)removeLastObject
|
||||
{
|
||||
self.pop();
|
||||
pop.call(self);
|
||||
}
|
||||
|
||||
- (void)replaceObjectAtIndex:(int)anIndex withObject:(id)anObject
|
||||
@@ -214,7 +211,7 @@
|
||||
|
||||
- (void)copy
|
||||
{
|
||||
return self.slice(0);
|
||||
return slice.call(self, 0);
|
||||
}
|
||||
|
||||
- (Class)classForCoder
|
||||
|
||||
@@ -132,3 +132,5 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@import "_CPConcreteMutableSet.j"
|
||||
|
||||
@@ -316,7 +316,7 @@
|
||||
objectEnumerator = [self objectEnumerator];
|
||||
|
||||
while ((object = [objectEnumerator nextObject]) !== nil)
|
||||
if (![self containsObject:object])
|
||||
if (![aSet containsObject:object])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
@@ -459,4 +459,6 @@ var _CPSharedPlaceholderSet = nil;
|
||||
|
||||
@end
|
||||
|
||||
@import "_CPConcreteMutableSet.j"
|
||||
// We actually want _CPConcreteMutableSet, but this introduces the possibility of an invalid @import loop.
|
||||
// This will be correctly solved when we move to true immutable/mutable pairs.
|
||||
@import "CPMutableSet.j"
|
||||
|
||||
@@ -173,11 +173,11 @@
|
||||
var testView = [DataViewTester new];
|
||||
[tableColumn prepareDataView:testView forRow:0];
|
||||
[self assert:'1' equals:testView.lastValue];
|
||||
[self assert:'value' equals:testView.lastKey];
|
||||
[self assert:'objectValue' equals:testView.lastKey];
|
||||
|
||||
[tableColumn prepareDataView:testView forRow:1];
|
||||
[self assert:'3' equals:testView.lastValue];
|
||||
[self assert:'value' equals:testView.lastKey];
|
||||
[self assert:'objectValue' equals:testView.lastKey];
|
||||
|
||||
// Test that CPTableColumn is optimized to only read one value per row.
|
||||
[self assert:0 equals:[content[2] accesses] message:"row 2 used "+[content[2] accesses]+" accesses but was never prepared"];
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
[tableColumn prepareDataView:testView forRow:1];
|
||||
[self assert:'old' equals:testView.lastValue];
|
||||
[self assert:'value' equals:testView.lastKey];
|
||||
[self assert:'objectValue' equals:testView.lastKey];
|
||||
}
|
||||
|
||||
- (void)testTextField
|
||||
@@ -215,16 +215,33 @@
|
||||
[textField bind:@"value" toObject:arrayController withKeyPath:@"selection.cheese" options:options];
|
||||
|
||||
[self assert:@"yellow" equals:[textField stringValue] message:@"text field string value should be 'yellow'"];
|
||||
[self assert:@"cheese" equals:[textField placeholderString] message:@"text field placeholder should be 'cheese'"];
|
||||
|
||||
[arrayController setSelectionIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 2)]];
|
||||
|
||||
[self assert:@"" equals:[textField stringValue] message:@"text field string value should be cleared"];
|
||||
[self assert:@"Multiple Values" equals:[textField placeholderString] message:@"text field placeholder should be 'Multiple Values'"];
|
||||
|
||||
[textField unbind:@"value"];
|
||||
// Cocoa doesn't do this
|
||||
// [self assert:@"cheese" equals:[textField placeholderString] message:@"text field placeholder should be reset"];
|
||||
|
||||
[textField bind:@"value" toObject:arrayController withKeyPath:@"selection.cheese" options:options];
|
||||
|
||||
[arrayController setSelectionIndex:0];
|
||||
[self assert:@"yellow" equals:[textField stringValue] message:"text field string value should be 'yellow'"];
|
||||
[self assert:@"cheese" equals:[textField placeholderString] message:"text field placeholder should be restored"];
|
||||
|
||||
// Cocoa doesn't do this
|
||||
// [self assert:@"cheese" equals:[textField placeholderString] message:"text field placeholder should be restored"];
|
||||
|
||||
textField = [[CPTextField alloc] init];
|
||||
[textField bind:@"value" toObject:arrayController withKeyPath:@"selection.cheese" options:options];
|
||||
[arrayController setSelectionIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 2)]];
|
||||
[self assert:@"Multiple Values" equals:[textField placeholderString] message:@"text field placeholder should 'Multiple Values'"];
|
||||
|
||||
// Cocoa doesn't do this
|
||||
// [arrayController setSelectionIndex:0];
|
||||
// [self assert:@"" equals:[textField placeholderString] message:@"empty text field placeholder should be restored"];
|
||||
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)aContext
|
||||
|
||||
@@ -196,6 +196,14 @@
|
||||
[self assertFalse:[set containsObject:nil]];
|
||||
}
|
||||
|
||||
- (void)testIsSubsetOfSet
|
||||
{
|
||||
var set = [CPSet setWithArray:[1, 2, 3, 4, 5]];
|
||||
[self assertTrue:[[CPSet setWithArray:[1, 2, 3]] isSubsetOfSet:set]];
|
||||
[self assertFalse:[[CPSet setWithArray:[1, 2, 3, 100]] isSubsetOfSet:set]];
|
||||
[self assertTrue:[[CPSet new] isSubsetOfSet:set]];
|
||||
}
|
||||
|
||||
- (void)testDescription
|
||||
{
|
||||
var set = [CPSet new];
|
||||
|
||||
Reference in New Issue
Block a user