Compare commits

..
62 Commits
Author SHA1 Message Date
release be0b97cb56 Changed version number to 1.0.0.019 2011-09-20 04:55:07 -05:00
Aparajita Fishman 6f7cbe21ef Main Jakefile improvements...
- 'jake clean' now cleans only the .build directories instead of doing the same as clobber.
- Added task 'clean-sprites', cleans sprited images.
- Added task 'clobber-theme', clobbers all Aristo.blend and Aristo.build directories.
2011-09-19 21:38:35 -07:00
Aparajita Fishman eff3dfc74a Merge branch 'master' of github.com:intalio/cappuccino 2011-09-19 11:12:57 -07:00
Aparajita Fishman 2ad1f4e4e5 Merge branch 'master' of github.com:cappuccino/cappuccino
Conflicts:
	Tests/Manual/CPTokenFieldTest/AppController.j
2011-09-18 16:04:42 -07:00
Alexander Ljungberg 4aec3f7466 Refs #1355. Manual window title test.
In the PlatformWindows test, change the window title both when theWindow is a non platform window and when it is a platform window to verify that the browser window title changes only when it should.
2011-09-17 11:07:38 +01:00
Alexander Ljungberg c8991e07b9 Merge pull request #1355 from primalmotion/cappuccino
---

if setTitle: is called on a CPWindow with the primaryPlatformWindow as platformWindow,
the main pages title is changed. This patch prevent changing the primaryPlatformWindows title.
This is not optimal, but this is better than changing the title at each window setTitle: call
2011-09-17 10:55:43 +01:00
Alexander Ljungberg 48157db973 Refs #1360. Fixed: index was always 0 in CPTokenField tokenField:shouldAddObjects:atIndex: delegate method. 2011-09-16 21:52:09 +01:00
Alexander Ljungberg d070e5fce5 Merge branch 'master' of github.com:cappuccino/cappuccino 2011-09-16 21:47:20 +01:00
Alexander Ljungberg a8fae51ea8 Refs #1360. Cursor movement fixes, optimisations.
Don't move the cursor forward if no token was inserted. Only count new tokens once.
2011-09-16 21:46:20 +01:00
Alexander Ljungberg 2815d462be Refs #1360. Test for CPTokenField tokenField:shouldAddObjects:atIndex:. 2011-09-16 20:51:45 +01:00
release ed002d7d3e Changed version number to 1.0.0.019-SNAPSHOT 2011-09-16 13:44:57 -05:00
release a7994c1480 Changed version number to 1.0.0.018 2011-09-16 13:44:51 -05:00
Alexander Ljungberg 85f8ca9241 Refs #1360. Format code. 2011-09-16 19:29:53 +01:00
Alexander Ljungberg b5fb9e8c23 Merge pull request #1360 from jigzat/cappuccino
---

Enabled tokenField:shouldAddObjects:atIndex delegate method and used on _autocompleteWithDOMEvent method to have some control over tokens. Not sure why wasnt enabled, it needed very few code. Maybe no one needed it til now.

This is my first collaboration ever, so Im not sure if is of any use.
2011-09-16 19:10:23 +01:00
release c605ca4531 Changed version number to 1.0.0.018-SNAPSHOT 2011-09-16 12:37:07 -05:00
release c288930a3c Changed version number to 1.0.0.017 2011-09-16 12:36:59 -05:00
release 596676a562 Changed version number to 1.0.0.017-SNAPSHOT 2011-09-16 06:01:02 -05:00
release cc3d9f337c Changed version number to 1.0.0.016 2011-09-16 06:00:55 -05:00
Klaas Pieter Annema 1addc002d3 Merge branch 'master' of github.com:cappuccino/cappuccino 2011-09-16 12:00:05 +02:00
Klaas Pieter Annema e99e2660e9 more fixes and tests for _CPKVCArray 2011-09-16 11:43:42 +02:00
Aparajita Fishman 03d1bb8bce Added missing statement separator, concatenated var block, fixed symlink deletion/creation sometimes failing. 2011-09-15 17:09:15 -07:00
Aparajita Fishman 8d210100a5 Fix for symlink creation sometimes failing. 2011-09-15 16:41:52 -07:00
Aparajita Fishman d25e96902f Added missing statement separator, concatenated var block 2011-09-15 14:56:24 -07:00
Aparajita Fishman ad792d9772 Fixed problem with FILE.remove sometimes failing to delete the symbolic link. 2011-09-15 14:28:57 -07:00
Klaas Pieter Annema 5b00f7f2e8 improve _CPKVCArray
_CPKVCArray now consistently calls both single and multiple indexes accessors consistently
Tests that verify the behavior are included
2011-09-15 22:32:23 +02:00
Klaas Pieter Annema 97b7f0901e add tests for key view loop behavior 2011-09-15 17:50:37 +02:00
Klaas Pieter Annema 67b2671dad improve key view loops
- include the window's content view at the start of the key view loop
- set the initial first responder to the window's content view (and keep it that way unless it is explicitly changed)
- CPWindow should return NO from acceptsFirstResponder (Cocoa compliance).
- change the type of setInitialFirstResponder, this is compliant with Cocoa. The new key view loop code will break if initial first responder is anything but a view
- change the implementation of selectNextKeyView:, selectPreviousKeyView:, selectKeyViewFollowingView: and selectKeyViewPrecedingView: to follow to Cocoa's documentation
2011-09-15 16:39:24 +02:00
Aparajita Fishman 9e7b737960 Merge branch 'master' of github.com:intalio/cappuccino 2011-09-13 12:36:53 -07:00
release 9bc6a69b76 Changed version number to 1.0.0.016-SNAPSHOT 2011-09-10 05:58:01 -05:00
release 1cb28e4206 Changed version number to 1.0.0.015 2011-09-10 05:57:56 -05:00
release 5311689265 Changed version number to 1.0.0.015-SNAPSHOT 2011-09-10 04:58:47 -05:00
release 4228a2a146 Changed version number to 1.0.0.014 2011-09-10 04:58:42 -05:00
aparajita 7886d49e65 Merge pull request #1359 from primalmotion/fix-and-improve-doxygen-theme
Fix and improve doxygen theme
2011-09-09 21:48:17 -07:00
Samir Gartner e5284e9b43 Fixed some possible error of my part where selectedRange is moved beyond bounds 2011-09-09 22:31:17 -05:00
Samir Gartner c6403baa04 Fixed cursor position issue in a little escapade...guess that's all for now folks 2011-09-09 13:28:37 -05:00
Samir Gartner 662b1ec696 Submitted the right CPTokenField file, was missing the part to use the delegate approved tokens. Still lacks a way to put the cursor after the last token (if the delegate returns more than one token) 2011-09-09 12:48:18 -05:00
Samir Gartner 043df71185 Enabled tokenField:shouldAddObjects:atIndex delegate method and used on _autocompleteWithDOMEvent method to have some control over tokens. Not sure why wasn't enabled, it was very few code. Maybe no one needed it 'til now 2011-09-08 22:56:52 -05:00
Antoine Mercadal 8dab47f4da mozilla compat 2011-09-08 18:12:32 +02:00
Alexander Ljungberg 90d069df2b Refs #1343. Remove now obsolete README.md.
Everything in the README has been fixed except 3 and 4. 4 is outside of the issue scope and 3 works as intended (nearly). The array controller does not have `setAvoidsEmptySelection:NO` so an empty selection should not be possible unless there are no items.
2011-09-08 17:02:15 +01:00
Antoine Mercadal dcbe3ee650 fix paremeters touching their description in bubbles 2011-09-08 17:15:12 +02:00
Antoine Mercadal e32489aba1 tiny padding improvment in generated html docs 2011-09-08 17:08:50 +02:00
Antoine Mercadal b619c0b793 some small graphical improvments 2011-09-08 16:55:12 +02:00
Antoine Mercadal fab61d14fa forget to restore the bg color of the tree view 2011-09-08 14:44:05 +02:00
Antoine Mercadal b4edc084f8 add Cappuccino logo 2011-09-08 14:00:20 +02:00
Antoine Mercadal c7518d0c49 merge Aparajita's previous improvments on the CSS 2011-09-08 12:44:10 +02:00
Antoine Mercadal a40345c14d fix the slider 2011-09-08 11:46:20 +02:00
Aparajita Fishman bacc50c271 Merge remote branch 'refs/remotes/cappuccino/master'
Conflicts:
	AppKit/CPArrayController.j
	Foundation/CPKeyValueObserving.j
	Tests/Manual/Bindings/AppController.j
2011-09-07 22:04:42 -04:00
Antoine Mercadal 909471a5d7 fix the documentation generation process 2011-09-08 01:30:58 +02:00
Antoine Mercadal 38f7ea00c2 update doxygen.css 2011-09-08 00:43:32 +02:00
Alexander Ljungberg 9f459f053e Fixed: several CPArrayController methods returned undefined instead of booleans. 2011-09-07 18:17:35 +01:00
Alexander Ljungberg 4195f3b8c6 Test that CPArrayController setSelectionIndexes: does not modify its input. 2011-09-07 18:02:53 +01:00
Alexander Ljungberg 4926824482 Fixed: CPArrayController setSelectionIndexes: sometimes modified its input.
Also very slightly improved performance as sometimes the input index set would be instantiated internally and then needlessly copied.
2011-09-07 17:53:48 +01:00
Alexander Ljungberg cb2f539cf7 Send didChange in reverse order of willChange in CPObjectController setContent:. 2011-09-07 17:32:19 +01:00
Alexander Ljungberg 7f31be7cb1 Fixed: array replaceObjectsInRange:withObjectsFromArray: always failed with a "'null' is not an object' error.
This was caused by the new range checks in f8404c7a97.
2011-09-07 16:18:08 +01:00
Alexander Ljungberg 78b9c5b576 Fixes #1343. Support nested willChange… didChange… calls.
When multiple calls are nested, only the first willChange… and the last didChange… will notify observers, avoiding duplicate notifications for the same change.
2011-09-07 16:14:01 +01:00
Alexander Ljungberg 01e35efdbb Refs #1343. Recreate manual bindings test as an automatic test. 2011-09-07 16:04:35 +01:00
Aparajita FishmanandAlexander Ljungberg bef1687b1f Test app for bindings fixes. 2011-09-07 12:51:36 +01:00
release da18a9eb24 Changed version number to 1.0.0.014-SNAPSHOT 2011-09-07 06:16:58 -05:00
release d975e90407 Changed version number to 1.0.0.013 2011-09-07 06:16:52 -05:00
Shao Fang abc8e14275 Change version back to 13-SNAPSHOT to prepare for next build. 2011-09-06 18:57:58 -07:00
Antoine Mercadal afa691376e fix unable to change mainWindow's title 2011-09-02 14:00:49 +02:00
Antoine Mercadal be10bcf27a Fix CPPlatformWindow's title bug
if setTitle: is called on a CPWindow with the primaryPlatformWindow as platformWindow,
the main page's title is changed. This patch prevent changing the primaryPlatformWindow's title.
This is not optimal, but this is better than changing the title at each window setTitle: call
2011-09-02 12:42:09 +02:00
23 changed files with 1769 additions and 600 deletions
+70 -108
View File
@@ -27,7 +27,6 @@
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
/*!
@class CPArrayController
@@ -285,7 +284,8 @@
if (value === nil)
value = [];
else if (![value isKindOfClass:[CPArray class]])
if (![value isKindOfClass:[CPArray class]])
value = [value];
var oldSelectedObjects = nil,
@@ -339,6 +339,14 @@
[self setContent:anArray];
}
/*!
@ignore
*/
- (void)_setContentSet:(id)aSet
{
[self setContent:[aSet allObjects]];
}
/*!
Returns the content array of the controller.
@return id the content array of the receiver
@@ -348,14 +356,6 @@
return [self content];
}
/*!
@ignore
*/
- (void)_setContentSet:(id)aSet
{
[self setContent:[aSet allObjects]];
}
/*!
Returns the content of the receiver as a CPSet.
@@ -564,13 +564,9 @@
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
// When explicitly setting the selection, ignore avoidsEmptySelection
var changed = [self __setSelectionIndexes:indexes obeyAvoidsEmptySelection:NO];
[self _selectionDidChangeNotify:NO];
return changed;
var r = [self __setSelectionIndexes:indexes];
[self _selectionDidChange];
return r;
}
/*
@@ -579,7 +575,7 @@
*/
- (BOOL)__setSelectionIndex:(int)theIndex
{
return [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex] obeyAvoidsEmptySelection:YES];
return [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
}
/*
@@ -588,37 +584,38 @@
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
[self __setSelectionIndexes:indexes obeyAvoidsEmptySelection:YES];
}
var newIndexes = indexes;
/*
Like setSelectionIndexes but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes obeyAvoidsEmptySelection:(BOOL)obeyAvoidsEmptySelection
{
if (!indexes)
indexes = [CPIndexSet indexSet];
if (!newIndexes)
newIndexes = [CPIndexSet indexSet];
if (![indexes count])
if (![newIndexes count])
{
if (obeyAvoidsEmptySelection && _avoidsEmptySelection && [[self arrangedObjects] count])
indexes = [CPIndexSet indexSetWithIndex:0];
if (_avoidsEmptySelection && [[self arrangedObjects] count])
newIndexes = [CPIndexSet indexSetWithIndex:0];
}
else
{
var objectsCount = [[self arrangedObjects] count];
// Don't trash the input - the caller might depend on it or we might have been
// given _selectionIndexes as the input in which case the equality test below
// would always succeed despite our change below.
newIndexes = [newIndexes copy];
// Remove out of bounds indexes.
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex] + 1)];
[newIndexes removeIndexesInRange:CPMakeRange(objectsCount, [newIndexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![indexes count] && _avoidsEmptySelection && objectsCount)
indexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
if (![newIndexes count] && _avoidsEmptySelection && objectsCount)
newIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
if ([_selectionIndexes isEqualToIndexSet:indexes])
if ([_selectionIndexes isEqualToIndexSet:newIndexes])
return NO;
_selectionIndexes = [indexes copy];
// If we haven't already created our own index instance, make sure to copy it here so that
// the copy the user sent in is decoupled from our internal copy.
_selectionIndexes = indexes === newIndexes ? [indexes copy] : newIndexes;
// 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.
@@ -650,10 +647,11 @@
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
[self __setSelectedObjects:objects obeyAvoidsEmptySelection:NO];
var r = [self __setSelectedObjects:objects];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChangeNotify:NO];
[self _selectionDidChange];
return r;
}
/*
@@ -661,15 +659,6 @@
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
[self __setSelectedObjects:objects obeyAvoidsEmptySelection:YES];
}
/*
Like setSelectedObjects but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects obeyAvoidsEmptySelection:(BOOL)obeyAvoidsEmptySelection
{
var set = [CPIndexSet indexSet],
count = [objects count],
@@ -683,7 +672,7 @@
[set addIndex:index];
}
[self __setSelectionIndexes:set obeyAvoidsEmptySelection:obeyAvoidsEmptySelection];
[self __setSelectionIndexes:set];
return YES;
}
@@ -752,13 +741,21 @@
}
[self willChangeValueForKey:@"content"];
[self _willModifyContent];
/*
If the content array is bound then our addObject: message below will cause the observed
array to change. The binding will call setContent:_contentObject on this array
controller to let it know about the change. We want to ignore that message since we
A) already have the right _contentObject and B) properly update _arrangedObjects
by hand below.
*/
_disableSetContent = YES;
[_contentObject addObject:object];
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
[self _didModifyContent];
_disableSetContent = NO;
if (willClearPredicate)
{
@@ -779,15 +776,14 @@
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
}
/*
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.
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 (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
}
@@ -813,7 +809,10 @@
[self willChangeValueForKey:@"content"];
[self _willModifyContent];
/*
See _disableSetContent explanation in addObject:.
*/
_disableSetContent = YES;
// The atArrangedObjectIndex: part of this method's name only refers to where the
// object goes in arrangedObjects, not in the content array. So use addObject:,
@@ -822,7 +821,7 @@
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
[self _didModifyContent];
_disableSetContent = NO;
if (willClearPredicate)
[self __setFilterPredicate:nil];
@@ -840,7 +839,6 @@
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
[self didChangeValueForKey:@"content"];
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
}
@@ -853,13 +851,15 @@
- (void)removeObject:(id)object
{
[self willChangeValueForKey:@"content"];
[self _willModifyContent];
// See _disableSetContent explanation in addObject:.
_disableSetContent = YES;
[_contentObject removeObject:object];
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
[self _didModifyContent];
_disableSetContent = NO;
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
@@ -910,15 +910,6 @@
[self removeObjectsAtArrangedObjectIndexes:_selectionIndexes];
}
/*!
Removes the object at the specified index in the controller's arranged objects from the content array.
@param int index - index of the object to remove.
*/
- (void)removeObjectAtArrangedObjectIndex:(int)index
{
[self removeObjectsAtArrangedObjectIndexes:[CPIndexSet indexSetWithIndex:index]];
}
/*!
Removes the objects at the specified indexes in the controller's arranged objects from the content array.
@param CPIndexSet indexes - indexes of the objects to remove.
@@ -927,21 +918,20 @@
{
[self willChangeValueForKey:@"content"];
/*
See _disableSetContent explanation in addObject:.
*/
_disableSetContent = YES;
var arrangedObjects = [self arrangedObjects],
index = [anIndexSet lastIndex],
position = CPNotFound,
newSelectionIndexes = [_selectionIndexes copy],
proxy = [_CPKVOProxy proxyForObject:self];
newSelectionIndexes = [_selectionIndexes copy];
while (index !== CPNotFound)
{
var object = [arrangedObjects objectAtIndex:index];
// Make sure arrangedObjects does not notify because of content change
[proxy suppressNotificationsForKeyPath:@"arrangedObjects"];
// First try the simple case which should work if there are no sort descriptors.
if ([_contentObject objectAtIndex:index] === object)
[_contentObject removeObjectAtIndex:index];
@@ -955,9 +945,6 @@
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
[_contentObject removeObjectAtIndex:contentIndex];
}
// Now arrangedObjects can notify
[proxy unsuppressNotificationsForKeyPath:@"arrangedObjects"];
[arrangedObjects removeObjectAtIndex:index];
// Deselect this row if it was selected, and either way shift all selection indexes
@@ -967,7 +954,6 @@
index = [anIndexSet indexLessThanIndex:index];
}
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
_disableSetContent = NO;
@@ -1014,13 +1000,15 @@
- (void)_removeObjects:(CPArray)objects
{
[self willChangeValueForKey:@"content"];
[self _willModifyContent];
// See _disableSetContent explanation in addObject:.
_disableSetContent = YES;
[_contentObject removeObjectsInArray:objects];
// Allow handlesContentAsCompoundValue reverse sets to trigger.
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
[self _didModifyContent];
_disableSetContent = NO;
var arrangedObjects = [self arrangedObjects],
position = [arrangedObjects indexOfObject:[objects objectAtIndex:0]];
@@ -1057,39 +1045,13 @@
return [self isEditable];
}
// Internal
- (void)_willModifyContent
{
/*
If the content array is bound then our addObject: message below will cause the observed
array to change. The binding will call setContent:_contentObject on this array
controller to let it know about the change. We want to ignore that message since we
A) already have the right _contentObject and B) properly update _arrangedObjects
by hand below.
*/
_disableSetContent = YES;
/*
When mutating arrangedObjects, we mutate the content first. But mutating the content
will trigger a notification that the arrangedObjects have changed, which we want to
suppress, since the arrangedObjects mutation will do the correct notification.
*/
[[_CPKVOProxy proxyForObject:self] suppressNotificationsForKeyPath:@"arrangedObjects"];
}
- (void)_didModifyContent
{
_disableSetContent = NO;
[[_CPKVOProxy proxyForObject:self] unsuppressNotificationsForKeyPath:@"arrangedObjects"];
}
@end
@implementation CPArrayController (CPBinder)
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === @"content" || theBinding === @"contentArray")
if (theBinding == @"contentArray")
return [_CPArrayControllerContentBinder class];
return [super _binderClassForBinding:theBinding];
@@ -1104,7 +1066,7 @@
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
isCompound = [self handlesContentAsCompoundValue] || keyPath.indexOf("@") !== -1;
isCompound = [self handlesContentAsCompoundValue];
if (!isCompound)
{
+1 -1
View File
@@ -131,8 +131,8 @@
_contentObject = aContent;
[self didChangeValueForKey:@"contentObject"];
[self _selectionDidChange];
[self didChangeValueForKey:@"contentObject"];
}
/*!
+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])
{
+1 -1
View File
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), "repositories.rb")
require File.join(File.dirname(__FILE__), "dependencies.rb")
# Keep this structure to allow the build system to update version numbers.
VERSION_NUMBER = "1.0.0.012"
VERSION_NUMBER = "1.0.0.019"
# Shorten expressions
+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
+1 -1
View File
@@ -259,7 +259,7 @@ var concat = Array.prototype.concat,
if (aRange.location < 0 || CPMaxRange(aRange) > self.length)
[CPException raise:CPRangeException reason:_cmd + " aRange out of bounds"];
if (otherRange.location < 0 || CPMaxRange(otherRange) > anArray.length)
if (otherRange && (otherRange.location < 0 || CPMaxRange(otherRange) > anArray.length))
[CPException raise:CPRangeException reason:_cmd + " otherRange out of bounds"];
if (otherRange && (otherRange.location !== 0 || otherRange.length !== [anArray count]))
+39 -26
View File
@@ -228,10 +228,10 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
id _targetObject;
Class _nativeClass;
CPDictionary _changesForKey;
CPDictionary _nestingForKey;
Object _observersForKey;
int _observersForKeyLength;
CPSet _replacedKeys;
CPSet _suppressedNotifications;
}
+ (id)proxyForObject:(CPObject)anObject
@@ -248,12 +248,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
{
if (self = [super init])
{
_targetObject = aTarget;
_nativeClass = [aTarget class];
_observersForKey = {};
_changesForKey = {};
_observersForKeyLength = 0;
_suppressedNotifications = [CPSet set];
_targetObject = aTarget;
_nativeClass = [aTarget class];
_observersForKey = {};
_changesForKey = {};
_nestingForKey = {};
_observersForKeyLength = 0;
[self _replaceClass];
aTarget[KVOProxyKey] = self;
@@ -631,12 +631,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
{
// Fire change events for the dependent keys
var dependentKeysForClass = _nativeClass[DependentKeysKey],
dependentKeys = [dependentKeysForClass[theKeyPath] allObjects],
isBeforeFlag = !![theChanges objectForKey:CPKeyValueChangeNotificationIsPriorKey];
dependantKeys = [dependentKeysForClass[theKeyPath] allObjects];
for (var i = 0; i < [dependentKeys count]; i++)
var isBeforeFlag = !![theChanges objectForKey:CPKeyValueChangeNotificationIsPriorKey];
for (var i = 0; i < [dependantKeys count]; i++)
{
var dependantKey = [dependentKeys objectAtIndex:i];
var dependantKey = [dependantKeys objectAtIndex:i];
[self _sendNotificationsForKey:dependantKey changeOptions:theChanges isBefore:isBeforeFlag];
}
}
@@ -717,6 +717,18 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
if (isBefore)
{
if (changes)
{
// "willChange:X" nesting.
var level = _nestingForKey[aKey];
if (!level)
[CPException raise:CPInternalInconsistencyException reason:@"_changesForKey without _nestingForKey"];
_nestingForKey[aKey] = level + 1;
// Only notify on the first willChange..., silently note any following nested calls.
return;
}
_nestingForKey[aKey] = 1;
changes = changeOptions;
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey],
@@ -774,9 +786,19 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
}
else
{
if (!changes)
var level = _nestingForKey[aKey];
if (!changes || !level)
[CPException raise:@"CPKeyValueObservingException" reason:@"'didChange...' message called without prior call of 'willChange...'"];
_nestingForKey[aKey] = level - 1;
if (level - 1 > 0)
{
// willChange... was called multiple times. Only fire observation notifications when
// didChange... has been called an equal number of times.
return;
}
delete _nestingForKey[aKey];
[changes removeObjectForKey:CPKeyValueChangeNotificationIsPriorKey];
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey],
@@ -814,6 +836,8 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
[changes setObject:newValue forKey:CPKeyValueChangeNewKey];
}
delete _changesForKey[aKey];
}
var observers = [_observersForKey[aKey] allValues],
@@ -844,23 +868,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
{
var keyPath = dependentKeyPaths[index];
if (![_suppressedNotifications containsObject:keyPath])
[self _sendNotificationsForKey:keyPath
changeOptions:isBefore ? [changeOptions copy] : _changesForKey[keyPath]
isBefore:isBefore];
[self _sendNotificationsForKey:keyPath
changeOptions:isBefore ? [changeOptions copy] : _changesForKey[keyPath]
isBefore:isBefore];
}
}
- (void)suppressNotificationsForKeyPath:(CPString)keyPath
{
[_suppressedNotifications addObject:keyPath];
}
- (void)unsuppressNotificationsForKeyPath:(CPString)keyPath
{
[_suppressedNotifications removeObject:keyPath];
}
@end
@implementation _CPKVOModelSubclass
+43 -11
View File
@@ -59,7 +59,7 @@ task ("sudo-install", ["CommonJS"], function()
if (OS.system(["sudo", "tusk", "install", "--force", $BUILD_CJS_OBJECTIVE_J, $BUILD_CJS_CAPPUCCINO]))
{
// Attempt a hackish work-around for sudo compiled with the --with-secure-path option
sudo("tusk install --force " + $BUILD_CJS_OBJECTIVE_J + " " + $BUILD_CJS_CAPPUCCINO)
sudo("tusk install --force " + $BUILD_CJS_OBJECTIVE_J + " " + $BUILD_CJS_CAPPUCCINO);
}
});
@@ -71,10 +71,38 @@ task ("install-symlinks", function()
task ("install-debug-symlinks", function()
{
SYSTEM.env["CONFIG"] = "Debug";
SYSTEM.env.CONFIG = "Debug";
spawnJake("install-symlinks");
});
task ("clean-sprites", function()
{
var f = new FileList(FILE.join(SYSTEM.env.CAPP_BUILD, "**/dataURLs.txt")),
paths = f.items();
f = new FileList(FILE.join(SYSTEM.env.CAPP_BUILD, "**/MHTML*.txt"));
paths = paths.concat(f.items());
paths.forEach(function(path)
{
FILE.remove(path);
});
});
task ("clobber-theme", function()
{
var f = new FileList(FILE.join(SYSTEM.env.CAPP_BUILD, "**/Aristo.blend")),
paths = f.items();
f = new FileList(FILE.join(SYSTEM.env.CAPP_BUILD, "Aristo.build"));
paths = paths.concat(f.items());
paths.forEach(function(path)
{
rm_rf(path);
});
});
// Documentation
$DOCUMENTATION_BUILD = FILE.join($BUILD_DIR, "Documentation");
@@ -160,6 +188,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"));
}
}
@@ -247,30 +279,30 @@ task ("demos", function()
if (key)
return this._plist.valueForKey(key);
return this._plist;
}
};
Demo.prototype.name = function()
{
return this.plist("CPBundleName");
}
};
Demo.prototype.path = function()
{
return this._path;
}
};
Demo.prototype.excluded = function()
{
return !!this.plist("CPDemoExcluded");
}
};
Demo.prototype.toString = function()
{
return this.name();
}
};
FILE.glob(FILE.join(demosDir, "demos", "**/Info.plist")).map(function(demoPath){
return new Demo(FILE.dirname(demoPath))
return new Demo(FILE.dirname(demoPath));
}).filter(function(demo){
return !demo.excluded();
}).forEach(function(demo)
@@ -315,7 +347,7 @@ task("push-cappuccino", function() {
pushPackage(
$BUILD_CJS_CAPPUCCINO,
"git@github.com:280north/cappuccino-package.git",
SYSTEM.env["PACKAGE_BRANCH"]
SYSTEM.env.PACKAGE_BRANCH
);
});
@@ -323,7 +355,7 @@ task("push-objective-j", function() {
pushPackage(
$BUILD_CJS_OBJECTIVE_J,
"git@github.com:280north/objective-j-package.git",
SYSTEM.env["PACKAGE_BRANCH"]
SYSTEM.env.PACKAGE_BRANCH
);
});
@@ -361,7 +393,7 @@ function pushPackage(path, remote, branch)
var pkg = JSON.parse(packagePath.join("package.json").read({ charset : "UTF-8" }));
stream.print(" Version: " + colorize(pkg["version"], "purple"));
stream.print(" Version: " + colorize(pkg.version, "purple"));
stream.print(" Revision: " + colorize(pkg["cappuccino-revision"], "purple"));
stream.print(" Timestamp: " + colorize(pkg["cappuccino-timestamp"], "purple"));
+74 -1
View File
@@ -464,6 +464,45 @@
[self assert:1 equals:[observations count] message:@"exactly 1 notification for insertObject x 2 (clearsFilterPredicate YES)"];
}
/**
Replicate the situation found in the Bindings manual test where one array controller's
contents depend on the selection of another.
*/
- (void)testObservationBetweenBoundControllers
{
var companies = [Companies new],
companiesController = [CPArrayController new],
employeesController = [CPArrayController new];
[companiesController bind:@"contentArray" toObject:companies withKeyPath:@"items" options:nil];
[employeesController bind:@"contentArray" toObject:companiesController withKeyPath:@"selection.employees" options:nil];
[companiesController addObserver:self forKeyPath:@"selection" options:0 context:@"companies.selection"];
[companiesController addObserver:self forKeyPath:@"selectionIndexes" options:0 context:@"companies.selectionIndexes"];
[companiesController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:@"companies.arrangedObjects"];
[employeesController addObserver:self forKeyPath:@"selectionIndexes" options:0 context:@"employees.selectionIndexes"];
[employeesController addObserver:self forKeyPath:@"selection" options:0 context:@"employees.selection"];
[employeesController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:@"employees.arrangedObjects"];
observations = [];
[companiesController setSelectionIndexes:[CPIndexSet indexSetWithIndex:1]];
//for (var i = 0; i < [observations count]; i++)
// CPLog.error(observations[i].context);
// There should be exactly one observation of each kind, and they should be in the right
// order.
[self assert:5 equals:[observations count]];
[self assert:@"companies.selectionIndexes" equals:observations[0].context];
[self assert:@"employees.arrangedObjects" equals:observations[1].context];
[self assert:@"employees.selectionIndexes" equals:observations[2].context];
[self assert:@"employees.selection" equals:observations[3].context];
// This observation registers after the employees update because we are later in the
// observation queue than the binding.
[self assert:@"companies.selection" equals:observations[4].context];
}
- (void)testCompoundKeyPaths
{
var departmentNameField = [[CPTextField alloc] init];
@@ -524,6 +563,18 @@
[self assert:[1, 2, 1] equals:[ac arrangedObjects] message:"only one copy of 1 removed + the right copy should be removed"];
}
- (void)testSetOutOfBoundsSelectedIndexes
{
var ac = [CPArrayController new],
contentArray = [1, 2, 3],
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 4)];
[ac setContent:contentArray];
[ac setSelectionIndexes:indexes];
[self assert:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 3)] equals:[ac selectionIndexes]];
[self assert:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, 4)] equals:indexes];
}
- (void)observeValueForKeyPath:keyPath
ofObject:anActivity
change:change
@@ -534,6 +585,7 @@
[observations addObject:{
keyPath: keyPath,
context: context,
oldValue: [change valueForKey:CPKeyValueChangeOldKey],
newValue: [change valueForKey:CPKeyValueChangeNewKey]
}];
@@ -620,4 +672,25 @@
return self;
}
@end
@end
@implementation Companies : CPObject
{
CPMutableArray items @accessors;
}
- (id)init
{
self = [super init];
if (self)
{
items = [CPMutableArray array];
[items addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Spacely Sprockets", @"name", [CPArray arrayWithObjects:@"Tom", @"Dick", @"Harry"], @"employees"]];
[items addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Cogswell Cogs", @"name", [CPArray arrayWithObjects:@"Jane", @"Mary", @"Vic"], @"employees"]];
}
return self;
}
@end
+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
-41
View File
@@ -78,27 +78,6 @@
[contentView addSubview:employeesScrollView];
[contentView addSubview:text];
var button = [CPButton buttonWithTitle:@"Add Item"];
[button setFrameOrigin:CGPointMake(500, 30)];
[button setTarget:self];
[button setAction:@selector(addItem:)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"Insert Item"];
[button setFrameOrigin:CGPointMake(500, 70)];
[button setTarget:self];
[button setAction:@selector(insertItem:)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"Remove Item"];
[button setFrameOrigin:CGPointMake(500, 110)];
[button setTarget:self];
[button setAction:@selector(removeItem:)];
[contentView addSubview:button];
companiesController = [CPArrayController new];
[companiesController bind:@"contentArray" toObject:companies withKeyPath:@"items" options:nil];
@@ -129,24 +108,4 @@
console.log("\nkeyPath: %s\ncontext: %s\nnew: %s\nold: %s", keyPath, context, [[change valueForKey:CPKeyValueChangeNewKey] description], [[change valueForKey:CPKeyValueChangeOldKey] description]);
}
- (void)addItem:(id)sender
{
var item = [CPDictionary dictionaryWithObjectsAndKeys:@"Seven Dwarves", @"name", [CPArray arrayWithObjects:@"Sneezy", @"Dopey", @"Sleepy", @"Doc", @"Bashful", @"Happy", @"Grumpy"], @"employees"];
[companiesController addObject:item];
}
- (void)insertItem:(id)sender
{
var item = [CPDictionary dictionaryWithObjectsAndKeys:@"Acme Corp", @"name", [CPArray arrayWithObjects:@"Road Runner", @"Wile E. Coyote"], @"employees"];
[companiesController insertObject:item atArrangedObjectIndex:1];
}
- (void)removeItem:(id)sender
{
if ([[companiesController arrangedObjects] count])
[companiesController removeObjectAtArrangedObjectIndex:0];
}
@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

+5 -7
View File
@@ -1,10 +1,10 @@
require("../../common.jake");
var OS = require("os");
var task = require("jake").task
var stream = require("narwhal/term").stream;
var applicationName = "xcodecapp-cocoa.app";
var OS = require("os"),
task = require("jake").task,
stream = require("narwhal/term").stream,
applicationName = "xcodecapp-cocoa.app";
task ("build", function()
{
@@ -22,9 +22,7 @@ task ("build", function()
cp_r(FILE.join("build", "Release", "xcodecapp-cocoa.app"), supportPath);
FILE.chmod(FILE.join(supportPath, "Contents", "MacOS", "xcodecapp-cocoa"), 0755);
if (FILE.exists(installPath))
FILE.remove(installPath);
FILE.symlink(supportPath, installPath);
OS.system(["ln", "-sf", supportPath, installPath]);
}
else
{
+1 -1
View File
@@ -133,7 +133,7 @@ global.$BUILD_CJS_CAPPUCCINO_FRAMEWORKS = FILE.join($BUILD_CJS_CAPPUCCINO, "Fram
global.CLEAN = require("jake/clean").CLEAN;
global.CLOBBER = require("jake/clean").CLOBBER;
global.CLEAN.include(global.$BUILD_DIR);
global.CLEAN.include(FILE.join(global.$BUILD_DIR, "*.build"));
global.CLOBBER.include(global.$BUILD_DIR);
global.$HOME_DIR = FILE.absolute(FILE.dirname(module.path));