diff --git a/.gitignore b/.gitignore index 496ee2ca6..68dba5b20 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.DS_Store \ No newline at end of file +.DS_Store +Frameworks diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index 0768d9b69..07e5abdcf 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 97cb4364b..0fde08dd2 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 23fbf5b1e..532e50a25 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -100,6 +100,8 @@ var CPControlBlackColor = [CPColor blackColor]; CPCellImagePosition _imagePosition; CPImageScaling _imageScaling; + CPString _toolTip; + // Target-Action Support id _target; SEL _action; @@ -314,6 +316,32 @@ var CPControlBlackColor = [CPColor blackColor]; return _textShadow; } +/*! + 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 the receiver's target action */ diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index 9e0131bf3..9f6d1092a 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -476,7 +476,7 @@ var CPPopUpButtonArrowsImage = nil; */ - (int)indexOfItemWithRepresentedObject:(id)anObject { - return [_menu indexOfItemWithRepresentedObejct:anObject]; + return [_menu indexOfItemWithRepresentedObject:anObject]; } /*! diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 703fa8c9c..38d001f14 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -459,20 +459,56 @@ var CPSplitViewHorizontalImage = nil, var index = 0, count = [_subviews count], bounds = [self bounds], - dividerThickness = [self dividerThickness]; - - for (; index < count; ++index) + dividerThickness = [self dividerThickness], + totalDividers = count - 1, + totalSizableSpace = 0, + nonSizableSpace = 0, + lastSizableIndex = -1, + totalSizablePanes = 0, + isVertical = [self isVertical]; + + for (index = 0; index < count; ++index) { var view = _subviews[index], - viewFrame = CGRectMakeCopy(bounds); - - if (index + 1 == count) - viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent]; - else - viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] * ([view frame].size[_sizeComponent] / oldSize[_sizeComponent]); - - bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness; - + isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable; + + if (isSizable) + { + totalSizableSpace += [view frame].size[_sizeComponent]; + lastSizableIndex = index; + totalSizablePanes++; + } + } + + if (totalSizablePanes === count) + totalSizableSpace = 0; + + var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0, + ratio = (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace), + remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent]; + + for (index = 0; index < count; ++index) + { + var view = _subviews[index], + viewFrame = CGRectMakeCopy(bounds), + isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable; + + if (index + 1 == count) + viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent]; + else if (totalSizableSpace && isSizable && lastSizableIndex === index) + viewFrame.size[_sizeComponent] = MAX(0, ROUND([view frame].size[_sizeComponent] + remainingFlexibleSpace)) + else if (isSizable || !totalSizableSpace) + { + viewFrame.size[_sizeComponent] = MAX(0, ROUND(ratio * [view frame].size[_sizeComponent])); + remainingFlexibleSpace -= (viewFrame.size[_sizeComponent] - [view frame].size[_sizeComponent]); + } + else if (totalSizableSpace && !isSizable) + viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent]; + else + alert("SHOULD NEVER GET HERE"); + + bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness; + [view setFrame:viewFrame]; } diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 17584e3af..40ac8c58c 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -708,6 +708,9 @@ var _CPTextFieldSquareBezelColor = nil, */ -(void)setPlaceholderString:(CPString)aStringValue { + if(_placeholderString && [self stringValue] === _placeholderString) + _value = @""; + _placeholderString = aStringValue; //if there is no set value, automatically display the placeholder diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 31ce618aa..dd4b5c92d 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -874,6 +874,15 @@ var DOMElementPrototype = nil, } // Fullscreen Mode + +/*! + Puts the receiver into full screen mode. +*/ +- (BOOL)enterFullScreenMode +{ + return [self enterFullScreenMode:nil withOptions:nil]; +} + /*! Puts the receiver into full screen mode. @param aScreen the that should be used @@ -905,6 +914,14 @@ var DOMElementPrototype = nil, return YES; } +/*! + The receiver should exit full screen mode. +*/ +- (void)exitFullScreenMode +{ + [self exitFullScreenModeWithOptions:nil]; +} + /*! The receiver should exit full screen mode. @param options configurations options 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 593558502..1c6238a2b 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -236,7 +236,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 5e26c0322..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 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/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