From a9034de9cd3e376eda95da001532e52293cd83a0 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 2 Feb 2009 18:16:23 -0700 Subject: [PATCH 01/41] Fix for textfield placeholders being completely broken. --- AppKit/CPTextField.j | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index c61740720..17584e3af 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -389,17 +389,17 @@ var _CPTextFieldSquareBezelColor = nil, /* @ignore */ - (BOOL)acceptsFirstResponder { - return _isEditable; + return _isEditable && _isEnabled; } /* @ignore */ - (BOOL)becomeFirstResponder -{ +{ +#if PLATFORM(DOM) var string = [self stringValue]; [self setStringValue:""]; - -#if PLATFORM(DOM) + var element = [[self class] _inputElement]; element.value = string; @@ -479,7 +479,7 @@ var _CPTextFieldSquareBezelColor = nil, // If current value is the placeholder value, remove it to allow user to update. if ([string lowercaseString] == [[self placeholderString] lowercaseString]) - [self setStringValue:""]; + element.value = ""; //post CPControlTextDidBeginEditingNotification [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]]; @@ -519,7 +519,7 @@ var _CPTextFieldSquareBezelColor = nil, { if (![self isEditable]) return [[self nextResponder] mouseDown:anEvent]; - + [super mouseDown:anEvent]; } /* @@ -683,7 +683,7 @@ var _CPTextFieldSquareBezelColor = nil, else displayString += aValue; } - + if ([[self window] firstResponder] == self) [[self class] _inputElement].value = displayString; @@ -712,7 +712,7 @@ var _CPTextFieldSquareBezelColor = nil, //if there is no set value, automatically display the placeholder if (!_value) - [self setStringValue:aStringValue]; + [self setStringValue:_placeholderString]; } /*! From 94c838dfde11d96db3287f0ce0a63ed94f0a0da7 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 2 Feb 2009 18:24:06 -0700 Subject: [PATCH 02/41] Various fixes. --- AppKit/CPMenuItem.j | 8 ++++++++ AppKit/CPPopUpButton.j | 9 +++++++++ Foundation/CPArray.j | 12 ++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/AppKit/CPMenuItem.j b/AppKit/CPMenuItem.j index 217382ed6..77031d9ea 100644 --- a/AppKit/CPMenuItem.j +++ b/AppKit/CPMenuItem.j @@ -230,6 +230,14 @@ return _title; } +/*! + Set's the item's text color +*/ +- (void)setTextColor:(CPString)aColor +{ + //FIXME IMPLEMENT +} + /*! Sets the font for the text of this menu item @param aFont the font for the menu item diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index d36c8a68d..9e0131bf3 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -138,6 +138,15 @@ var CPPopUpButtonArrowsImage = nil; } // Inserting and Deleting Items + +/*! + Adds a new menu item using a CPMenuItem object. +*/ +- (void)addItem:(CPMenuItem)anItem +{ + [_menu addItem:anItem]; +} + /*! Adds a new menu item with the specified title. @param the new menu item's tite diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index cb4951ad6..98b5bcf05 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -51,7 +51,7 @@ if (++_index >= [_array count]) return nil; - return _array[_index]; + return [_array objectAtIndex:_index]; } @end @@ -81,7 +81,7 @@ if (--_index < 0) return nil; - return _array[_index]; + return [_array objectAtIndex:_index]; } @end @@ -735,6 +735,14 @@ return sorted; } +/*! + Return a copy of the receiver sorted using the function passed into the first parameter. +*/ +- (CPArray)sortedArrayUsingFunction:(Function)aFunction +{ + return [self sortedArrayUsingFunction:aFunction context:nil]; +} + /*! Returns an array in which the objects are ordered according to a sort with aFunction. This invokes From f671b89da558b89f68c938e65ddc3624f0d4172a Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 4 Feb 2009 08:11:46 -0700 Subject: [PATCH 03/41] Add "setCenter:" to CPView, which takes a point and moves the center of the view's frame to that point. --- AppKit/CPView.j | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 86257d3fc..20967cdbe 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -561,6 +561,18 @@ var DOMElementPrototype = nil, return _CGRectMakeCopy(_frame); } +/*! + Moves the center of the receiver's frame to the provided point. The point is defined in the superview's coordinate system. + The method posts a CPViewFrameDidChangeNotification to the default notification center if the receiver + is configured to do so. If the specified origin is the same as the frame's current origin, the method will + simply return (and no notification will be posted). + @param aPoint the new origin point +*/ +- (void)setCenter:(CGPoint)aPoint +{ + [self setFrameOrigin:CGPointMake(aPoint.x - _frame.size.width / 2.0, aPoint.y - _frame.size.height / 2.0)]; +} + /*! Sets the receiver's frame origin to the provided point. The point is defined in the superview's coordinate system. The method posts a CPViewFrameDidChangeNotification to the default notification center if the receiver From ecaab49c08d2a6738cf17fcece862bbcb62ad59d Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 4 Feb 2009 08:52:18 -0700 Subject: [PATCH 04/41] In addition to setting the center of a view's frame, now you can query it. --- AppKit/CPView.j | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 20967cdbe..504983e56 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -573,6 +573,15 @@ var DOMElementPrototype = nil, [self setFrameOrigin:CGPointMake(aPoint.x - _frame.size.width / 2.0, aPoint.y - _frame.size.height / 2.0)]; } +/*! + Returns the center of the receiver's frame to the provided point. The point is defined in the superview's coordinate system. + @return CGPoint the center point of the receiver's frame +*/ +- (void)center +{ + return CGPointMake(_frame.size.width / 2.0 + _frame.origin.x, _frame.size.height / 2.0 + _frame.origin.y); +} + /*! Sets the receiver's frame origin to the provided point. The point is defined in the superview's coordinate system. The method posts a CPViewFrameDidChangeNotification to the default notification center if the receiver From 0e965f73b75cb2ad549ff157a8c7fa9c7fe8c6af Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 4 Feb 2009 09:17:45 -0700 Subject: [PATCH 05/41] Return type was incorrect on "center" --- AppKit/CPView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 504983e56..31ce618aa 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -577,7 +577,7 @@ var DOMElementPrototype = nil, Returns the center of the receiver's frame to the provided point. The point is defined in the superview's coordinate system. @return CGPoint the center point of the receiver's frame */ -- (void)center +- (CGPoint)center { return CGPointMake(_frame.size.width / 2.0 + _frame.origin.x, _frame.size.height / 2.0 + _frame.origin.y); } From 40def352d95b6997d767b60eaccf6095d180eacc Mon Sep 17 00:00:00 2001 From: Marc Chung Date: Wed, 4 Feb 2009 11:23:10 -0700 Subject: [PATCH 06/41] Removing borking characters from CPURLResponse.j --- Foundation/CPURLResponse.j | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Foundation/CPURLResponse.j b/Foundation/CPURLResponse.j index 1287a0c15..15bf17f66 100644 --- a/Foundation/CPURLResponse.j +++ b/Foundation/CPURLResponse.j @@ -53,13 +53,13 @@ } /* Creating a Response -РinitWithURL:MIMEType:expectedContentLength:textEncodingName: +initWithURL:MIMEType:expectedContentLength:textEncodingName: Getting the Response Properties -РexpectedContentLength -РsuggestedFilename -РMIMEType -РtextEncodingName -РURL +expectedContentLength +suggestedFilename +MIMEType +textEncodingName +URL */ @end From 1758e18bd248cb07814bd4aabfbc0caa30fbffec Mon Sep 17 00:00:00 2001 From: nciagra Date: Fri, 30 Jan 2009 23:19:51 -0500 Subject: [PATCH 07/41] Added UUID generator method to CPString. --- Foundation/CPString.j | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 6a83344a5..b91974d3c 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -662,4 +662,22 @@ var CPStringHashes = new objj_dictionary(); @end + +@implementation CPString (UUID) + +/*! + Returns a randomly generated Universally Unique Identifier. +*/ ++ (CPString)UUID +{ + var g = @""; + + for(var i = 0; i < 32; i++) + g += Math.floor(Math.random() * 0xF).toString(0xF); + + return g; +} + +@end + String.prototype.isa = CPString; From 471f6cb5e54b93869ff73fd992b884d22d1e8c57 Mon Sep 17 00:00:00 2001 From: nciagra Date: Fri, 30 Jan 2009 01:13:04 -0500 Subject: [PATCH 08/41] Added setTitle: accessors to CPAlert. --- AppKit/CPAlert.j | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j index 152fe19ef..9d7572f57 100644 --- a/AppKit/CPAlert.j +++ b/AppKit/CPAlert.j @@ -84,6 +84,7 @@ var CPAlertWarningImage, CPImageView _alertImageView; CPAlertStyle _alertStyle; + CPString _windowTitle; int _windowStyle; int _buttonCount; CPArray _buttons; @@ -163,6 +164,23 @@ var CPAlertWarningImage, [[_alertPanel contentView] addSubview:_alertImageView]; } +/*! + Sets the window's title. If this is not defined, a default title based on your warning level will be used. + @param aTitle the title to use in place of the default. Set to nil to use default. +*/ +- (void)setTitle:(CPString)aTitle +{ + _windowTitle = aTitle; +} + +/*! + Gets the window's title. +*/ +- (CPString)title +{ + return _windowTitle; +} + /*! Gets the window's style. */ @@ -252,19 +270,23 @@ var CPAlertWarningImage, */ - (void)runModal { + var theTitle; + switch (_alertStyle) { case CPWarningAlertStyle: [_alertImageView setImage:CPAlertWarningImage]; - [_alertPanel setTitle:@"Warning"]; + theTitle = @"Warning"; break; case CPInformationalAlertStyle: [_alertImageView setImage:CPAlertInformationImage]; - [_alertPanel setTitle:@"Information"]; + theTitle = @"Information"; break; case CPCriticalAlertStyle: [_alertImageView setImage:CPAlertErrorImage]; - [_alertPanel setTitle:@"Error"]; + theTitle = @"Error"; break; } - + + [_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle]; + [CPApp runModalForWindow:_alertPanel]; } From c29b5f2fef6c4b4b06c5c2984aa8926908091aee Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 4 Feb 2009 14:37:48 -0700 Subject: [PATCH 09/41] Use cached math library functions in UUID. --- Foundation/CPString.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index b91974d3c..96be2311f 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -673,7 +673,7 @@ var CPStringHashes = new objj_dictionary(); var g = @""; for(var i = 0; i < 32; i++) - g += Math.floor(Math.random() * 0xF).toString(0xF); + g += FLOOR(RAND() * 0xF).toString(0xF); return g; } From 3f410ea6888f980b6821ca754e96f7d9287c632f Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 4 Feb 2009 23:11:00 -0700 Subject: [PATCH 10/41] Add missing _delegate to CAAnimation.j --- AppKit/CoreAnimation/CAAnimation.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/CoreAnimation/CAAnimation.j b/AppKit/CoreAnimation/CAAnimation.j index fbaca60fd..8303b7ef4 100644 --- a/AppKit/CoreAnimation/CAAnimation.j +++ b/AppKit/CoreAnimation/CAAnimation.j @@ -31,6 +31,7 @@ @implementation CAAnimation : CPObject { BOOL _isRemovedOnCompletion; + id _delegate; } /*! From 48fb8f00caf29d28aaf0bea5045a5e22f220faa6 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 9 Feb 2009 23:34:49 -0800 Subject: [PATCH 11/41] Add convenience methods for full screen. --- AppKit/CPView.j | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 From a5f23035ae7f6374a13db4449b8d825a74e1d9a1 Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Sun, 15 Feb 2009 22:54:29 -0800 Subject: [PATCH 12/41] Added Frameworks to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From 0bd543b57b2dcedcfcf9439d500729372827a08d Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 16 Feb 2009 22:59:44 -0800 Subject: [PATCH 13/41] Added support for autoresizing inner split view subviews. --- AppKit/CPSplitView.j | 55 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 703fa8c9c..2c3405b55 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -459,20 +459,51 @@ 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, + 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; + } + } + + 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]; } From b7f2f315e28006504c1adb7729858b0a8b29ef98 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Tue, 17 Feb 2009 02:21:46 -0800 Subject: [PATCH 14/41] Bugfix for new splitview resze behavior. --- AppKit/CPSplitView.j | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 2c3405b55..38d001f14 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -464,6 +464,7 @@ var CPSplitViewHorizontalImage = nil, totalSizableSpace = 0, nonSizableSpace = 0, lastSizableIndex = -1, + totalSizablePanes = 0, isVertical = [self isVertical]; for (index = 0; index < count; ++index) @@ -475,9 +476,13 @@ var CPSplitViewHorizontalImage = nil, { 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]; From ac6260bf0d9731985fe619649a8657cca3cfd651 Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 19 Feb 2009 04:19:22 -0800 Subject: [PATCH 15/41] CPException CPCoding bug fixes --- Foundation/CPException.j | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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; From ec3dcaa2875eaf9e7def9076d110a5a357c0e185 Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 19 Feb 2009 04:32:15 -0800 Subject: [PATCH 16/41] Delete the stupid debug.txt file after building documentation. --- build.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.xml b/build.xml index eb3fa2de8..81f14bba4 100644 --- a/build.xml +++ b/build.xml @@ -125,6 +125,8 @@ + + From 1da9e93241740c1b4cfe3c0bfb30648db07cfa4f Mon Sep 17 00:00:00 2001 From: Landon Fuller Date: Thu, 19 Feb 2009 22:59:37 -0800 Subject: [PATCH 17/41] Implement support for UNIX epoch initialization. Add support for the +[CPDate dateWithTimeIntervalSince1970:] and -[CPDate initWithTimeIntervalSince1970]. --- Foundation/CPDate.j | 10 +++++++++- Tests/Foundation/CPDateTest.j | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index db83c63c4..d30084ce6 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -43,6 +43,9 @@ var CPDateReferenceDate = new Date(Date.UTC(2001,1,1,0,0,0,0)); { return [[CPDate alloc] initWithTimeIntervalSinceNow:seconds]; } ++ (id)dateWithTimeIntervalSince1970:(CPTimeInterval)seconds { + return [[CPDate alloc] initWithTimeIntervalSince1970:seconds]; +} + (id)dateWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { return [[CPDate alloc] initWithTimeIntervalSinceReferenceDate:seconds]; @@ -63,6 +66,11 @@ 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]; @@ -129,4 +137,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/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 @implementation CPDateTest : OJTestCase +- (void)testSince1970 +{ + /* These two dates should be equal to Fri Feb 13 2009 15:31:30 GMT-0800 */ + unixDate = [CPDate dateWithTimeIntervalSince1970: 1234567890]; + cocoaDate = [CPDate dateWithTimeIntervalSinceReferenceDate: 253582290]; + [self assertTrue:[unixDate isEqualToDate: cocoaDate]]; +} + - (void)testDate { var before = new Date(); @@ -17,4 +25,4 @@ import [self assert:middle equals:[middle laterDate:past] message:"laterDate incorrect"]; } -@end \ No newline at end of file +@end From 8da7b0ee911c4f9b0aa5f8b1ae195f9734941aed Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 26 Feb 2009 17:21:40 -0800 Subject: [PATCH 18/41] Fix some spacing/style issues in CPDate. --- Foundation/CPDate.j | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index d30084ce6..cf893248e 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -39,13 +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 { + ++ (id)dateWithTimeIntervalSince1970:(CPTimeInterval)seconds +{ return [[CPDate alloc] initWithTimeIntervalSince1970:seconds]; } + + (id)dateWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { return [[CPDate alloc] initWithTimeIntervalSinceReferenceDate:seconds]; @@ -66,28 +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; @@ -97,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]; From 547ed38855691a472783320c6eded20bd8d6a6d5 Mon Sep 17 00:00:00 2001 From: Leif Singer Date: Sun, 8 Feb 2009 17:16:22 +0100 Subject: [PATCH 19/41] Modified CPColor's hexToRGB to also accept hex colors with only three characters, as is possible in CSS. E.g., 'ccc' will expand to 'cccccc', etc. --- AppKit/CPColor.j | 2 ++ 1 file changed, 2 insertions(+) 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; From 1d38ca64c75cbd58297a28ac4c9381fdbe27f2ff Mon Sep 17 00:00:00 2001 From: Thomas Balthazar Date: Fri, 13 Feb 2009 18:03:29 +0100 Subject: [PATCH 20/41] ticket 220 fixed http://cappuccino.lighthouseapp.com:80/projects/16499/tickets/220-typo-in-cppopupbutton-indexofitemwithrepresentedobject#ticket-220-1 --- AppKit/CPPopUpButton.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]; } /*! From 723c9ae55677b85683f626412730f1de3c4e33d9 Mon Sep 17 00:00:00 2001 From: Russell Mull Date: Sun, 14 Sep 2008 10:57:35 -0700 Subject: [PATCH 21/41] improved CPStringTest --- Tests/Foundation/CPStringTest.j | 108 ++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 5 deletions(-) diff --git a/Tests/Foundation/CPStringTest.j b/Tests/Foundation/CPStringTest.j index f509e8128..61aa61a50 100644 --- a/Tests/Foundation/CPStringTest.j +++ b/Tests/Foundation/CPStringTest.j @@ -16,14 +16,112 @@ import } - (void)testStringByAppendingFormat { - var format = @"%d X %d = %d"; - var expectedString = "2 X 3 = 6"; - var dummyString = @""; - var actualString = [dummyString stringByAppendingFormat:format ,2 ,3 ,6]; + var format = @"%d X %d = %d", + expectedString = "2 X 3 = 6", + dummyString = @"", + actualString = [dummyString stringByAppendingFormat:format, 2, 3, 6]; + [self assertTrue:(expectedString === actualString) message:"stringByAppendingFormat: expected:" + expectedString + " actual:" + actualString]; - } + +- (void)testStringWithString +{ + var original = [[CPString alloc] initWithString:"str"], + copy = [CPString stringWithString:original]; + + [self assertTrue:(original == copy) message:"Contents should be equal"]; +} + +- (void)testInitWithString +{ + var str = [[CPString alloc] initWithString:"str"]; + [self assert:"str" equals:str]; +} + +- (void) testInitWithFormat +{ + // this could be really big + var str = [[CPString alloc] initWithFormat:"%s", "str"]; + [self assert:"str" equals:str]; + + str = [[CPString alloc] initWithFormat:"%d", 42]; + [self assert:"42" equals:str]; + + str = [[CPString alloc] initWithFormat:"%f", 42.2]; + [self assert:"42.2" equals:str]; +} + +- (void)testStringWithFormat +{ + // this could be equally big + var str = [CPString stringWithFormat:"%s", "str"]; + [self assert:"str" equals:str]; + + str = [CPString stringWithFormat:"%d", 42]; + [self assert:"42" equals:str]; + + str = [CPString stringWithFormat:"%f", 42.2]; + [self assert:"42.2" equals:str]; +} + +- (void)testLength +{ + [self assert:0 equals:["" length]]; + [self assert:1 equals:["a" length]]; + [self assert:5 equals:["abcde" length]]; + [self assert:3 equals:["日本語" length]]; +} + +- (void)testCharacterAtIndex +{ + [self assert:"a" equals:["abcd" characterAtIndex:0]]; + [self assert:"b" equals:["abcd" characterAtIndex:1]]; + [self assert:"d" equals:["abcd" characterAtIndex:3]]; + [self assert:"語" equals:["日本語" characterAtIndex:2]]; +} + +- (void)testStringByAppendingSting +{ + [self assert:"onetwo" equals:["one" stringByAppendingString:"two"]]; +} + + +- (void)testStringByPaddingToLength +{ + [self assert:"onebcd" + equals:["one" stringByPaddingToLength:6 + withString:"abcdefg" + startingAtIndex:1]]; +} + +- (void)testComponentsSeparatedByString +{ + [self assert:["arash", "francisco", "ross", "tom"] + equals:["arash.francisco.ross.tom" componentsSeparatedByString:"."]]; +} + +- (void)testSubstringFromIndex +{ + [self assert:"abcd" equals:["abcd" substringFromIndex:0]]; + [self assert:"bcd" equals:["abcd" substringFromIndex:1]]; + [self assert:"" equals:["abcd" substringFromIndex:4]]; +} + +- (void)testSubstringWithRange +{ + [self assert:"bcd" equals:["abcde" substringWithRange:CPMakeRange(1,3)]]; + [self assert:"abcde" equals:["abcde" substringWithRange:CPMakeRange(0,5)]]; + [self assert:"" equals:["abcde" substringWithRange:CPMakeRange(1,0)]]; +} + +- (void)testSubstringToIndex +{ + [self assert:"abcd" equals:["abcd" substringToIndex:4]]; + [self assert:"abc" equals:["abcd" substringToIndex:3]]; + [self assert:"" equals:["abcd" substringToIndex:0]]; +} + - (void)testBoolValue { var testStrings = [ From 6750b906717c7efb067cea71824483c92ae149d0 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 26 Feb 2009 21:30:54 -0800 Subject: [PATCH 22/41] Fixes for some new CPString tests. --- Foundation/CPString.j | 11 +++++++---- Tests/Foundation/CPStringTest.j | 27 ++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 96be2311f..cf2953388 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/Tests/Foundation/CPStringTest.j b/Tests/Foundation/CPStringTest.j index 61aa61a50..a7d8f0e8d 100644 --- a/Tests/Foundation/CPStringTest.j +++ b/Tests/Foundation/CPStringTest.j @@ -90,9 +90,9 @@ import - (void)testStringByPaddingToLength { [self assert:"onebcd" - equals:["one" stringByPaddingToLength:6 - withString:"abcdefg" - startingAtIndex:1]]; + equals:["one" stringByPaddingToLength:6 + withString:"abcdefg" + startingAtIndex:1]]; } - (void)testComponentsSeparatedByString @@ -157,6 +157,27 @@ import [self assert:[testStrings[i][0] capitalizedString] equals:testStrings[i][1]]; } +- (void)testUppercaseString +{ + var str = "This is a test"; + [self assert:[str uppercaseString] equals:"THIS IS A TEST"]; +} + +- (void)testLowercaseString +{ + var str = "This Is A TEST"; + [self assert:"this is a test" equals:[str lowercaseString]]; +} + +- (void)testStringWithHash +{ + [self assert:"000000" equals:[CPString stringWithHash:0]]; + [self assert:"000001" equals:[CPString stringWithHash:1]]; + [self assert:"00000a" equals:[CPString stringWithHash:10]]; + [self assert:"000010" equals:[CPString stringWithHash:16]]; + [self assert:"ffffff" equals:[CPString stringWithHash:16777215]]; +} + - (void)testStringByDeletingLastPathComponent { var testStrings = [ From d81c944e457c4710b08544fe6b720e5fcc4c6262 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 2 Mar 2009 15:59:58 -0800 Subject: [PATCH 23/41] minor fix to the objective-j mode. --- Tools/SubEthaEdit/Objective-J.mode.zip | Bin 78342 -> 78383 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tools/SubEthaEdit/Objective-J.mode.zip b/Tools/SubEthaEdit/Objective-J.mode.zip index 95f9b988fec9225db7533c6bf94e27d783e7cdb4..83fa37b092c3fc13f8679b37a3f2d97bd334ca7d 100644 GIT binary patch delta 22626 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

|r0 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 Y$Dqy-<0k?E-1j*x2;>37skMUs2Xd!a*Z=?k delta 22550 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 Date: Sun, 1 Mar 2009 12:40:48 +0000 Subject: [PATCH 24/41] Added @mainpage for doxygen that simply includes the README and LiCENSE docs. Also added groups for appkit and foundation classes. --- Foundation/Foundation.j | 16 ++++++++++++++++ Tools/Documentation/Cappuccino.doxygen | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j index 0fbdad3c3..8fbec7323 100755 --- a/Foundation/Foundation.j +++ b/Foundation/Foundation.j @@ -55,3 +55,19 @@ @import "CPURLResponse.j" @import "CPUserSessionManager.j" @import "CPValue.j" + +/*! @defgroup appkit AppKit + @defgroup foundation Foundation + + @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 +*/ diff --git a/Tools/Documentation/Cappuccino.doxygen b/Tools/Documentation/Cappuccino.doxygen index d083ca453..91129133f 100644 --- a/Tools/Documentation/Cappuccino.doxygen +++ b/Tools/Documentation/Cappuccino.doxygen @@ -137,7 +137,8 @@ EXCLUDE = AppKit/Cib \ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = _* EXCLUDE_SYMBOLS = _* -EXAMPLE_PATH = +EXAMPLE_PATH = ./README \ + ./LICENSE EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = From 0508c5479934908b1ce0562d71f1e6861816e922 Mon Sep 17 00:00:00 2001 From: stephen Date: Sun, 1 Mar 2009 14:11:47 +0000 Subject: [PATCH 25/41] Defgroups must go at end of comment otherwise previous obj-j statements become part of the group name. --- Foundation/Foundation.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j index 8fbec7323..cf2719ef9 100755 --- a/Foundation/Foundation.j +++ b/Foundation/Foundation.j @@ -56,10 +56,7 @@ @import "CPUserSessionManager.j" @import "CPValue.j" -/*! @defgroup appkit AppKit - @defgroup foundation Foundation - - @mainpage +/*! @mainpage Cappuccino is distributed under the @ref license "GNU LGPL". @htmlonly
@endhtmlonly
@@ -70,4 +67,7 @@
     @htmlonly 
@endhtmlonly
     @htmlinclude LICENSE
     @htmlonly 
@endhtmlonly + + @defgroup appkit AppKit + @defgroup foundation Foundation */ From 46a975b9660707205ee55bf3f08967f87a29d0e9 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 5 Mar 2009 14:30:38 -0800 Subject: [PATCH 26/41] Updated CPObject's instancesRespondToSelector to return BOOL --- Foundation/CPArray.j | 2 +- Foundation/CPObject.j | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/CPObject.j b/Foundation/CPObject.j index 224439bd6..eeb8406be 100644 --- a/Foundation/CPObject.j +++ b/Foundation/CPObject.j @@ -177,7 +177,7 @@ */ + (BOOL)instancesRespondToSelector:(SEL)aSelector { - return class_getInstanceMethod(self, aSelector); + return !!class_getInstanceMethod(self, aSelector); } /*! @@ -187,7 +187,7 @@ */ - (BOOL)respondsToSelector:(SEL)aSelector { - return class_getInstanceMethod(isa, aSelector) != NULL; + return !!class_getInstanceMethod(isa, aSelector); } // Obtaining method information From a1e3feda4ffd53d2ea436b4611bdfa308e25b601 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 7 Feb 2009 15:28:28 +0100 Subject: [PATCH 27/41] Fixed typo --- AppKit/CoreAnimation/CAMediaTimingFunction.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } } From 55fa6024dbade24c5263ded5aa61d471c22b825a Mon Sep 17 00:00:00 2001 From: M ESCO Date: Sat, 7 Feb 2009 14:26:37 +0100 Subject: [PATCH 28/41] Added tooltip support --- AppKit/CPControl.j | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 23fbf5b1e..3edb5a8bb 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,30 @@ 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 cssString]; +#endif +} + +/*! + Returns the receiver's tooltip +*/ +-(CPString)toolTip +{ + return _toolTip; +} + /*! Returns the receiver's target action */ From 0fdfd8919f492e6e4f9d3da8df5a973d49fed774 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 5 Mar 2009 14:45:34 -0800 Subject: [PATCH 29/41] Remove the tabs. --- AppKit/CPControl.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 3edb5a8bb..adbc5c5d2 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -100,7 +100,7 @@ var CPControlBlackColor = [CPColor blackColor]; CPCellImagePosition _imagePosition; CPImageScaling _imageScaling; - CPString _toolTip; + CPString _toolTip; // Target-Action Support id _target; @@ -337,7 +337,7 @@ var CPControlBlackColor = [CPColor blackColor]; */ -(CPString)toolTip { - return _toolTip; + return _toolTip; } /*! From faac82287f43c57775b859f1e180e8b31e71aa88 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 7 Feb 2009 17:12:44 +0100 Subject: [PATCH 30/41] Fixed bug in previous commit of setToolTip: --- AppKit/CPControl.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index adbc5c5d2..e08fbed6b 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -328,7 +328,7 @@ var CPControlBlackColor = [CPColor blackColor]; _toolTip = aToolTip; #if PLATFORM(DOM) - _DOMElement.title = [aToolTip cssString]; + _DOMElement.title = aToolTip; #endif } From 546c95bdf645abee13863f637a3e8583dee631df Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 7 Feb 2009 16:46:52 +0100 Subject: [PATCH 31/41] Fixed typos in CPArray+KVO ; added suport for *objects:atIndexes: --- Foundation/CPArray+KVO.j | 59 +++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 19 deletions(-) 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 From bbe1b58437eab5519f95498f59ecb7c931296644 Mon Sep 17 00:00:00 2001 From: Vladimir Pouzanov Date: Thu, 5 Mar 2009 21:38:17 +0200 Subject: [PATCH 32/41] Added more api docs to CPObject --- Foundation/CPObject.j | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j index eeb8406be..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 { From 4422530fe447963893681a29041a435cc80b02fc Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Sat, 7 Mar 2009 19:34:24 -0800 Subject: [PATCH 33/41] Fixed press bug (hasOwnProperty to lookup dependencies) and cleaned up output --- Tools/press/objj-analysis-tools.j | 4 +-- Tools/press/press.j | 45 +++++++++++++++++++------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Tools/press/objj-analysis-tools.j b/Tools/press/objj-analysis-tools.j index 628c6c78a..c225998fc 100644 --- a/Tools/press/objj-analysis-tools.j +++ b/Tools/press/objj-analysis-tools.j @@ -85,7 +85,7 @@ function traverseDependencies(context, file) { if (context.dependencies[token]) { - var files = context.dependencies[token] + var files = context.dependencies[token]; for (var j = 0; j < files.length; j++) { // don't record references to self @@ -232,7 +232,7 @@ function findGlobalDefines(context, scope, rootPath, evaledFragments) if (evaledFragments) { - evaledFragments.push(aFragment); + evaledFragments.push(aFragment); } var result = fragment_evaluate_code_original(aFragment); diff --git a/Tools/press/press.j b/Tools/press/press.j index b3aa7aba9..ed96f4536 100644 --- a/Tools/press/press.j +++ b/Tools/press/press.j @@ -11,7 +11,8 @@ var usageMessage = --frameworks path The relative path (from root_directory) to the frameworks directory (default: 'Frameworks')\n\ --png Run pngcrush on all PNGs (pngcrush must be installed!)\n\ --flatten Flatten all code into a single Application.js file and attempt add script tag to index.html (useful for Adobe AIR and CDN deployment)\n\ - --nostrip Don't strip any files"; + --nostrip Don't strip any files\n\ + --v Verbose"; function main() { @@ -22,7 +23,7 @@ function main() optimizePNG = false, flatten = false, noStrip = false, - verbose = true; + verbose = false; var usageError = false; while (args.length && !usageError) @@ -51,6 +52,9 @@ function main() case "--nostrip": noStrip = true; break; + case "--v": + verbose = true; + break; default: if (rootDirectory == null) rootDirectory = arg.replace(/\/$/, ""); @@ -125,6 +129,11 @@ function main() // coalesce the results var dependencies = coalesceGlobalDefines(globals); + // Log + CPLog.trace("Global defines:"); + for (var i in dependencies) + CPLog.trace(" " + i + " => " + dependencies[i]); + // phase 2: walk the dependency tree (both imports and references) to determine exactly which files need to be included CPLog.error("PHASE 2: Walk dependency tree..."); @@ -143,7 +152,7 @@ function main() return; } - CPLog.info("Analyzing dependencies..."); + CPLog.warn("Analyzing dependencies..."); var context = { scope : scope, @@ -172,21 +181,21 @@ function main() } else { - CPLog.warn("Excluded: " + path); + CPLog.info("Excluded: " + path); } total++; } - CPLog.info("Total required files: " + count + " out of " + total); + CPLog.warn("Total required files: " + count + " out of " + total); // FIXME: sprite images - for (var i in context.bundleImages) - { - var images = context.bundleImages[i]; - - //CPLog.info("Bundle images for " + i); - //for (var j in images) - // CPLog.debug(j + " = " + images[j]); - } + //for (var i in context.bundleImages) + //{ + // var images = context.bundleImages[i]; + // + // CPLog.debug("Bundle images for " + i); + // for (var j in images) + // CPLog.trace(j + " = " + images[j]); + //} } var outputFiles = {}; @@ -236,7 +245,7 @@ function main() } else { - CPLog.warn("Stripping " + evaledFragments[i].file.path); + CPLog.info("Stripping " + evaledFragments[i].file.path); } } @@ -272,7 +281,7 @@ function main() directory = dirname(path); if (file.path != path) - CPLog.warn("Sanity check (file path): " + file.path + " vs. " + path); + CPLog.warn("Sanity check failed (file path): " + file.path + " vs. " + path); if (file.bundle) { @@ -282,7 +291,7 @@ function main() bundles[file.bundle.path] = file.bundle; if (bundleDirectory != directory) - CPLog.warn("Sanity check (directory path): " + directory + " vs. " + bundleDirectory); + CPLog.warn("Sanity check failed (directory path): " + directory + " vs. " + bundleDirectory); // if it's in a .sj var dict = file.bundle.info, @@ -337,7 +346,7 @@ function main() } } else - CPLog.warn("Ignoring import fragment " + file.fragments[i].info + " in " + path); + CPLog.info("Ignoring import fragment " + file.fragments[i].info + " in " + path); } else CPLog.error("Unknown fragment type"); @@ -362,6 +371,8 @@ function main() dict = bundles[path].info, replacedFiles = [dict objectForKey:"CPBundleReplacedFiles"]; + CPLog.info("Modifying .sj: " + path); + if (replacedFiles) { var newReplacedFiles = []; From 25c7d98d2c353582dddc9a662c67536647cbf1ec Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Sat, 7 Mar 2009 19:35:14 -0800 Subject: [PATCH 34/41] Fix cplutil using "arguments" instead of "args" --- Tools/cplutil/cplutil.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/cplutil/cplutil.js b/Tools/cplutil/cplutil.js index 455df7a0f..1904d0a29 100644 --- a/Tools/cplutil/cplutil.js +++ b/Tools/cplutil/cplutil.js @@ -100,4 +100,4 @@ function main() } } -main.apply(main, arguments); +main.apply(main, args); From 88035429bb5de912a7d804a8659b5af542f6faeb Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sat, 7 Mar 2009 21:05:18 -0800 Subject: [PATCH 35/41] Fix in CPString setPlaceholderString [#238 state:resolved] --- AppKit/CPTextField.j | 3 +++ 1 file changed, 3 insertions(+) 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 From 3268081d1f5cc0b813f2ba46a1c679f4cc86a0e3 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sat, 7 Mar 2009 21:54:39 -0800 Subject: [PATCH 36/41] CPDictionary should check for isa's before calling isEqual: in isEqualToDictionary: --- Foundation/CPDictionary.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 2f85a417d650a3d26a854e07d0e1dd23c78ce216 Mon Sep 17 00:00:00 2001 From: Thomas Balthazar Date: Sun, 8 Mar 2009 14:53:13 +0100 Subject: [PATCH 37/41] [#239 state:resolved] : typo in CPNotificationCenter --- Foundation/CPNotificationCenter.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]; From 19d26f148f8ab57bca83c2807d12869abe85c234 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Tue, 10 Mar 2009 11:50:31 -0700 Subject: [PATCH 38/41] Reverting the tooltip change, fixes bug in CPToolbar. --- AppKit/CPControl.j | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index e08fbed6b..532e50a25 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -320,6 +320,7 @@ var CPControlBlackColor = [CPColor blackColor]; Sets the tooltip for the receiver. @param aToolTip the tooltip */ +/* -(void)setToolTip:(CPString)aToolTip { if (_toolTip == aToolTip) @@ -331,15 +332,16 @@ var CPControlBlackColor = [CPColor blackColor]; _DOMElement.title = aToolTip; #endif } - +*/ /*! Returns the receiver's tooltip */ +/* -(CPString)toolTip { return _toolTip; } - +*/ /*! Returns the receiver's target action */ From 38d72bc672ebe10ef9aa28ac823b10517b3a57ef Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Tue, 10 Mar 2009 23:18:43 -0700 Subject: [PATCH 39/41] Respect _isSelectable on CPCollectionView --- AppKit/CPCollectionView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index 0768d9b69..c05deeef2 100644 --- a/AppKit/CPCollectionView.j +++ b/AppKit/CPCollectionView.j @@ -258,7 +258,7 @@ */ - (void)setSelectionIndexes:(CPIndexSet)anIndexSet { - if (_selectionIndexes == anIndexSet) + if (_selectionIndexes == anIndexSet || !_isSelectable) return; var index = CPNotFound; From 9f8ca93a577f879f66d1d225fd66178c18e471de Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Fri, 13 Mar 2009 15:51:54 -0700 Subject: [PATCH 40/41] Collection views should be selectable by default. --- AppKit/CPCollectionView.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index c05deeef2..07e5abdcf 100644 --- a/AppKit/CPCollectionView.j +++ b/AppKit/CPCollectionView.j @@ -111,6 +111,7 @@ _tileWidth = -1.0; _selectionIndexes = [CPIndexSet indexSet]; + _isSelectable = YES; } return self; From b7b0ca40b09d7ea177d3b4c067d4e59c9a75525f Mon Sep 17 00:00:00 2001 From: tlrobinson Date: Tue, 17 Mar 2009 18:38:14 -0700 Subject: [PATCH 41/41] Fixed CPString pathComponents and lastPathComponent to match Cocoa. Added tests. --- Foundation/CPString.j | 7 ++++++- Tests/Foundation/CPStringTest.j | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 96be2311f..5e26c0322 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -584,7 +584,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/Tests/Foundation/CPStringTest.j b/Tests/Foundation/CPStringTest.j index f509e8128..1533ab0b7 100644 --- a/Tests/Foundation/CPStringTest.j +++ b/Tests/Foundation/CPStringTest.j @@ -80,4 +80,31 @@ import [self assert:[testStrings[i][0] stringByDeletingLastPathComponent] equals:testStrings[i][1]]; } +- (void)testPathComponents +{ + var testStrings = [ + ["tmp/scratch", ["tmp", "scratch"]], + ["/tmp/scratch", ["/", "tmp", "scratch"]] + ] + + for (var i = 0; i < testStrings.length; i++) { + var result = [testStrings[i][0] pathComponents]; + [self assertTrue:[result isEqualToArray:testStrings[i][1]] message:"Expected [" + testStrings[i][1] + "] was [" + result + "]"]; + } +} + +- (void)testLastPathComponent +{ + var testStrings = [ + ["/tmp/scratch.tiff", "scratch.tiff"], + ["/tmp/scratch", "scratch"], + ["/tmp/", "tmp"], + ["scratch", "scratch"], + ["/", "/"] + ]; + + for (var i = 0; i < testStrings.length; i++) + [self assert:testStrings[i][1] equals:[testStrings[i][0] lastPathComponent]]; +} + @end