Files
cappuccino/AppKit/CPTheme.j
T
2009-02-05 21:17:59 -08:00

296 lines
6.6 KiB
Plaintext

@import <Foundation/CPObject.j>
@import <AppKit/_CPCibCustomResource.j>
@import <AppKit/_CPCibKeyedUnarchiver.j>
@import "CPThemedValue.j"
var CPThemesByName = nil,
CPThemeDefaultTheme = nil,
CPThemeViewClass = Nil,
CPThemeWindowClass = Nil;
@implementation CPTheme : CPObject
{
CPString _name;
Class _activeClass;
JSObject _classTable;
}
+ (void)initialize
{
if (self !== [CPTheme class])
return;
CPThemesByName = {};
CPThemeViewClass = [CPView class];
CPThemeWindowClass = [CPWindow class];
var bundle = [CPBundle bundleForClass:self];
defaultThemePath = [bundle objectForInfoDictionaryKey:@"Default Themes Path"],
defaultThemeName = [bundle objectForInfoDictionaryKey:@"Default Theme Name"];
if (!defaultThemePath)
return;
defaultThemePath = [bundle pathForResource:defaultThemePath];
var file = objj_files[defaultThemePath + "/Info.plist"];
if (!file)
return;
// Oh boy are we tricky.
var infoDictionary = CPPropertyListCreateFromData([CPData dataWithString:objj_files[defaultThemePath + "/Info.plist"].contents]);
themes = [infoDictionary objectForKey:@"CPBundleReplacedFiles"],
themeIndex = 0,
themeCount = [themes count];
for (; themeIndex < themeCount; ++themeIndex)
{
var unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[CPData dataWithString:objj_files[defaultThemePath + '/' + themes[themeIndex]].contents]
bundle:file.bundle];
[unarchiver decodeObjectForKey:@"root"];
[unarchiver finishDecoding];
}
[self setDefaultTheme:[CPTheme themeNamed:defaultThemeName]];
}
+ (void)setDefaultTheme:(CPTheme)aTheme
{
CPThemeDefaultTheme = aTheme;
}
+ (CPTheme)defaultTheme
{
return CPThemeDefaultTheme;
}
+ (CPTheme)themeNamed:(CPString)aName
{
return CPThemesByName[aName];
}
+ (void)loadThemesAtURL:(CPURL)aURL delegate:(id)aLoadDelegate
{
}
- (id)initWithName:(CPString)aName
{
self = [super init];
if (self)
{
_name = aName;
_classTable = {};
_classTable[[[self class] className]] = {};
CPThemesByName[_name] = aName;
}
return self;
}
- (CPString)name
{
return _name;
}
- (void)setActiveClass:(Class)aClass
{
_activeClass = aClass;
}
- (Class)activeClass
{
return _activeClass;
}
- (id)valueForKey:(CPString)aKey
{
return [self valueForKey:aKey inClass:_activeClass];
}
- (id)valueForKey:(CPString)aKey inClass:(CPClass)aClass
{
if (!aClass)
return nil;
var className = [aClass className],
table = _classTable[className];
if (!table)
return nil;
var value = table[aKey];
if (!value)
return nil;
return value;
}
- (id)valueForIdentifier:(CPString)anIdentifier inClass:(Class)aClass
{
return [self valueForKey:anIdentifier inClass:aClass];
}
- (void)takeThemeFromObject:(id)anObject
{
var values = [anObject themedValues],
key = nil,
keys = [values keyEnumerator],
objectClass = [anObject class];
while (key = [keys nextObject])
[self addValue:[values objectForKey:key] forKey:key inClass:objectClass];
}
- (void)setDefaultValue:(id)aValue forKey:(CPString)aKey
{
[self addValue:aValue forKey:aKey inClass:[self class]];
}
- (void)addValue:(id)aValue forKey:(CPString)aKey inClass:(Class)aClass
{
if (!aValue)
return;
var className = [aClass className],
table = _classTable[className];
if (!table)
{
var classNames = [];
while (!table && (aClass !== CPThemeViewClass) && (aClass !== CPThemeWindowClass))
{
classNames.push(className);
aClass = [aClass superclass];
className = [aClass className];
table = _classTable[className];
}
if (!table)
table = _classTable[[[self class] className]];
var count = [classNames count];
while (count--)
{
className = classNames[count];
_classTable[className] = {};
_classTable[className].prototype = table;
table = _classTable[className];
}
}
if (table[aKey] !== aValue)
// {
// if (table.hasOwnProperty(aKey)
table[aKey] = aValue;
}
@end
var CPThemeNameKey = @"CPThemeNameKey",
CPThemeClassNamesArrayKey = @"CPThemeClassNamesArrayKey";
@implementation CPTheme (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
_name = [aCoder decodeObjectForKey:CPThemeNameKey];
_classTable = {};
CPThemesByName[_name] = self;
if (self)
{
var classNamesArray = [aCoder decodeObjectForKey:CPThemeClassNamesArrayKey],
count = classNamesArray.length;
while (count--)
{
var className = classNamesArray[count],
theClass = objj_getClass(className),
values = [aCoder decodeObjectForKey:className],
keys = [values allKeys],
keyCount = keys.length;
while (keyCount--)
{
var key = keys[keyCount];
[self addValue:[values objectForKey:key] forKey:key inClass:theClass];
}
}
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
var classNamesArray = [];
for (var className in _classTable)
{
if (_classTable.hasOwnProperty(className))
{
var values = _classTable[className],
valuesDictionary = [CPDictionary dictionary];
for (var key in values)
if (key !== "prototype" && values.hasOwnProperty(key))
[valuesDictionary setObject:values[key] forKey:key];
[aCoder encodeObject:valuesDictionary forKey:className];
classNamesArray.push(className);
}
}
[aCoder encodeObject:_name forKey:CPThemeNameKey];
[aCoder encodeObject:classNamesArray forKey:CPThemeClassNamesArrayKey];
}
@end
@implementation _CPThemeKeyedUnarchiver : CPKeyedUnarchiver
{
CPBundle _bundle;
}
- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle
{
self = [super initForReadingWithData:data];
if (self)
_bundle = aBundle;
return self;
}
- (CPBundle)bundle
{
return _bundle;
}
@end