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

Conflicts:
	Tests/Manual/CPTokenFieldTest/AppController.j
This commit is contained in:
Aparajita Fishman
2011-09-18 16:04:42 -07:00
14 changed files with 1538 additions and 402 deletions
+30 -3
View File
@@ -210,10 +210,25 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
if (shouldRemoveLastObject)
[objectValue removeObjectAtIndex:_selectedRange.location];
[objectValue insertObject:token atIndex:_selectedRange.location];
// Give the delegate a chance to confirm, replace or add to the list of tokens being added.
var delegateApprovedObjects = [self tokenField:self shouldAddObjects:[CPArray arrayWithObject:token] atIndex:_selectedRange.location],
delegateApprovedObjectsCount = [delegateApprovedObjects count];
if (delegateApprovedObjects)
{
for (var i = 0; i < delegateApprovedObjectsCount; i++)
{
[objectValue insertObject:[delegateApprovedObjects objectAtIndex:i] atIndex:_selectedRange.location + i];
}
}
// Put the cursor after the last inserted token.
var location = _selectedRange.location;
[self setObjectValue:objectValue];
_selectedRange = CPMakeRange(location + 1, 0);
if (delegateApprovedObjectsCount)
location += delegateApprovedObjectsCount;
_selectedRange = CPMakeRange(location, 0);
[self _inputElement].value = @"";
[self setNeedsLayout];
@@ -1175,7 +1190,19 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
// // return an array of represented objects you want to add.
// // If you want to reject the add, return an empty array.
// // returning nil will cause an error.
// - (NSArray *)tokenField:(NSTokenField *)tokenField shouldAddObjects:(NSArray *)tokens atIndex:(NSUInteger)index;
- (CPArray)tokenField:(CPTokenField)tokenField shouldAddObjects:(CPArray)tokens atIndex:(int)index
{
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
{
var approvedObjects = [delegate tokenField:tokenField shouldAddObjects:tokens atIndex:index];
if (approvedObjects !== nil)
return approvedObjects;
}
return tokens;
}
//
// // If you return nil or don't implement these delegate methods, we will assume
// // editing string = display string = represented object
+63 -14
View File
@@ -426,6 +426,7 @@ CPTexturedBackgroundWindowMask
// Create a generic content view.
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
[self setInitialFirstResponder:[self contentView]];
_firstResponder = self;
@@ -480,7 +481,7 @@ CPTexturedBackgroundWindowMask
[self close];
_platformWindow = aPlatformWindow;
[_platformWindow setTitle:_title];
[_platformWindow _setTitle:_title window:self];
if (wasVisible)
[self orderFront:self];
@@ -950,6 +951,12 @@ CPTexturedBackgroundWindowMask
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
// During init the initial first responder is set to the contentView
// if it hasn't changed in the mean time we need to update that reference
// to the new contentView
if ([self initialFirstResponder] === _contentView)
[self setInitialFirstResponder:aView];
_contentView = aView;
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
@@ -1274,17 +1281,17 @@ CPTexturedBackgroundWindowMask
- (BOOL)acceptsFirstResponder
{
return YES;
return NO;
}
- (id)initialFirstResponder
- (CPView)initialFirstResponder
{
return _initialFirstResponder;
}
- (void)setInitialFirstResponder:(id)aResponder
- (void)setInitialFirstResponder:(CPView)aView
{
_initialFirstResponder = aResponder;
_initialFirstResponder = aView;
}
/*!
@@ -1360,7 +1367,7 @@ CPTexturedBackgroundWindowMask
_title = aTitle;
[_windowView setTitle:aTitle];
[_platformWindow setTitle:_title];
[_platformWindow _setTitle:_title window:self];
[self _synchronizeMenuBarTitleWithWindowTitle];
}
@@ -2487,30 +2494,70 @@ CPTexturedBackgroundWindowMask
- (void)selectNextKeyView:(id)sender
{
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
var nextValidKeyView = nil;
if ([_firstResponder isKindOfClass:[CPView class]])
[self selectKeyViewFollowingView:_firstResponder];
nextValidKeyView = [_firstResponder nextValidKeyView];
if (!nextValidKeyView)
{
var initialFirstResponder = [self initialFirstResponder];
if ([initialFirstResponder acceptsFirstResponder])
nextValidKeyView = initialFirstResponder;
else
nextValidKeyView = [initialFirstResponder nextValidKeyView];
}
[self makeFirstResponder:nextValidKeyView];
}
- (void)selectPreviousKeyView:(id)sender
{
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
var previousValidKeyView = nil;
if ([_firstResponder isKindOfClass:[CPView class]])
[self selectKeyViewPrecedingView:_firstResponder];
previousValidKeyView = [_firstResponder previousValidKeyView];
if (!previousValidKeyView)
{
var initialFirstResponder = [self initialFirstResponder];
if ([initialFirstResponder acceptsFirstResponder])
previousValidKeyView = initialFirstResponder;
else
previousValidKeyView = [initialFirstResponder previousValidKeyView];
}
[self makeFirstResponder:previousValidKeyView];
}
- (void)selectKeyViewFollowingView:(CPView)aView
{
if (_keyViewLoopIsDirty)
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
[self makeFirstResponder:[aView nextValidKeyView]];
var nextValidKeyView = [aView nextValidKeyView];
if ([nextValidKeyView isKindOfClass:[CPView class]])
[self makeFirstResponder:nextValidKeyView];
}
- (void)selectKeyViewPrecedingView:(CPView)aView
{
if (_keyViewLoopIsDirty)
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
[self makeFirstResponder:[aView previousValidKeyView]];
var previousValidKeyView = [aView previousValidKeyView];
if ([previousValidKeyView isKindOfClass:[CPView class]])
[self makeFirstResponder:previousValidKeyView];
}
/*!
@@ -2598,9 +2645,11 @@ CPTexturedBackgroundWindowMask
var allViews = function(aWindow)
{
var views = [[aWindow contentView] subviews],
index = 0;
var views = [CPArray arrayWithObject:[aWindow contentView]];
[views addObjectsFromArray:[[aWindow contentView] subviews]];
var index = 0;
for (; index < views.length; ++index)
views = views.concat([views[index] subviews]);
+2 -2
View File
@@ -259,12 +259,12 @@ var PrimaryPlatformWindow = NULL;
return [CPPlatform isBrowser];
}
- (void)setTitle:(CPString)aTitle
- (void)_setTitle:(CPString)aTitle window:(CPWindow)aWindow
{
_title = aTitle;
#if PLATFORM(DOM)
if (_DOMWindow && _DOMWindow.document)
if (_DOMWindow && _DOMWindow.document && (aWindow === [CPApp mainWindow]))
_DOMWindow.document.title = _title;
#endif
}
+2 -1
View File
@@ -541,7 +541,8 @@ var ModifierKeyCodes = [
// FIXME: cpSetFrame?
_DOMWindow.document.write("<!DOCTYPE html><html lang='en'><head></head><body style='background-color:transparent;'></body></html>");
_DOMWindow.document.close();
_DOMWindow.document.title = _title;
if (self != [CPPlatformWindow primaryPlatformWindow])
_DOMWindow.document.title = _title;
if (![CPPlatform isBrowser])
{
+108 -19
View File
@@ -131,7 +131,7 @@
_replaceManySEL = sel_getName(@"replace" + capitalizedKey + "AtIndexes:with" + capitalizedKey + ":");
if ([_proxyObject respondsToSelector:_replaceManySEL])
_replace = [_proxyObject methodForSelector:_replaceManySEL];
_replaceMany = [_proxyObject methodForSelector:_replaceManySEL];
_objectAtIndexSEL = sel_getName(@"objectIn" + capitalizedKey + "AtIndex:");
if ([_proxyObject respondsToSelector:_objectAtIndexSEL])
@@ -233,10 +233,25 @@
- (id)objectAtIndex:(unsigned)anIndex
{
if (_objectAtIndex)
return _objectAtIndex(_proxyObject, _objectAtIndexSEL, anIndex);
return [[self objectsAtIndexes:[CPIndexSet indexSetWithIndex:anIndex]] firstObject];
}
return [[self _representedObject] objectAtIndex:anIndex];
- (CPArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
if (_objectsAtIndexes)
return _objectsAtIndexes(_proxyObject, _objectsAtIndexesSEL, theIndexes);
if (_objectAtIndex)
{
var index = CPNotFound,
objects = [];
while ((index = [theIndexes indexGreaterThanIndex:index]) !== CPNotFound)
objects.push(_objectAtIndex(_proxyObject, _objectAtIndexSEL, index));
return objects;
}
return [[self _representedObject] objectsAtIndexes:theIndexes];
}
- (void)addObject:(id)anObject
@@ -288,37 +303,111 @@
[self removeObject:anObject inRange:CPMakeRange(0, [self count])];
}
- (void)removeLastObject
- (void)removeObjectsInArray:(CPArray)theObjects
{
if (_removeMany)
{
var indexes = [CPIndexSet indexSet],
index = [theObjects count];
while (index--)
[indexes addIndex:[self indexOfObject:[theObjects objectAtIndex:index]]];
_removeMany(_proxyObject, _removeManySEL, indexes);
}
else if (_remove)
{
var index = [theObjects count];
while (index--)
_remove(_proxyObject, _removeSEL, [self indexOfObject:[theObjects objectAtIndex:index]]);
}
else
{
var target = [[self _representedObject] copy];
[target removeObjectsInArray:theObjects];
[self _setRepresentedObject:target];
}
}
- (void)removeObject:(id)theObject inRange:(CPRange)theRange
{
if (_remove)
return _remove(_proxyObject, _removeSEL, [self count] - 1);
_remove(_proxyObject, _removeSEL, [self indexOfObject:theObject inRange:theRange]);
else if (_removeMany)
{
var index = [self indexOfObject:theObject inRange:theRange];
_removeMany(_proxyObject, _removeManySEL, [CPIndexSet indexSetWithIndex:index]);
}
else
{
var index;
var target = [[self _representedObject] copy];
while ((index = [self indexOfObject:theObject inRange:theRange]) !== CPNotFound)
{
[self removeObjectAtIndex:index];
theRange = CPIntersectionRange(CPMakeRange(index, length - index), theRange);
}
}
}
[target removeLastObject];
[self _setRepresentedObject:target];
- (void)removeLastObject
{
[self removeObjectsAtIndexes:[CPIndexSet indexSetWithIndex:[self count] - 1]];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
{
if (_remove)
return _remove(_proxyObject, _removeSEL, anIndex);
[self removeObjectsAtIndexes:[CPIndexSet indexSetWithIndex:anIndex]];
}
var target = [[self _representedObject] copy];
- (void)removeObjectsAtIndexes:(CPIndexSet)theIndexes
{
if (_removeMany)
_removeMany(_proxyObject, _removeManySEL, theIndexes);
else if (_remove)
{
var index = [theIndexes lastIndex];
[target removeObjectAtIndex:anIndex];
[self _setRepresentedObject:target];
while (index !== CPNotFound)
{
_remove(_proxyObject, _removeSEL, index)
index = [theIndexes indexLessThanIndex:index];
}
}
else
{
var target = [[self _representedObject] copy];
[target removeObjectsAtIndexes:theIndexes];
[self _setRepresentedObject:target];
}
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
if (_replace)
return _replace(_proxyObject, _replaceSEL, anIndex, anObject);
[self replaceObjectsAtIndexes:[CPIndexSet indexSetWithIndex:anIndex] withObjects:[anObject]]
}
var target = [[self _representedObject] copy];
- (void)replaceObjectsAtIndexes:(CPIndexSet)theIndexes withObjects:(CPArray)theObjects
{
if (_replaceMany)
return _replaceMany(_proxyObject, _replaceManySEL, theIndexes, theObjects);
else if (_replace)
{
var i = 0,
index = [theIndexes firstIndex];
[target replaceObjectAtIndex:anIndex withObject:anObject];
[self _setRepresentedObject:target];
while (index !== CPNotFound)
{
_replace(_proxyObject, _replaceSEL, index, [theObjects objectAtIndex:i++]);
index = [theIndexes indexGreaterThanIndex:index];
}
}
else
{
var target = [[self _representedObject] copy];
[target replaceObjectsAtIndexes:theIndexes withObjects:theObjects];
[self _setRepresentedObject:target];
}
}
@end
+4
View File
@@ -160,6 +160,10 @@ function generateDocs(/* boolean */ noFrame)
rm_rf($DOCUMENTATION_BUILD);
mv("debug.txt", FILE.join("Documentation", "debug.txt"));
mv("Documentation", $DOCUMENTATION_BUILD);
// There is a bug in doxygen 1.7.x preventing loading correctly the custom CSS
// So let's do it manually
cp(FILE.join(documentationDir, "doxygen.css"), FILE.join($DOCUMENTATION_BUILD, "html", "doxygen.css"));
}
}
+98 -5
View File
@@ -5,15 +5,108 @@
@implementation CPWindowTest : OJTestCase
{
CPWindow theWindow;
CPWindow _window @accessors(property=window);
}
-(void)testCanAllocWindow
- (void)setUp
{
theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0,0,200,150)
styleMask:CPWindowNotSizable];
_window = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0)
styleMask:CPWindowNotSizable];
}
[self assertTrue:!!theWindow];
- (void)testCanAllocWindow
{
[self assertTrue:!![self window]];
}
- (void)testThatContentViewIsInitialFirstResponder
{
var contentView = [[self window] contentView];
[self assert:contentView
equals:[[self window] initialFirstResponder]
message:@"The window's content view must be the initial first responder"];
}
- (void)testKeyViewLoop
{
var contentView = [[self window] contentView],
textField = [CPTextField textFieldWithStringValue:@"" placeholder:@"" width:100.0];
[textField setFrame:CGRectMake(100.0, 100.0, 100.0, 26.0)];
[contentView addSubview:textField];
[[self window] recalculateKeyViewLoop];
var nextTextField = [CPTextField textFieldWithStringValue:@"" placeholder:@"" width:100];
[nextTextField setFrame:CGRectMake(100.0, 200.0, 100.0, 26.0)];
[contentView addSubview:nextTextField];
[[self window] recalculateKeyViewLoop];
// Test nextKeyView
[self assert:textField
equals:[contentView nextKeyView]
message:@"textField should be the next key view of contentView"];
[self assert:nextTextField
equals:[textField nextKeyView]
message:@"nextTextField should be the next key view of textField"];
[self assert:contentView
equals:[nextTextField nextKeyView]
message:@"contentView should be the next key view of nextTextField"];
// Test previousKeyView
[self assert:contentView
equals:[textField previousKeyView]
message:@"contentView should be the previous key view of textField"];
[self assert:textField
equals:[nextTextField previousKeyView]
message:@"textField should be the previous key view of nextTextField"];
[self assert:nextTextField
equals:[contentView previousKeyView]
message:@"nextTextField should be the previous key view of contentView"];
}
- (void)testValiKeyViewLoop
{
var contentView = [[self window] contentView],
textField = [CPTextField textFieldWithStringValue:@"" placeholder:@"" width:100.0];
[textField setFrame:CGRectMake(100.0, 100.0, 100.0, 26.0)];
[contentView addSubview:textField];
[[self window] recalculateKeyViewLoop];
var nextTextField = [CPTextField textFieldWithStringValue:@"" placeholder:@"" width:100];
[nextTextField setFrame:CGRectMake(100.0, 200.0, 100.0, 26.0)];
[contentView addSubview:nextTextField];
[[self window] recalculateKeyViewLoop];
// Test nextValidKeyView
[self assert:textField
equals:[contentView nextValidKeyView]
message:@"textField should be the next valid key view of contentView"];
[self assert:nextTextField
equals:[textField nextValidKeyView]
message:@"nextTextField should be the next valid key view of textField"];
[self assert:textField
equals:[nextTextField nextValidKeyView]
message:@"textField should be the next key valid view of nextTextField"];
// Test previousValidKeyView
[self assert:nextTextField
equals:[textField previousValidKeyView]
message:@"nextTextField should be the previous valid key view of textField"];
[self assert:textField
equals:[nextTextField previousValidKeyView]
message:@"textField should be the previous key valid view of nextTextField"];
[self assert:nextTextField
equals:[contentView previousValidKeyView]
message:@"nextTextField should be the previous valid key view of contentView"];
}
@end
+396
View File
@@ -0,0 +1,396 @@
var COUNTER;
@implementation CPKVCArrayTest : OJTestCase
{
TestObject _object @accessors(property=object);
ImplementedTestObject _implementedObject @accessors(property=implementedObject);
}
- (void)setUp
{
_object = [[TestObject alloc] init];
_implementedObject = [[ImplementedTestObject alloc] init];
COUNTER = 0;
}
- (void)_patchSelector:(SEL)theSelector
{
var method_dtable = [[self object] class].method_dtable,
method_list = [[self object] class].method_list,
selectorsToRemove = [@selector(countOfValues), @selector(objectInValuesAtIndex),
@selector(objectInValuesAtIndex:), @selector(valuesAtIndexes:),
@selector(insertObject:inValuesAtIndex:), @selector(insertValues:atIndexes:),
@selector(removeObjectFromValuesAtIndex:), @selector(removeValuesAtIndexes:),
@selector(removeObjectFromValuesAtIndex:),
@selector(replaceObjectInValuesAtIndex:withObject:),
@selector(replaceValuesAtIndexes:withValues:)],
selectorIndex = [selectorsToRemove count];
while (selectorIndex--)
{
var selector = [selectorsToRemove objectAtIndex:selectorIndex],
implementation = method_dtable[selector];
if (!implementation)
continue;
delete method_dtable[selector]
[method_list removeObject:implementation];
}
var method = class_getInstanceMethod([[self implementedObject] class], theSelector),
implementation = method_getImplementation(method);
class_addMethod([[self object] class], theSelector, implementation);
}
- (void)testUsesCountOfKey
{
[self _patchSelector:@selector(countOfValues)];
var count = [[[self object] mutableArrayValueForKey:@"values"] count];
[self assert:10 equals:count message:@"countOfValues should return 10"];
[self assert:1 equals:COUNTER message:@"countOfValues should have been called once"]
}
- (void)testObjectAtIndexUsesObjectInKeyAtIndex
{
[self _patchSelector:@selector(objectInValuesAtIndex:)];
var values = [[self object] mutableArrayValueForKey:@"values"],
object = [values objectAtIndex:0];
[self assert:0 equals:object]
[self assert:1 equals:COUNTER message:@"objectInValuesAtIndex: should have been called once"];
}
- (void)testObjectsAtIndexesUsesObjectInKeyAtIndex
{
[self _patchSelector:@selector(objectInValuesAtIndex:)];
var values = [[self object] mutableArrayValueForKey:@"values"],
objects = [values objectsAtIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 2)]];
[self assert:[0, 1] equals:objects]
[self assert:2 equals:COUNTER message:@"objectInValuesAtIndex: should have been called once"];
}
- (void)testObjectAtIndexUsesKeyAtIndexes
{
[self _patchSelector:@selector(valuesAtIndexes:)];
var values = [[self object] mutableArrayValueForKey:@"values"],
object = [values objectAtIndex:0];
[self assert:0 equals:object]
[self assert:1 equals:COUNTER message:@"valuesAtIndexes: should have been called once"];
}
- (void)testObjectsAtIndexesUsesKeyAtIndexes
{
[self _patchSelector:@selector(valuesAtIndexes:)];
var values = [[self object] mutableArrayValueForKey:@"values"],
objects = [values objectsAtIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 2)]];
[self assert:[0, 1] equals:objects]
[self assert:1 equals:COUNTER message:@"valuesAtIndexes: should have been called once"];
}
- (void)testInsertObjectAtIndexUsesInsertKeyAtIndex
{
[self _patchSelector:@selector(insertObject:inValuesAtIndex:)];
[[[self object] mutableArrayValueForKey:@"values"] insertObject:11 atIndex:10];
[self assert:11 equals:[[[self object] values] objectAtIndex:10]];
[self assert:1 equals:COUNTER message:@"insertObject:inValuesAtIndex: should have been called once"];
}
- (void)testInsertObjectsAtIndexesUsesInsertKeyAtIndex
{
[self _patchSelector:@selector(insertObject:inValuesAtIndex:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(10, 2)];
[[[self object] mutableArrayValueForKey:@"values"] insertObjects:[11, 12] atIndexes:indexes];
[self assert:[11, 12] equals:[[[self object] values] objectsAtIndexes:indexes]];
[self assert:2
equals:COUNTER
message:@"insertValues:atIndexes: should have been called once for each object"];
}
- (void)testInsertObjectAtIndexUsesInsertKeyAtIndexes
{
[self _patchSelector:@selector(insertValues:atIndexes:)];
[[[self object] mutableArrayValueForKey:@"values"] insertObject:11 atIndex:10];
[self assert:11 equals:[[[self object] values] objectAtIndex:10]];
[self assert:1 equals:COUNTER message:@"insertValues:atIndexes: should have been called once"];
}
- (void)testInsertObjectsAtIndexesUsesInsertKeyAtIndexes
{
[self _patchSelector:@selector(insertValues:atIndexes:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(10, 2)];
[[[self object] mutableArrayValueForKey:@"values"] insertObjects:[11, 12] atIndexes:indexes];
[self assert:[11, 12] equals:[[[self object] values] objectsAtIndexes:indexes]];
[self assert:1
equals:COUNTER
message:@"insertValues:atIndexes: should have been called once for each object"];
}
- (void)testRemoveObjectAtIndexUsesRemoveObjectFromKeyAtIndex
{
[self _patchSelector:@selector(removeObjectFromValuesAtIndex:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectAtIndex:0];
[self assert:[1, 2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:@"removeObjectFromValuesAtIndex: should have been called once"];
}
- (void)testRemoveObjectAtIndexesUsesRemoveObjectFromKeyAtIndex
{
[self _patchSelector:@selector(removeObjectFromValuesAtIndex:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 2)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectsAtIndexes:indexes];
[self assert:[2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:2 equals:COUNTER message:@"removeValuesAtIndex: should have been called once for each object"];
}
- (void)testRemoveObjectsAtIndexesUsesRemoveKeyAtIndex
{
[self _patchSelector:@selector(removeValuesAtIndexes:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectAtIndex:0];
[self assert:[1, 2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1
equals:COUNTER
message:@"removeValuesAtIndexes: should have been once for each object"];
}
- (void)testRemoveObjectsAtIndexesUsesRemoveKeyAtIndexes
{
[self _patchSelector:@selector(removeValuesAtIndexes:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(3, 2)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectsAtIndexes:indexes];
[self assert:[0, 1, 2, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"];
}
- (void)testRemoveObjectUsesRemoveKeyAtIndex
{
[self _patchSelector:@selector(removeObjectFromValuesAtIndex:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObject:1];
[self assert:[0, 2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"]
}
- (void)testeRemoveObjectUsesRemoveKeyAtIndexes
{
[self _patchSelector:@selector(removeValuesAtIndexes:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObject:5];
[self assert:[0, 1, 2, 3, 4, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"];
}
- (void)testRemoveObjectsInArrayUsesRemoveKeyAtIndex
{
[self _patchSelector:@selector(removeObjectFromValuesAtIndex:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectsInArray:[3, 6]];
[self assert:[0, 1, 2, 4, 5, 7, 8, 9] equals:[[self object] values]];
[self assert:2 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"]
}
- (void)testRemoveObjectsInArrayUsesRemoveKeyAtIndexes
{
[self _patchSelector:@selector(removeValuesAtIndexes:)];
[[[self object] mutableArrayValueForKey:@"values"] removeObjectsInArray:[0, 9]];
[self assert:[1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"];
}
- (void)testRemoveLastObjectUsesRemoveKeyAtIndex
{
[self _patchSelector:@selector(removeObjectFromValuesAtIndex:)];
[[[self object] mutableArrayValueForKey:@"values"] removeLastObject];
[self assert:[0, 1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"]
}
- (void)testRemoveLastObjectUsesRemoveKeyAtIndexes
{
[self _patchSelector:@selector(removeValuesAtIndexes:)];
[[[self object] mutableArrayValueForKey:@"values"] removeLastObject];
[self assert:[0, 1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]];
[self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"];
}
- (void)testReplaceObjectAtIndexWithObjectUsesReplaceObjectInKeyAtIndexWithObject
{
[self _patchSelector:@selector(replaceObjectInValuesAtIndex:withObject:)];
[[[self object] mutableArrayValueForKey:@"values"] replaceObjectAtIndex:0 withObject:1];
[self assert:[1, 1, 2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1
equals:COUNTER
message:@"replaceObjectInValuesAtIndex:withObject: should have been called once"];
}
- (void)testReplaceObjectsAtIndexesWithObjectsUsesReplaceObjectInKeyAtIndexWithObject
{
[self _patchSelector:@selector(replaceObjectInValuesAtIndex:withObject:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(5, 3)];
[[[self object] mutableArrayValueForKey:@"values"] replaceObjectsAtIndexes:indexes withObjects:[1, 2, 3]];
[self assert:[0, 1, 2, 3, 4, 1, 2, 3, 8, 9] equals:[[self object] values]];
[self assert:3
equals:COUNTER
message:@"replaceObjectInValuesAtIndex:withObject: should have been called once"];
}
- (void)testReplaceObjectAtIndexWithObjectUsesReplaceKeyAtIndexesWithKeys
{
[self _patchSelector:@selector(replaceValuesAtIndexes:withValues:)];
[[[self object] mutableArrayValueForKey:@"values"] replaceObjectAtIndex:5 withObject:6];
[self assert:[0, 1, 2, 3, 4, 6, 6, 7, 8, 9] equals:[[self object] values]];
[self assert:1
equals:COUNTER
message:@"replaceObjectInValuesAtIndex:withObject: should have been called once"];
}
- (void)testReplaceObjectsAtIndexesWithObjectsUsesReplaceKeyAtIndexesWithKeys
{
[self _patchSelector:@selector(replaceValuesAtIndexes:withValues:)];
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(6, 2)];
[[[self object] mutableArrayValueForKey:@"values"] replaceObjectsAtIndexes:indexes withObjects:[7, 8]];
[self assert:[0, 1, 2, 3, 4, 5, 7, 8, 8, 9] equals:[[self object] values]];
[self assert:1
equals:COUNTER
message:@"replaceObjectInValuesAtIndexes:withValues: should have been called once"];
}
@end
@implementation TestObject : CPObject
{
CPArray _values @accessors(property=values);
}
- (id)init
{
if (self = [super init])
{
_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
return self;
}
@end
@implementation ImplementedTestObject : TestObject
{
}
- (int)countOfValues
{
// CPLog.warn(@"countOfValues");
COUNTER += 1;
return [[self values] count];
}
- (id)objectInValuesAtIndex:(int)theIndex
{
// CPLog.warn(@"objectInValuesAtIndex: %@", theIndex);
COUNTER += 1;
return [[self values] objectAtIndex:theIndex];
}
- (CPArray)valuesAtIndexes:(CPIndexSet)theIndexes
{
// CPLog.warn(@"valuesAtIndexes: %@", theIndexes);
COUNTER += 1;
return [[self values] objectsAtIndexes:theIndexes];
}
- (void)insertObject:(id)theObject inValuesAtIndex:(int)theIndex
{
// CPLog.warn(@"insertObject: %@ inValuesAtIndex: %@", theObject, theIndex);
COUNTER += 1;
[[self values] insertObject:theObject atIndex:theIndex];
}
- (void)insertValues:(CPArray)theObjects atIndexes:(CPIndexSet)theIndexes
{
// CPLog.warn(@"insertValues: %@ atIndexes: %@", theObjects, theIndexes);
COUNTER += 1;
[[self values] insertObjects:theObjects atIndexes:theIndexes];
}
- (void)removeObjectFromValuesAtIndex:(int)theIndex
{
// CPLog.warn(@"removeObjectFromValuesAtIndex: %@", theIndex);
COUNTER += 1;
[[self values] removeObjectAtIndex:theIndex];
}
- (void)removeValuesAtIndexes:(CPIndexSet)theIndexes
{
// CPLog.warn(@"removeValuesAtIndexes: %@", theIndexes);
COUNTER += 1;
[[self values] removeObjectsAtIndexes:theIndexes];
}
- (void)replaceObjectInValuesAtIndex:(int)theIndex withObject:(id)theObject
{
// CPLog.warn(@"replaceObjectInValuesAtIndex: %@ withObject: %@", theIndex, theObject);
COUNTER += 1;
[[self values] replaceObjectAtIndex:theIndex withObject:theObject];
}
- (void)replaceValuesAtIndexes:(CPIndexSet)theIndexes withValues:(id)theObjects
{
// CPLog.warn(@"replaceValuesAtIndexes: %@ withValues: %@", theIndexes, theObjects);
COUNTER += 1;
[[self values] replaceObjectsAtIndexes:theIndexes withObjects:theObjects];
}
@end
-14
View File
@@ -1,14 +0,0 @@
Run this application with the current master, and note the following bugs:
- When you click on any item, there are two selection change notifications instead of one.
- If you compare the order of the notifications with Cocoa, they are slightly different.
- The right hand table is configured to allow an empty selection. If you click in the
empty area below the names, there is an empty selection notification, but then the
the current selection changes to the first item and generates another notification.
- If you select multiple items on the left, there is an error. This is a bug that will
have to be fixed in a later commit.
If you apply the changes in these commits, the first three bugs are fixed.
+36 -12
View File
@@ -15,6 +15,7 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
CPTokenField tokenFieldD;
CPArray allPersons;
CPButton manipulateTokenInsertionButton;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
@@ -22,28 +23,28 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
contentView = [theWindow contentView],
tokenFieldA = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 40, 500, 29)],
tokenFieldA = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 40, 500, 30)],
label = [[CPTextField alloc] initWithFrame:CGRectMake(15, 15, 500, 24)];
[label setStringValue:@"This token field has no auto suggestions and uses space to separate tokens."];
[label setStringValue:"This token field has no auto suggestions and uses space to separate tokens."];
[contentView addSubview:label];
[tokenFieldA setEditable:YES];
[tokenFieldA setPlaceholderString:@"Type in a token!"];
[tokenFieldA setPlaceholderString:"Type in a token!"];
[tokenFieldA setTokenizingCharacterSet:[CPCharacterSet characterSetWithCharactersInString:@" "]];
[contentView addSubview:tokenFieldA];
var tokenFieldB = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 110, 500, 29)],
var tokenFieldB = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 110, 500, 30)],
labelB = [[CPTextField alloc] initWithFrame:CGRectMake(15, 80, 500, 24)];
[labelB setStringValue:@"This token field has no bezel, uses comma to separate tokens and has auto suggest."];
[labelB setStringValue:"This token field has no bezel, uses comma to separate tokens and has auto suggest."];
[contentView addSubview:labelB];
[tokenFieldB setEditable:YES];
[tokenFieldB setBezeled:NO];
[tokenFieldB setPlaceholderString:@"Edit me!"];
[tokenFieldB setPlaceholderString:"Edit me!"];
[tokenFieldB setObjectValue:["Missouri", "California"]];
[tokenFieldB setDelegate:self];
@@ -53,14 +54,18 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
[contentView addSubview:tokenFieldB];
var tokenFieldC = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 170, 500, 29)],
manipulateTokenInsertionButton = [CPCheckBox checkBoxWithTitle:"Token transformations"];
[manipulateTokenInsertionButton setFrame:CGRectMake(525, 110, 200, 50)];
[contentView addSubview:manipulateTokenInsertionButton];
var tokenFieldC = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 170, 500, 30)],
labelC = [[CPTextField alloc] initWithFrame:CGRectMake(15, 150, 500, 24)];
[labelC setStringValue:@"This token field can't fit all its tokens."];
[labelC setStringValue:"This token field can't fit all its tokens."];
[contentView addSubview:labelC];
[tokenFieldC setEditable:YES];
[tokenFieldC setPlaceholderString:@"Edit me!"];
[tokenFieldC setPlaceholderString:"Edit me!"];
[tokenFieldC setObjectValue:['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado']];
[tokenFieldC setDelegate:self];
@@ -71,10 +76,10 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
[tokenFieldC setAction:@selector(tokenFieldAction:)];
[tokenFieldC setTarget:self];
tokenFieldD = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 230, 500, 29)],
tokenFieldD = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 230, 500, 30)],
labelD = [[CPTextField alloc] initWithFrame:CGRectMake(15, 210, 500, 24)];
[labelD setStringValue:@"This token field contains represented objects."];
[labelD setStringValue:"This token field contains represented objects."];
[contentView addSubview:labelD];
[tokenFieldD setEditable:YES];
@@ -93,7 +98,7 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
[contentView addSubview:tokenFieldD];
var button = [[CPButton alloc] initWithFrame:CGRectMake(15, 270, 0, 0)];
[button setTitle:@"Get Object Values"];
[button setTitle:"Get Object Values"];
[button sizeToFit];
[button setTarget:self];
[button setAction:@selector(getObjectValues:)];
@@ -148,6 +153,25 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad
CPLog.info("tokenFieldAction: " + sender);
}
- (CPArray)tokenField:tokenField shouldAddObjects:tokens atIndex:index
{
CPLog.info("tokenField: " + tokenField + " shouldAddObjects: " + tokens + " atIndex: " + index);
// Texas -> Utah, Michigan -> Michigan & Arkansas, Washington -> nil
if ([manipulateTokenInsertionButton intValue])
{
if (tokens[0] == "Texas")
return ["Utah"];
else if (tokens[0] == "Michigan")
return ["Michigan", "Arkansas"];
else if (tokens[0] == "Washington")
return [];
}
return tokens;
}
@end
// A sample of a custom Object
+25 -23
View File
@@ -37,44 +37,46 @@
platformWindow = [[CPPlatformWindow alloc] init];
// [platformWindow orderFront:self];//console.log(CPStringFromRect([theWindow contentRectForFrameRect:[theWindow frame]]));
// [platformWindow orderFront:self];//console.log(CPStringFromRect([theWindow contentRectForFrameRect:[theWindow frame]]));
[platformWindow setContentRect:[theWindow contentRectForFrameRect:[theWindow frame]]];
// [theWindow setTitle:@"My Custom Title"];
//[platformWindow orderFront:self];
// seriously, this test file is dirty :)
var slider = [[theWindow contentView] subviews][0];
[slider setTarget:self];
[slider setAction:@selector(randomTitle:)];
[slider setContinuous:NO];
window.setTimeout(function(){
[theWindow orderOut:self];
[theWindow setPlatformWindow:platformWindow];
[theWindow orderFront:self];
[theWindow setFullBridge:YES];
var button = [[theWindow contentView] subviews][2];
[theWindow setTitle:"Initial title (pop out pending)"];
window.setTimeout(function()
{
[theWindow orderOut:self];
[theWindow setPlatformWindow:platformWindow];
[theWindow orderFront:self];
[theWindow setFullBridge:YES];
var button = [[theWindow contentView] subviews][2];
[button setTarget:self];
[button setAction:@selector(close)];
[button setTarget:self];
[button setAction:@selector(close)];
[theWindow setTitle:"Title after pop out (red box pending)"];
window.setTimeout(function(){
var view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
[view setBackgroundColor:[CPColor redColor]];
[[theWindow contentView] addSubview:view];},1000);
}, 1000);
//window.setTimeout(function() { [platformWindow orderOut:self]; [platformWindow orderFront:self]; }, 2000);
window.setTimeout(function()
{
var view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
[view setBackgroundColor:[CPColor redColor]];
[[theWindow contentView] addSubview:view];
[theWindow setTitle:"Title in final stage"];
}, 1000);
}, 2000);
}
- (void)close
{
[[theWindow platformWindow] orderOut:self];
window.setTimeout(function(){
[[theWindow platformWindow] orderFront:self];}, 1000);
window.setTimeout(function()
{
[[theWindow platformWindow] orderFront:self];
}, 1000);
}
- (void)another:(id)aSender
@@ -84,7 +86,7 @@ window.setTimeout(function(){
- (IBAction)randomTitle:(id)aSender
{
[theWindow setTitle:@"Window random number " + Math.random(1000)]
[theWindow setTitle:@"Window random number " + Math.random(1000)];
}
@end
+4 -2
View File
@@ -25,7 +25,7 @@ DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = "Cappuccino API"
PROJECT_NAME = " API"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -33,6 +33,8 @@ PROJECT_NAME = "Cappuccino API"
PROJECT_NUMBER = 0.9.1
PROJECT_LOGO = ./Tools/Documentation/logo.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
@@ -845,7 +847,7 @@ HTML_FOOTER =
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET = ./Tools/Documentation/doxygen.css
#HTML_STYLESHEET = doxygen.css
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
# Doxygen will adjust the colors in the stylesheet and background images
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB