From 6d3f430b24f53f386d833b2275801cea16178b5b Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 22 Oct 2014 17:27:46 -0700 Subject: [PATCH 01/53] Fixed: constructor of CPDate can take string param Previously, when making a CPDate with some constructors, we could pass a string or nil to create a date. For example it was allowed to do var date = [CPDate dateWithTimeIntervalSince1970:"10"]; Now this is not possible anymore and it works like in Cocoa, only number are authorized. --- Foundation/CPDate.j | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 736ca9ff2..62eebc25c 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -74,24 +74,36 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSinceNow:(CPTimeInterval)seconds { + if (!_isNumberType(seconds)) + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceNow: has to be an integer"]; + self = new Date((new Date()).getTime() + seconds * 1000); return self; } - (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds { + if (!_isNumberType(seconds)) + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSince1970: has to be an integer"]; + self = new Date(seconds * 1000); return self; } - (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { + if (!_isNumberType(seconds)) + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceReferenceDate: has to be an integer"]; + self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate]; return self; } - (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate { + if (!_isNumberType(seconds)) + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeInterval:sinceDate: has to be an integer"]; + self = new Date(refDate.getTime() + seconds * 1000); return self; } @@ -275,3 +287,11 @@ Date.parseISO8601 = function (date) }; Date.prototype.isa = CPDate; + +function _isNumberType(value) +{ + if (typeof value === 'number') + return YES; + else + return NO; +} \ No newline at end of file From d5e811f9f1ecef6d000ad664e96160a30ee5a9d8 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Sun, 26 Oct 2014 21:27:10 -0700 Subject: [PATCH 02/53] Fixed: exception descriptions in CPDate did not countain all of the needed informations --- Foundation/CPDate.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 62eebc25c..47abdfe7d 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -75,7 +75,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSinceNow:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceNow: has to be an integer"]; + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceNow: has to be an integer or a float"]; self = new Date((new Date()).getTime() + seconds * 1000); return self; @@ -84,7 +84,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSince1970: has to be an integer"]; + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSince1970: has to be an integer or a float"]; self = new Date(seconds * 1000); return self; @@ -93,7 +93,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceReferenceDate: has to be an integer"]; + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceReferenceDate: has to be an integer or a float"]; self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate]; return self; @@ -102,7 +102,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeInterval:sinceDate: has to be an integer"]; + [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeInterval:sinceDate: has to be an integer or a float"]; self = new Date(refDate.getTime() + seconds * 1000); return self; From 82c32d7dee65ef7321311e74fa2c38836fa56733 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Fri, 31 Oct 2014 17:14:55 -0400 Subject: [PATCH 03/53] New: Implementation of the CoreFoundation CFError This commit adds an implementation of the CoreFoundation CFError classes and functions. --- Objective-J/CFError.js | 158 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 Objective-J/CFError.js diff --git a/Objective-J/CFError.js b/Objective-J/CFError.js new file mode 100644 index 000000000..5169de5c6 --- /dev/null +++ b/Objective-J/CFError.js @@ -0,0 +1,158 @@ +/* + * CFError.js + * Objective-J + * + * Created by Andrew Hankinson. + * Copyright 2014, Andrew Hankinson. + * + * 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 + */ + +GLOBAL(kCFErrorLocalizedDescriptionKey) = "CPLocalizedDescription"; +GLOBAL(kCFErrorLocalizedFailureReasonKey) = "CPLocalizedFailureReason"; +GLOBAL(kCFErrorLocalizedRecoverySuggestionKey) = "CPLocalizedRecoverySuggestion"; +GLOBAL(kCFErrorDescriptionKey) = "CPDescription"; +GLOBAL(kCFErrorUnderlyingErrorKey) = "CPUnderlyingError"; + +GLOBAL(kCFErrorURLKey) = "_kCFErrorURLKey"; +GLOBAL(kCFErrorFilePathKey) = "_kCFErrorFilePathKey"; + +// GLOBAL(kCFErrorDomainPOSIX) = ""; +// GLOBAL(kCFErrorDomainOSStatus) = ""; +// GLOBAL(kCFErrorDomainMach) = ""; +GLOBAL(kCFErrorDomainCappuccino) = "CPErrorDomainCappuccino"; +GLOBAL(kCFErrorDomainCocoa) = kCFErrorDomainCappuccino; + + +GLOBAL(CFError) = function(/* CFString */ domain, /* int */ code, /* CFDictionary */ userInfo) +{ + this._domain = domain || NULL; + this._code = code || NULL; + this._userInfo = userInfo || new CFDictionary(); + this._UID = objj_generateObjectUID(); +} + +CFError.prototype.domain = function () +{ + return this._domain; +} +DISPLAY_NAME(CFError.prototype.domain) + +CFError.prototype.code = function () +{ + return this._code; +} +DISPLAY_NAME(CFError.prototype.code) + +/* + This follows the same logic to generate a description as the "real" CFError. +*/ +CFError.prototype.description = function () +{ + var localizedDesc = this._userInfo.valueForKey(kCFErrorLocalizedDescriptionKey); + if (localizedDesc) + return localizedDesc; + + var reason = this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey); + if (reason) + { + var operationFailedStr = "The operation couldn\u2019t be completed. " + reason; + return operationFailedStr; + } + + // @TODO Add the bundle localized domain handler. + var result = "", + desc = this._userInfo.valueForKey(kCFErrorDescriptionKey); + if (desc) + { + // we have a description key. + var result = "The operation couldn\u2019t be completed. (error " + this._code + "- " + desc + ")"; + } + else + { + // just use error and code; + var result = "The operation couldn\u2019t be completed. (error " + this._code + ")"; + } + + return result; +} +DISPLAY_NAME(CFError.prototype.description) + +CFError.prototype.failureReason = function () +{ + return this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey); +} +DISPLAY_NAME(CFError.prototype.failureReason) + +CFError.prototype.recoverySuggestion = function () +{ + return this._userInfo.valueForKey(kCFErrorLocalizedRecoverySuggestionKey); +} +DISPLAY_NAME(CFError.prototype.recoverySuggestion) + +CFError.prototype.userInfo = function () +{ + return this._userInfo; +} +DISPLAY_NAME(CFError.prototype.userInfo) + +/* + CFError Bridge Functions + The "Create" and "Copy" in the function names do not have any meaning + in Cappuccino; they are bridged here for compatibility reasons only. +*/ +GLOBAL(CFErrorCreate) = function(/* String */ domain, /*int */ code, /* CFDictionary */ userInfo) +{ + return new CFError(domain, code, userInfo); +} + +GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, /* int */ code, /* array */ userInfoKeys, /* array */ userInfoValues, /* int */ numUserInfoValues) +{ + var userInfo = new CFDictionary(); + while(numUserInfoValues--) + userInfo.setValueForKey(userInfoKeys[numUserInfoValues], userInfoValues[numUserInfoValues]); + + return new CFError(domain, code, userInfo); +} + +GLOBAL(CFErrorGetCode) = function(/* CFError */ err) +{ + return err.code; +} + +GLOBAL(CFErrorGetDomain) = function(/* CFError */ err) +{ + return err.domain; +} + +GLOBAL(CFErrorCopyDescription) = function(/* CFError */ err) +{ + return err.description; +} + +GLOBAL(CFErrorCopyUserInfo) = function(/* CFError */ err) +{ + return err.userInfo; +} + +GLOBAL(CFErrorCopyFailureReason) = function(/* CFError */ err) +{ + return err.failureReason; +} + +GLOBAL(CFErrorCopyRecoverySuggestion) = function(/* CFError */err) +{ + return err.recoverySuggestion; +} From 49cb446f8b36f0e141111f258334b0bda5b7dfd0 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Fri, 31 Oct 2014 17:15:52 -0400 Subject: [PATCH 04/53] New: Initial commit of CFNetworkErrors file This commit adds constants for CFURL Errors to enable cross-compatibility with the Cocoa CF and CPURL error reporting functions --- Objective-J/CFNetworkErrors.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Objective-J/CFNetworkErrors.js diff --git a/Objective-J/CFNetworkErrors.js b/Objective-J/CFNetworkErrors.js new file mode 100644 index 000000000..9473579b9 --- /dev/null +++ b/Objective-J/CFNetworkErrors.js @@ -0,0 +1,25 @@ +GLOBAL(kCFURLErrorUnknown) = -998; +GLOBAL(kCFURLErrorCancelled) = -999; +GLOBAL(kCFURLErrorBadURL) = -1000; +GLOBAL(kCFURLErrorTimedOut) = -1001; +GLOBAL(kCFURLErrorUnsupportedURL) = -1002; +GLOBAL(kCFURLErrorCannotFindHost) = -1003; +GLOBAL(kCFURLErrorCannotConnectToHost) = -1004; +GLOBAL(kCFURLErrorNetworkConnectionLost) = -1005; +GLOBAL(kCFURLErrorDNSLookupFailed) = -1006; +GLOBAL(kCFURLErrorHTTPTooManyRedirects) = -1007; +GLOBAL(kCFURLErrorResourceUnavailable) = -1008; +GLOBAL(kCFURLErrorNotConnectedToInternet) = -1009; +GLOBAL(kCFURLErrorRedirectToNonExistentLocation) = -1010; +GLOBAL(kCFURLErrorBadServerResponse) = -1011; +GLOBAL(kCFURLErrorUserCancelledAuthentication) = -1012; +GLOBAL(kCFURLErrorUserAuthenticationRequired) = -1013; +GLOBAL(kCFURLErrorZeroByteResource) = -1014; +GLOBAL(kCFURLErrorCannotDecodeRawData) = -1015; +GLOBAL(kCFURLErrorCannotDecodeContentData) = -1016; +GLOBAL(kCFURLErrorCannotParseResponse) = -1017; +GLOBAL(kCFURLErrorRequestBodyStreamExhausted) = -1021; +GLOBAL(kCFURLErrorFileDoesNotExist) = -1100; +GLOBAL(kCFURLErrorFileIsDirectory) = -1101; +GLOBAL(kCFURLErrorNoPermissionsToReadFile) = -1102; +GLOBAL(kCFURLErrorDataLengthExceedsMaximum) = -1103; \ No newline at end of file From 0399b3daeda48760471a36d0cbfec578b2b2679a Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 07:41:51 -0400 Subject: [PATCH 05/53] Fixed: Renamed CPCoder method to match language Previously CPCoder had a method named "encodeValueOfObjCType" which is a misnomer. This commit renames the method to "encodeValueOfObjJType." --- Foundation/CPCoder.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/CPCoder.j b/Foundation/CPCoder.j index d02d918e0..0bdc7b89a 100644 --- a/Foundation/CPCoder.j +++ b/Foundation/CPCoder.j @@ -53,7 +53,7 @@ @param aType the structure or object type @param anObject the object to be encoded */ -- (void)encodeValueOfObjCType:(CPString)aType at:(id)anObject +- (void)encodeValueOfObjJType:(CPString)aType at:(id)anObject { _CPRaiseInvalidAbstractInvocation(self, _cmd); } From a34e8fbc9aa5c5cdc4a3ec8d2e4ebab5fbbc42ac Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 08:59:10 -0400 Subject: [PATCH 06/53] Fixed method calls for global CFError methods --- Objective-J/CFError.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Objective-J/CFError.js b/Objective-J/CFError.js index 5169de5c6..545c7eef5 100644 --- a/Objective-J/CFError.js +++ b/Objective-J/CFError.js @@ -26,20 +26,20 @@ GLOBAL(kCFErrorLocalizedRecoverySuggestionKey) = "CPLocalizedRecoverySuggestion" GLOBAL(kCFErrorDescriptionKey) = "CPDescription"; GLOBAL(kCFErrorUnderlyingErrorKey) = "CPUnderlyingError"; -GLOBAL(kCFErrorURLKey) = "_kCFErrorURLKey"; -GLOBAL(kCFErrorFilePathKey) = "_kCFErrorFilePathKey"; +GLOBAL(kCFErrorURLKey) = "CPURL"; +GLOBAL(kCFErrorFilePathKey) = "CPFilePath"; // GLOBAL(kCFErrorDomainPOSIX) = ""; // GLOBAL(kCFErrorDomainOSStatus) = ""; // GLOBAL(kCFErrorDomainMach) = ""; -GLOBAL(kCFErrorDomainCappuccino) = "CPErrorDomainCappuccino"; +GLOBAL(kCFErrorDomainCappuccino) = "CPCappuccinoErrorDomain"; GLOBAL(kCFErrorDomainCocoa) = kCFErrorDomainCappuccino; GLOBAL(CFError) = function(/* CFString */ domain, /* int */ code, /* CFDictionary */ userInfo) { this._domain = domain || NULL; - this._code = code || NULL; + this._code = code || 0; this._userInfo = userInfo || new CFDictionary(); this._UID = objj_generateObjectUID(); } @@ -78,7 +78,7 @@ CFError.prototype.description = function () if (desc) { // we have a description key. - var result = "The operation couldn\u2019t be completed. (error " + this._code + "- " + desc + ")"; + var result = "The operation couldn\u2019t be completed. (error " + this._code + " - " + desc + ")"; } else { @@ -120,7 +120,7 @@ GLOBAL(CFErrorCreate) = function(/* String */ domain, /*int */ code, /* CFDictio GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, /* int */ code, /* array */ userInfoKeys, /* array */ userInfoValues, /* int */ numUserInfoValues) { - var userInfo = new CFDictionary(); + var userInfo = new CFMutableDictionary(); while(numUserInfoValues--) userInfo.setValueForKey(userInfoKeys[numUserInfoValues], userInfoValues[numUserInfoValues]); @@ -129,30 +129,30 @@ GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, / GLOBAL(CFErrorGetCode) = function(/* CFError */ err) { - return err.code; + return err.code(); } GLOBAL(CFErrorGetDomain) = function(/* CFError */ err) { - return err.domain; + return err.domain(); } GLOBAL(CFErrorCopyDescription) = function(/* CFError */ err) { - return err.description; + return err.description(); } GLOBAL(CFErrorCopyUserInfo) = function(/* CFError */ err) { - return err.userInfo; + return err.userInfo(); } GLOBAL(CFErrorCopyFailureReason) = function(/* CFError */ err) { - return err.failureReason; + return err.failureReason(); } GLOBAL(CFErrorCopyRecoverySuggestion) = function(/* CFError */err) { - return err.recoverySuggestion; + return err.recoverySuggestion(); } From 0038eab6ab951750f9ee296ae3fbf59318ba7dea Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 08:59:35 -0400 Subject: [PATCH 07/53] Add CFError and CFNetworkErrors to the Includes list --- Objective-J/Includes.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objective-J/Includes.js b/Objective-J/Includes.js index a4373e3a0..43adc2de2 100644 --- a/Objective-J/Includes.js +++ b/Objective-J/Includes.js @@ -38,6 +38,8 @@ #include "CFHTTPRequest.js" #include "CFPropertyList.js" #include "CFDictionary.js" +#include "CFError.js" +#include "CFNetworkErrors.js" #include "CFData.js" #include "CFURL.js" #include "MarkedStream.js" From 96135c9875d5256fba37073ebd3b2dfe35c174a7 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:01:42 -0400 Subject: [PATCH 08/53] New: Toll-free bridged CPError with CFError This commit changes CPError to use a toll-free bridge with CFError, matching Cocoa's implementation of this class. --- Foundation/CPError.j | 152 +++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 43 deletions(-) diff --git a/Foundation/CPError.j b/Foundation/CPError.j index 4acafe2ce..7062bd08f 100644 --- a/Foundation/CPError.j +++ b/Foundation/CPError.j @@ -24,31 +24,52 @@ @import "CPObject.j" @import "CPString.j" -CPCappuccinoErrorDomain = CPCocoaErrorDomain = @"CPCappuccinoErrorDomain"; -// CPPOSIXErrorDomain = @"CPPOSIXErrorDomain"; -// CPOSStatusErrorDomain = @"CPOSStatusErrorDomain"; +CPCappuccinoErrorDomain = kCFErrorDomainCappuccino; +CPCocoaErrorDomain = kCFErrorDomainCappuccino; // compat -CPUnderlyingErrorKey = @"CPUnderlyingErrorKey"; +CPUnderlyingErrorKey = kCFErrorUnderlyingErrorKey; -CPLocalizedDescriptionKey = @"CPLocalizedDescriptionKey"; -CPLocalizedFailureReasonErrorKey = @"CPLocalizedFailureReasonErrorKey"; -CPLocalizedRecoverySuggestionErrorKey = @"CPLocalizedRecoverySuggestionErrorKey"; +CPLocalizedDescriptionKey = kCFErrorLocalizedDescriptionKey; +CPLocalizedFailureReasonErrorKey = kCFErrorLocalizedFailureReasonKey; +CPLocalizedRecoverySuggestionErrorKey = kCFErrorLocalizedRecoverySuggestionKey; CPLocalizedRecoveryOptionsErrorKey = @"CPLocalizedRecoveryOptionsErrorKey"; CPRecoveryAttempterErrorKey = @"CPRecoveryAttempterErrorKey"; CPHelpAnchorErrorKey = @"CPHelpAnchorErrorKey"; CPStringEncodingErrorKey = @"CPStringEncodingErrorKey"; -CPURLErrorKey = @"CPURLErrorKey"; -CPFilePathErrorKey = @"CPFilePathErrorKey"; +CPURLErrorKey = kCFErrorURLKey; +CPFilePathErrorKey = kCFErrorFilePathKey; +/*! + @class CPError + @ingroup foundation + @brief Used for encapsulating, presenting, and recovery from errors. + CPError is toll-free bridged with CFError() methods. + + An example of initializing a CPError: +
+
+var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description",
+                 CPLocalizedFailureReasonErrorKey: @"A localized failure reason",
+                 CPUnderlyingErrorKey: @"An underlying error message"},
+
+    err = [CPError errorWithDomain:CPCappuccinoErrorDomain code:-10 userInfo:userInfo];
+
+ */ @implementation CPError : CPObject { - CPInteger _code @accessors(property=code, readonly); - CPString _domain @accessors(property=domain, readonly); - CPDictionary _userInfo @accessors(property=userInfo, readonly); } ++ (id)alloc +{ + var obj = new CFError(); + obj.isa = [self class]; + + return obj; +} + + + (id)errorWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict { return [[CPError alloc] initWithDomain:aDomain code:aCode userInfo:aDict]; @@ -56,44 +77,89 @@ CPFilePathErrorKey = @"CPFilePathErrorKey"; - (id)initWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict { - if (self = [super init]) - { - _domain = aDomain; - _code = aCode; - _userInfo = aDict; - } - - return self; + var result = new CFError(aDomain, aCode, aDict); + result.isa = [self class]; + return result; } -- (CPString)localizedDescription +- (CPInteger)code { - return [_userInfo objectForKey:CPLocalizedDescriptionKey]; -} - -- (CPString)localizedFailureReason -{ - return [_userInfo objectForKey:CPLocalizedFailureReasonErrorKey]; -} - -- (CPArray)localizedRecoveryOptions -{ - return [_userInfo objectForKey:CPLocalizedRecoveryOptionsErrorKey]; -} - -- (CPString)localizedRecoverySuggestion -{ - return [_userInfo objectForKey:CPLocalizedRecoverySuggestionErrorKey]; -} - -- (id)recoveryAttempter -{ - return [_userInfo objectForKey:CPRecoveryAttempterErrorKey]; + return self.code(); } - (CPString)description { - return [CPString stringWithFormat:@"Error Domain=%@ Code=%d UserInfo=%p %@", _domain, _code, _userInfo, [self localizedDescription]]; + return self.description(); +} + +- (CPString)domain +{ + return self.domain(); +} + +- (CPString)localizedDescription +{ + return self.description(); +} + +- (CPString)localizedFailureReason +{ + return self.failureReason(); +} + +- (CPArray)localizedRecoveryOptions +{ + var userInfo = self.userInfo(), + recoveryOptions = userInfo.valueForKey(CPLocalizedRecoveryOptionsErrorKey); + + return recoveryOptions; +} + +- (CPString)localizedRecoverySuggestion +{ + return self.recoverySuggestion(); +} + +- (id)recoveryAttempter +{ + var userInfo = self.userInfo(), + recoveryAttempter = userInfo.valueForKey(CPRecoveryAttempterErrorKey); + + return recoveryAttempter; +} + +- (CPString)description +{ + return [CPString stringWithFormat:@"Error Domain=%@ Code=%d \"%@\" UserInfo=%@", self.domain(), self.code(), self.description(), self.userInfo()]; } @end + +var CPErrorCodeKey = @"CPErrorCodeKey", + CPErrorDomainKey = @"CPErrorDomainKey", + CPErrorUserInfoKey = @"CPErrorUserInfoKey"; + +@implementation CPError (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + var code = [aCoder decodeIntForKey:CPErrorCodeKey], + domain = [aCoder decodeObjectForKey:CPErrorDomainKey], + userInfo = [aCoder decodeObjectForKey:CPErrorUserInfoKey]; + + return [self initWithDomain:domain + code:code + userInfo:userInfo]; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:self.domain() forKey:CPErrorDomainKey]; + [aCoder encodeObject:self.code() forKey:CPErrorCodeKey]; + [aCoder encodeObject:self.userInfo() forKey:CPErrorUserInfoKey]; +} + +@end + +CFError.prototype.isa = CPError; + From 7811521c0895bbd334cad59674ff5453239be667 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:02:56 -0400 Subject: [PATCH 09/53] New: CPURLError definitions This commit adds support for the CPURLError codes, with underlying support provided by Foundation's CFURL Errors. --- Foundation/CPURLError.j | 26 ++++++++++++++++++++++++++ Foundation/Foundation.j | 1 + 2 files changed, 27 insertions(+) create mode 100644 Foundation/CPURLError.j diff --git a/Foundation/CPURLError.j b/Foundation/CPURLError.j new file mode 100644 index 000000000..a54ebdaaf --- /dev/null +++ b/Foundation/CPURLError.j @@ -0,0 +1,26 @@ + +CPURLErrorDomain = @"CPURLErrorDomain"; +CPURLErrorUnknown = -1; +CPURLErrorCancelled = kCFURLErrorCancelled; +CPURLErrorBadURL = kCFURLErrorBadURL; +CPURLErrorTimedOut = kCFURLErrorTimedOut; +CPURLErrorUnsupportedURL = kCFURLErrorUnsupportedURL; +CPURLErrorCannotFindHost = kCFURLErrorCannotFindHost; +CPURLErrorCannotConnectToHost = kCFURLErrorCannotConnectToHost; +CPURLErrorNetworkConnectionLost = kCFURLErrorNetworkConnectionLost; +CPURLErrorDNSLookupFailed = kCFURLErrorDNSLookupFailed; +CPURLErrorHTTPTooManyRedirects = kCFURLErrorHTTPTooManyRedirects; +CPURLErrorResourceUnavailable = kCFURLErrorResourceUnavailable; +CPURLErrorNotConnectedToInternet = kCFURLErrorNotConnectedToInternet; +CPURLErrorRedirectToNonExistentLocation = kCFURLErrorRedirectToNonExistentLocation; +CPURLErrorBadServerResponse = kCFURLErrorBadServerResponse; +CPURLErrorUserCancelledAuthentication = kCFURLErrorUserCancelledAuthentication; +CPURLErrorUserAuthenticationRequired = kCFURLErrorUserAuthenticationRequired; +CPURLErrorZeroByteResource = kCFURLErrorZeroByteResource; +CPURLErrorCannotDecodeRawData = kCFURLErrorCannotDecodeRawData; +CPURLErrorCannotDecodeContentData = kCFURLErrorCannotDecodeContentData; +CPURLErrorCannotParseResponse = kCFURLErrorCannotParseResponse; +CPURLErrorFileDoesNotExist = kCFURLErrorFileDoesNotExist; +CPURLErrorFileIsDirectory = kCFURLErrorFileIsDirectory; +CPURLErrorNoPermissionsToReadFile = kCFURLErrorNoPermissionsToReadFile; +CPURLErrorDataLengthExceedsMaximum = kCFURLErrorDataLengthExceedsMaximum; \ No newline at end of file diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j index ab9d5fdb2..3fa485412 100755 --- a/Foundation/Foundation.j +++ b/Foundation/Foundation.j @@ -73,6 +73,7 @@ @import "CPUndoManager.j" @import "CPURL.j" @import "CPURLConnection.j" +@import "CPURLError.j" @import "CPURLRequest.j" @import "CPURLResponse.j" @import "CPUserDefaults.j" From 6fe30547388aa3925641b7786fe503988bfd7115 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:04:57 -0400 Subject: [PATCH 10/53] New: Unit tests for CFError methods --- Tests/Objective-J/CFErrorTest.j | 60 +++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Tests/Objective-J/CFErrorTest.j diff --git a/Tests/Objective-J/CFErrorTest.j b/Tests/Objective-J/CFErrorTest.j new file mode 100644 index 000000000..b839ff723 --- /dev/null +++ b/Tests/Objective-J/CFErrorTest.j @@ -0,0 +1,60 @@ +@import + + +@implementation CFErrorTest : OJTestCase + +- (void)testCreate +{ + var err = new CFError(); + [self assertNotNull:err]; +} + +- (void)testCreateWithParams +{ + var err = new CFError(kCFErrorDomainCappuccino, -1000, nil); + [self assertNotNull:err]; + [self assert:-1000 equals:err.code()]; +} + +- (void)testCreateGlobal +{ + var err = CFErrorCreate(kCFErrorDomainCappuccino, -1000, nil); + [self assertNotNull:err]; + + [self assert:kCFErrorDomainCappuccino equals:err.domain()]; + [self assert:-1000 equals:err.code()]; + [self assert:@"CPErrorDomainCappuccino" equals:CFErrorGetDomain(err)]; +} + +- (void)testCreateWithUserInfoKeysAndValues +{ + var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey, kCFErrorDescriptionKey], [@"A localized description", @"An error description"], 2); + [self assertNotNull:err]; + + var info = err.userInfo(); + [self assert:2 equals:info.count()]; +} + +- (void)testDescriptionCaseOne +{ + // Description case 1: Localized Key set + var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey], [@"A localized Description Key"], 1); + [self assert:@"A localized Description Key" equals:err.description()]; + [self assert:@"A localized Description Key" equals:CFErrorCopyDescription(err)]; +} + +- (void)testDescriptionCaseTwo +{ + // Case 2: Reason set; description generated + var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedFailureReasonKey], [@"A localized reason"], 1); + [self assert:@"The operation couldn\u2019t be completed. A localized reason" equals:err.description()]; +} + +- (void)testDescriptionCaseThree +{ + // Case 3: Final fall-back. + var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorDescriptionKey], [@"A description key"], 1); + [self assert:@"The operation couldn\u2019t be completed. (error -1000 - A description key)" equals:err.description()]; +} + +@end \ No newline at end of file From 2cc67f23ab93a095ba68ab7be5a94e2c39c3bc2e Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:12:35 -0400 Subject: [PATCH 11/53] New: CPError unit test --- Tests/Foundation/CPErrorTest.j | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Tests/Foundation/CPErrorTest.j diff --git a/Tests/Foundation/CPErrorTest.j b/Tests/Foundation/CPErrorTest.j new file mode 100644 index 000000000..4705f558a --- /dev/null +++ b/Tests/Foundation/CPErrorTest.j @@ -0,0 +1,24 @@ +@import +@import + +@implementation CPErrorTest : OJTestCase +{ +} + +- (void)testInstanceInstantiation +{ + var err = [[CPError alloc] initWithDomain:CPCappuccinoErrorDomain + code:-10 + userInfo:nil]; + [self assertNotNull:err]; +} + +- (void)testClassInstantiation +{ + var err = [CPError errorWithDomain:CPCappuccinoErrorDomain + code:-10 + userInfo:nil]; + [self assertNotNull:err]; +} + +@end \ No newline at end of file From 660d36e001dc928c7f18d0f744ea0d4ae9e38550 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:26:37 -0400 Subject: [PATCH 12/53] Updating CPError tests --- Tests/Foundation/CPErrorTest.j | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Tests/Foundation/CPErrorTest.j b/Tests/Foundation/CPErrorTest.j index 4705f558a..7e482a3a2 100644 --- a/Tests/Foundation/CPErrorTest.j +++ b/Tests/Foundation/CPErrorTest.j @@ -21,4 +21,23 @@ [self assertNotNull:err]; } +- (void)testUserInfoDict +{ + var userInfo = @{ + CPLocalizedDescriptionKey: @"A localized error description", + CPUnderlyingErrorKey: @"An underlying error", + CPLocalizedFailureReasonErrorKey: @"A localized error reason", + CPLocalizedRecoverySuggestionErrorKey: @"The world is about to explode. You can choose to ignore this.", + CPLocalizedRecoveryOptionsErrorKey: ["Cry", "Ignore"] + }, + err = [CPError errorWithDomain:CPCappuccinoErrorDomain + code:-10 + userInfo:userInfo]; + + [self assertNotNull:[err userInfo]]; + [self assert:[err localizedDescription] equals:@"A localized error description"]; + [self assert:[err localizedRecoveryOptions] equals:["Cry", "Ignore"]]; + [self assertNull:[err recoveryAttempter]]; +} + @end \ No newline at end of file From ef5d1d6e58cd6556021818d8c4a34650df4d4622 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 09:27:12 -0400 Subject: [PATCH 13/53] Fixed: Wrong method included on CPError --- Foundation/CPError.j | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Foundation/CPError.j b/Foundation/CPError.j index 7062bd08f..4ac772d61 100644 --- a/Foundation/CPError.j +++ b/Foundation/CPError.j @@ -87,9 +87,9 @@ var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description", return self.code(); } -- (CPString)description +- (CPString)userInfo { - return self.description(); + return self.userInfo(); } - (CPString)domain @@ -97,6 +97,11 @@ var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description", return self.domain(); } +/*! + By default this method returns the object in the user info dictionary for the key + NSLocalizedDescriptionKey. If the user info dictionary doesn’t contain a value for + NSLocalizedDescriptionKey, a default string is constructed from the domain and code. + */ - (CPString)localizedDescription { return self.description(); From 32c252393ab663e8a49d6c4e0800ecbd41638dd0 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Sat, 1 Nov 2014 10:01:56 -0400 Subject: [PATCH 14/53] Fixed: Broken unit test --- Tests/Objective-J/CFErrorTest.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Objective-J/CFErrorTest.j b/Tests/Objective-J/CFErrorTest.j index b839ff723..cea9ba69a 100644 --- a/Tests/Objective-J/CFErrorTest.j +++ b/Tests/Objective-J/CFErrorTest.j @@ -23,7 +23,7 @@ [self assert:kCFErrorDomainCappuccino equals:err.domain()]; [self assert:-1000 equals:err.code()]; - [self assert:@"CPErrorDomainCappuccino" equals:CFErrorGetDomain(err)]; + [self assert:@"CPCappuccinoErrorDomain" equals:CFErrorGetDomain(err)]; } - (void)testCreateWithUserInfoKeysAndValues From de2e77cc8659fd2bca58185ddfddaf05a0f5951a Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 6 Nov 2014 17:23:27 -0500 Subject: [PATCH 15/53] Adding userInfo error keys and documenting CPURLError.j --- Foundation/CPURLError.j | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Foundation/CPURLError.j b/Foundation/CPURLError.j index a54ebdaaf..77d901256 100644 --- a/Foundation/CPURLError.j +++ b/Foundation/CPURLError.j @@ -1,5 +1,18 @@ +/* + * The CPURL Error Domain + */ CPURLErrorDomain = @"CPURLErrorDomain"; + +/* + * CPURL UserInfo Error Keys + */ +CPURLErrorFailingURLErrorKey = @"CPErrorFailingURLKey"; +CPURLErrorFailingURLStringErrorKey = @"CPURLErrorFailingURLStringKey"; + +/* + * CPURL Error Codes + */ CPURLErrorUnknown = -1; CPURLErrorCancelled = kCFURLErrorCancelled; CPURLErrorBadURL = kCFURLErrorBadURL; From b1d56924e6411ca123971c1d7056dc4ae636b91d Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Tue, 25 Nov 2014 17:56:04 -0500 Subject: [PATCH 16/53] Fixed: Formatting --- Objective-J/CFError.js | 60 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/Objective-J/CFError.js b/Objective-J/CFError.js index 545c7eef5..615bbade8 100644 --- a/Objective-J/CFError.js +++ b/Objective-J/CFError.js @@ -42,24 +42,26 @@ GLOBAL(CFError) = function(/* CFString */ domain, /* int */ code, /* CFDictionar this._code = code || 0; this._userInfo = userInfo || new CFDictionary(); this._UID = objj_generateObjectUID(); -} +}; -CFError.prototype.domain = function () +CFError.prototype.domain = function() { return this._domain; -} -DISPLAY_NAME(CFError.prototype.domain) +}; -CFError.prototype.code = function () +DISPLAY_NAME(CFError.prototype.domain); + +CFError.prototype.code = function() { return this._code; -} -DISPLAY_NAME(CFError.prototype.code) +}; + +DISPLAY_NAME(CFError.prototype.code); /* This follows the same logic to generate a description as the "real" CFError. */ -CFError.prototype.description = function () +CFError.prototype.description = function() { var localizedDesc = this._userInfo.valueForKey(kCFErrorLocalizedDescriptionKey); if (localizedDesc) @@ -87,26 +89,30 @@ CFError.prototype.description = function () } return result; -} -DISPLAY_NAME(CFError.prototype.description) +}; -CFError.prototype.failureReason = function () +DISPLAY_NAME(CFError.prototype.description); + +CFError.prototype.failureReason = function() { return this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey); -} -DISPLAY_NAME(CFError.prototype.failureReason) +}; -CFError.prototype.recoverySuggestion = function () +DISPLAY_NAME(CFError.prototype.failureReason); + +CFError.prototype.recoverySuggestion = function() { return this._userInfo.valueForKey(kCFErrorLocalizedRecoverySuggestionKey); -} -DISPLAY_NAME(CFError.prototype.recoverySuggestion) +}; + +DISPLAY_NAME(CFError.prototype.recoverySuggestion); CFError.prototype.userInfo = function () { return this._userInfo; -} -DISPLAY_NAME(CFError.prototype.userInfo) +}; + +DISPLAY_NAME(CFError.prototype.userInfo); /* CFError Bridge Functions @@ -116,43 +122,43 @@ DISPLAY_NAME(CFError.prototype.userInfo) GLOBAL(CFErrorCreate) = function(/* String */ domain, /*int */ code, /* CFDictionary */ userInfo) { return new CFError(domain, code, userInfo); -} +}; GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, /* int */ code, /* array */ userInfoKeys, /* array */ userInfoValues, /* int */ numUserInfoValues) { var userInfo = new CFMutableDictionary(); - while(numUserInfoValues--) + while (numUserInfoValues--) userInfo.setValueForKey(userInfoKeys[numUserInfoValues], userInfoValues[numUserInfoValues]); return new CFError(domain, code, userInfo); -} +}; GLOBAL(CFErrorGetCode) = function(/* CFError */ err) { return err.code(); -} +}; GLOBAL(CFErrorGetDomain) = function(/* CFError */ err) { return err.domain(); -} +}; GLOBAL(CFErrorCopyDescription) = function(/* CFError */ err) { return err.description(); -} +}; GLOBAL(CFErrorCopyUserInfo) = function(/* CFError */ err) { return err.userInfo(); -} +}; GLOBAL(CFErrorCopyFailureReason) = function(/* CFError */ err) { return err.failureReason(); -} +}; GLOBAL(CFErrorCopyRecoverySuggestion) = function(/* CFError */err) { return err.recoverySuggestion(); -} +}; From 6f6938deb7356bcfb27f46868b5723537bd22f4b Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Tue, 25 Nov 2014 17:58:17 -0500 Subject: [PATCH 17/53] Fixed: Updated Comment --- Foundation/CPError.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Foundation/CPError.j b/Foundation/CPError.j index 4ac772d61..edc270514 100644 --- a/Foundation/CPError.j +++ b/Foundation/CPError.j @@ -99,8 +99,8 @@ var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description", /*! By default this method returns the object in the user info dictionary for the key - NSLocalizedDescriptionKey. If the user info dictionary doesn’t contain a value for - NSLocalizedDescriptionKey, a default string is constructed from the domain and code. + CPLocalizedDescriptionKey. If the user info dictionary doesn’t contain a value for + CPLocalizedDescriptionKey, a default string is constructed from the domain and code. */ - (CPString)localizedDescription { From b36cc8f1e949f152e45f89dfd9f1448dafaa6898 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 25 Nov 2014 17:29:30 -0800 Subject: [PATCH 18/53] Fixed: Memory leak in CPTableView, CPScrollView Prevously, when removing a CPTableView or a CPScrollView, the CPNotificationCenter kept a reference of these observers in the notification center. Now, the CPNotificationCenter does only have a observer when necessary. --- AppKit/CPClipView.j | 11 +++-- AppKit/CPScrollView.j | 36 +++++++++++++--- AppKit/CPTableView.j | 99 +++++++++++++++++++++++++++---------------- 3 files changed, 101 insertions(+), 45 deletions(-) diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index 8503c4cc5..a0071ab45 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -62,6 +62,9 @@ - (void)_observeDocumentView { + if (!_documentView) + return; + var defaultCenter = [CPNotificationCenter defaultCenter]; [_documentView setPostsFrameChangedNotifications:YES]; @@ -87,15 +90,15 @@ [defaultCenter removeObserver:self name:CPViewFrameDidChangeNotification - object:_documentView]; + object:aDocumentView]; [defaultCenter removeObserver:self name:CPViewBoundsDidChangeNotification - object:_documentView]; + object:aDocumentView]; } -- (void)_addObservers +/*- (void)_addObservers { if (_isObserving) return; @@ -115,7 +118,7 @@ if (_documentView) [self _removeObserverDocumentView:_documentView]; -} +}*/ /*! Returns the document view. diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index c93543315..aef8453a9 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -264,11 +264,6 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, _delegate = nil; _scrollTimer = nil; _implementedDelegateMethods = 0; - - [[CPNotificationCenter defaultCenter] addObserver:self - selector:@selector(_didReceiveDefaultStyleChange:) - name:CPScrollerStyleGlobalChangeNotification - object:nil]; } return self; @@ -1270,6 +1265,37 @@ Notifies the delegate when the scroll view has finished scrolling. #pragma mark - #pragma mark Overrides + +- (void)_removeObservers +{ + if (!_isObserving) + return; + + [[CPNotificationCenter defaultCenter] removeObserver:self + name:CPScrollerStyleGlobalChangeNotification + object:nil]; + + [super _removeObservers]; +} + +- (void)_addObservers +{ + if (_isObserving) + return; + + //Make sure to have the last global style for the scroller + [self _didReceiveDefaultStyleChange:nil]; + + [[CPNotificationCenter defaultCenter] addObserver:self + selector:@selector(_didReceiveDefaultStyleChange:) + name:CPScrollerStyleGlobalChangeNotification + object:nil]; + + [super _addObservers]; +} + + + - (void)drawRect:(CGRect)aRect { [super drawRect:aRect]; diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 48157b537..604ec8d23 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -320,6 +320,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; CPTableColumn _draggedColumn; CPArray _differedColumnDataToRemove; + + CPView _observedClipView; } /*! @@ -4454,41 +4456,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad */ - (void)viewWillMoveToSuperview:(CPView)aView { - [super viewWillMoveToSuperview:aView]; - - var superview = [self superview], - defaultCenter = [CPNotificationCenter defaultCenter]; - - if (superview) - { - [defaultCenter - removeObserver:self - name:CPViewFrameDidChangeNotification - object:superview]; - - [defaultCenter - removeObserver:self - name:CPViewBoundsDidChangeNotification - object:superview]; - } - if ([aView isKindOfClass:[CPClipView class]]) + _observedClipView = aView; + else { - [aView setPostsFrameChangedNotifications:YES]; - [aView setPostsBoundsChangedNotifications:YES]; - - [defaultCenter - addObserver:self - selector:@selector(superviewFrameChanged:) - name:CPViewFrameDidChangeNotification - object:aView]; - - [defaultCenter - addObserver:self - selector:@selector(superviewBoundsChanged:) - name:CPViewBoundsDidChangeNotification - object:aView]; + [self _stopObservingClipView]; + _observedClipView = nil; } + + [super viewWillMoveToSuperview:aView]; } /*! @@ -5138,8 +5114,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (!_isObserving) return; + [self _stopObservingClipView]; [super _removeObservers]; - [self _stopObservingFirstResponder]; } - (void)_addObservers @@ -5147,13 +5123,64 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (_isObserving) return; + [self _startObservingClipView]; [super _addObservers]; - [self _startObservingFirstResponder]; } -- (void)_startObservingFirstResponder +/*! + Called when the receiver is about to be moved to a new window. + @param aWindow the window to which the receiver will be moved. +*/ +- (void)viewWillMoveToWindow:(CPWindow)aWindow { - [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:[self window]]; + [super viewWillMoveToWindow:aWindow]; + + [self _stopObservingFirstResponder]; + + if (aWindow) + [self _startObservingFirstResponderForWindow:aWindow]; +} + +- (void)_startObservingClipView +{ + if (!_observedClipView) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [_observedClipView setPostsFrameChangedNotifications:YES]; + [_observedClipView setPostsBoundsChangedNotifications:YES]; + + [defaultCenter addObserver:self + selector:@selector(superviewFrameChanged:) + name:CPViewFrameDidChangeNotification + object:_observedClipView]; + + [defaultCenter addObserver:self + selector:@selector(superviewBoundsChanged:) + name:CPViewBoundsDidChangeNotification + object:_observedClipView]; +} + +- (void)_stopObservingClipView +{ + if (!_observedClipView) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter removeObserver:self + name:CPViewFrameDidChangeNotification + object:_observedClipView]; + + [defaultCenter removeObserver:self + name:CPViewBoundsDidChangeNotification + object:_observedClipView]; +} + +- (void)_startObservingFirstResponderForWindow:(CPWindow)aWindow +{ + [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:aWindow]; } - (void)_stopObservingFirstResponder From fc5bb7417fc621bcc4b6b928dad11d1ae658ace7 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 10:20:07 -0800 Subject: [PATCH 19/53] Fixed: removed useless comment in CPClipView.j --- AppKit/CPClipView.j | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index a0071ab45..655d3c36c 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -98,28 +98,6 @@ object:aDocumentView]; } -/*- (void)_addObservers -{ - if (_isObserving) - return; - - [super _addObservers]; - - if (_documentView) - [self _observeDocumentView]; -} - -- (void)_removeObservers -{ - if (!_isObserving) - return; - - [super _removeObservers]; - - if (_documentView) - [self _removeObserverDocumentView:_documentView]; -}*/ - /*! Returns the document view. */ From 547522a0a41f559171839b50a2f655ecb5a842be Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 13:06:03 -0800 Subject: [PATCH 20/53] Fixed: Memory leak in CPClipView Previously, the CPClipView registered the documentView to the notificationCenter as an observer to be notified when the frame/bounds of the documentView change. Now, we don't use the notificationCenter anymore. The class CPView send a message to its superview (when it's a clipView) when the frame or bounds change. This fix the memory leak of the CPClipView Fixed #2264 --- AppKit/CPClipView.j | 64 --------------------------------------------- AppKit/CPView.j | 21 +++++++++++++++ 2 files changed, 21 insertions(+), 64 deletions(-) diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index 8503c4cc5..93f8aacd6 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -46,75 +46,12 @@ return; if (_documentView) - { - [self _removeObserverDocumentView:_documentView]; [_documentView removeFromSuperview]; - } _documentView = aView; if (_documentView) - { [self addSubview:_documentView]; - [self _observeDocumentView]; - } -} - -- (void)_observeDocumentView -{ - var defaultCenter = [CPNotificationCenter defaultCenter]; - - [_documentView setPostsFrameChangedNotifications:YES]; - [_documentView setPostsBoundsChangedNotifications:YES]; - - [defaultCenter - addObserver:self - selector:@selector(viewFrameChanged:) - name:CPViewFrameDidChangeNotification - object:_documentView]; - - [defaultCenter - addObserver:self - selector:@selector(viewBoundsChanged:) - name:CPViewBoundsDidChangeNotification - object:_documentView]; -} - -- (void)_removeObserverDocumentView:(CPView)aDocumentView -{ - var defaultCenter = [CPNotificationCenter defaultCenter]; - - [defaultCenter - removeObserver:self - name:CPViewFrameDidChangeNotification - object:_documentView]; - - [defaultCenter - removeObserver:self - name:CPViewBoundsDidChangeNotification - object:_documentView]; -} - -- (void)_addObservers -{ - if (_isObserving) - return; - - [super _addObservers]; - - if (_documentView) - [self _observeDocumentView]; -} - -- (void)_removeObservers -{ - if (!_isObserving) - return; - - [super _removeObservers]; - - if (_documentView) - [self _removeObserverDocumentView:_documentView]; } /*! @@ -275,7 +212,6 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView"; // Don't call setDocumentView: here. It calls addSubview:, but it's A) not necessary since the // view hierarchy is fully encoded and B) dangerous if the subview is not fully decoded. _documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey]; - [self _observeDocumentView]; } return self; diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 1a600667c..7649b45ca 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -172,6 +172,7 @@ var CPViewFlags = { }, BOOL _postsBoundsChangedNotifications; BOOL _inhibitFrameAndBoundsChangedNotifications; BOOL _inLiveResize; + BOOL _isSuperviewAClipView; #if PLATFORM(DOM) DOMElement _DOMElement; @@ -821,6 +822,8 @@ var CPViewFlags = { }, */ - (void)viewWillMoveToSuperview:(CPView)aView { + _isSuperviewAClipView = [aView isKindOfClass:[CPClipView class]]; + [self _removeObservers]; if (aView) @@ -952,6 +955,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + + if (_isSuperviewAClipView) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1014,6 +1020,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; + #if PLATFORM(DOM) var transform = _superview ? _superview._boundsTransform : NULL; @@ -1173,6 +1182,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1207,6 +1219,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1269,6 +1284,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1307,6 +1325,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } From e62fd4dc005902e3285788f40c52d9e0d6dba3c0 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 13:06:03 -0800 Subject: [PATCH 21/53] Merged of CPCLipView --- AppKit/CPClipView.j | 45 --------------------------------------------- AppKit/CPView.j | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index 655d3c36c..93f8aacd6 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -46,56 +46,12 @@ return; if (_documentView) - { - [self _removeObserverDocumentView:_documentView]; [_documentView removeFromSuperview]; - } _documentView = aView; if (_documentView) - { [self addSubview:_documentView]; - [self _observeDocumentView]; - } -} - -- (void)_observeDocumentView -{ - if (!_documentView) - return; - - var defaultCenter = [CPNotificationCenter defaultCenter]; - - [_documentView setPostsFrameChangedNotifications:YES]; - [_documentView setPostsBoundsChangedNotifications:YES]; - - [defaultCenter - addObserver:self - selector:@selector(viewFrameChanged:) - name:CPViewFrameDidChangeNotification - object:_documentView]; - - [defaultCenter - addObserver:self - selector:@selector(viewBoundsChanged:) - name:CPViewBoundsDidChangeNotification - object:_documentView]; -} - -- (void)_removeObserverDocumentView:(CPView)aDocumentView -{ - var defaultCenter = [CPNotificationCenter defaultCenter]; - - [defaultCenter - removeObserver:self - name:CPViewFrameDidChangeNotification - object:aDocumentView]; - - [defaultCenter - removeObserver:self - name:CPViewBoundsDidChangeNotification - object:aDocumentView]; } /*! @@ -256,7 +212,6 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView"; // Don't call setDocumentView: here. It calls addSubview:, but it's A) not necessary since the // view hierarchy is fully encoded and B) dangerous if the subview is not fully decoded. _documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey]; - [self _observeDocumentView]; } return self; diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 1a600667c..7649b45ca 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -172,6 +172,7 @@ var CPViewFlags = { }, BOOL _postsBoundsChangedNotifications; BOOL _inhibitFrameAndBoundsChangedNotifications; BOOL _inLiveResize; + BOOL _isSuperviewAClipView; #if PLATFORM(DOM) DOMElement _DOMElement; @@ -821,6 +822,8 @@ var CPViewFlags = { }, */ - (void)viewWillMoveToSuperview:(CPView)aView { + _isSuperviewAClipView = [aView isKindOfClass:[CPClipView class]]; + [self _removeObservers]; if (aView) @@ -952,6 +955,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + + if (_isSuperviewAClipView) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1014,6 +1020,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; + #if PLATFORM(DOM) var transform = _superview ? _superview._boundsTransform : NULL; @@ -1173,6 +1182,9 @@ var CPViewFlags = { }, if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1207,6 +1219,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1269,6 +1284,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } /*! @@ -1307,6 +1325,9 @@ var CPViewFlags = { }, if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; + + if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications) + [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]]; } From 51940cea3da21190380cac6886ab704d6f9a00ec Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 15:05:22 -0800 Subject: [PATCH 22/53] Fixed: leak memory with CPTableViews delegate --- AppKit/CPTableColumn.j | 17 +-------- AppKit/CPTableView.j | 82 +++++++++++++++--------------------------- 2 files changed, 29 insertions(+), 70 deletions(-) diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 951cf45e4..44f4de504 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -28,8 +28,6 @@ @import "CPTextField.j" -@global CPTableViewColumnDidResizeNotification - @class _CPTableColumnHeaderView CPTableColumnNoResizing = 0; @@ -185,7 +183,7 @@ CPTableColumnUserResizingMask = 1 << 1; [tableView tile]; if (!_disableResizingPosting) - [self _postDidResizeNotificationWithOldWidth:oldWidth]; + [[self tableView] _didResizeTableColumn:self oldWidth:oldWidth]; } } @@ -538,19 +536,6 @@ CPTableColumnUserResizingMask = 1 << 1; return _headerToolTip; } -/*! - @ignore -*/ -- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth -{ - [[self tableView] _didResizeTableColumn:self]; - - [[CPNotificationCenter defaultCenter] - postNotificationName:CPTableViewColumnDidResizeNotification - object:[self tableView] - userInfo:@{ @"CPTableColumn": self, @"CPOldWidth": oldWidth }]; -} - @end @implementation CPTableColumnValueBinder : CPBinder diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 604ec8d23..ea9851716 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -80,10 +80,12 @@ var CPTableViewDelegate_selectionShouldChangeInTableView_ CPTableViewDelegate_tableView_typeSelectStringForTableColumn_row_ = 1 << 17, CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_ = 1 << 18, CPTableViewDelegate_tableView_willRemoveView_forTableColumn_row_ = 1 << 19, - CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 20, - CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 21, - CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 22, - CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 23; + CPTableViewDelegate_tableViewColumnDidMove_ = 1 << 20, + CPTableViewDelegate_tableViewColumnDidResize_ = 1 << 21, + CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 22, + CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 23, + CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 24, + CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 25; //CPTableViewDraggingDestinationFeedbackStyles CPTableViewDraggingDestinationFeedbackStyleNone = -1; @@ -1168,6 +1170,9 @@ NOT YET IMPLEMENTED [[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewColumnDidMoveNotification object:self userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }]; + + if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidMove_) + [_delegate tableViewColumnDidMove:[[CPNotification alloc] initWithName:CPTableViewColumnDidMoveNotification object:self userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }]]; } /*! @@ -1246,9 +1251,17 @@ NOT YET IMPLEMENTED /*! @ignore */ -- (void)_didResizeTableColumn:(CPTableColumn)theColumn +- (void)_didResizeTableColumn:(CPTableColumn)theColumn oldWidth:(int)oldWidth { [self _autosave]; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPTableViewColumnDidResizeNotification + object:self + userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }]; + + if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidResize_) + [_delegate tableViewColumnDidResize:[[CPNotification alloc] initWithName:CPTableViewColumnDidResizeNotification object:self userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }]]; } //Selecting Columns and Rows @@ -2861,35 +2874,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (_delegate === aDelegate) return; - var defaultCenter = [CPNotificationCenter defaultCenter]; - - if (_delegate) - { - if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)]) - [defaultCenter - removeObserver:_delegate - name:CPTableViewColumnDidMoveNotification - object:self]; - - if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)]) - [defaultCenter - removeObserver:_delegate - name:CPTableViewColumnDidResizeNotification - object:self]; - - if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)]) - [defaultCenter - removeObserver:_delegate - name:CPTableViewSelectionDidChangeNotification - object:self]; - - if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)]) - [defaultCenter - removeObserver:_delegate - name:CPTableViewSelectionIsChangingNotification - object:self]; - } - _delegate = aDelegate; _implementedDelegateMethods = 0; @@ -2964,32 +2948,16 @@ Your delegate can implement this method to avoid subclassing the tableview to ad _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_; if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(tableViewColumnDidMove:) - name:CPTableViewColumnDidMoveNotification - object:self]; + _implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidMove_; if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(tableViewColumnDidResize:) - name:CPTableViewColumnDidResizeNotification - object:self]; + _implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidResize_; if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(tableViewSelectionDidChange:) - name:CPTableViewSelectionDidChangeNotification - object:self]; + _implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionDidChange_; if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(tableViewSelectionIsChanging:) - name:CPTableViewSelectionIsChangingNotification - object:self]; + _implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionIsChanging_; } /*! @@ -5046,6 +5014,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad postNotificationName:CPTableViewSelectionIsChangingNotification object:self userInfo:nil]; + + if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionIsChanging_) + [_delegate tableViewSelectionIsChanging:[[CPNotification alloc] initWithName:CPTableViewSelectionIsChangingNotification object:self userInfo:nil]]; } /*! @@ -5057,6 +5028,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad postNotificationName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil]; + + if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionDidChange_) + [_delegate tableViewSelectionDidChange:[[CPNotification alloc] initWithName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil]]; } /*! From e03b6b382416618643720ce7727a170ab2c3618d Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 15:18:39 -0800 Subject: [PATCH 23/53] Fixed: _postDidResizeNotificationWithOldWidth does not exists anymore, replace by _didResizeTableColumn:tableColumn:oldWidht: --- AppKit/CPTableHeaderView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index d22dc4f71..55e297eb8 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -625,7 +625,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal - (void)stopResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint { var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex]; - [tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth]; + [_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth]; [tableColumn setDisableResizingPosting:NO]; [_tableView setDisableAutomaticResizing:NO]; From 392a6cfbca7a544486de571f7a24f17f1bd4e8f4 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 15:55:50 -0800 Subject: [PATCH 24/53] Fixed: memory leak when using a delegate with a CPComboBox --- AppKit/CPComboBox.j | 66 +++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index b8a4481b8..4c8f49c45 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -53,6 +53,11 @@ CPComboBoxWillPopUpNotification = @"CPComboBoxWillPopUpNotification"; CPComboBoxStateButtonBordered = CPThemeState("button-bordered"); +var CPComboBoxDelegate_comboBoxSelectionIsChanging_ = 1 << 0, + CPComboBoxDelegate_comboBoxSelectionDidChange_ = 1 << 1, + CPComboBoxDelegate_comboBoxWillPopUp_ = 1 << 2, + CPComboBoxDelegate_comboBoxWillDismiss_ = 1 << 3; + var CPComboBoxTextSubview = @"text", CPComboBoxButtonSubview = @"button", CPComboBoxDefaultNumberOfVisibleItems = 5, @@ -61,19 +66,20 @@ var CPComboBoxTextSubview = @"text", @implementation CPComboBox : CPTextField { - CPArray _items; - _CPPopUpList _listDelegate; - CPComboBoxDataSource _dataSource; - BOOL _usesDataSource; - BOOL _completes; BOOL _canComplete; - int _numberOfVisibleItems; + BOOL _completes; BOOL _forceSelection; BOOL _hasVerticalScroller; - CPString _selectedStringValue; - CGSize _intercellSpacing; - float _itemHeight; BOOL _popUpButtonCausedResign; + BOOL _usesDataSource; + CGSize _intercellSpacing; + CPArray _items; + CPComboBoxDataSource _dataSource; + CPInteger _implementedDelegateMethods; + CPString _selectedStringValue; + float _itemHeight; + int _numberOfVisibleItems; + _CPPopUpList _listDelegate; } + (CPString)defaultThemeClass @@ -228,41 +234,19 @@ var CPComboBoxTextSubview = @"text", if (aDelegate === delegate) return; - var defaultCenter = [CPNotificationCenter defaultCenter]; - - if (delegate) - { - [defaultCenter removeObserver:delegate name:CPComboBoxSelectionIsChangingNotification object:self]; - [defaultCenter removeObserver:delegate name:CPComboBoxSelectionDidChangeNotification object:self]; - [defaultCenter removeObserver:delegate name:CPComboBoxWillDismissNotification object:self]; - [defaultCenter removeObserver:delegate name:CPComboBoxWillPopUpNotification object:self]; - } - if (aDelegate) { if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)]) - [defaultCenter addObserver:delegate - selector:@selector(comboBoxSelectionIsChanging:) - name:CPComboBoxSelectionIsChangingNotification - object:self]; + _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_ if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)]) - [defaultCenter addObserver:delegate - selector:@selector(comboBoxSelectionDidChange:) - name:CPComboBoxSelectionDidChangeNotification - object:self]; + _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_ if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)]) - [defaultCenter addObserver:delegate - selector:@selector(comboBoxWillPopUp:) - name:CPComboBoxWillPopUpNotification - object:self]; + _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxWillPopUp_ if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)]) - [defaultCenter addObserver:delegate - selector:@selector(comboBoxWillDissmis:) - name:CPComboBoxWillDismissNotification - object:self]; + _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxWillDismiss_ } [super setDelegate:aDelegate]; @@ -1005,24 +989,36 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxSelectionIsChanging:(CPNotification)aNotification { + if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_) + [_delegate comboBoxSelectionIsChanging:[[CPNotification alloc] initWithName:CPComboBoxSelectionIsChangingNotification object:self userInfo:nil]]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self]; } /*! @ignore */ - (void)comboBoxSelectionDidChange:(CPNotification)aNotification { + if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_) + [_delegate comboBoxSelectionDidChange:[[CPNotification alloc] initWithName:CPComboBoxSelectionDidChangeNotification object:self userInfo:nil]]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self]; } /*! @ignore */ - (void)comboBoxWillPopUp:(CPNotification)aNotification { + if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxWillPopUp_) + [_delegate comboBoxWillPopUp:[[CPNotification alloc] initWithName:CPComboBoxWillPopUpNotification object:self userInfo:nil]]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self]; } /*! @ignore */ - (void)comboBoxWillDismiss:(CPNotification)aNotification { + if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxWillDismiss_) + [_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self]; } From 94f89acc8477b18c1e313af2532caca8c449d8a5 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 26 Nov 2014 15:56:10 -0800 Subject: [PATCH 25/53] Fixed: memory leaks when using a delegate with a CPTextField --- AppKit/CPTextField.j | 84 ++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 56d7cdccb..1a9202c06 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -38,8 +38,13 @@ @end +var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ = 1 << 1, + CPTextFieldDelegate_controlTextDidBeginEditing_ = 1 << 2, + CPTextFieldDelegate_controlTextDidChange_ = 1 << 3, + CPTextFieldDelegate_controlTextDidEndEditing_ = 1 << 4, + CPTextFieldDelegate_controlTextDidFocus_ = 1 << 5, + CPTextFieldDelegate_controlTextDidBlur_ = 1 << 6; -var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ = 1 << 1; CPTextFieldSquareBezel = 0; /*! A textfield bezel with squared corners. */ CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */ @@ -1146,6 +1151,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if ([note object] != self) return; + if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBlur_) + [_delegate controlTextDidBlur:note]; + [[CPNotificationCenter defaultCenter] postNotification:note]; } @@ -1155,6 +1163,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if ([note object] != self) return; + if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_) + [_delegate controlTextDidFocus:note]; + [[CPNotificationCenter defaultCenter] postNotification:note]; } @@ -1165,9 +1176,36 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [self _continuouslyReverseSetBinding]; + if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidChange_) + [_delegate controlTextDidChange:note]; + [super textDidChange:note]; } +- (void)textDidBeginEditing:(CPNotification)note +{ + //this looks to prevent false propagation of notifications for other objects + if ([note object] != self) + return; + + if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_) + [_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]] + + [super textDidBeginEditing:note]; +} + +- (void)textDidEndEditing:(CPNotification)note +{ + //this looks to prevent false propagation of notifications for other objects + if ([note object] != self) + return; + + [super textDidEndEditing:note]; + + if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidEndEditing_) + [_delegate controlTextDidEndEditing:note]; +} + - (void)_updateCursorForEvent:(CPEvent)anEvent { var frame = CGRectMakeCopy([self frame]), @@ -1712,17 +1750,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); - (void)setDelegate:(id )aDelegate { - var defaultCenter = [CPNotificationCenter defaultCenter]; - - //unsubscribe the existing delegate if it exists - if (_delegate) - { - [defaultCenter removeObserver:_delegate name:CPControlTextDidBeginEditingNotification object:self]; - [defaultCenter removeObserver:_delegate name:CPControlTextDidChangeNotification object:self]; - [defaultCenter removeObserver:_delegate name:CPControlTextDidEndEditingNotification object:self]; - [defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self]; - [defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self]; - } + if (_delegate == aDelegate) + return; _delegate = aDelegate; _implementedDelegateMethods = 0; @@ -1731,40 +1760,19 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); _implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(controlTextDidBeginEditing:) - name:CPControlTextDidBeginEditingNotification - object:self]; + _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_; if ([_delegate respondsToSelector:@selector(controlTextDidChange:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(controlTextDidChange:) - name:CPControlTextDidChangeNotification - object:self]; - + _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidChange_; if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(controlTextDidEndEditing:) - name:CPControlTextDidEndEditingNotification - object:self]; + _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidEndEditing_; if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(controlTextDidFocus:) - name:CPTextFieldDidFocusNotification - object:self]; + _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidFocus_; if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)]) - [defaultCenter - addObserver:_delegate - selector:@selector(controlTextDidBlur:) - name:CPTextFieldDidBlurNotification - object:self]; + _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBlur_; } - (id)delegate From 18a6ecc79a66532cc9f1d4591a018ecd6665a973 Mon Sep 17 00:00:00 2001 From: Andrew Hankinson Date: Thu, 27 Nov 2014 11:22:40 -0500 Subject: [PATCH 26/53] Fixed: z-index of -1000 caused a blank screen in some browsers Previously, a z-index value of -1000 caused some browsers to not display certain UI elements correctly. Setting this value to 0 instead seems to fix this. This commit changes the default value in the templates generated by `capp gen`. Fixes #2232, Refs #2194 --- Tools/capp/Resources/Templates/Application/index-debug.html | 2 +- Tools/capp/Resources/Templates/Application/index.html | 2 +- Tools/capp/Resources/Templates/NibApplication/index-debug.html | 2 +- Tools/capp/Resources/Templates/NibApplication/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/capp/Resources/Templates/Application/index-debug.html b/Tools/capp/Resources/Templates/Application/index-debug.html index 525fedab5..d862fd07e 100644 --- a/Tools/capp/Resources/Templates/Application/index-debug.html +++ b/Tools/capp/Resources/Templates/Application/index-debug.html @@ -102,7 +102,7 @@ width: 100%; /* Put it at the bottom of the stack so it doesn't interfere with UI */ - z-index: -1000; + z-index: 0; } #cappuccino-body .container { diff --git a/Tools/capp/Resources/Templates/Application/index.html b/Tools/capp/Resources/Templates/Application/index.html index 9dec4e8db..414301b1e 100644 --- a/Tools/capp/Resources/Templates/Application/index.html +++ b/Tools/capp/Resources/Templates/Application/index.html @@ -72,7 +72,7 @@ width: 100%; /* Put it at the bottom of the stack so it doesn't interfere with UI */ - z-index: -1000; + z-index: 0; } #cappuccino-body .container { diff --git a/Tools/capp/Resources/Templates/NibApplication/index-debug.html b/Tools/capp/Resources/Templates/NibApplication/index-debug.html index 525fedab5..d862fd07e 100644 --- a/Tools/capp/Resources/Templates/NibApplication/index-debug.html +++ b/Tools/capp/Resources/Templates/NibApplication/index-debug.html @@ -102,7 +102,7 @@ width: 100%; /* Put it at the bottom of the stack so it doesn't interfere with UI */ - z-index: -1000; + z-index: 0; } #cappuccino-body .container { diff --git a/Tools/capp/Resources/Templates/NibApplication/index.html b/Tools/capp/Resources/Templates/NibApplication/index.html index 9dec4e8db..414301b1e 100644 --- a/Tools/capp/Resources/Templates/NibApplication/index.html +++ b/Tools/capp/Resources/Templates/NibApplication/index.html @@ -72,7 +72,7 @@ width: 100%; /* Put it at the bottom of the stack so it doesn't interfere with UI */ - z-index: -1000; + z-index: 0; } #cappuccino-body .container { From 56acbfc85c1edf9043d1a4ed3559c26cbd136e61 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Fri, 28 Nov 2014 10:00:27 -0800 Subject: [PATCH 27/53] Fixed: change == to === on CPTextField when assigning a delegateo --- AppKit/CPTextField.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 77d76cf7c..d3dca7380 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -1751,7 +1751,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); - (void)setDelegate:(id )aDelegate { - if (_delegate == aDelegate) + if (_delegate === aDelegate) return; _delegate = aDelegate; From 2484fb85e9646feac6bb2786fbba8aceff40eda4 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 1 Dec 2014 14:22:06 -0800 Subject: [PATCH 28/53] Fixed: warning raised by the compiler due to unknown type in var declarations --- AppKit/CPCursor.j | 1 + AppKit/CPEvent.j | 1 + 2 files changed, 2 insertions(+) diff --git a/AppKit/CPCursor.j b/AppKit/CPCursor.j index c6c96acdc..6e0b36cff 100755 --- a/AppKit/CPCursor.j +++ b/AppKit/CPCursor.j @@ -22,6 +22,7 @@ Cursor support by browser: */ @import +@import "CPImage.j" @global CPApp diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j index d0ab4e128..a1699aa34 100644 --- a/AppKit/CPEvent.j +++ b/AppKit/CPEvent.j @@ -32,6 +32,7 @@ @class CPTextField @class CPWindow +@class CPGraphicsContext @global CPApp From 2e66601c19faf21416671a88886a00fa2dbd9bf3 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 1 Dec 2014 14:22:39 -0800 Subject: [PATCH 29/53] Fixed: memory leak in CPComboBox Previously, when assigning a listDelegate to a CPComboBox, we never deleted the observers added by this method. Now we add and delete these observers in the method addObservers and removeObservers. This PR fix another issue. Previously, the behavior of the panel of the comboBox wasn't the same as the one in Cocoa. Now, when closing the panel, the hit view won't be the first responder as it was. Cocoa works like this as well. --- AppKit/CPComboBox.j | 100 +++++++++++++++++++++++++++++------------- AppKit/_CPPopUpList.j | 34 +++++++++----- 2 files changed, 94 insertions(+), 40 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index 844149d4b..f313e38de 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -160,7 +160,7 @@ var CPComboBoxTextSubview = @"text", - (void)setIntercellSpacing:(CGSize)aSize { - if (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing)) + if (!aSize || (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing))) return; _intercellSpacing = aSize; @@ -396,49 +396,53 @@ var CPComboBoxTextSubview = @"text", if (_listDelegate === aDelegate) return; - var defaultCenter = [CPNotificationCenter defaultCenter]; - - if (_listDelegate) - { - [defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:_listDelegate]; - [defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:_listDelegate]; - [defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:_listDelegate]; - [defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:_listDelegate]; - - var oldTableView = [_listDelegate tableView]; - - if (oldTableView) - { - [defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView]; - [defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView]; - } - } + [self _removeObserversForListDelegate:_listDelegate]; _listDelegate = aDelegate; + // We only add the observers if the CPComboBox is displayed + if ([self window]) + [self _addObserversForListDelegate:_listDelegate] + + // Apply our text style to the list + [_listDelegate setFont:[self font]]; + [_listDelegate setAlignment:[self alignment]]; + + [self setHasVerticalScroller:_hasVerticalScroller]; + [self setIntercellSpacing:_intercellSpacing]; + [self setItemHeight:_itemHeight]; +} + +- (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate +{ + if (!aDelegate) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + [defaultCenter addObserver:self selector:@selector(comboBoxWillPopUp:) name:_CPPopUpListWillPopUpNotification - object:_listDelegate]; + object:aDelegate]; [defaultCenter addObserver:self selector:@selector(comboBoxWillDismiss:) name:_CPPopUpListWillDismissNotification - object:_listDelegate]; + object:aDelegate]; [defaultCenter addObserver:self selector:@selector(listDidDismiss:) name:_CPPopUpListDidDismissNotification - object:_listDelegate]; + object:aDelegate]; [defaultCenter addObserver:self selector:@selector(itemWasClicked:) name:_CPPopUpListItemWasClickedNotification - object:_listDelegate]; + object:aDelegate]; - [[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller]; + [[aDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller]; - var tableView = [_listDelegate tableView]; + var tableView = [aDelegate tableView]; [defaultCenter addObserver:self selector:@selector(comboBoxSelectionIsChanging:) @@ -449,13 +453,27 @@ var CPComboBoxTextSubview = @"text", selector:@selector(comboBoxSelectionDidChange:) name:CPTableViewSelectionDidChangeNotification object:tableView]; +} - // Apply our text style to the list - [_listDelegate setFont:[self font]]; - [_listDelegate setAlignment:[self alignment]]; - [[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller]; - [[_listDelegate tableView] setIntercellSpacing:_intercellSpacing]; - [[_listDelegate tableView] setRowHeight:_itemHeight]; +- (void)_removeObserversForListDelegate:(_CPPopUpList)aDelegate +{ + if (!aDelegate) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:aDelegate]; + [defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:aDelegate]; + [defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:aDelegate]; + [defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:aDelegate]; + + var oldTableView = [aDelegate tableView]; + + if (oldTableView) + { + [defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView]; + [defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView]; + } } - (int)indexOfItemWithObjectValue:(id)anObject @@ -982,6 +1000,28 @@ var CPComboBoxTextSubview = @"text", } } + +#pragma mark - +#pragma mark Observers method + +- (void)_addObservers +{ + if (_isObserving) + return; + + [super _addObservers]; + [self _addObserversForListDelegate:_listDelegate]; +} + +- (void)_removeObservers +{ + if (!_isObserving) + return; + + [super _removeObservers]; + [self _removeObserversForListDelegate:_listDelegate]; +} + @end @implementation CPComboBox (CPComboBoxDelegate) diff --git a/AppKit/_CPPopUpList.j b/AppKit/_CPPopUpList.j index 3dd357132..845768bd6 100644 --- a/AppKit/_CPPopUpList.j +++ b/AppKit/_CPPopUpList.j @@ -96,28 +96,41 @@ var ListColumnIdentifier = @"1"; return [super sendEvent:anEvent]; } -- (void)orderFront:(id)sender -{ - [self _trapNextMouseDown]; - [super orderFront:sender]; -} - - (void)_mouseWasClicked:(CPEvent)anEvent { + // This is needed, when the user close the list with the key enter + if (![self isVisible]) + { + [CPApp sendEvent:anEvent]; + return; + } + var mouseWindow = [anEvent window], - rect = [[[self delegate] dataSource] bounds], + rect = CGRectInsetByInset([[[self delegate] dataSource] bounds], [[[self delegate] dataSource] currentValueForThemeAttribute:@"content-inset"]), point = [[[self delegate] dataSource] convertPoint:[anEvent locationInWindow] fromView:nil]; + // If we click somewhere else than the comboBox or the panel we close the panel if (mouseWindow != self && !CGRectContainsPoint(rect, point)) + { [[self delegate] close]; + } else - [self _trapNextMouseDown]; + { + // If we click on the panel, the app will know what to do + if (mouseWindow == self) + [CPApp sendEvent:anEvent]; + + // If we click on the comboBox field, we will trap the next mouse down + if (CGRectContainsPoint(rect, point)) + [self _trapNextMouseDown]; + } + } - (void)_trapNextMouseDown { - // Don't dequeue the event so clicks in controls will work - [CPApp setTarget:self selector:@selector(_mouseWasClicked:) forNextEventMatchingMask:CPLeftMouseDownMask untilDate:nil inMode:CPDefaultRunLoopMode dequeue:NO]; + // Dequeue the event and mouseWasClicked will do what it needs to do + [CPApp setTarget:self selector:@selector(_mouseWasClicked:) forNextEventMatchingMask:CPLeftMouseDownMask untilDate:nil inMode:CPDefaultRunLoopMode dequeue:YES]; } @end @@ -336,6 +349,7 @@ var ListColumnIdentifier = @"1"; [self listWillPopUp]; + [_panel _trapNextMouseDown]; [[aView window] addChildWindow:_panel ordered:CPWindowAbove]; } From e4bfd0ef5e80cf8bb7a73ff40dc8dcea63bc970c Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 1 Dec 2014 16:07:13 -0800 Subject: [PATCH 30/53] Fixed: issue when opening a popUpList of a CPComboBox. We now firstly open the panel and then we modify the content of the panel, this occured an issue with the rendering of the view --- AppKit/CPComboBox.j | 3 +-- AppKit/_CPPopUpList.j | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index f313e38de..bfc7887ef 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -518,8 +518,6 @@ var CPComboBoxTextSubview = @"text", if (!_listDelegate) [self setListDelegate:[[_CPPopUpList alloc] initWithDataSource:self]]; - [self _selectMatchingItem]; - // Note the offset here is 1 less than the focus ring width because the outer edge // of the focus ring is very transparent and it looks better if the list is closer. if (CPComboBoxFocusRingWidth < 0) @@ -530,6 +528,7 @@ var CPComboBoxTextSubview = @"text", } [_listDelegate popUpRelativeToRect:[self _borderFrame] view:self offset:CPComboBoxFocusRingWidth - 1]; + [self _selectMatchingItem]; } /*! @ignore */ diff --git a/AppKit/_CPPopUpList.j b/AppKit/_CPPopUpList.j index 845768bd6..6ee4e1ff0 100644 --- a/AppKit/_CPPopUpList.j +++ b/AppKit/_CPPopUpList.j @@ -336,6 +336,11 @@ var ListColumnIdentifier = @"1"; if ([_panel isVisible]) return; + [self listWillPopUp]; + + [_panel _trapNextMouseDown]; + [[aView window] addChildWindow:_panel ordered:CPWindowAbove]; + var rowRect = [_tableView rectOfRow:[self numberOfRowsInTableView:_tableView] - 1], frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(aRect)), CGRectGetMaxY(rowRect)); @@ -346,11 +351,6 @@ var ListColumnIdentifier = @"1"; [_scrollView setFrameSize:CGSizeMakeCopy(frame.size)]; [_tableView setEnabled:[_dataSource numberOfItemsInList:self] > 0]; [self scrollItemAtIndexToTop:[_tableView selectedRow]]; - - [self listWillPopUp]; - - [_panel _trapNextMouseDown]; - [[aView window] addChildWindow:_panel ordered:CPWindowAbove]; } #pragma mark Setting Display Attributes From 1df0da7509cdb693b91f9f9c10eeac23e0586acc Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 1 Dec 2014 16:07:48 -0800 Subject: [PATCH 31/53] Fixed: method addObservers and removeObservers were not call all the time when ordering or not a window --- AppKit/CPWindow/CPWindow.j | 29 ++++++++++++++++++---- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 8 ++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index e2836fe32..4d0ec1c12 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -907,18 +907,21 @@ CPTexturedBackgroundWindowMask - (void)_orderFront { - [[self contentView] _addObservers]; #if PLATFORM(DOM) // -dw- if a sheet is clicked, the parent window should come up too if (_isSheet) [_parentView orderFront:self]; - if (!_isVisible) - [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES]; + // Save the boolean since it will be updated in the method order:window:relativeTo: + var isVisible = _isVisible; [_platformWindow orderFront:self]; [_platformWindow order:CPWindowAbove window:self relativeTo:nil]; + + // setFrame is set after ordering the window as this method can send some notifications + if (isVisible) + [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES]; #endif if (!CPApp._keyWindow) @@ -937,8 +940,26 @@ CPTexturedBackgroundWindowMask */ - (void)_parentDidOrderInChild { + } +/* + Called when the window is displayed in the DOM +*/ +- (void)_windowWillBeAddedInTheDOM +{ + [[self contentView] _addObservers]; +} + +/* + Called when the window is removed in the DOM +*/ +- (void)_windowWillBeRemovedFromTheDOM +{ + [[self contentView] _removeObservers]; +} + + /* Makes the receiver the last window in the screen ordering. @param aSender the object that requested this @@ -968,8 +989,6 @@ CPTexturedBackgroundWindowMask if (!_isVisible) return; - [[self contentView] _removeObservers]; - if ([self isSheet]) { // -dw- as in Cocoa, orderOut: detaches the sheet and animates out diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index eeba3a894..60e0166b6 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -1299,7 +1299,10 @@ var PreventScroll = true; // When ordering out, ignore otherWindow, simply remove aWindow from its level. // If layer is nil, this will be a no-op. if (orderingMode === CPWindowOut) + { + [aWindow _windowWillBeRemovedFromTheDOM]; return [layer removeWindow:aWindow]; + } /* If aWindow is a child of otherWindow and is not yet visible, @@ -1345,6 +1348,8 @@ var PreventScroll = true; if (otherWindow) insertionIndex = orderingMode === CPWindowAbove ? otherWindow._index + 1 : otherWindow._index; + [aWindow _windowWillBeAddedInTheDOM]; + // Place the window at the appropriate index. [layer insertWindow:aWindow atIndex:insertionIndex]; @@ -1395,6 +1400,9 @@ var PreventScroll = true; var index = ordering === CPWindowAbove ? parent._index + 1 : parent._index; + if (!childWasVisible) + [child _windowWillBeAddInTheDOM]; + [aLayer insertWindow:child atIndex:index]; if (!childWasVisible) From f5d847f32059e1bb6da42d7f138f9e7f08094a4c Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 1 Dec 2014 16:08:49 -0800 Subject: [PATCH 32/53] Style: style in CPWindow --- AppKit/CPWindow/CPWindow.j | 1 - 1 file changed, 1 deletion(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 4d0ec1c12..31e7b156a 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -940,7 +940,6 @@ CPTexturedBackgroundWindowMask */ - (void)_parentDidOrderInChild { - } /* From ee13978115c23afdfd16ee0c768f52a12a737a30 Mon Sep 17 00:00:00 2001 From: Martin Carlberg Date: Tue, 2 Dec 2014 13:54:02 +0100 Subject: [PATCH 33/53] Fixed: @ref did not generate self.x for an ivar x --- Objective-J/ObjJAcornCompiler.js | 4 ++-- .../Preprocessor/OutputTests/Misc/ref-self.j | 11 +++++++++++ .../Preprocessor/OutputTests/Misc/ref-self.js | 9 +++++++++ .../Objective-J/Preprocessor/OutputTests/OutputTest.j | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.j create mode 100644 Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.js diff --git a/Objective-J/ObjJAcornCompiler.js b/Objective-J/ObjJAcornCompiler.js index 79646a0e6..0e9d16f98 100644 --- a/Objective-J/ObjJAcornCompiler.js +++ b/Objective-J/ObjJAcornCompiler.js @@ -2381,9 +2381,9 @@ Reference: function(node, st, c) { buffer.concat(" "); // Add an extra space if it looks something like this: "return()". No space between return and expression. } buffer.concat("function(__input) { if (arguments.length) return "); - buffer.concat(node.element.name); + c(node.element, st, "Expression"); buffer.concat(" = __input; return "); - buffer.concat(node.element.name); + c(node.element, st, "Expression"); buffer.concat("; }"); if (!generate) compiler.lastPos = node.end; }, diff --git a/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.j b/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.j new file mode 100644 index 000000000..d94fa2450 --- /dev/null +++ b/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.j @@ -0,0 +1,11 @@ +@implementation TC +{ + id _control; +} + +- (id)a +{ + @ref(_control); +} + +@end diff --git a/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.js b/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.js new file mode 100644 index 000000000..778d931d6 --- /dev/null +++ b/Tests/Objective-J/Preprocessor/OutputTests/Misc/ref-self.js @@ -0,0 +1,9 @@ +{var the_class = objj_allocateClassPair(Nil, "TC"), +meta_class = the_class.isa;class_addIvars(the_class, [new objj_ivar("_control")]);objj_registerClassPair(the_class); +class_addMethods(the_class, [new objj_method(sel_getUid("a"), function $TC__a(self, _cmd) +{ + function(__input) { if (arguments.length) return self._control = __input; return self._control; }; +} + +,["id"])]); +} diff --git a/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j b/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j index a94c74f3b..fcd96ba3c 100644 --- a/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j +++ b/Tests/Objective-J/Preprocessor/OutputTests/OutputTest.j @@ -22,6 +22,7 @@ var FILENAMES = [ "Misc/regex-simple-char-classes", "Misc/empty-loops", "Misc/empty-statements", + "Misc/ref-self", ]; @implementation OutputTest : OJTestCase From c3ce0a61b6293c28d33eef970efc5038f1432810 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 10:03:13 -0800 Subject: [PATCH 34/53] Fixed: type with the method _windowWillBeAddedToTheDOM in CPWindow --- AppKit/CPWindow/CPWindow.j | 6 +++--- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 31e7b156a..25fd9bcf8 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -914,13 +914,13 @@ CPTexturedBackgroundWindowMask [_parentView orderFront:self]; // Save the boolean since it will be updated in the method order:window:relativeTo: - var isVisible = _isVisible; + var wasVisible = _isVisible; [_platformWindow orderFront:self]; [_platformWindow order:CPWindowAbove window:self relativeTo:nil]; // setFrame is set after ordering the window as this method can send some notifications - if (isVisible) + if (wasVisible) [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES]; #endif @@ -945,7 +945,7 @@ CPTexturedBackgroundWindowMask /* Called when the window is displayed in the DOM */ -- (void)_windowWillBeAddedInTheDOM +- (void)_windowWillBeAddedToTheDOM { [[self contentView] _addObservers]; } diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 60e0166b6..80a04feae 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -1348,7 +1348,7 @@ var PreventScroll = true; if (otherWindow) insertionIndex = orderingMode === CPWindowAbove ? otherWindow._index + 1 : otherWindow._index; - [aWindow _windowWillBeAddedInTheDOM]; + [aWindow _windowWillBeAddedToTheDOM]; // Place the window at the appropriate index. [layer insertWindow:aWindow atIndex:insertionIndex]; @@ -1401,7 +1401,7 @@ var PreventScroll = true; var index = ordering === CPWindowAbove ? parent._index + 1 : parent._index; if (!childWasVisible) - [child _windowWillBeAddInTheDOM]; + [child _windowWillBeAddedToTheDOM]; [aLayer insertWindow:child atIndex:index]; From 12ed70fec2a4fd517e3cc19d0e45f8968e766684 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:37:02 -0800 Subject: [PATCH 35/53] Fixed: notifications CPWindowDidResignKeyNotification and CPWindowDidBecomeKeyNotification were not registered for a firstresponder textField when ordered again a window --- AppKit/CPTextField.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index d3dca7380..0d8576a45 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -882,7 +882,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [super _addObservers]; - if ([self window] === self) + if ([[self window] firstResponder] === self) [self _setObserveWindowKeyNotifications:YES]; } From b45399a045b64fd812572b6d0e455cbf340f530e Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:37:57 -0800 Subject: [PATCH 36/53] Test: added class notificationHelper with the method registeredNotificationsForObserver --- Tests/AppKit/CPNotificationCenterHelper.j | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Tests/AppKit/CPNotificationCenterHelper.j diff --git a/Tests/AppKit/CPNotificationCenterHelper.j b/Tests/AppKit/CPNotificationCenterHelper.j new file mode 100644 index 000000000..69aaed26c --- /dev/null +++ b/Tests/AppKit/CPNotificationCenterHelper.j @@ -0,0 +1,39 @@ +@import + +@implementation CPNotificationCenterHelper : CPObject +{ +} + ++ (void)registeredNotificationsForObserver:(id)anObserver +{ + var defaultCenter = [CPNotificationCenter defaultCenter], + names = [defaultCenter._namedRegistries keyEnumerator], + notifications = [], + name; + + while ((name = [names nextObject]) !== nil) + { + var notificationRegistry = [defaultCenter._namedRegistries objectForKey:name], + objectObservers = notificationRegistry._objectObservers, + keys = [objectObservers keyEnumerator], + key; + + // Iterate through every set of observers + while ((key = [keys nextObject]) !== nil) + { + var observers = [objectObservers objectForKey:key], + observer = nil, + observersEnumerator = [observers objectEnumerator]; + + while ((observer = [observersEnumerator nextObject]) !== nil) + { + if ([observer observer] == anObserver) + [notifications addObject:name]; + } + } + } + + return notifications.sort(); +} + +@end From ec3af04f296c355d54cd7036dc3f76914c5c5a90 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:38:17 -0800 Subject: [PATCH 37/53] Test: added tests for CPComboBox --- Tests/AppKit/CPComboBoxTest.j | 78 +++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Tests/AppKit/CPComboBoxTest.j diff --git a/Tests/AppKit/CPComboBoxTest.j b/Tests/AppKit/CPComboBoxTest.j new file mode 100644 index 000000000..3d12ed91c --- /dev/null +++ b/Tests/AppKit/CPComboBoxTest.j @@ -0,0 +1,78 @@ +@import +@import +@import + +@import "CPNotificationCenterHelper.j" + +[CPApplication sharedApplication]; + +@implementation CPComboBoxTest : OJTestCase +{ + CPComboBox comboBox; + BOOL wasClicked +} + +- (void)setUp +{ + comboBox = [[CPComboBox alloc] initWithFrame:CGRectMake(0, 0, 200, 30)]; +} + +- (void)testCanCreate +{ + [self assertTrue:!!comboBox]; +} + +- (void)testPublicAccessors +{ + [comboBox setHasVerticalScroller:YES]; + [comboBox setIntercellSpacing:CGSizeMakeZero()]; + [comboBox setButtonBordered:YES]; + [comboBox setItemHeight:30]; + [comboBox setNumberOfVisibleItems:10]; +} + +- (void)testPerformClick +{ + [comboBox setTarget:self]; + [comboBox setAction:@selector(clickMe:)]; + [comboBox performClick:nil]; + [self assertTrue:wasClicked]; +} + +- (void)clickMe:(id)sender +{ + wasClicked = YES; +} + +- (void)testNotificationsRegistered +{ + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + [comboBox setListDelegate:[[_CPPopUpList alloc] initWithDataSource:comboBox]]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0) + styleMask:CPWindowNotSizable]; + + [[theWindow contentView] addSubview:comboBox]; + + var expectedNotifications = [@"_CPPopUpListWillPopUpNotification", @"_CPPopUpListWillDismissNotification", @"_CPPopUpListDidDismissNotification", @"_CPPopUpListItemWasClickedNotification", @"CPTableViewSelectionIsChangingNotification", @"CPTableViewSelectionDidChangeNotification"].sort(); + + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + [comboBox removeFromSuperview]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + [[theWindow contentView] addSubview:comboBox]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + [[theWindow contentView] addSubview:comboBox]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + [comboBox setListDelegate:nil]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"]; + + [comboBox setListDelegate:[[_CPPopUpList alloc] initWithDataSource:comboBox]]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"]; +} + +@end \ No newline at end of file From 006bf72c1735e618aa840365432d1e6c18c4a26a Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:38:55 -0800 Subject: [PATCH 38/53] Test: added unit test for registered notification for the scrollView --- Tests/AppKit/CPScrollViewTest.j | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/AppKit/CPScrollViewTest.j b/Tests/AppKit/CPScrollViewTest.j index d95839438..379cea865 100644 --- a/Tests/AppKit/CPScrollViewTest.j +++ b/Tests/AppKit/CPScrollViewTest.j @@ -1,5 +1,9 @@ @import +@import "CPNotificationCenterHelper.j" + +[CPApplication sharedApplication]; + @implementation CPScrollViewTest : OJTestCase { } @@ -256,6 +260,24 @@ [self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"]; } +-(void)testNotificationsRegistered +{ + var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)], + theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0) + styleMask:CPWindowNotSizable]; + + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[] message:@"Notications registered for the scrollView in the notification center are wrong"]; + + [[theWindow contentView] addSubview:scrollView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[@"CPScrollerStyleGlobalChangeNotification"] message:@"Notications registered for the scrollView in the notification center are wrong"]; + + [[theWindow contentView] addSubview:scrollView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[@"CPScrollerStyleGlobalChangeNotification"] message:@"Notications registered for the scrollView in the notification center are wrong"]; + + [scrollView removeFromSuperview]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[] message:@"Notications registered for the scrollView in the notification center are wrong"]; +} + - (void)assertPoint:(CGPoint)expected equals:(CGPoint)actual message:(CPString)message { [self assert:expected.x equals:actual.x message:@"X: " + message]; From 8efb6f8808a0998d19f48cb8ba5af2a19518c749 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:39:07 -0800 Subject: [PATCH 39/53] Test: added unit test for registered notification for the tableView --- Tests/AppKit/CPTableViewTest.j | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Tests/AppKit/CPTableViewTest.j b/Tests/AppKit/CPTableViewTest.j index c1c5d0180..ede7ed1e9 100644 --- a/Tests/AppKit/CPTableViewTest.j +++ b/Tests/AppKit/CPTableViewTest.j @@ -1,5 +1,7 @@ @import +@import "CPNotificationCenterHelper.j" + [CPApplication sharedApplication]; @implementation CPTableViewTest : OJTestCase @@ -303,6 +305,36 @@ [self assertTrue:[table bounds].size.width >= 200]; } +-(void)testNotificationsRegistered +{ + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"]; + + [tableView removeFromSuperview]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[] message:@"Notications registered for the tableView in the notification center are wrong"]; + + [[theWindow contentView] addSubview:tableView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"]; + + [[theWindow contentView] addSubview:tableView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"]; + + + var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100.0, 100.0)], + expectedNotifications = [@"_CPWindowDidChangeFirstResponderNotification", @"CPViewFrameDidChangeNotification", @"CPViewBoundsDidChangeNotification"].sort(); + + [scrollView setDocumentView:tableView]; + + [[theWindow contentView] addSubview:scrollView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:expectedNotifications message:@"Notications registered for the tableView in the notification center are wrong"]; + + [[theWindow contentView] addSubview:scrollView]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:expectedNotifications message:@"Notications registered for the tableView in the notification center are wrong"]; + + [scrollView removeFromSuperview]; + [self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[] message:@"Notications registered for the tableView in the notification center are wrong"]; + +} + @end @implementation FirstResponderConfigurableTableView : CPTableView From c7ccff914f8b661d82a88938728eb152a601e6a7 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 2 Dec 2014 16:48:44 -0800 Subject: [PATCH 40/53] Test: added basic test for ordering window --- Tests/AppKit/CPWindowTest.j | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/AppKit/CPWindowTest.j b/Tests/AppKit/CPWindowTest.j index 2244a28d9..cf51e8cba 100644 --- a/Tests/AppKit/CPWindowTest.j +++ b/Tests/AppKit/CPWindowTest.j @@ -128,4 +128,12 @@ [self assertTrue:[[[self window] representedURL] class] === [CPURL class]]; } +- (void)testOrderingMethod +{ + [_window orderFront:self]; + [_window orderBack:self]; + [_window orderFront:self]; + [_window orderOut:self]; +} + @end From 46a0ce8e981627c55a4c4cbad2e6c6e3c47e4c09 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Thu, 4 Dec 2014 11:06:50 -0800 Subject: [PATCH 41/53] Fixed: wrong condition when setting the frame in CPWindow when ordering a view --- AppKit/CPWindow/CPWindow.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 25fd9bcf8..160a03ee4 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -920,7 +920,7 @@ CPTexturedBackgroundWindowMask [_platformWindow order:CPWindowAbove window:self relativeTo:nil]; // setFrame is set after ordering the window as this method can send some notifications - if (wasVisible) + if (!wasVisible) [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES]; #endif From 0f4a938dfc4ef7c94331d46b6c3aaa0810cef83d Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Fri, 5 Dec 2014 09:50:49 -0800 Subject: [PATCH 42/53] Fixed: attributes of the listDelegate of a CPComboBox could crash cappuccino --- AppKit/CPComboBox.j | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index bfc7887ef..a9bc2353f 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -160,7 +160,7 @@ var CPComboBoxTextSubview = @"text", - (void)setIntercellSpacing:(CGSize)aSize { - if (!aSize || (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing))) + if (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing)) return; _intercellSpacing = aSize; @@ -408,9 +408,12 @@ var CPComboBoxTextSubview = @"text", [_listDelegate setFont:[self font]]; [_listDelegate setAlignment:[self alignment]]; - [self setHasVerticalScroller:_hasVerticalScroller]; - [self setIntercellSpacing:_intercellSpacing]; - [self setItemHeight:_itemHeight]; + [[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller]; + + if (_intercellSpacing) + [[_listDelegate tableView] setIntercellSpacing:_intercellSpacing]; + + [[_listDelegate tableView] setRowHeight:_itemHeight]; } - (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate From cd511da67875ee22e9a9f9642c066d024fbe3c89 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 10 Dec 2014 10:25:10 -0800 Subject: [PATCH 43/53] Fixed: used _implementedDelegateMethods in CPComboBox at the same time in CPTextField. This occured some issues with the delegate of the comboBoxDelegate when using textField delegate. This commit fix a issue about the row height of a an element in the list of the comboBox --- AppKit/CPComboBox.j | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index a9bc2353f..06b5a6b15 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -75,7 +75,7 @@ var CPComboBoxTextSubview = @"text", CGSize _intercellSpacing; CPArray _items; id _dataSource; - CPInteger _implementedDelegateMethods; + CPInteger _implementedDelegateComboBoxMethods; CPString _selectedStringValue; float _itemHeight; int _numberOfVisibleItems; @@ -234,19 +234,21 @@ var CPComboBoxTextSubview = @"text", if (aDelegate === delegate) return; + _implementedDelegateComboBoxMethods = 0; + if (aDelegate) { if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)]) - _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_ if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)]) - _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_ if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)]) - _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxWillPopUp_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_ if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)]) - _implementedDelegateMethods |= CPComboBoxDelegate_comboBoxWillDismiss_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_ } [super setDelegate:aDelegate]; @@ -413,7 +415,8 @@ var CPComboBoxTextSubview = @"text", if (_intercellSpacing) [[_listDelegate tableView] setIntercellSpacing:_intercellSpacing]; - [[_listDelegate tableView] setRowHeight:_itemHeight]; + if (_itemHeight) + [[_listDelegate tableView] setRowHeight:_itemHeight]; } - (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate @@ -1031,7 +1034,7 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxSelectionIsChanging:(CPNotification)aNotification { - if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_) + if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_) [_delegate comboBoxSelectionIsChanging:[[CPNotification alloc] initWithName:CPComboBoxSelectionIsChangingNotification object:self userInfo:nil]]; [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self]; @@ -1040,7 +1043,7 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxSelectionDidChange:(CPNotification)aNotification { - if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_) + if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_) [_delegate comboBoxSelectionDidChange:[[CPNotification alloc] initWithName:CPComboBoxSelectionDidChangeNotification object:self userInfo:nil]]; [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self]; @@ -1049,7 +1052,7 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxWillPopUp:(CPNotification)aNotification { - if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxWillPopUp_) + if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillPopUp_) [_delegate comboBoxWillPopUp:[[CPNotification alloc] initWithName:CPComboBoxWillPopUpNotification object:self userInfo:nil]]; [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self]; @@ -1058,7 +1061,9 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxWillDismiss:(CPNotification)aNotification { - if (_implementedDelegateMethods & CPComboBoxDelegate_comboBoxWillDismiss_) + console.error(@"coucou"); + + if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillDismiss_) [_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]]; [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self]; From 5b4bddc2e0cd73fea395b128f94692c58ac0cd6d Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 10 Dec 2014 10:29:46 -0800 Subject: [PATCH 44/53] Fixed: removed stupid console.error(coucou).... --- AppKit/CPComboBox.j | 2 -- 1 file changed, 2 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index 06b5a6b15..18ef6487e 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -1061,8 +1061,6 @@ var CPComboBoxTextSubview = @"text", /*! @ignore */ - (void)comboBoxWillDismiss:(CPNotification)aNotification { - console.error(@"coucou"); - if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillDismiss_) [_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]]; From 47cced540e8e0cc1d0daa0d054154511271fd2bd Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 10 Dec 2014 10:31:38 -0800 Subject: [PATCH 45/53] Style: added missing semi-colon in CPComboBox --- AppKit/CPComboBox.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index 18ef6487e..f6d094eb1 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -239,16 +239,16 @@ var CPComboBoxTextSubview = @"text", if (aDelegate) { if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)]) - _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_; if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)]) - _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_; if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)]) - _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_; if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)]) - _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_ + _implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_; } [super setDelegate:aDelegate]; From 873232d5606af86299a3ae278d9320bd29d85c57 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Tue, 16 Dec 2014 18:43:08 +0100 Subject: [PATCH 46/53] FIXED : a CPOperation marked as cancelled was never started (CPOperation -start) when managed in a queue. FIXED : After an operation started, either from a queue or explicitely, its finished property was never set to true. This was causing dependant operation to never be executed. After this commit, cancelled operations are started (but not executed) and correctly marked as finished. Tests: CPOperationQueueTest and CPOperationTest for an operation managed by a queue or run explicitely. --- Foundation/CPOperation.j | 7 ++-- Foundation/CPOperationQueue.j | 4 +- Tests/Foundation/CPOperationQueueTest.j | 50 +++++++++++++++++++++++++ Tests/Foundation/CPOperationTest.j | 17 +++++++++ 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Foundation/CPOperation.j b/Foundation/CPOperation.j index 4fbdd5612..b0b8a6154 100644 --- a/Foundation/CPOperation.j +++ b/Foundation/CPOperation.j @@ -117,10 +117,11 @@ CPOperationQueuePriorityVeryHigh = 8; [self willChangeValueForKey:@"isExecuting"]; _executing = NO; [self didChangeValueForKey:@"isExecuting"]; - [self willChangeValueForKey:@"isFinished"]; - _finished = YES; - [self didChangeValueForKey:@"isFinished"]; } + + [self willChangeValueForKey:@"isFinished"]; + _finished = YES; + [self didChangeValueForKey:@"isFinished"]; } /*! diff --git a/Foundation/CPOperationQueue.j b/Foundation/CPOperationQueue.j index 1e018df15..de9322ce6 100644 --- a/Foundation/CPOperationQueue.j +++ b/Foundation/CPOperationQueue.j @@ -70,7 +70,7 @@ var cpOperationMainQueue = nil; for (; i < count; i++) { var op = [_operations objectAtIndex:i]; - if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting]) + if ([op isReady] && ![op isFinished] && ![op isExecuting]) { [op start]; } @@ -260,7 +260,7 @@ var cpOperationMainQueue = nil; for (; i < count; i++) { var op = [ops objectAtIndex:i]; - if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting]) + if ([op isReady] && ![op isFinished] && ![op isExecuting]) { [op start]; } diff --git a/Tests/Foundation/CPOperationQueueTest.j b/Tests/Foundation/CPOperationQueueTest.j index 0cc5de666..23bea619e 100644 --- a/Tests/Foundation/CPOperationQueueTest.j +++ b/Tests/Foundation/CPOperationQueueTest.j @@ -16,6 +16,33 @@ globalResults = []; @end +@implementation TestOperation2 : CPOperation +{ + BOOL _started @accessors(getter=didStart); + BOOL _mained @accessors(getter=didMain); +} + +- (id)init +{ + self = [super init]; + _started = NO; + _mained = NO; + return self; +} + +- (void)main +{ + _mained = YES; +} + +- (void)start +{ + [super start]; + _started = YES; +} + +@end + @implementation TestObserver : CPObject { CPArray changedKeyPaths @accessors; @@ -167,4 +194,27 @@ globalResults = []; [self assert:@"name" equals:[[obs changedKeyPaths] objectAtIndex:4]]; } +- (void)testCancelledOperationDoesStart +{ + var op = [[TestOperation2 alloc] init], + queue = [[CPOperationQueue alloc] init]; + + [self assertFalse:[op isCancelled]]; + [self assertFalse:[op isFinished]]; + [self assertFalse:[op didMain]]; + [self assertFalse:[op didStart]]; + + [op cancel]; + + [self assertTrue:[op isCancelled]]; + [self assertFalse:[op isFinished]]; + + [queue addOperations:[op] waitUntilFinished:YES]; + + [self assertFalse:[op didMain]]; + [self assertTrue:[op didStart]]; + [self assertTrue:[op isCancelled]]; + [self assertTrue:[op isFinished]]; +} + @end \ No newline at end of file diff --git a/Tests/Foundation/CPOperationTest.j b/Tests/Foundation/CPOperationTest.j index 1c1beef56..ea424ef56 100644 --- a/Tests/Foundation/CPOperationTest.j +++ b/Tests/Foundation/CPOperationTest.j @@ -180,4 +180,21 @@ [self assert:@"isCancelled" equals:[[obs changedKeyPaths] objectAtIndex:9]]; } +- (void)testCancelledOperationIsFinished +{ + var results = @[], + funcOp = [CPFunctionOperation functionOperationWithFunction:function() {[results addObject:"funcOp"];}]; + + [funcOp cancel]; + [self assertTrue:[funcOp isCancelled]]; + [self assertFalse:[funcOp isFinished]]; + + [funcOp start]; + + [self assertTrue:[funcOp isCancelled]]; + [self assertTrue:[funcOp isFinished]]; + + [self assertTrue:([results count] == 0)]; +} + @end From e407eeea4069d92cb7b1d59d7a42b5b58a15835f Mon Sep 17 00:00:00 2001 From: cacaodev Date: Tue, 16 Dec 2014 21:43:19 +0100 Subject: [PATCH 47/53] FIXED : travis build --- Tests/Foundation/CPOperationQueueTest.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Foundation/CPOperationQueueTest.j b/Tests/Foundation/CPOperationQueueTest.j index 23bea619e..5005a1ae7 100644 --- a/Tests/Foundation/CPOperationQueueTest.j +++ b/Tests/Foundation/CPOperationQueueTest.j @@ -16,7 +16,7 @@ globalResults = []; @end -@implementation TestOperation2 : CPOperation +@implementation TestCancelOperation : CPOperation { BOOL _started @accessors(getter=didStart); BOOL _mained @accessors(getter=didMain); @@ -196,7 +196,7 @@ globalResults = []; - (void)testCancelledOperationDoesStart { - var op = [[TestOperation2 alloc] init], + var op = [[TestCancelOperation alloc] init], queue = [[CPOperationQueue alloc] init]; [self assertFalse:[op isCancelled]]; From 5995b428721dd89bbe9061d39e0c2d5ebd3d92d7 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Thu, 25 Dec 2014 17:37:18 +0100 Subject: [PATCH 48/53] fixed: popover positioning --- AppKit/_CPPopoverWindow.j | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index ce2a7898b..19bfa82ac 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -581,10 +581,12 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, - (void)_orderFront { - if (![self isVisible]) - [self _addFrameObserver]; + var wasVisible = [self isVisible]; [super _orderFront]; + + if (!wasVisible) + [self _addFrameObserver]; } - (void)_parentDidOrderInChild From 00ebc265d87f2d2cd778c31709d325ebdf174db3 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Fri, 2 Jan 2015 19:35:09 +0100 Subject: [PATCH 49/53] make _targetRect an ivar --- AppKit/_CPPopoverWindow.j | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index 19bfa82ac..d915b7bd5 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -64,6 +64,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, BOOL _isObservingFrame; BOOL _shouldPerformAnimation; CPInteger _implementedDelegateMethods; + CGRect _targetRect; CPWindow _targetWindow; JSObject _orderOutTransitionFunction; JSObject _transitionCompleteFunction; @@ -206,7 +207,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, if (![_targetView window]) return; - var point = [self computeOriginFromRect:[_targetView bounds] ofView:_targetView preferredEdge:[_windowView preferredEdge]]; + var point = [self computeOriginFromRect:_targetRect ofView:_targetView preferredEdge:[_windowView preferredEdge]]; [self setFrameOrigin:point]; } } @@ -369,6 +370,13 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, _targetView = positioningView; } + if (positioningView !== _targetView) + { + [[_targetView window] removeChildWindow:self]; + [self _removeFrameObserver]; + _targetView = positioningView; + } + [self makeKeyAndOrderFront:nil]; /* @@ -382,6 +390,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, [[_targetView window] addChildWindow:self ordered:CPWindowAbove]; _targetWindow = targetWindow; + _targetRect = aRect; if (!wasVisible) [self _trapNextMouseDown]; From 2f9f3db19845a8dc55cb1fc3c7831e26283d791c Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sat, 3 Jan 2015 10:21:28 +0100 Subject: [PATCH 50/53] remove accidental code duplication --- AppKit/_CPPopoverWindow.j | 7 ------- 1 file changed, 7 deletions(-) diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index d915b7bd5..f7cc50d68 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -370,13 +370,6 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, _targetView = positioningView; } - if (positioningView !== _targetView) - { - [[_targetView window] removeChildWindow:self]; - [self _removeFrameObserver]; - _targetView = positioningView; - } - [self makeKeyAndOrderFront:nil]; /* From 0f5dd991675ebc7ce4656d70a17c1d018df97a2a Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 6 Jan 2015 15:20:02 -0800 Subject: [PATCH 51/53] Fixed: the method setContentSize: of the CPPopover did not take care about the rect given when displaying the popover --- AppKit/_CPPopoverWindow.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index f7cc50d68..36fab0b48 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -419,7 +419,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, if ([self isVisible]) { - var point = [self computeOriginFromRect:[_targetView bounds] ofView:_targetView preferredEdge:[_windowView preferredEdge]]; + var point = [self computeOriginFromRect:_targetRect ofView:_targetView preferredEdge:[_windowView preferredEdge]]; [self setFrameOrigin:point]; } } From e49a9f1f064d407678b5b20f9f47df38c7b2a9f2 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 6 Jan 2015 15:28:14 -0800 Subject: [PATCH 52/53] Fixed: targetRect was assigned too late when displaying a popoverWindow. This var can be used before ordering the popoverWindow --- AppKit/_CPPopoverWindow.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index 36fab0b48..27d160e17 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -370,6 +370,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, _targetView = positioningView; } + _targetRect = aRect; [self makeKeyAndOrderFront:nil]; /* @@ -383,7 +384,6 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4, [[_targetView window] addChildWindow:self ordered:CPWindowAbove]; _targetWindow = targetWindow; - _targetRect = aRect; if (!wasVisible) [self _trapNextMouseDown]; From fa7b71cabe851f4b19e0bf22fa8874d1320b55e8 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Fri, 9 Jan 2015 08:37:29 -0800 Subject: [PATCH 53/53] Fixed: cappuccino raised an exception when the param of constructor method of a CPDate are not a string. It now raises an warning --- Foundation/CPDate.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 47abdfe7d..574873ef6 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -75,7 +75,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSinceNow:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceNow: has to be an integer or a float"]; + CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceNow: should be an integer or a float"); self = new Date((new Date()).getTime() + seconds * 1000); return self; @@ -84,7 +84,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSince1970: has to be an integer or a float"]; + CPLog.warn(@"The parameter of the method initWithTimeIntervalSince1970: should be an integer or a float"); self = new Date(seconds * 1000); return self; @@ -93,7 +93,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeIntervalSinceReferenceDate: has to be an integer or a float"]; + CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceReferenceDate: should be an integer or a float"); self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate]; return self; @@ -102,7 +102,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0)); - (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate { if (!_isNumberType(seconds)) - [CPException raise:CPInvalidArgumentException reason:@"The parameter of the method initWithTimeInterval:sinceDate: has to be an integer or a float"]; + CPLog.warn(@"The parameter of the method initWithTimeInterval:sinceDate: should be an integer or a float"); self = new Date(refDate.getTime() + seconds * 1000); return self;