diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index 1e1d7f30a..343cfca55 100644 --- a/AppKit/CPCollectionView.j +++ b/AppKit/CPCollectionView.j @@ -111,6 +111,7 @@ _tileWidth = -1.0; _selectionIndexes = [CPIndexSet indexSet]; + _isSelectable = YES; } return self; @@ -258,7 +259,7 @@ */ - (void)setSelectionIndexes:(CPIndexSet)anIndexSet { - if (_selectionIndexes == anIndexSet) + if (_selectionIndexes == anIndexSet || !_isSelectable) return; var index = CPNotFound; diff --git a/AppKit/CPColor.j b/AppKit/CPColor.j index c26071173..47517a5de 100644 --- a/AppKit/CPColor.j +++ b/AppKit/CPColor.j @@ -523,6 +523,8 @@ var hexCharacters = "0123456789ABCDEF"; */ function hexToRGB(hex) { + if ( hex.length == 3 ) + hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2); if(hex.length != 6) return null; diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 626fe0cb8..a06ba9ba3 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -103,6 +103,8 @@ var CPControlBlackColor = [CPColor blackColor]; JSObject _ephemeralSubviewsForNames; CPSet _ephereralSubviews; + + CPString _toolTip; // FIXME: Who uses this? BOOL _isBezeled; @@ -183,6 +185,33 @@ var CPControlBlackColor = [CPColor blackColor]; return previousMask; } +/*! + Sets the tooltip for the receiver. + @param aToolTip the tooltip +*/ +/* +-(void)setToolTip:(CPString)aToolTip +{ + if (_toolTip == aToolTip) + return; + + _toolTip = aToolTip; + +#if PLATFORM(DOM) + _DOMElement.title = aToolTip; +#endif +} +*/ +/*! + Returns the receiver's tooltip +*/ +/* +-(CPString)toolTip +{ + return _toolTip; +} +*/ + /*! Returns whether the control can continuously send its action messages. */ diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index 80d463868..bc68954dc 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -450,7 +450,7 @@ CPPopUpButtonStatePullsDown = 1 << 12; */ - (int)indexOfItemWithRepresentedObject:(id)anObject { - return [_menu indexOfItemWithRepresentedObejct:anObject]; + return [_menu indexOfItemWithRepresentedObject:anObject]; } /*! diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 449a2c119..43cb1c14f 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -780,4 +780,4 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey", [aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey]; } -@end +@end \ No newline at end of file diff --git a/AppKit/CoreAnimation/CAMediaTimingFunction.j b/AppKit/CoreAnimation/CAMediaTimingFunction.j index 9a6091da1..c75df75cf 100644 --- a/AppKit/CoreAnimation/CAMediaTimingFunction.j +++ b/AppKit/CoreAnimation/CAMediaTimingFunction.j @@ -95,7 +95,7 @@ var CAMediaNamedTimingFunctions = nil; else { reference[0] = 1.0; - reference[0] = 1.0; + reference[1] = 1.0; } } diff --git a/Foundation/CPArray+KVO.j b/Foundation/CPArray+KVO.j index 37772dd13..64ccd2a8f 100644 --- a/Foundation/CPArray+KVO.j +++ b/Foundation/CPArray+KVO.j @@ -57,7 +57,16 @@ SEL _replaceSEL; Function _replace; + + SEL _insertManySEL; + Function _insertMany; + SEL _removeManySEL; + Function _removeMany; + + SEL _replaceManySEL; + Function _replaceMany; + SEL _objectAtIndexSEL; Function _objectAtIndex; @@ -95,32 +104,44 @@ var capitalizedKey = _key.charAt(0).toUpperCase() + _key.substring(1); _insertSEL = sel_getName(@"insertObject:in"+capitalizedKey+"AtIndex:"); - if ([_proxyObject respondsToSelector:selector]) - _insert = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_insertSEL]) + _insert = [_proxyObject methodForSelector:_insertSEL]; _removeSEL = sel_getName(@"removeObjectFrom"+capitalizedKey+"AtIndex:"); - if ([_proxyObject respondsToSelector:selector]) - _remove = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_removeSEL]) + _remove = [_proxyObject methodForSelector:_removeSEL]; _replaceSEL = sel_getName(@"replaceObjectFrom"+capitalizedKey+"AtIndex:withObject:"); - if ([_proxyObject respondsToSelector:selector]) - _replace = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_replaceSEL]) + _replace = [_proxyObject methodForSelector:_replaceSEL]; + + _insertManySEL = sel_getName(@"insertObjects:in"+capitalizedKey+"AtIndexes:"); + if ([_proxyObject respondsToSelector:_insertManySEL]) + _insert = [_proxyObject methodForSelector:_insertManySEL]; + + _removeManySEL = sel_getName(@"removeObjectsFrom"+capitalizedKey+"AtIndexes:"); + if ([_proxyObject respondsToSelector:_removeManySEL]) + _remove = [_proxyObject methodForSelector:_removeManySEL]; + + _replaceManySEL = sel_getName(@"replaceObjectsFrom"+capitalizedKey+"AtIndexes:withObjects:"); + if ([_proxyObject respondsToSelector:_replaceManySEL]) + _replace = [_proxyObject methodForSelector:_replaceManySEL]; _objectAtIndexSEL = sel_getName(@"objectIn"+capitalizedKey+"AtIndex:"); - if ([_proxyObject respondsToSelector:selector]) - _objectAtIndex = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_objectAtIndexSEL]) + _objectAtIndex = [_proxyObject methodForSelector:_objectAtIndexSEL]; _countSEL = sel_getName(@"countOf"+capitalizedKey); - if ([_proxyObject respondsToSelector:selector]) - _count = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_countSEL]) + _count = [_proxyObject methodForSelector:_countSEL]; _accessSEL = sel_getName(_key); - if ([_proxyObject respondsToSelector:selector]) - _access = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_accessSEL]) + _access = [_proxyObject methodForSelector:_accessSEL]; _setSEL = sel_getName(@"set"+capitalizedKey+":"); - if ([_proxyObject respondsToSelector:selector]) - _set = [_proxyObject methodForSelector:selector]; + if ([_proxyObject respondsToSelector:_setSEL]) + _set = [_proxyObject methodForSelector:_setSEL]; return self; } @@ -176,7 +197,7 @@ var target = [[self _representedObject] copy]; [target addObject:anObject]; - [_self _setRepresentedObject:target]; + [self _setRepresentedObject:target]; } - (void)insertObject:(id)anObject atIndex:(unsigned)anIndex @@ -187,7 +208,7 @@ var target = [[self _representedObject] copy]; [target insertObject:anObject atIndex:anIndex]; - [_self _setRepresentedObject:target]; + [self _setRepresentedObject:target]; } - (void)removeLastObject @@ -198,7 +219,7 @@ var target = [[self _representedObject] copy]; [target removeLastObject]; - [_self _setRepresentedObject:target]; + [self _setRepresentedObject:target]; } - (void)removeObjectAtIndex:(unsigned)anIndex @@ -209,7 +230,7 @@ var target = [[self _representedObject] copy]; [target removeObjectAtIndex:anIndex]; - [_self _setRepresentedObject:target]; + [self _setRepresentedObject:target]; } - (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject @@ -220,7 +241,7 @@ var target = [[self _representedObject] copy]; [target replaceObjectAtIndex:anIndex withObject:anObject]; - [_self _setRepresentedObject:target]; + [self _setRepresentedObject:target]; } - (CPArray)objectsAtIndexes:(CPIndexSet)indexes diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index 98b5bcf05..fa8e3e73e 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -674,7 +674,7 @@ */ - (CPArray)arrayByAddingObject:(id)anObject { - if (!anObject) + if (anObject === nil || anObject === undefined) [CPException raise:CPInvalidArgumentException reason:"arrayByAddingObject: object can't be nil"]; diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index db83c63c4..cf893248e 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -39,10 +39,17 @@ var CPDateReferenceDate = new Date(Date.UTC(2001,1,1,0,0,0,0)); { return [[self alloc] init]; } + + (id)dateWithTimeIntervalSinceNow:(CPTimeInterval)seconds { return [[CPDate alloc] initWithTimeIntervalSinceNow:seconds]; } + ++ (id)dateWithTimeIntervalSince1970:(CPTimeInterval)seconds +{ + return [[CPDate alloc] initWithTimeIntervalSince1970:seconds]; +} + + (id)dateWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { return [[CPDate alloc] initWithTimeIntervalSinceReferenceDate:seconds]; @@ -63,23 +70,31 @@ var CPDateReferenceDate = new Date(Date.UTC(2001,1,1,0,0,0,0)); self = new Date((new Date()).getTime() + seconds * 1000); return self; } + +- (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds +{ + self = new Date(seconds * 1000); + return self; +} + - (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate]; return self; } + - (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate { self = new Date(refDate.getTime() + seconds * 1000); return self; } + - (id)initWithString:(CPString)description { self = new Date(description); // FIXME: not same format as NSString return self; } - - (CPTimeInterval)timeIntervalSinceDate:(CPDate)anotherDate { return (self.getTime() - anotherDate.getTime()) / 1000.0; @@ -89,14 +104,17 @@ var CPDateReferenceDate = new Date(Date.UTC(2001,1,1,0,0,0,0)); { return [self timeIntervalSinceDate:[CPDate date]]; } + - (CPTimeInterval)timeIntervalSince1970 { return self.getTime() / 1000.0; } + - (CPTimeInterval)timeIntervalSinceReferenceDate { return (self.getTime() - CPDateReferenceDate.getTime()) / 1000.0; } + + (CPTimeInterval)timeIntervalSinceReferenceDate { return [[CPDate date] timeIntervalSinceReferenceDate]; @@ -129,4 +147,4 @@ var CPDateReferenceDate = new Date(Date.UTC(2001,1,1,0,0,0,0)); @end -Date.prototype.isa = CPDate; \ No newline at end of file +Date.prototype.isa = CPDate; diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index 48cbe59e5..926a33fbf 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -268,7 +268,7 @@ if (lhsObject === rhsObject) continue; - if ([lhsObject respondsToSelector:@selector(isEqual:)] && [lhsObject isEqual:rhsObject]) + if (lhsObject.isa && rhsObject.isa && [lhsObject respondsToSelector:@selector(isEqual:)] && [lhsObject isEqual:rhsObject]) continue; return NO; diff --git a/Foundation/CPException.j b/Foundation/CPException.j index 861e4bf51..e6b615f4d 100755 --- a/Foundation/CPException.j +++ b/Foundation/CPException.j @@ -146,6 +146,10 @@ if (input == nil) @end +var CPExceptionNameKey = "CPExceptionNameKey", + CPExceptionReasonKey = "CPExceptionReasonKey", + CPExceptionUserInfoKey = "CPExceptionUserInfoKey"; + @implementation CPException (CPCoding) /*! @@ -161,7 +165,7 @@ if (input == nil) { name = [aCoder decodeObjectForKey:CPExceptionNameKey]; reason = [aCoder decodeObjectForKey:CPExceptionReasonKey]; - userInfo = [aCoer decodeObjectForKey:CPExceptionUserInfoKey]; + userInfo = [aCoder decodeObjectForKey:CPExceptionUserInfoKey]; } return self; diff --git a/Foundation/CPNotificationCenter.j b/Foundation/CPNotificationCenter.j index 7a78d662f..375ff855c 100644 --- a/Foundation/CPNotificationCenter.j +++ b/Foundation/CPNotificationCenter.j @@ -41,7 +41,7 @@ var CPNotificationDefaultCenter = nil; /*! Returns the application's notification center */ -+ (CPNotifcationCenter)defaultCenter ++ (CPNotificationCenter)defaultCenter { if (!CPNotificationDefaultCenter) CPNotificationDefaultCenter = [[CPNotificationCenter alloc] init]; diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j index 224439bd6..90f59227d 100644 --- a/Foundation/CPObject.j +++ b/Foundation/CPObject.j @@ -23,8 +23,41 @@ /*! @class CPObject - CPObject is the root class for most Cappuccino classes. Your custom classes - should almost always subclass CPObject or one of its children. + CPObject is the root class for most Cappuccino classes. Like in Objective-C, + you have to declare parent class explicitly in Objective-J, so your custom + classes should almost always subclass CPObject or one of its children. + + CPObject provides facilities for class allocation and initialization, + querying runtime about parent classes and available selectors, using KVC + (key-value coding). + + When you subclass CPObject, most of the time you override one selector - init. + It is called for default initialization of custom object. You must call + parent class init in your overriden code: +
- (id)init
+{
+ self = [super init];
+ if(self) {
+ ... provide default initialization code for your object ...
+ }
+ return self;
+}
+
+ One more useful thing to override is description(). This selector
+ is used to provide developer-readable information about object. description
+ selector is often used with CPLog debugging:
+ - (CPString)description
+{
+ return [CPString stringWithFormat:@"", someValue];
+}
+ To get description value you can use %@ specifier everywhere where format
+ specifiers are allowed:
+ var inst = [[SomeClass alloc] initWithSomeValue:10]; +CPLog(@"Got some class: %@", inst);+ would output: +
Got some class:+ + @todo document KVC usage. */ @implementation CPObject { @@ -177,7 +210,7 @@ */ + (BOOL)instancesRespondToSelector:(SEL)aSelector { - return class_getInstanceMethod(self, aSelector); + return !!class_getInstanceMethod(self, aSelector); } /*! @@ -187,7 +220,7 @@ */ - (BOOL)respondsToSelector:(SEL)aSelector { - return class_getInstanceMethod(isa, aSelector) != NULL; + return !!class_getInstanceMethod(isa, aSelector); } // Obtaining method information diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 96be2311f..43537ffe1 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -91,7 +91,7 @@ var CPStringHashes = new objj_dictionary(); */ + (id)stringWithHash:(unsigned)aHash { - var hashString = String(aHash); + var hashString = parseInt(aHash, 10).toString(16); return "000000".substring(0, MAX(6-hashString.length, 0)) + hashString; } @@ -222,13 +222,16 @@ var CPStringHashes = new objj_dictionary(); return substr(0, aLength); var string = self, - substring = aString.substr(anIndex), + substring = aString.substring(anIndex), difference = aLength - length; - while ((difference -= substring.length) > 0) + while ((difference -= substring.length) >= 0) string += substring; - if (difference) string += substring.substr(difference + substring.length); + if (-difference < substring.length) + string += substring.substring(0, -difference); + + return string; } //Dividing Strings @@ -584,7 +587,12 @@ var CPStringHashes = new objj_dictionary(); */ - (CPArray)pathComponents { - return split('/'); + var result = split('/'); + if (result[0] === "") + result[0] = "/"; + if (result[result.length - 1] === "") + result.pop(); + return result; } /*! diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j index 0fbdad3c3..cf2719ef9 100755 --- a/Foundation/Foundation.j +++ b/Foundation/Foundation.j @@ -55,3 +55,19 @@ @import "CPURLResponse.j" @import "CPUserSessionManager.j" @import "CPValue.j" + +/*! @mainpage + Cappuccino is distributed under the @ref license "GNU LGPL". + + @htmlonly
@endhtmlonly + @htmlinclude README + @htmlonly@endhtmlonly + + @page license License + @htmlonly
@endhtmlonly + @htmlinclude LICENSE + @htmlonly@endhtmlonly + + @defgroup appkit AppKit + @defgroup foundation Foundation +*/ diff --git a/Objective-J/Tools/cplutil/main.js b/Objective-J/Tools/cplutil/main.js index 455df7a0f..1904d0a29 100644 --- a/Objective-J/Tools/cplutil/main.js +++ b/Objective-J/Tools/cplutil/main.js @@ -100,4 +100,4 @@ function main() } } -main.apply(main, arguments); +main.apply(main, args); diff --git a/Tests/Foundation/CPDateTest.j b/Tests/Foundation/CPDateTest.j index a94ec00c5..075f93ce7 100644 --- a/Tests/Foundation/CPDateTest.j +++ b/Tests/Foundation/CPDateTest.j @@ -2,6 +2,14 @@ import