mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 12:17:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be0b97cb56 | ||
|
|
6f7cbe21ef | ||
|
|
eff3dfc74a | ||
|
|
2ad1f4e4e5 | ||
|
|
4aec3f7466 | ||
|
|
c8991e07b9 | ||
|
|
48157db973 | ||
|
|
d070e5fce5 | ||
|
|
a8fae51ea8 | ||
|
|
2815d462be | ||
|
|
ed002d7d3e | ||
|
|
a7994c1480 | ||
|
|
85f8ca9241 | ||
|
|
b5fb9e8c23 | ||
|
|
c605ca4531 | ||
|
|
c288930a3c | ||
|
|
596676a562 | ||
|
|
cc3d9f337c | ||
|
|
1addc002d3 | ||
|
|
e99e2660e9 | ||
|
|
03d1bb8bce | ||
|
|
8d210100a5 | ||
|
|
d25e96902f | ||
|
|
ad792d9772 | ||
|
|
5b00f7f2e8 | ||
|
|
97b7f0901e | ||
|
|
67b2671dad | ||
|
|
9e7b737960 | ||
|
|
9bc6a69b76 | ||
|
|
1cb28e4206 | ||
|
|
5311689265 | ||
|
|
4228a2a146 | ||
|
|
7886d49e65 | ||
|
|
e5284e9b43 | ||
|
|
c6403baa04 | ||
|
|
662b1ec696 | ||
|
|
043df71185 | ||
|
|
8dab47f4da | ||
|
|
90d069df2b | ||
|
|
dcbe3ee650 | ||
|
|
e32489aba1 | ||
|
|
b619c0b793 | ||
|
|
fab61d14fa | ||
|
|
b4edc084f8 | ||
|
|
c7518d0c49 | ||
|
|
a40345c14d | ||
|
|
bacc50c271 | ||
|
|
909471a5d7 | ||
|
|
38f7ea00c2 | ||
|
|
9f459f053e | ||
|
|
4195f3b8c6 | ||
|
|
4926824482 | ||
|
|
cb2f539cf7 | ||
|
|
7f31be7cb1 | ||
|
|
78b9c5b576 | ||
|
|
01e35efdbb | ||
|
|
bef1687b1f | ||
|
|
da18a9eb24 | ||
|
|
d975e90407 | ||
|
|
abc8e14275 | ||
|
|
b032cd5b7d | ||
|
|
bb589285e3 | ||
|
|
1d52c3e957 | ||
|
|
df5ce9e0f3 | ||
|
|
16b446ae08 | ||
|
|
afa691376e | ||
|
|
be10bcf27a | ||
|
|
d0a5b6e1c7 | ||
|
|
271a1ef3b4 | ||
|
|
b91042eb08 | ||
|
|
608cb86a4a | ||
|
|
88780ff0a9 | ||
|
|
a5e241afd7 | ||
|
|
28772d3254 | ||
|
|
d1f5c1eebc | ||
|
|
d40ebaf369 | ||
|
|
06f74e5ef0 | ||
|
|
5eaeb5f05e | ||
|
|
961cb2f6ed | ||
|
|
4dca2bbb85 | ||
|
|
892d3d7120 | ||
|
|
c0fe499937 | ||
|
|
01e8e9e597 | ||
|
|
08b740c36f | ||
|
|
31918bc0cd | ||
|
|
d45aeed224 | ||
|
|
7d2835c522 | ||
|
|
c77a282aaf | ||
|
|
7a1cd5c545 |
+70
-108
@@ -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)
|
||||
{
|
||||
|
||||
+53
-88
@@ -389,12 +389,12 @@ var CPComboBoxTextSubview = @"text",
|
||||
_listDelegate = aDelegate;
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(listWillPopUp:)
|
||||
selector:@selector(comboBoxWillPopUp:)
|
||||
name:_CPPopUpListWillPopUpNotification
|
||||
object:_listDelegate];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(listWillDismiss:)
|
||||
selector:@selector(comboBoxWillDismiss:)
|
||||
name:_CPPopUpListWillDismissNotification
|
||||
object:_listDelegate];
|
||||
|
||||
@@ -467,7 +467,7 @@ var CPComboBoxTextSubview = @"text",
|
||||
- (void)popUpList
|
||||
{
|
||||
if (!_listDelegate)
|
||||
[self setListDelegate:[[_CPPopUpList alloc] initWithDelegate:self]];
|
||||
[self setListDelegate:[[_CPPopUpList alloc] initWithDataSource:self]];
|
||||
|
||||
[self selectMatchingItem];
|
||||
|
||||
@@ -521,24 +521,6 @@ var CPComboBoxTextSubview = @"text",
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
The receiver receives this notification when the list is about to be pop up.
|
||||
@ignore
|
||||
*/
|
||||
- (void)listWillPopUp:(CPNotification)aNotification
|
||||
{
|
||||
[self comboBoxWillPopUp];
|
||||
}
|
||||
|
||||
/*!
|
||||
The receiver receives this notification when the list is about to be dismissed.
|
||||
@ignore
|
||||
*/
|
||||
- (void)listWillDismiss:(CPNotification)aNotification
|
||||
{
|
||||
[self comboBoxWillDismiss];
|
||||
}
|
||||
|
||||
/*!
|
||||
The receiver receives this notification when the list is closed.
|
||||
@ignore
|
||||
@@ -731,7 +713,10 @@ var CPComboBoxTextSubview = @"text",
|
||||
[super textDidChange:aNotification];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
/*!
|
||||
Override of CPView -performKeyEquivalent
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
|
||||
{
|
||||
if ([[self window] firstResponder] === self)
|
||||
@@ -741,17 +726,9 @@ var CPComboBoxTextSubview = @"text",
|
||||
switch (key)
|
||||
{
|
||||
case CPDownArrowFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
[_listDelegate selectNextItem];
|
||||
else
|
||||
[self popUpList];
|
||||
|
||||
return YES;
|
||||
|
||||
case CPUpArrowFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
if (![self listIsVisible])
|
||||
{
|
||||
[_listDelegate selectPreviousItem];
|
||||
[self popUpList];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
@@ -763,44 +740,12 @@ var CPComboBoxTextSubview = @"text",
|
||||
// in the list, revert to the most recent valid value.
|
||||
if (_forceSelection && ([self _inputElement].value !== _selectedStringValue))
|
||||
[self setStringValue:_selectedStringValue];
|
||||
|
||||
[_listDelegate close];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPPageUpFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
{
|
||||
[_listDelegate scrollPageUp];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPPageDownFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
{
|
||||
[_listDelegate scrollPageDown];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPHomeFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
{
|
||||
[_listDelegate scrollToTop];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPEndFunctionKey:
|
||||
if ([self listIsVisible])
|
||||
{
|
||||
[_listDelegate scrollToBottom];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ([_listDelegate performKeyEquivalent:anEvent])
|
||||
return YES;
|
||||
}
|
||||
|
||||
return [super performKeyEquivalent:anEvent];
|
||||
@@ -817,18 +762,15 @@ var CPComboBoxTextSubview = @"text",
|
||||
If the list or popup button is clicked, we lose focus. The list will refuse first responder,
|
||||
and we refuse to resign. But we still have to manually restore the focus to the input element.
|
||||
*/
|
||||
if ([_listDelegate listWasClicked] || buttonCausedResign)
|
||||
{
|
||||
/*
|
||||
If an item was not clicked (probably the scrollbar), clear the click flag so that future
|
||||
clicks outside the list will allow it to close. It isn't so great doing that here, but
|
||||
the sequence of events is such that it has to be done here.
|
||||
*/
|
||||
if ([_listDelegate listWasClicked] && ![_listDelegate itemWasClicked])
|
||||
[_listDelegate setListWasClicked:NO];
|
||||
var shouldResign = !buttonCausedResign && [_listDelegate controllingViewShouldResign];
|
||||
|
||||
if (!shouldResign)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
[self _inputElement].focus();
|
||||
// In FireFox this needs to be done in setTimeout, otherwise there is no caret
|
||||
// We have to save the input element now, when we lose focus it will change.
|
||||
var element = [self _inputElement];
|
||||
window.setTimeout(function() { element.focus(); }, 0);
|
||||
#endif
|
||||
|
||||
return NO;
|
||||
@@ -917,14 +859,6 @@ var CPComboBoxTextSubview = @"text",
|
||||
CPLog.warn("-[%s %s] should not be called when usesDataSource is set to %s", [self className], cmd, flag ? "YES" : "NO");
|
||||
}
|
||||
|
||||
- (id)objectValueForItemAtIndex:(int)index
|
||||
{
|
||||
if (_usesDataSource)
|
||||
return [_dataSource comboBox:self objectValueForItemAtIndex:index];
|
||||
else
|
||||
return _items[index];
|
||||
}
|
||||
|
||||
/*!
|
||||
Select the item that matches the current value of the combobox.
|
||||
@ignore
|
||||
@@ -971,7 +905,6 @@ var CPComboBoxTextSubview = @"text",
|
||||
- (CGRect)borderFrame
|
||||
{
|
||||
var inset = [self borderInset],
|
||||
buttonSize = [self currentValueForThemeAttribute:@"popup-button-size"],
|
||||
frame = [self bounds];
|
||||
|
||||
frame.origin.x += inset.left;
|
||||
@@ -1022,13 +955,13 @@ var CPComboBoxTextSubview = @"text",
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)comboBoxWillPopUp
|
||||
- (void)comboBoxWillPopUp:(CPNotification)aNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)comboBoxWillDismiss
|
||||
- (void)comboBoxWillDismiss:(CPNotification)aNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self];
|
||||
}
|
||||
@@ -1048,6 +981,38 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPComboBox (_CPPopUpListDataSource)
|
||||
|
||||
- (int)numberOfItemsInList:(_CPPopUpList)aList
|
||||
{
|
||||
return [self numberOfItems];
|
||||
}
|
||||
|
||||
- (int)numberOfVisibleItemsInList:(_CPPopUpList)aList
|
||||
{
|
||||
return [self numberOfVisibleItems];
|
||||
}
|
||||
|
||||
- (id)list:(_CPPopUpList)aList objectValueForItemAtIndex:(int)index
|
||||
{
|
||||
if (_usesDataSource)
|
||||
return [_dataSource comboBox:self objectValueForItemAtIndex:index];
|
||||
else
|
||||
return _items[index];
|
||||
}
|
||||
|
||||
- (id)list:(_CPPopUpList)aList displayValueForObjectValue:(id)aValue
|
||||
{
|
||||
return aValue || @"";
|
||||
}
|
||||
|
||||
- (CPString)list:(_CPPopUpList)aList stringValueForObjectValue:(id)aValue
|
||||
{
|
||||
return String(aValue);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPComboBox (Bindings)
|
||||
|
||||
/*! @ignore */
|
||||
|
||||
+3
-3
@@ -526,7 +526,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
// Cocoa raises an invalid parameter assertion and returns if you pass nil.
|
||||
if (aString === nil || aString === undefined)
|
||||
{
|
||||
CPLog.warn("nil sent to CPControl -setStringValue");
|
||||
CPLog.warn("nil or undefined sent to CPControl -setStringValue");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -536,10 +536,10 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
{
|
||||
value = nil;
|
||||
|
||||
if ([_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil] === NO)
|
||||
if (![_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil])
|
||||
{
|
||||
// If the given string is non-empty and doesn't work, Cocoa tries an empty string.
|
||||
if (!aString || [_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO)
|
||||
if (!aString || ![_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil])
|
||||
value = undefined; // Means the value is invalid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
|
||||
_contentObject = aContent;
|
||||
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
[self _selectionDidChange];
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -626,15 +626,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#endif
|
||||
|
||||
// post CPControlTextDidEndEditingNotification
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
|
||||
|
||||
|
||||
+30
-3
@@ -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
-12
@@ -426,6 +426,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
// Create a generic content view.
|
||||
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
|
||||
[self setInitialFirstResponder:[self contentView]];
|
||||
|
||||
_firstResponder = self;
|
||||
|
||||
@@ -480,6 +481,7 @@ CPTexturedBackgroundWindowMask
|
||||
[self close];
|
||||
|
||||
_platformWindow = aPlatformWindow;
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
if (wasVisible)
|
||||
[self orderFront:self];
|
||||
@@ -949,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]];
|
||||
|
||||
@@ -1273,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;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1359,6 +1367,7 @@ CPTexturedBackgroundWindowMask
|
||||
_title = aTitle;
|
||||
|
||||
[_windowView setTitle:aTitle];
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||
}
|
||||
@@ -2485,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];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2596,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]);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ var PrimaryPlatformWindow = NULL;
|
||||
CPInteger _level;
|
||||
BOOL _hasShadow;
|
||||
unsigned _shadowStyle;
|
||||
CPString _title;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
DOMWindow _DOMWindow;
|
||||
@@ -258,6 +259,21 @@ var PrimaryPlatformWindow = NULL;
|
||||
return [CPPlatform isBrowser];
|
||||
}
|
||||
|
||||
- (void)_setTitle:(CPString)aTitle window:(CPWindow)aWindow
|
||||
{
|
||||
_title = aTitle;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.document && (aWindow === [CPApp mainWindow]))
|
||||
_DOMWindow.document.title = _title;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (CPString)title
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if PLATFORM(BROWSER)
|
||||
|
||||
@@ -534,13 +534,15 @@ var ModifierKeyCodes = [
|
||||
if (_DOMWindow)
|
||||
return _DOMWindow.focus();
|
||||
|
||||
_DOMWindow = window.open("", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect));
|
||||
_DOMWindow = window.open("about:blank", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect));
|
||||
|
||||
[PlatformWindows addObject:self];
|
||||
|
||||
// FIXME: cpSetFrame?
|
||||
_DOMWindow.document.write("<!DOCTYPE html><html lang='en'><head></head><body style='background-color:transparent;'></body></html>");
|
||||
_DOMWindow.document.close();
|
||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||
_DOMWindow.document.title = _title;
|
||||
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
|
||||
+431
-308
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
@import "CPTableView.j"
|
||||
@import "_CPPopUpListDataSource.j"
|
||||
|
||||
|
||||
/*!
|
||||
@@ -69,13 +70,9 @@ var ListColumnIdentifier = @"1";
|
||||
|
||||
/*!
|
||||
This class is a controller for a panel that can pop up and display a scrollable list of items in a CPTableView.
|
||||
For tables that display single-line rows of scalar data, no subclassing should be necessary.
|
||||
It is used by CPComboBox to display the list of choices.
|
||||
|
||||
The delegate of this class MUST implement the following methods:
|
||||
|
||||
numberOfItems The number of items the list should display
|
||||
numberOfVisibleItems The maximum number of items to display at once
|
||||
objectValueForItemAtIndex: Retrieves an object value for an item in the range 0..(numberOfItems - 1)
|
||||
This class requires a data source which must conform to the interface of _CPPopUpListDataSource.
|
||||
|
||||
Objects of this class send the following notifications:
|
||||
|
||||
@@ -86,28 +83,30 @@ var ListColumnIdentifier = @"1";
|
||||
*/
|
||||
@implementation _CPPopUpList : CPObject
|
||||
{
|
||||
_CPPopUpListDelegate _delegate;
|
||||
_CPPopUpListDataSource _dataSource;
|
||||
BOOL _itemWasClicked;
|
||||
BOOL _listWasClicked;
|
||||
int _listWidth;
|
||||
_CPPopUpPanel _panel @accessors(readonly, property=panel);
|
||||
CPScrollView _scrollView @accessors(readonly, property=scrollView);
|
||||
_CPPopUpTableView _tableView @accessors(readonly, property=tableView);
|
||||
_CPPopUpPanel _panel;
|
||||
CPScrollView _scrollView;
|
||||
_CPPopUpTableView _tableView;
|
||||
CPTableColumn _tableColumn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a pop up list of choices which will display relative to the given rect in base coordinates.
|
||||
#pragma mark Creating and Displaying a List
|
||||
|
||||
@param aDelegate The object that usually is controlling this list.
|
||||
/*!
|
||||
Creates a pop up list of choices that will display in a scrollable CPTableView.
|
||||
|
||||
@param aDataSource A subclass of _CPPopUpListDataSource
|
||||
*/
|
||||
- (id)initWithDelegate:(_CPPopUpListDelegate)aDelegate
|
||||
- (id)initWithDataSource:(_CPPopUpListDataSource)aDataSource
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_delegate = aDelegate;
|
||||
[self setDataSource:aDataSource];
|
||||
_itemWasClicked = NO;
|
||||
_listWasClicked = NO;
|
||||
_listWidth = 0;
|
||||
@@ -132,24 +131,18 @@ var ListColumnIdentifier = @"1";
|
||||
[[_panel contentView] addSubview:_scrollView];
|
||||
[_panel setInitialFirstResponder:_tableView];
|
||||
|
||||
if ([_delegate numberOfItems] > 0)
|
||||
if ([_dataSource numberOfItemsInList:self] > 0)
|
||||
[_tableView selectRowIndexes:[CPIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
|
||||
else
|
||||
[_tableView setEnabled:NO];
|
||||
|
||||
[_scrollView scrollToBeginningOfDocument:nil];
|
||||
|
||||
[self finalizeTableView:_tableView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Create and configure the panel containing the table view.
|
||||
Subclasses should override this (and usually call super first)
|
||||
if they want to customize the list panel.
|
||||
*/
|
||||
/*! @ignore */
|
||||
- (CPPanel)makeListPanelWithFrame:(CGRect)aFrame
|
||||
{
|
||||
var panel = [[_CPPopUpPanel alloc] initWithContentRect:aFrame styleMask:CPBorderlessWindowMask];
|
||||
@@ -164,9 +157,7 @@ var ListColumnIdentifier = @"1";
|
||||
return panel;
|
||||
}
|
||||
|
||||
/*!
|
||||
Create and configure the table view. Subclasses should use \ref finalizeTableView:.
|
||||
*/
|
||||
/*! @ignore */
|
||||
- (_CPPopUpTableView)makeTableView
|
||||
{
|
||||
[self removeTableViewObservers];
|
||||
@@ -187,6 +178,7 @@ var ListColumnIdentifier = @"1";
|
||||
return table;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)removeTableViewObservers
|
||||
{
|
||||
if (_tableView)
|
||||
@@ -198,21 +190,7 @@ var ListColumnIdentifier = @"1";
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
If subclasses want to configure the table view after it has been
|
||||
completely configured, for example to set a custom data view,
|
||||
this is the place. Such customization can also be done by an
|
||||
observer of _CPPopUpListListWillDisplayNotification.
|
||||
*/
|
||||
- (void)finalizeTableView:(CPTableView)aTableView
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and configures the scroll view containing the table view.
|
||||
Subclasses should override this (and usually call super first)
|
||||
if they want to customize the scroll view.
|
||||
*/
|
||||
/*! @ignore */
|
||||
- (CPScrollView)makeScrollViewWithFrame:(CGRect)aFrame
|
||||
{
|
||||
var scroll = [[CPScrollView alloc] initWithFrame:aFrame];
|
||||
@@ -227,6 +205,37 @@ var ListColumnIdentifier = @"1";
|
||||
return scroll;
|
||||
}
|
||||
|
||||
/*!
|
||||
Pop up the list if it is not already visible.
|
||||
If it is not visible, a _CPPopUpListWillPopUpNotification will be sent.
|
||||
|
||||
@param aRect A rect (in \c aView coordinates) to display relative to
|
||||
@param aView The view whose coordinate system \c aRect is in
|
||||
@param offset How far to offset the list from \c aRect
|
||||
*/
|
||||
- (void)popUpRelativeToRect:(CGRect)aRect view:(CPView)aView offset:(int)offset
|
||||
{
|
||||
if ([_panel isVisible])
|
||||
return;
|
||||
|
||||
var rowRect = [_tableView rectOfRow:[self numberOfRowsInTableView:_tableView] - 1],
|
||||
frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(aRect)), CGRectGetMaxY(rowRect));
|
||||
|
||||
// Place the frame relative to aRect and constrain it to the screen bounds
|
||||
frame = [self constrain:frame relativeToRect:aRect view:aView offset:offset];
|
||||
|
||||
[_panel setFrame:frame];
|
||||
[_scrollView setFrameSize:CGSizeMakeCopy(frame.size)];
|
||||
[_tableView setEnabled:[_dataSource numberOfItemsInList:self] > 0];
|
||||
[self scrollItemAtIndexToTop:[_tableView selectedRow]];
|
||||
|
||||
[self listWillPopUp];
|
||||
|
||||
[_panel orderFront:nil];
|
||||
}
|
||||
|
||||
#pragma mark Setting Display Attributes
|
||||
|
||||
/*!
|
||||
Returns the desired width of the list.
|
||||
*/
|
||||
@@ -272,31 +281,388 @@ var ListColumnIdentifier = @"1";
|
||||
}
|
||||
|
||||
/*!
|
||||
Pop up the list if it is not already visible.
|
||||
If it is not visible, a _CPPopUpListWillPopUpNotification will be sent.
|
||||
|
||||
@param aRect A rect (in \c aView coordinates) to display relative to
|
||||
@param aView The view whose coordinate system \c aRect is in
|
||||
@param offset How far to offset the list from \c aRect
|
||||
Returns whether the list is currently visible.
|
||||
*/
|
||||
- (void)popUpRelativeToRect:(CGRect)aRect view:(CPView)aView offset:(int)offset
|
||||
- (BOOL)isVisible
|
||||
{
|
||||
if ([_panel isVisible])
|
||||
return [_panel isVisible];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the desired row height for the table view.
|
||||
Subclasses should override this if they want something other than the default.
|
||||
*/
|
||||
- (int)rowHeightForTableView:(CPTableView)aTableView
|
||||
{
|
||||
return [aTableView rowHeight];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the table view used by the list.
|
||||
*/
|
||||
- (CPTableView)tableView
|
||||
{
|
||||
return _tableView;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the single table column used by the list.
|
||||
*/
|
||||
- (CPTableColumn)tableColumn
|
||||
{
|
||||
return _tableColumn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the scroll view used by the list.
|
||||
*/
|
||||
- (CPScrollView)scrollView
|
||||
{
|
||||
return _scrollView;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the panel in which the list appears.
|
||||
*/
|
||||
- (CPPanel)panel
|
||||
{
|
||||
return _panel;
|
||||
}
|
||||
|
||||
#pragma mark Setting a Data Source
|
||||
|
||||
- (void)setDataSource:(_CPPopUpListDataSource)aDataSource
|
||||
{
|
||||
if (_dataSource === aDataSource)
|
||||
return;
|
||||
|
||||
var rowRect = [_tableView rectOfRow:[self numberOfRowsInTableView:_tableView] - 1],
|
||||
frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(aRect)), CGRectGetMaxY(rowRect));
|
||||
if (![_CPPopUpListDataSource protocolIsImplementedByObject:aDataSource])
|
||||
{
|
||||
CPLog.warn("Illegal %s data source (%s). Must implement the methods in _CPPopUpListDataSource.", [self className], [aDataSource description]);
|
||||
}
|
||||
else
|
||||
_dataSource = aDataSource;
|
||||
}
|
||||
|
||||
// Place the frame relative to aRect and constrain it to the screen bounds
|
||||
frame = [self constrain:frame relativeToRect:aRect view:aView offset:offset];
|
||||
- (_CPPopUpListDataSource)dataSource
|
||||
{
|
||||
return _dataSource;
|
||||
}
|
||||
|
||||
[_panel setFrame:frame];
|
||||
[_scrollView setFrameSize:CGSizeMakeCopy(frame.size)];
|
||||
[self scrollItemAtIndexToTop:[_tableView selectedRow]];
|
||||
#pragma mark Manipulating the Selection
|
||||
|
||||
[self listWillPopUp];
|
||||
/*!
|
||||
Select the next item in the list if there one. If there is currently no selected item,
|
||||
the first item is selected. Returns YES if the selection changed.
|
||||
*/
|
||||
- (BOOL)selectNextItem
|
||||
{
|
||||
if (![_tableView isEnabled])
|
||||
return NO;
|
||||
|
||||
[_panel orderFront:nil];
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
if (row < ([_dataSource numberOfItemsInList:self] - 1))
|
||||
return [self selectRow:++row];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Select the previous item in the list. If there is currently no selected item,
|
||||
nothing happens. Returns YES if the selection changed.
|
||||
*/
|
||||
- (BOOL)selectPreviousItem
|
||||
{
|
||||
if (![_tableView isEnabled])
|
||||
return NO;
|
||||
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
if (row > 0)
|
||||
return [self selectRow:--row];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the selected object value. If no value is selected,
|
||||
returns nil.
|
||||
*/
|
||||
- (id)selectedObjectValue
|
||||
{
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
return (row >= 0) ? [_dataSource list:self objectValueForItemAtIndex:row] : nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the selected value as a single-line string. If no value is selected,
|
||||
returns nil.
|
||||
*/
|
||||
- (CPString)selectedStringValue
|
||||
{
|
||||
var value = [self selectedObjectValue];
|
||||
|
||||
return value !== nil ? [_dataSource list:self stringValueForObjectValue:value] : nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the last selected row in the list. If no row has been selected, returns -1.
|
||||
*/
|
||||
- (int)selectedRow
|
||||
{
|
||||
return [_tableView selectedRow];
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects a row and scrolls it to be visible. Returns YES if the selection actually changed.
|
||||
*/
|
||||
- (BOOL)selectRow:(int)row
|
||||
{
|
||||
if (row === [_tableView selectedRow])
|
||||
return NO;
|
||||
|
||||
var validRow = (row >= 0 && row < [self numberOfRowsInTableView:_tableView]),
|
||||
indexes = validRow ? [CPIndexSet indexSetWithIndex:row] : [CPIndexSet indexSet];
|
||||
|
||||
[_tableView selectRowIndexes:indexes byExtendingSelection:NO];
|
||||
|
||||
if (validRow)
|
||||
{
|
||||
[_tableView scrollRowToVisible:row];
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark Manipulating the Displayed List
|
||||
|
||||
/*!
|
||||
Scroll the list down one page.
|
||||
*/
|
||||
- (void)scrollPageDown
|
||||
{
|
||||
[_scrollView scrollPageDown:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll the list up one page.
|
||||
*/
|
||||
- (void)scrollPageUp
|
||||
{
|
||||
[_scrollView scrollPageUp:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll to the top of the list.
|
||||
*/
|
||||
- (void)scrollToTop
|
||||
{
|
||||
[_scrollView scrollToBeginningOfDocument:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll to the bottom of the list.
|
||||
*/
|
||||
- (void)scrollToBottom
|
||||
{
|
||||
[_scrollView scrollToEndOfDocument:nil];
|
||||
}
|
||||
|
||||
- (void)scrollItemAtIndexToTop:(int)row
|
||||
{
|
||||
var rect = [_tableView rectOfRow:row];
|
||||
|
||||
[[_tableView superview] scrollToPoint:rect.origin];
|
||||
}
|
||||
|
||||
/*!
|
||||
Close the list if it is currently visible. If it is visible,
|
||||
a CPComboBoxWillDismissNotification will be sent. If the
|
||||
list is being closed after an item was clicked, the close
|
||||
is delayed slightly so the user can briefly see the clicked row
|
||||
get highlighted.
|
||||
*/
|
||||
- (void)close
|
||||
{
|
||||
if (![_panel isVisible])
|
||||
return;
|
||||
|
||||
if ([self listWasClicked])
|
||||
{
|
||||
[self setListWasClicked:NO];
|
||||
|
||||
// Wait until we get through the run loop and delay a little
|
||||
// so the user can briefly see the clicked row get highlighted.
|
||||
if ([self itemWasClicked])
|
||||
{
|
||||
[self setItemWasClicked:NO];
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(closeListAfterItemClick) userInfo:nil repeats:NO];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListWillDismissNotification object:self];
|
||||
[_panel close];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListDidDismissNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Close the list after an item was clicked.
|
||||
*/
|
||||
- (void)closeListAfterItemClick
|
||||
{
|
||||
[self close];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListItemWasClickedNotification object:self];
|
||||
}
|
||||
|
||||
#pragma mark Handling Events
|
||||
|
||||
/*!
|
||||
Handles standard key equivalents for moving the selection
|
||||
and selecting an item. This method should be called by
|
||||
the -performKeyEquivalent method of the field that is
|
||||
controlling the list.
|
||||
*/
|
||||
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
|
||||
{
|
||||
var key = [anEvent charactersIgnoringModifiers];
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case CPDownArrowFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self selectNextItem];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPUpArrowFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self selectPreviousItem];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPEscapeFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self close];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPPageUpFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self scrollPageUp];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPPageDownFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self scrollPageDown];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPHomeFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self scrollToTop];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPEndFunctionKey:
|
||||
if ([self isVisible])
|
||||
{
|
||||
[self scrollToBottom];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether an item in the list was clicked since it was opened.
|
||||
If there are no items, \ref itemWasClicked will always return NO.
|
||||
*/
|
||||
- (BOOL)itemWasClicked
|
||||
{
|
||||
return _itemWasClicked && ([_dataSource numberOfItemsInList:self] > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether an item in the list was clicked since it was opened.
|
||||
If there are no items, \ref itemWasClicked will always return NO.
|
||||
|
||||
Subclasses will usually want to set this in the mouseDown:
|
||||
of the control.
|
||||
*/
|
||||
- (void)setItemWasClicked:(BOOL)flag
|
||||
{
|
||||
_itemWasClicked = ([_dataSource numberOfItemsInList:self] > 0) && flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether any view in the list was clicked since it was opened.
|
||||
If there are no items, \ref listWasClicked will always return NO.
|
||||
*/
|
||||
- (BOOL)listWasClicked
|
||||
{
|
||||
return _listWasClicked && ([_dataSource numberOfItemsInList:self] > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether any view in the list was clicked since it was opened.
|
||||
If there are no items, \ref listWasClicked will always return NO.
|
||||
|
||||
Subclasses will usually want to use a subclass of CPPanel and override
|
||||
sendEvent: to set this flag when the event type is CPLeftMouseDown
|
||||
or CPRightMouseDown. This is distinct from \ref itemWasClicked because,
|
||||
for example, a scroller in the list may be clicked without clicking an
|
||||
item in the list.
|
||||
*/
|
||||
- (void)setListWasClicked:(BOOL)flag
|
||||
{
|
||||
_listWasClicked = ([_dataSource numberOfItemsInList:self] > 0) && flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether a controlling view should resign. This should be called
|
||||
from the controlling view's resignFirstResponder method.
|
||||
*/
|
||||
- (BOOL)controllingViewShouldResign
|
||||
{
|
||||
if ([self listWasClicked])
|
||||
{
|
||||
/*
|
||||
If an item was not clicked (probably the scrollbar), clear the click flag so that future
|
||||
clicks outside the list will allow it to close.
|
||||
*/
|
||||
if ([self listWasClicked] && ![self itemWasClicked])
|
||||
[self setListWasClicked:NO];
|
||||
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
return YES;
|
||||
}
|
||||
#pragma mark Internal Helpers
|
||||
|
||||
/*! @ignore */
|
||||
- (void)listWillPopUp
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListWillPopUpNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -305,6 +671,7 @@ var ListColumnIdentifier = @"1";
|
||||
for at least ListMinimumItems items, an attempt should be made to display that many
|
||||
items above \c aRect. If the minimum cannot be displayed on top, whichever direction can display more items
|
||||
is chosen.
|
||||
@ignore
|
||||
*/
|
||||
- (CGRect)constrain:(CGRect)aFrame relativeToRect:(CGRect)aRect view:(CPView)aView offset:(int)offset
|
||||
{
|
||||
@@ -314,7 +681,7 @@ var ListColumnIdentifier = @"1";
|
||||
rowHeight = [self rowHeightForTableView:_tableView] + [_tableView intercellSpacing].height,
|
||||
|
||||
// Be sure to clip the number of displayed rows to what the field wants
|
||||
numberOfRows = MIN([self numberOfRowsInTableView:_tableView], [_delegate numberOfVisibleItems]),
|
||||
numberOfRows = MIN([self numberOfRowsInTableView:_tableView], [_dataSource numberOfVisibleItemsInList:self]),
|
||||
|
||||
// Add 2 to height for border
|
||||
frame = CGRectMake(windowOrigin.x, windowOrigin.y + CGRectGetHeight(aRect) + offset, MAX(_listWidth, CGRectGetWidth(aFrame)), (rowHeight * numberOfRows) + 2),
|
||||
@@ -363,250 +730,6 @@ var ListColumnIdentifier = @"1";
|
||||
return frame;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether the list is currently visible.
|
||||
*/
|
||||
- (BOOL)isVisible
|
||||
{
|
||||
return [_panel isVisible];
|
||||
}
|
||||
|
||||
/*!
|
||||
Subclasses MUST call this method just before the list is about to display.
|
||||
*/
|
||||
- (void)listWillPopUp
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListWillPopUpNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Select the next item in the list if there one. If there is currently no selected item,
|
||||
the first item is selected. Returns YES if the selection changed.
|
||||
*/
|
||||
- (BOOL)selectNextItem
|
||||
{
|
||||
if (![_tableView isEnabled])
|
||||
return NO;
|
||||
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
if (row < ([_delegate numberOfItems] - 1))
|
||||
return [self selectRow:++row];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Select the previous item in the list. If there is currently no selected item,
|
||||
nothing happens. Returns YES if the selection changed.
|
||||
*/
|
||||
- (BOOL)selectPreviousItem
|
||||
{
|
||||
if (![_tableView isEnabled])
|
||||
return NO;
|
||||
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
if (row > 0)
|
||||
return [self selectRow:--row];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll the list down one page.
|
||||
*/
|
||||
- (void)scrollPageDown
|
||||
{
|
||||
[_scrollView scrollPageDown:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll the list up one page.
|
||||
*/
|
||||
- (void)scrollPageUp
|
||||
{
|
||||
[_scrollView scrollPageUp:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll to the top of the list.
|
||||
*/
|
||||
- (void)scrollToTop
|
||||
{
|
||||
[_scrollView scrollToBeginningOfDocument:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Scroll to the bottom of the list.
|
||||
*/
|
||||
- (void)scrollToBottom
|
||||
{
|
||||
[_scrollView scrollToEndOfDocument:nil];
|
||||
}
|
||||
|
||||
- (BOOL)selectRow:(int)row
|
||||
{
|
||||
if (row === [_tableView selectedRow])
|
||||
return NO;
|
||||
|
||||
var indexes = row >= 0 ? [CPIndexSet indexSetWithIndex:row] : [CPIndexSet indexSet];
|
||||
|
||||
[_tableView selectRowIndexes:indexes byExtendingSelection:NO];
|
||||
|
||||
if (row >= 0)
|
||||
{
|
||||
[_tableView scrollRowToVisible:row];
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)scrollItemAtIndexToTop:(int)row
|
||||
{
|
||||
var rect = [_tableView rectOfRow:row];
|
||||
|
||||
[[_tableView superview] scrollToPoint:rect.origin];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the selected value as a single-line string. If no value is selected,
|
||||
returns nil.
|
||||
*/
|
||||
- (CPString)selectedStringValue
|
||||
{
|
||||
var row = [_tableView selectedRow];
|
||||
|
||||
return (row >= 0) ? [self stringValueForObjectValue:[_delegate objectValueForItemAtIndex:row] row:row] : nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether an item in the list was clicked since it was opened.
|
||||
If there are no items, \ref itemWasClicked will always return NO.
|
||||
*/
|
||||
- (BOOL)itemWasClicked
|
||||
{
|
||||
return _itemWasClicked && ([_delegate numberOfItems] > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether an item in the list was clicked since it was opened.
|
||||
If there are no items, \ref itemWasClicked will always return NO.
|
||||
|
||||
Subclasses will usually want to set this in the mouseDown:
|
||||
of the control.
|
||||
*/
|
||||
- (void)setItemWasClicked:(BOOL)flag
|
||||
{
|
||||
_itemWasClicked = ([_delegate numberOfItems] > 0) && flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether any view in the list was clicked since it was opened.
|
||||
If there are no items, \ref listWasClicked will always return NO.
|
||||
*/
|
||||
- (BOOL)listWasClicked
|
||||
{
|
||||
return _listWasClicked && ([_delegate numberOfItems] > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether any view in the list was clicked since it was opened.
|
||||
If there are no items, \ref listWasClicked will always return NO.
|
||||
|
||||
Subclasses will usually want to use a subclass of CPPanel and override
|
||||
sendEvent: to set this flag when the event type is CPLeftMouseDown
|
||||
or CPRightMouseDown. This is distinct from \ref itemWasClicked because,
|
||||
for example, a scroller in the list may be clicked without clicking an
|
||||
item in the list.
|
||||
*/
|
||||
- (void)setListWasClicked:(BOOL)flag
|
||||
{
|
||||
_listWasClicked = ([_delegate numberOfItems] > 0) && flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Close the list if it is currently visible. If it is visible,
|
||||
a CPComboBoxWillDismissNotification will be sent. If the
|
||||
list is being closed after an item was clicked, the close
|
||||
is delayed slightly so the user can briefly see the clicked row
|
||||
get highlighted.
|
||||
*/
|
||||
- (void)close
|
||||
{
|
||||
if (![_panel isVisible])
|
||||
return;
|
||||
|
||||
if ([self listWasClicked])
|
||||
{
|
||||
[self setListWasClicked:NO];
|
||||
|
||||
// Wait until we get through the run loop and delay a little
|
||||
// so the user can briefly see the clicked row get highlighted.
|
||||
if ([self itemWasClicked])
|
||||
{
|
||||
[self setItemWasClicked:NO];
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(closeListAfterItemClick) userInfo:nil repeats:NO];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListWillDismissNotification object:self];
|
||||
[_panel close];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListDidDismissNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Close the list after an item was clicked.
|
||||
*/
|
||||
- (void)closeListAfterItemClick
|
||||
{
|
||||
[self close];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPopUpListItemWasClickedNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the desired row height for the table view.
|
||||
Subclasses should override this if they want something other than the default.
|
||||
*/
|
||||
- (int)rowHeightForTableView:(CPTableView)aTableView
|
||||
{
|
||||
return [aTableView rowHeight];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a value to display for a single row in the list. Subclasses should override
|
||||
this if the table data needs to be converted or formatted in some way to be displayed.
|
||||
If there are no search results, an empty string is returned.
|
||||
If subclasses use a data representation other than CPStrings, they must override
|
||||
this method and return the appropriate data when there are no search results.
|
||||
|
||||
If the table uses a custom data view, this method should return a value suitable
|
||||
for sending to the setObjectValue: method of the data view.
|
||||
|
||||
@param aValue Table data for the given row
|
||||
@param aRow The row being displayed
|
||||
@return A value to be displayed in the list
|
||||
*/
|
||||
- (id)displayValueForObjectValue:(id)aValue row:(int)aRow
|
||||
{
|
||||
return aValue || @"";
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a single-line string for use in an autocomplete field. Subclasses should override
|
||||
this if the row data is not convertable to a simple string, and return the data as a single-line string.
|
||||
|
||||
@param aValue Table data to be converted to a string
|
||||
@param aRow The row whose data is being converted
|
||||
@return A value to be displayed in the autocomplete field
|
||||
*/
|
||||
- (CPString)stringValueForObjectValue:(id)aValue row:(int)aRow
|
||||
{
|
||||
return String(aValue);
|
||||
}
|
||||
|
||||
- (void)tableViewClickAction:(id)sender
|
||||
{
|
||||
[self close];
|
||||
@@ -615,7 +738,7 @@ var ListColumnIdentifier = @"1";
|
||||
@end
|
||||
|
||||
|
||||
var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey",
|
||||
var _CPPopUpListDataSourceKey = @"_CPPopUpListDataSourceKey",
|
||||
_CPPopUpListListWidthKey = @"_CPPopUpListListWidthKey",
|
||||
_CPPopUpListListPanelKey = @"_CPPopUpListListPanelKey",
|
||||
_CPPopUpListScrollViewKey = @"_CPPopUpListScrollViewKey",
|
||||
@@ -632,7 +755,7 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey",
|
||||
_listWasClicked = NO;
|
||||
_itemWasClicked = NO;
|
||||
|
||||
_delegate = [aCoder decodeObjectForKey:_CPPopUpListDelegateKey];
|
||||
_dataSource = [aCoder decodeObjectForKey:_CPPopUpListDataSourceKey];
|
||||
_listWidth = [aCoder decodeIntForKey:_CPPopUpListListWidthKey];
|
||||
_panel = [aCoder decodeObjectForKey:_CPPopUpListListPanelKey];
|
||||
_scrollView = [aCoder decodeObjectForKey:_CPPopUpListScrollViewKey];
|
||||
@@ -648,7 +771,7 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey",
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeObject:_delegate forKey:_CPPopUpListDelegateKey];
|
||||
[aCoder encodeObject:_dataSource forKey:_CPPopUpListDataSourceKey];
|
||||
[aCoder encodeObject:_listWidth forKey:_CPPopUpListListWidthKey];
|
||||
[aCoder encodeObject:_panel forKey:_CPPopUpListListPanelKey];
|
||||
[aCoder encodeObject:_scrollView forKey:_CPPopUpListScrollViewKey];
|
||||
@@ -661,12 +784,12 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey",
|
||||
|
||||
- (int)numberOfRowsInTableView:(id)aTableView
|
||||
{
|
||||
return MAX([_delegate numberOfItems], 1);
|
||||
return MAX([_dataSource numberOfItemsInList:self], 1);
|
||||
}
|
||||
|
||||
- (id)tableView:(id)aTableView objectValueForTableColumn:(CPTableColumn)aColumn row:(int)aRow
|
||||
{
|
||||
return [self displayValueForObjectValue:[_delegate objectValueForItemAtIndex:aRow] row:aRow];
|
||||
return [_dataSource list:self displayValueForObjectValue:[_dataSource list:self objectValueForItemAtIndex:aRow]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* _CPPopUpListDataSource.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Aparajita Fishman.
|
||||
* Copyright (c) 2011, Intalio, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
This abstract base class defines the methods that delegates of _CPPopUpList must implement.
|
||||
You may either subclass this class to use the default implementation of
|
||||
list:objectValueForItemAtIndex: and list:displayValueForObjectValue: or use your
|
||||
own class and define these methods yourself.
|
||||
*/
|
||||
@implementation _CPPopUpListDataSource : CPObject
|
||||
|
||||
/*!
|
||||
Returns whether the given object conforms to the minimum protocol defined by this class.
|
||||
*/
|
||||
+ (BOOL)protocolIsImplementedByObject:(id)anObject
|
||||
{
|
||||
return (anObject &&
|
||||
[anObject respondsToSelector:@selector(numberOfItemsInList:)] &&
|
||||
[anObject respondsToSelector:@selector(numberOfVisibleItemsInList:)] &&
|
||||
[anObject respondsToSelector:@selector(list:objectValueForItemAtIndex:)] &&
|
||||
[anObject respondsToSelector:@selector(list:displayValueForObjectValue:)] &&
|
||||
[anObject respondsToSelector:@selector(list:stringValueForObjectValue:)]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of items managed by the list.
|
||||
*/
|
||||
- (int)numberOfItemsInList:(_CPPopUpList)aList
|
||||
{
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of items to display at one time.
|
||||
*/
|
||||
- (int)numberOfVisibleItemsInList:(_CPPopUpList)aList
|
||||
{
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the data for a given row index.
|
||||
*/
|
||||
- (id)list:(_CPPopUpList)aList objectValueForItemAtIndex:(int)index
|
||||
{
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a value to display for a single row in the list. Subclasses should override
|
||||
this if the table data needs to be converted or formatted in some way to be displayed.
|
||||
If your data source use a data representation other than CPStrings, you must override
|
||||
this method and return the appropriate data when there are no search results.
|
||||
|
||||
If the _CPPopUpList's table uses a custom data view, this method should return a value suitable
|
||||
for sending to the setObjectValue: method of the data view.
|
||||
|
||||
@param aValue Data for the given row
|
||||
@return A value to be displayed in the list
|
||||
*/
|
||||
- (id)list:(_CPPopUpList)aList displayValueForObjectValue:(id)aValue
|
||||
{
|
||||
return aValue || @"";
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a single-line string representation for an object value. Subclasses should override
|
||||
this if the object data is not convertible to a simple single-line string.
|
||||
|
||||
@param aValue Table data to be converted to a string
|
||||
@return A value to be displayed in the autocomplete field
|
||||
*/
|
||||
- (CPString)list:(_CPPopUpList)aList stringValueForObjectValue:(id)aValue
|
||||
{
|
||||
return String(aValue);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -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.007"
|
||||
VERSION_NUMBER = "1.0.0.019"
|
||||
|
||||
|
||||
# Shorten expressions
|
||||
|
||||
+108
-19
@@ -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
|
||||
|
||||
@@ -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]))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -306,12 +306,17 @@ var CPStringRegexSpecialCharacters = [
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a substring from the beginning of the receiver to the specified index.
|
||||
@param anIndex the last index of the receiver to use for the substring (inclusive)
|
||||
Creates a substring of characters from the receiver, starting at the beginning and up to
|
||||
the given index.
|
||||
|
||||
@param anIndex the index of the receiver where the substring should end (non inclusive)
|
||||
@return the substring
|
||||
*/
|
||||
- (CPString)substringToIndex:(unsigned)anIndex
|
||||
{
|
||||
if (anIndex > length)
|
||||
[CPException raise:CPRangeException reason:"index out of bounds"];
|
||||
|
||||
return substring(0, anIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -128,6 +128,18 @@
|
||||
[self assert:"abcd" equals:["abcd" substringToIndex:4]];
|
||||
[self assert:"abc" equals:["abcd" substringToIndex:3]];
|
||||
[self assert:"" equals:["abcd" substringToIndex:0]];
|
||||
|
||||
var sawException = false;
|
||||
try
|
||||
{
|
||||
[@"abcd" substringToIndex:5];
|
||||
}
|
||||
catch (anException)
|
||||
{
|
||||
sawException = true;
|
||||
[self assert:CPRangeException equals:[anException name]];
|
||||
}
|
||||
[self assertTrue:sawException message:"expected CPRangeException"];
|
||||
}
|
||||
|
||||
- (void)testBoolValue
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -54,6 +54,7 @@
|
||||
@implementation AppController : CPObject
|
||||
{
|
||||
@outlet CPWindow theWindow;
|
||||
CPWindow testWindow;
|
||||
CPString employee @accessors;
|
||||
Companies companies @accessors;
|
||||
CPArrayController companiesController;
|
||||
@@ -81,18 +82,17 @@
|
||||
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
||||
{
|
||||
theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(30, 50, 500, 400) styleMask:CPTitledWindowMask | CPResizableWindowMask];
|
||||
testWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(30, 50, 500, 400) styleMask:CPTitledWindowMask | CPResizableWindowMask];
|
||||
|
||||
var contentView = [theWindow contentView],
|
||||
var contentView = [testWindow contentView],
|
||||
companiesScrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(30, 30, 200, 100)],
|
||||
companiesTable = [[CPTableView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
|
||||
employeesScrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(250, 30, 200, 200)],
|
||||
employeesTable = [[CPTableView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
|
||||
|
||||
[theWindow setTitle:@"CPComboBox (from code)"];
|
||||
[testWindow setTitle:@"CPComboBox (from code)"];
|
||||
|
||||
var column = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
|
||||
[column setResizingMask:CPTableColumnAutoresizingMask];
|
||||
[companiesTable addTableColumn:column];
|
||||
[companiesTable setAllowsMultipleSelection:YES];
|
||||
@@ -107,7 +107,6 @@
|
||||
[contentView addSubview:companiesScrollView];
|
||||
|
||||
column = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
|
||||
[column setResizingMask:CPTableColumnAutoresizingMask];
|
||||
[employeesTable addTableColumn:column];
|
||||
[employeesTable setAllowsMultipleSelection:YES];
|
||||
@@ -130,11 +129,11 @@
|
||||
[contentView addSubview:textfield];
|
||||
|
||||
var center = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[center addObserver:self selector:@selector(comboNote:) name:CPComboBoxSelectionDidChangeNotification object:combo];
|
||||
[center addObserver:self selector:@selector(comboNote:) name:CPComboBoxSelectionIsChangingNotification object:combo];
|
||||
[center addObserver:self selector:@selector(comboNote:) name:CPComboBoxWillDismissNotification object:combo];
|
||||
[center addObserver:self selector:@selector(comboNote:) name:CPComboBoxWillPopUpNotification object:combo];
|
||||
[center addObserver:self selector:@selector(comboNote:) name:CPControlTextDidEndEditingNotification object:combo];
|
||||
|
||||
nextCheckboxY = 166;
|
||||
[self makeCheckBoxWithTitle:@"Enabled" defaultState:CPOnState];
|
||||
@@ -153,7 +152,6 @@
|
||||
[employeesController bind:@"contentArray" toObject:companiesController withKeyPath:@"selection.employees" options:nil];
|
||||
|
||||
var employeeController = [CPObjectController new];
|
||||
|
||||
[employeeController bind:@"content" toObject:employeesController withKeyPath:@"selection.self" options:nil];
|
||||
|
||||
[[companiesTable tableColumnWithIdentifier:@"name"] bind:@"value" toObject:companiesController withKeyPath:@"arrangedObjects.name" options:nil];
|
||||
@@ -169,8 +167,8 @@
|
||||
[employeesController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:@"employees.arrangedObjects"];
|
||||
[combo addObserver:self forKeyPath:@"value" options:0 context:@"combo.value"];
|
||||
|
||||
[theWindow setInitialFirstResponder:companiesTable];
|
||||
[theWindow orderFront:self];
|
||||
[testWindow setInitialFirstResponder:combo];
|
||||
[testWindow makeKeyAndOrderFront:self];
|
||||
}
|
||||
|
||||
- (void)makeCheckBoxWithTitle:(CPString)aTitle defaultState:(BOOL)aState
|
||||
@@ -180,7 +178,7 @@
|
||||
[checkbox setState:aState];
|
||||
[checkbox setTarget:self];
|
||||
[checkbox setAction:@selector(setComboState:)];
|
||||
[[theWindow contentView] addSubview:checkbox];
|
||||
[[testWindow contentView] addSubview:checkbox];
|
||||
|
||||
nextCheckboxY += 25;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -735,7 +735,7 @@
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">574</int>
|
||||
<int key="maxID">576</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,44 +30,53 @@
|
||||
{
|
||||
// This is called when the cib is done loading.
|
||||
// You can implement this method on any object instantiated from a Cib.
|
||||
// It's a useful hook for setting up current UI values, and other things.
|
||||
|
||||
// It's a useful hook for setting up current UI values, and other things.
|
||||
|
||||
// In this case, we want the window from Cib to become our full browser window
|
||||
//[theWindow setFullBridge:YES];
|
||||
|
||||
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]]];
|
||||
|
||||
//[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
|
||||
@@ -75,4 +84,9 @@ window.setTimeout(function(){
|
||||
[platformWindow orderFront:self];
|
||||
}
|
||||
|
||||
- (IBAction)randomTitle:(id)aSender
|
||||
{
|
||||
[theWindow setTitle:@"Window random number " + Math.random(1000)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
|
||||
@interface AppController : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
|
||||
@interface AppController : NSObject
|
||||
{
|
||||
IBOutlet NSWindow* theWindow;
|
||||
IBOutlet NSTextField* field1;
|
||||
IBOutlet NSTextField* field2;
|
||||
IBOutlet NSTextField* status;
|
||||
}
|
||||
|
||||
@end
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; };
|
||||
9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; };
|
||||
9EEC44CC13574A0B00615446 /* resignFirstResponder-CPControlTextDidEndEditing in Resources */ = {isa = PBXBuildFile; fileRef = 9EEC44CB13574A0B00615446 /* resignFirstResponder-CPControlTextDidEndEditing */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
9EEC44B6135749D300615446 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9EEC448A135749D200615446 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 9EEC4492135749D200615446;
|
||||
remoteInfo = Another;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9EEC4493135749D200615446 /* Another.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Another.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9EEC4497135749D200615446 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
9EEC449A135749D300615446 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
9EEC449B135749D300615446 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
9EEC449C135749D300615446 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
9EEC44B4135749D300615446 /* AnotherTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnotherTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9EEC44CB13574A0B00615446 /* resignFirstResponder-CPControlTextDidEndEditing */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "resignFirstResponder-CPControlTextDidEndEditing"; path = ..; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
9EEC4490135749D200615446 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9EEC44B0135749D300615446 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
9EEC4488135749D200615446 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EEC44CB13574A0B00615446 /* resignFirstResponder-CPControlTextDidEndEditing */,
|
||||
9EEC4496135749D200615446 /* Frameworks */,
|
||||
9EEC4494135749D200615446 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EEC4494135749D200615446 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EEC4493135749D200615446 /* Another.app */,
|
||||
9EEC44B4135749D300615446 /* AnotherTests.octest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EEC4496135749D200615446 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EEC4497135749D200615446 /* Cocoa.framework */,
|
||||
9EEC4499135749D300615446 /* Other Frameworks */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EEC4499135749D300615446 /* Other Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EEC449A135749D300615446 /* AppKit.framework */,
|
||||
9EEC449B135749D300615446 /* CoreData.framework */,
|
||||
9EEC449C135749D300615446 /* Foundation.framework */,
|
||||
);
|
||||
name = "Other Frameworks";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
9EEC4492135749D200615446 /* Another */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */;
|
||||
buildPhases = (
|
||||
9EEC448F135749D200615446 /* Sources */,
|
||||
9EEC4490135749D200615446 /* Frameworks */,
|
||||
9EEC4491135749D200615446 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Another;
|
||||
productName = Another;
|
||||
productReference = 9EEC4493135749D200615446 /* Another.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
9EEC44B3135749D300615446 /* AnotherTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */;
|
||||
buildPhases = (
|
||||
9EEC44AF135749D300615446 /* Sources */,
|
||||
9EEC44B0135749D300615446 /* Frameworks */,
|
||||
9EEC44B1135749D300615446 /* Resources */,
|
||||
9EEC44B2135749D300615446 /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
9EEC44B7135749D300615446 /* PBXTargetDependency */,
|
||||
);
|
||||
name = AnotherTests;
|
||||
productName = AnotherTests;
|
||||
productReference = 9EEC44B4135749D300615446 /* AnotherTests.octest */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
9EEC448A135749D200615446 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0420;
|
||||
ORGANIZATIONNAME = "280 North, Inc.";
|
||||
};
|
||||
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "resignFirstResponder-CPControlTextDidEndEditing" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 9EEC4488135749D200615446;
|
||||
productRefGroup = 9EEC4494135749D200615446 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
9EEC4492135749D200615446 /* Another */,
|
||||
9EEC44B3135749D300615446 /* AnotherTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
9EEC4491135749D200615446 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9EEC44CC13574A0B00615446 /* resignFirstResponder-CPControlTextDidEndEditing in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9EEC44B1135749D300615446 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
9EEC44B2135749D300615446 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
9EEC448F135749D200615446 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9EEC44AF135749D300615446 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
9EEC44B7135749D300615446 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 9EEC4492135749D200615446 /* Another */;
|
||||
targetProxy = 9EEC44B6135749D300615446 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
9EEC44C3135749D300615446 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9EEC44C4135749D300615446 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
9EEC44C6135749D300615446 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Another/Another-Prefix.pch";
|
||||
INFOPLIST_FILE = "Another/Another-Info.plist";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9EEC44C7135749D300615446 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Another/Another-Prefix.pch";
|
||||
INFOPLIST_FILE = "Another/Another-Info.plist";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
9EEC44C9135749D300615446 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch";
|
||||
INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SenTestingKit,
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = octest;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9EEC44CA135749D300615446 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch";
|
||||
INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SenTestingKit,
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUNDLE_LOADER)";
|
||||
WRAPPER_EXTENSION = octest;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
9EEC448D135749D200615446 /* Build configuration list for PBXProject "resignFirstResponder-CPControlTextDidEndEditing" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9EEC44C3135749D300615446 /* Debug */,
|
||||
9EEC44C4135749D300615446 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9EEC44C6135749D300615446 /* Debug */,
|
||||
9EEC44C7135749D300615446 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9EEC44C9135749D300615446 /* Debug */,
|
||||
9EEC44CA135749D300615446 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 9EEC448A135749D200615446 /* Project object */;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:resignFirstResponder-CPControlTextDidEndEditing.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* resignFirstResponder-CPControlTextDidEndEditing
|
||||
*
|
||||
* Created by aparajita on September 2, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
@implementation AppController : CPObject
|
||||
{
|
||||
@outlet CPWindow theWindow;
|
||||
@outlet CPTextField field1;
|
||||
@outlet CPTextField field2;
|
||||
@outlet CPTextField status;
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
var center = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[center addObserver:self selector:@selector(showNote:) name:CPControlTextDidBeginEditingNotification object:field1];
|
||||
[center addObserver:self selector:@selector(showNote:) name:CPControlTextDidEndEditingNotification object:field1];
|
||||
[center addObserver:self selector:@selector(showNote:) name:CPControlTextDidBeginEditingNotification object:field2];
|
||||
[center addObserver:self selector:@selector(showNote:) name:CPControlTextDidEndEditingNotification object:field2];
|
||||
|
||||
[status setStringValue:@""];
|
||||
}
|
||||
|
||||
- (void)showNote:(CPNotification)note
|
||||
{
|
||||
var fieldName = [note object] === field1 ? "field1" : "field2";
|
||||
[status setStringValue:[CPString stringWithFormat:@"%@\n%@", fieldName, [note name]]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Main cib file base name</key>
|
||||
<string>MainMenu.cib</string>
|
||||
<key>CPBundleName</key>
|
||||
<string>resignFirstResponder-CPControlTextDidEndEditing</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Jakefile
|
||||
* resignFirstResponder-CPControlTextDidEndEditing
|
||||
*
|
||||
* Created by aparajita on September 2, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
*/
|
||||
|
||||
var ENV = require("system").env,
|
||||
FILE = require("file"),
|
||||
JAKE = require("jake"),
|
||||
task = JAKE.task,
|
||||
FileList = JAKE.FileList,
|
||||
app = require("cappuccino/jake").app,
|
||||
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
|
||||
OS = require("os");
|
||||
|
||||
app ("resignFirstResponderCPControlTextDidEndEditing", function(task)
|
||||
{
|
||||
task.setBuildIntermediatesPath(FILE.join("Build", "resignFirstResponderCPControlTextDidEndEditing.build", configuration));
|
||||
task.setBuildPath(FILE.join("Build", configuration));
|
||||
|
||||
task.setProductName("resignFirstResponder-CPControlTextDidEndEditing");
|
||||
task.setIdentifier("com.aparajita.resignFirstResponderCPControlTextDidEndEditing");
|
||||
task.setVersion("1.0");
|
||||
task.setAuthor("Victory-Heart Productions");
|
||||
task.setEmail("feedback @nospam@ yourcompany.com");
|
||||
task.setSummary("resignFirstResponder-CPControlTextDidEndEditing");
|
||||
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
|
||||
task.setResources(new FileList("Resources/**"));
|
||||
task.setIndexFilePath("index.html");
|
||||
task.setInfoPlistPath("Info.plist");
|
||||
task.setNib2CibFlags("-R Resources/");
|
||||
|
||||
if (configuration === "Debug")
|
||||
task.setCompilerFlags("-DDEBUG -g");
|
||||
else
|
||||
task.setCompilerFlags("-O");
|
||||
});
|
||||
|
||||
task ("default", ["resignFirstResponderCPControlTextDidEndEditing"], function()
|
||||
{
|
||||
printResults(configuration);
|
||||
});
|
||||
|
||||
task ("build", ["default"]);
|
||||
|
||||
task ("debug", function()
|
||||
{
|
||||
ENV["CONFIGURATION"] = "Debug";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("release", function()
|
||||
{
|
||||
ENV["CONFIGURATION"] = "Release";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("run", ["debug"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Debug", "resignFirstResponderCPControlTextDidEndEditing", "index.html")]);
|
||||
});
|
||||
|
||||
task ("run-release", ["release"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Release", "resignFirstResponderCPControlTextDidEndEditing", "index.html")]);
|
||||
});
|
||||
|
||||
task ("deploy", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Deployment", "resignFirstResponderCPControlTextDidEndEditing"));
|
||||
OS.system(["press", "-f", FILE.join("Build", "Release", "resignFirstResponderCPControlTextDidEndEditing"), FILE.join("Build", "Deployment", "resignFirstResponderCPControlTextDidEndEditing")]);
|
||||
printResults("Deployment")
|
||||
});
|
||||
|
||||
task ("desktop", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Desktop", "resignFirstResponderCPControlTextDidEndEditing"));
|
||||
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "resignFirstResponderCPControlTextDidEndEditing"), FILE.join("Build", "Desktop", "resignFirstResponderCPControlTextDidEndEditing", "resignFirstResponderCPControlTextDidEndEditing.app"));
|
||||
printResults("Desktop")
|
||||
});
|
||||
|
||||
task ("run-desktop", ["desktop"], function()
|
||||
{
|
||||
OS.system([FILE.join("Build", "Desktop", "resignFirstResponderCPControlTextDidEndEditing", "resignFirstResponderCPControlTextDidEndEditing.app", "Contents", "MacOS", "NativeHost"), "-i"]);
|
||||
});
|
||||
|
||||
function printResults(configuration)
|
||||
{
|
||||
print("----------------------------");
|
||||
print(configuration+" app built at path: "+FILE.join("Build", configuration, "resignFirstResponderCPControlTextDidEndEditing"));
|
||||
print("----------------------------");
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,431 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1050</int>
|
||||
<string key="IBDocument.SystemVersion">10K549</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1923</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.36</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="NS.object.0">1923</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>NSTextField</string>
|
||||
<string>NSTextFieldCell</string>
|
||||
<string>NSWindowTemplate</string>
|
||||
<string>NSView</string>
|
||||
<string>NSCustomObject</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSCustomObject" id="1021">
|
||||
<string key="NSClassName">NSApplication</string>
|
||||
</object>
|
||||
<object class="NSCustomObject" id="1014">
|
||||
<string key="NSClassName">FirstResponder</string>
|
||||
</object>
|
||||
<object class="NSCustomObject" id="1050">
|
||||
<string key="NSClassName">NSApplication</string>
|
||||
</object>
|
||||
<object class="NSWindowTemplate" id="972006081">
|
||||
<int key="NSWindowStyleMask">7</int>
|
||||
<int key="NSWindowBacking">2</int>
|
||||
<string key="NSWindowRect">{{131, 728}, {480, 360}}</string>
|
||||
<int key="NSWTFlags">1946157056</int>
|
||||
<string key="NSWindowTitle">Window</string>
|
||||
<string key="NSWindowClass">NSWindow</string>
|
||||
<nil key="NSViewClass"/>
|
||||
<object class="NSView" key="NSWindowView" id="439893737">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">256</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSTextField" id="160623561">
|
||||
<reference key="NSNextResponder" ref="439893737"/>
|
||||
<int key="NSvFlags">301</int>
|
||||
<string key="NSFrame">{{192, 275}, {96, 22}}</string>
|
||||
<reference key="NSSuperview" ref="439893737"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="818861456"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="46991665">
|
||||
<int key="NSCellFlags">-1804468671</int>
|
||||
<int key="NSCellFlags2">272630784</int>
|
||||
<string key="NSContents"/>
|
||||
<object class="NSFont" key="NSSupport" id="105728881">
|
||||
<string key="NSName">LucidaGrande</string>
|
||||
<double key="NSSize">13</double>
|
||||
<int key="NSfFlags">1044</int>
|
||||
</object>
|
||||
<reference key="NSControlView" ref="160623561"/>
|
||||
<bool key="NSDrawsBackground">YES</bool>
|
||||
<object class="NSColor" key="NSBackgroundColor" id="878641937">
|
||||
<int key="NSColorSpace">6</int>
|
||||
<string key="NSCatalogName">System</string>
|
||||
<string key="NSColorName">textBackgroundColor</string>
|
||||
<object class="NSColor" key="NSColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSColor" key="NSTextColor" id="286271178">
|
||||
<int key="NSColorSpace">6</int>
|
||||
<string key="NSCatalogName">System</string>
|
||||
<string key="NSColorName">textColor</string>
|
||||
<object class="NSColor" key="NSColor" id="658927846">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSTextField" id="818861456">
|
||||
<reference key="NSNextResponder" ref="439893737"/>
|
||||
<int key="NSvFlags">301</int>
|
||||
<string key="NSFrame">{{192, 220}, {96, 22}}</string>
|
||||
<reference key="NSSuperview" ref="439893737"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="279373907">
|
||||
<int key="NSCellFlags">-1804468671</int>
|
||||
<int key="NSCellFlags2">272630784</int>
|
||||
<string key="NSContents"/>
|
||||
<reference key="NSSupport" ref="105728881"/>
|
||||
<reference key="NSControlView" ref="818861456"/>
|
||||
<bool key="NSDrawsBackground">YES</bool>
|
||||
<reference key="NSBackgroundColor" ref="878641937"/>
|
||||
<reference key="NSTextColor" ref="286271178"/>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSTextField" id="883996342">
|
||||
<reference key="NSNextResponder" ref="439893737"/>
|
||||
<int key="NSvFlags">268</int>
|
||||
<string key="NSFrame">{{17, 76}, {446, 94}}</string>
|
||||
<reference key="NSSuperview" ref="439893737"/>
|
||||
<reference key="NSWindow"/>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSTextFieldCell" key="NSCell" id="483058531">
|
||||
<int key="NSCellFlags">67239424</int>
|
||||
<int key="NSCellFlags2">138412032</int>
|
||||
<string key="NSContents">Multiline Label</string>
|
||||
<object class="NSFont" key="NSSupport">
|
||||
<string key="NSName">LucidaGrande</string>
|
||||
<double key="NSSize">13</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<reference key="NSControlView" ref="883996342"/>
|
||||
<object class="NSColor" key="NSBackgroundColor">
|
||||
<int key="NSColorSpace">6</int>
|
||||
<string key="NSCatalogName">System</string>
|
||||
<string key="NSColorName">controlColor</string>
|
||||
<object class="NSColor" key="NSColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSColor" key="NSTextColor">
|
||||
<int key="NSColorSpace">6</int>
|
||||
<string key="NSCatalogName">System</string>
|
||||
<string key="NSColorName">controlTextColor</string>
|
||||
<reference key="NSColor" ref="658927846"/>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSFrameSize">{480, 360}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="160623561"/>
|
||||
</object>
|
||||
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
|
||||
<string key="NSMaxSize">{1e+13, 1e+13}</string>
|
||||
</object>
|
||||
<object class="NSCustomObject" id="635946545">
|
||||
<string key="NSClassName">AppController</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<object class="NSMutableArray" key="connectionRecords">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="1021"/>
|
||||
<reference key="destination" ref="635946545"/>
|
||||
</object>
|
||||
<int key="connectionID">451</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">initialFirstResponder</string>
|
||||
<reference key="source" ref="972006081"/>
|
||||
<reference key="destination" ref="160623561"/>
|
||||
</object>
|
||||
<int key="connectionID">469</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">theWindow</string>
|
||||
<reference key="source" ref="635946545"/>
|
||||
<reference key="destination" ref="972006081"/>
|
||||
</object>
|
||||
<int key="connectionID">459</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">field1</string>
|
||||
<reference key="source" ref="635946545"/>
|
||||
<reference key="destination" ref="160623561"/>
|
||||
</object>
|
||||
<int key="connectionID">466</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">field2</string>
|
||||
<reference key="source" ref="635946545"/>
|
||||
<reference key="destination" ref="818861456"/>
|
||||
</object>
|
||||
<int key="connectionID">467</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBOutletConnection" key="connection">
|
||||
<string key="label">status</string>
|
||||
<reference key="source" ref="635946545"/>
|
||||
<reference key="destination" ref="883996342"/>
|
||||
</object>
|
||||
<int key="connectionID">468</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<object class="NSArray" key="orderedObjects">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<object class="NSArray" key="object" id="0">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="children" ref="1048"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="1021"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="1014"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">First Responder</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-3</int>
|
||||
<reference key="object" ref="1050"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">Application</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">371</int>
|
||||
<reference key="object" ref="972006081"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="439893737"/>
|
||||
</object>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">372</int>
|
||||
<reference key="object" ref="439893737"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="160623561"/>
|
||||
<reference ref="818861456"/>
|
||||
<reference ref="883996342"/>
|
||||
</object>
|
||||
<reference key="parent" ref="972006081"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">450</int>
|
||||
<reference key="object" ref="635946545"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">456</int>
|
||||
<reference key="object" ref="160623561"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="46991665"/>
|
||||
</object>
|
||||
<reference key="parent" ref="439893737"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">457</int>
|
||||
<reference key="object" ref="46991665"/>
|
||||
<reference key="parent" ref="160623561"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">460</int>
|
||||
<reference key="object" ref="818861456"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="279373907"/>
|
||||
</object>
|
||||
<reference key="parent" ref="439893737"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">461</int>
|
||||
<reference key="object" ref="279373907"/>
|
||||
<reference key="parent" ref="818861456"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">464</int>
|
||||
<reference key="object" ref="883996342"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="483058531"/>
|
||||
</object>
|
||||
<reference key="parent" ref="439893737"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">465</int>
|
||||
<reference key="object" ref="483058531"/>
|
||||
<reference key="parent" ref="883996342"/>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="flattenedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>-1.IBPluginDependency</string>
|
||||
<string>-2.IBPluginDependency</string>
|
||||
<string>-3.IBPluginDependency</string>
|
||||
<string>371.IBPluginDependency</string>
|
||||
<string>371.IBWindowTemplateEditedContentRect</string>
|
||||
<string>371.NSWindowTemplate.visibleAtLaunch</string>
|
||||
<string>372.IBPluginDependency</string>
|
||||
<string>450.IBPluginDependency</string>
|
||||
<string>456.IBPluginDependency</string>
|
||||
<string>457.IBPluginDependency</string>
|
||||
<string>460.IBPluginDependency</string>
|
||||
<string>461.IBPluginDependency</string>
|
||||
<string>464.IBPluginDependency</string>
|
||||
<string>465.IBPluginDependency</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>{{303, 221}, {480, 360}}</string>
|
||||
<integer value="1"/>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="activeLocalization"/>
|
||||
<object class="NSMutableDictionary" key="localizations">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">469</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">AppController</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>field1</string>
|
||||
<string>field2</string>
|
||||
<string>status</string>
|
||||
<string>theWindow</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>NSTextField</string>
|
||||
<string>NSTextField</string>
|
||||
<string>NSTextField</string>
|
||||
<string>NSWindow</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>field1</string>
|
||||
<string>field2</string>
|
||||
<string>status</string>
|
||||
<string>theWindow</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">field1</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">field2</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">status</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">theWindow</string>
|
||||
<string key="candidateClassName">NSWindow</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/AppController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
|
||||
<integer value="1050" key="NS.object.0"/>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
|
||||
<integer value="3000" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
</data>
|
||||
</archive>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!--
|
||||
index-debug.html
|
||||
resignFirstResponder-CPControlTextDidEndEditing
|
||||
|
||||
Created by aparajita on September 2, 2011.
|
||||
Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
<link rel="apple-touch-icon" href="Resources/icon.png" />
|
||||
<link rel="apple-touch-startup-image" href="Resources/default.png" />
|
||||
|
||||
<title>resignFirstResponder-CPControlTextDidEndEditing</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
objj_msgSend_reset();
|
||||
|
||||
// DEBUG OPTIONS:
|
||||
|
||||
// Uncomment to enable printing of backtraces on exceptions:
|
||||
//objj_msgSend_decorate(objj_backtrace_decorator);
|
||||
|
||||
// Uncomment to supress exceptions that take place inside a message
|
||||
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
|
||||
|
||||
// Uncomment to enable runtime type checking:
|
||||
//objj_msgSend_decorate(objj_typecheck_decorator);
|
||||
|
||||
// Uncomment (along with both above) to print backtraces on type check errors:
|
||||
//objj_typecheck_prints_backtrace = true;
|
||||
|
||||
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
|
||||
//CPLogUnregister(CPLogDefault);
|
||||
|
||||
// Uncomment to enable a specific logger:
|
||||
//CPLogRegister(CPLogConsole);
|
||||
//CPLogRegister(CPLogPopup);
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
body{margin:0; padding:0;}
|
||||
#container {position: absolute; top:50%; left:50%;}
|
||||
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
|
||||
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
|
||||
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
|
||||
</style>
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<STYLE type="text/css">
|
||||
#container { position: relative; top: 50%; }
|
||||
#content { position: relative;}
|
||||
</STYLE>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body style="">
|
||||
<div id="cappuccino-body">
|
||||
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
|
||||
<script type="text/javascript">
|
||||
document.write("<div id='container'><p id='content'>" +
|
||||
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
|
||||
"Loading resignFirstResponder-CPControlTextDidEndEditing...</p></div>");
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<div id="container">
|
||||
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
|
||||
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
|
||||
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
|
||||
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
|
||||
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
|
||||
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
|
||||
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
|
||||
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
|
||||
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
|
||||
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!--
|
||||
index.html
|
||||
resignFirstResponder-CPControlTextDidEndEditing
|
||||
|
||||
Created by aparajita on September 2, 2011.
|
||||
Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
<link rel="apple-touch-icon" href="Resources/icon.png" />
|
||||
<link rel="apple-touch-startup-image" href="Resources/default.png" />
|
||||
|
||||
<title>resignFirstResponder-CPControlTextDidEndEditing</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body{margin:0; padding:0;}
|
||||
#container {position: absolute; top:50%; left:50%;}
|
||||
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
|
||||
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
|
||||
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
|
||||
</style>
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<STYLE type="text/css">
|
||||
#container { position: relative; top: 50%; }
|
||||
#content { position: relative;}
|
||||
</STYLE>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body style="">
|
||||
<div id="cappuccino-body">
|
||||
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
|
||||
<script type="text/javascript">
|
||||
document.write("<div id='container'><p id='content'>" +
|
||||
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
|
||||
"Loading resignFirstResponder-CPControlTextDidEndEditing...</p></div>");
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<div id="container">
|
||||
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
|
||||
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
|
||||
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
|
||||
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
|
||||
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
|
||||
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
|
||||
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
|
||||
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
|
||||
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
|
||||
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* resignFirstResponder-CPControlTextDidEndEditing
|
||||
*
|
||||
* Created by aparajita on September 2, 2011.
|
||||
* Copyright 2011, Victory-Heart Productions All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
@import "AppController.j"
|
||||
|
||||
|
||||
function main(args, namedArgs)
|
||||
{
|
||||
CPApplicationMain(args, namedArgs);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
+770
-307
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -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
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user