diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j index 2e44da5e6..09b1ca765 100644 --- a/AppKit/Cib/CPCib.j +++ b/AppKit/Cib/CPCib.j @@ -24,6 +24,7 @@ @import @import +@import "_CPCibClassSwapper.j" @import "_CPCibCustomObject.j" @import "_CPCibCustomResource.j" @import "_CPCibCustomView.j" diff --git a/AppKit/Cib/_CPCibClassSwapper.j b/AppKit/Cib/_CPCibClassSwapper.j new file mode 100644 index 000000000..6b41bfae0 --- /dev/null +++ b/AppKit/Cib/_CPCibClassSwapper.j @@ -0,0 +1,53 @@ +/* + * _CPCibClassSwapper.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2009, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@import +@import + + +var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey", + _CPCibClassSwapperOriginalClassNameKey = @"_CPCibClassSwapperOriginalClassNameKey"; + +@implementation _CPCibClassSwapper : CPObject +{ +} + ++ (id)allocWithCoder:(CPCoder)aCoder +{ + var theClassName = [aCoder decodeObjectForKey:_CPCibClassSwapperClassNameKey], + theClass = objj_lookUpClass(theClassName); + + if (!theClass) + { + CPLog.error("Unable to find class " + theClassName + " in cib file."); + + theClassName = [aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]; + theClass = objj_lookUpClass(theClassName); + + if (!theClass) + [CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."]; + } + + return [theClass alloc]; +} + +@end diff --git a/Foundation/CPKeyedUnarchiver.j b/Foundation/CPKeyedUnarchiver.j index 3a4f2a87b..0bf92f2f6 100644 --- a/Foundation/CPKeyedUnarchiver.j +++ b/Foundation/CPKeyedUnarchiver.j @@ -426,15 +426,16 @@ var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex) if (!theClass) theClass = CPClassFromString(className); - object = [theClass alloc]; - - // It is important to do this before calling initWithCoder so that decoding can be self referential (something = self). - self._objects[anIndex] = object; - var savedPlistObject = self._plistObject; self._plistObject = plistObject; - var string = className; + + // Should we only call this on _CPCibClassSwapper? (currently the only class that makes use of this). + object = [theClass allocWithCoder:self]; + + // It is important to do this before calling initWithCoder so that decoding can be self referential (something = self). + self._objects[anIndex] = object; + var processedObject = [object initWithCoder:self]; self._plistObject = savedPlistObject; diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j index 06e744efb..0cb462fbe 100644 --- a/Foundation/CPObject.j +++ b/Foundation/CPObject.j @@ -93,6 +93,11 @@ CPLog(@"Got some class: %@", inst); return class_createInstance(self); } ++ (id)allocWithCoder:(CPCoder)aCoder +{ + return [self alloc]; +} + /*! Initializes the receiver @return the initialized receiver diff --git a/Objective-J/runtime.js b/Objective-J/runtime.js index 5ed505846..365ab725a 100644 --- a/Objective-J/runtime.js +++ b/Objective-J/runtime.js @@ -177,8 +177,8 @@ function class_addMethod(/*Class*/ aClass, /*SEL*/ aName, /*IMP*/ anImplementati // FIXME: Should this be done here? // If this is a root class... if (!ISMETA(aClass) && GETMETA(aClass).isa === GETMETA(aClass)) - class_addMethods(GETMETA(aClass), methods); - + class_addMethod(GETMETA(aClass), method); + return YES; } diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j index 955c45b20..5e13cb706 100644 --- a/Tools/nib2cib/NSAppKit.j +++ b/Tools/nib2cib/NSAppKit.j @@ -22,6 +22,7 @@ @import "NSButton.j" @import "NSCell.j" +@import "NSClassSwapper.j" @import "NSClipView.j" @import "NSColor.j" @import "NSColorWell.j" diff --git a/Tools/nib2cib/NSClassSwapper.j b/Tools/nib2cib/NSClassSwapper.j new file mode 100644 index 000000000..a0e8822fd --- /dev/null +++ b/Tools/nib2cib/NSClassSwapper.j @@ -0,0 +1,66 @@ + +var NSClassSwapperClassNames = {}, + NSClassSwapperOriginalClassNames = {}; + +var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey", + _CPCibClassSwapperOriginalClassNameKey = @"_CPCibClassSwapperOriginalClassNameKey"; + +@implementation NSClassSwapper : _CPCibClassSwapper +{ +} + ++ (id)swapperClassForClassName:(CPString)aClassName originalClassName:(CPString)anOriginalClassName +{ + var swapperClassName = "$NSClassSwapper_" + aClassName + "_" + anOriginalClassName; + swapperClass = objj_lookUpClass(swapperClassName); + + if (!swapperClass) + { + var originalClass = objj_lookUpClass(anOriginalClassName); + + swapperClass = objj_allocateClassPair(originalClass, swapperClassName); + + objj_registerClassPair(swapperClass); +try{ + class_addMethod(swapperClass, @selector(initWithCoder:), function(self, _cmd, aCoder) + { + self = objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder); + + if (self) + { + var UID = [self UID]; + + NSClassSwapperClassNames[UID] = aClassName; + NSClassSwapperOriginalClassNames[UID] = anOriginalClassName; + } + + return self; + }, ""); + }catch(e) { alert("B"); }try{ + class_addMethod(swapperClass, @selector(classForKeyedArchiver), function(self, _cmd) + { + return [_CPCibClassSwapper class]; + }, ""); + + class_addMethod(swapperClass, @selector(encodeWithCoder:), function(self, _cmd, aCoder) + { + objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder); + + // FIXME: map class name as well? + [aCoder encodeObject:aClassName forKey:_CPCibClassSwapperClassNameKey]; + [aCoder encodeObject:CP_NSMapClassName(anOriginalClassName) forKey:_CPCibClassSwapperOriginalClassNameKey]; + }, "");}catch(e) { alert("C"); } + } + + return swapperClass; +} + ++ (id)allocWithCoder:(CPCoder)aCoder +{ + var className = [aCoder decodeObjectForKey:@"NSClassName"], + originalClassName = [aCoder decodeObjectForKey:@"NSOriginalClassName"]; + + return [[self swapperClassForClassName:className originalClassName:originalClassName] alloc]; +} + +@end