mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 12:17:13 +00:00
Load userland NS classes from the main bundle as well as frameworks, and temporarily change the class of NSSwapper classes to the target class when calling KVC methods.
This commit is contained in:
@@ -40,12 +40,12 @@ ConverterConversionException = @"ConverterConversionException";
|
||||
|
||||
@implementation Converter : CPObject
|
||||
{
|
||||
CPString inputPath @accessors(readonly);
|
||||
CPString outputPath @accessors;
|
||||
CPString resourcesPath @accessors;
|
||||
NibFormat format @accessors(readonly);
|
||||
CPArray themes @accessors(readonly);
|
||||
CPArray frameworkNSClasses @accessors;
|
||||
CPString inputPath @accessors(readonly);
|
||||
CPString outputPath @accessors;
|
||||
CPString resourcesPath @accessors;
|
||||
NibFormat format @accessors(readonly);
|
||||
CPArray themes @accessors(readonly);
|
||||
CPArray userNSClasses @accessors;
|
||||
}
|
||||
|
||||
+ (Converter)sharedConverter
|
||||
|
||||
@@ -39,10 +39,10 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
|
||||
|
||||
if (!swapperClass)
|
||||
{
|
||||
// If this is a framework NS class, call its KVC methods directly
|
||||
// If this is a userland NS class, call its KVC methods directly
|
||||
var nsClass = nil;
|
||||
|
||||
if ([[[Converter sharedConverter] frameworkNSClasses] containsObject:aClassName])
|
||||
if ([[[Converter sharedConverter] userNSClasses] containsObject:aClassName])
|
||||
nsClass = objj_lookUpClass("NS_" + aClassName);
|
||||
|
||||
var originalClass = nsClass || objj_lookUpClass(anOriginalClassName);
|
||||
@@ -51,9 +51,26 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
|
||||
|
||||
objj_registerClassPair(swapperClass);
|
||||
|
||||
/*
|
||||
When calling userland KVC methods, they should think that the class is
|
||||
the NS class (not the swapper class) so that they are in their userland space,
|
||||
not in AppKit space. For example, this ensures that bundleForClass:[self class] will work correctly.
|
||||
We can accomplish this safely by changing the class of self temporarily and sending directly
|
||||
to self instead of to super. This swizzle is safe because NSClassSwapper and _CPCibClassSwapper
|
||||
do not add any ivars.
|
||||
*/
|
||||
|
||||
class_addMethod(swapperClass, @selector(initWithCoder:), function(self, _cmd, aCoder)
|
||||
{
|
||||
self = objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder);
|
||||
if (nsClass)
|
||||
{
|
||||
// Switch to userland temporarily
|
||||
self.isa = nsClass;
|
||||
self = objj_msgSend(self, _cmd, aCoder);
|
||||
self.isa = swapperClass;
|
||||
}
|
||||
else
|
||||
self = objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder);
|
||||
|
||||
if (self)
|
||||
{
|
||||
@@ -73,7 +90,15 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
|
||||
|
||||
class_addMethod(swapperClass, @selector(encodeWithCoder:), function(self, _cmd, aCoder)
|
||||
{
|
||||
objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder);
|
||||
if (nsClass)
|
||||
{
|
||||
// Switch to userland temporarily
|
||||
self.isa = nsClass;
|
||||
objj_msgSend(self, _cmd, aCoder);
|
||||
self.isa = swapperClass;
|
||||
}
|
||||
else
|
||||
objj_msgSendSuper({super_class:originalClass, receiver:self}, _cmd, aCoder);
|
||||
|
||||
// If this is a custom NS class, lookup its archiver class so that
|
||||
// the correct class is swapped during unarchiving.
|
||||
|
||||
+25
-15
@@ -52,7 +52,7 @@ var FILE = require("file"),
|
||||
CPString appDirectory;
|
||||
CPString resourcesDirectory;
|
||||
CPDictionary infoPlist;
|
||||
CPArray frameworkNSClasses;
|
||||
CPArray userNSClasses;
|
||||
}
|
||||
|
||||
- (id)initWithArgs:(CPArray)theArgs
|
||||
@@ -67,7 +67,7 @@ var FILE = require("file"),
|
||||
appDirectory = @"";
|
||||
resourcesDirectory = @"";
|
||||
infoPlist = [CPDictionary dictionary];
|
||||
frameworkNSClasses = [];
|
||||
userNSClasses = [];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -153,7 +153,8 @@ var FILE = require("file"),
|
||||
|
||||
var loadFrameworksCallback = function()
|
||||
{
|
||||
[converter setFrameworkNSClasses:frameworkNSClasses];
|
||||
[self loadNSClassesFromBundle:[CPBundle mainBundle]];
|
||||
[converter setUserNSClasses:userNSClasses];
|
||||
[converter convert];
|
||||
};
|
||||
|
||||
@@ -573,18 +574,7 @@ var FILE = require("file"),
|
||||
[frameworkBundle loadWithDelegate:nil];
|
||||
[self setLogLevel:verbosity];
|
||||
|
||||
// See if the framework defines NS classes
|
||||
var nsClasses = [frameworkBundle objectForInfoDictionaryKey:@"IBClasses"] || [];
|
||||
|
||||
for (var i = 0; i < nsClasses.length; ++i)
|
||||
{
|
||||
var filename = "NS_" + nsClasses[i] + ".j";
|
||||
|
||||
objj_importFile(FILE.join(frameworkPath, filename), YES);
|
||||
CPLog.debug("Imported framework NS class: %s", filename);
|
||||
|
||||
frameworkNSClasses.push(nsClasses[i]);
|
||||
}
|
||||
[self loadNSClassesFromBundle:frameworkBundle];
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -597,6 +587,26 @@ var FILE = require("file"),
|
||||
aCallback();
|
||||
}
|
||||
|
||||
- (void)loadNSClassesFromBundle:(CPBundle)aBundle
|
||||
{
|
||||
// See if the framework defines NS classes
|
||||
var nsClasses = [aBundle objectForInfoDictionaryKey:@"IBClasses"] || [],
|
||||
bundlePath = [aBundle bundlePath];
|
||||
|
||||
for (var i = 0; i < nsClasses.length; ++i)
|
||||
{
|
||||
if (userNSClasses.indexOf(nsClasses[i]) >= 0)
|
||||
continue;
|
||||
|
||||
var path = FILE.join(bundlePath, "NS_" + nsClasses[i] + ".j");
|
||||
|
||||
objj_importFile(path, YES);
|
||||
CPLog.debug("Imported NS class: %s", path);
|
||||
|
||||
userNSClasses.push(nsClasses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
- (CPArray)getThemeList:(JSObject)options
|
||||
{
|
||||
var defaultTheme = options.defaultTheme;
|
||||
|
||||
Reference in New Issue
Block a user