diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 8699a7a52..c6046ad0b 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -107,7 +107,7 @@ CPRunContinuesResponse = -1002; CPPanel _aboutPanel; - CPThemeBlend _themeBlend @accessors(property=themeBlend); + CPArray _themeBlends @accessors(property=themeBlends); } /*! @@ -141,6 +141,8 @@ CPRunContinuesResponse = -1002; _windows = []; [_windows addObject:nil]; + + _themeBlends = []; } return self; @@ -338,7 +340,7 @@ CPRunContinuesResponse = -1002; Copyright - Human readable copyright information. - If you choose not the include any of the above keys, they will default + If you choose not the include any of the above keys, they will default to the following respective keys in your info.plist file.
@@ -1003,7 +1005,7 @@ CPRunContinuesResponse = -1002;
}
/*!
- Sets the arguments of your application.
+ Sets the arguments of your application.
That is, set the slash seperated values of an array as the window location hash.
For example if you pass an array:
@@ -1156,6 +1158,16 @@ CPRunContinuesResponse = -1002;
userInfo:nil];
}
+- (CPThemeBlend)themeBlend
+{
+ return (_themeBlends.length > 0 ? _themeBlends[0] : nil);
+}
+
+- (void)setThemeBlend:(CPThemeBlend)aThemeBlend
+{
+ _themeBlends[0] = aThemeBlend;
+}
+
+ (CPString)defaultThemeName
{
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
@@ -1218,15 +1230,14 @@ function CPApplicationMain(args, namedArgs)
[_CPAppBootstrapper performActions];
}
-var _CPAppBootstrapperActions = nil;
+var _CPAppBootstrapperActions = nil,
+ _CPAppThemeURLsToLoad = [];
@implementation _CPAppBootstrapper : CPObject
-{
-}
+ (CPArray)actions
{
- return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
+ return [@selector(bootstrapPlatform), @selector(loadThemes), @selector(loadMainCibFile)];
}
+ (void)performActions
@@ -1250,17 +1261,30 @@ var _CPAppBootstrapperActions = nil;
return [CPPlatform bootstrap];
}
-+ (BOOL)loadDefaultTheme
++ (BOOL)loadThemes
{
- var defaultThemeName = [CPApplication defaultThemeName],
- themeURL = nil;
+ _CPAppThemeURLsToLoad.push([CPApplication defaultThemeName]);
- if (defaultThemeName === @"Aristo")
- themeURL = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:defaultThemeName + @".blend"];
+ var auxiliaryThemes = ([[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPAuxiliaryThemes"] || []);
+
+ _CPAppThemeURLsToLoad = _CPAppThemeURLsToLoad.concat(auxiliaryThemes);
+
+ [self loadNextTheme];
+
+ return YES;
+}
+
++ (BOOL)loadNextTheme
+{
+ var themeName = _CPAppThemeURLsToLoad.shift();
+
+ if (themeName === @"Aristo")
+ themeURL = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:themeName + @".blend"];
else
- themeURL = [[CPBundle mainBundle] pathForResource:defaultThemeName + @".blend"];
+ themeURL = [[CPBundle mainBundle] pathForResource:themeName + @".blend"];
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:themeURL];
+
[blend loadWithDelegate:self];
return YES;
@@ -1271,7 +1295,10 @@ var _CPAppBootstrapperActions = nil;
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
- [self performActions];
+ if (_CPAppThemeURLsToLoad.length === 0)
+ [self performActions];
+ else
+ [self loadNextTheme];
}
+ (BOOL)loadMainCibFile
diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j
index ff37bee69..1383fa831 100644
--- a/AppKit/CPTheme.j
+++ b/AppKit/CPTheme.j
@@ -25,9 +25,10 @@
@import
-var CPThemesByName = { },
- CPThemeDefaultTheme = nil,
- CPThemeDefaultHudTheme = nil;
+var CPThemesByName = { },
+ CPThemeNamesByInheritance = [],
+ CPThemeDefaultTheme = nil,
+ CPThemeDefaultHudTheme = nil;
/*!
@@ -76,6 +77,45 @@ var CPThemesByName = { },
return CPThemesByName[aName];
}
+/*!
+ Returns an array of names of all loaded themes, in the order they were loaded.
+*/
++ (CPArray)allThemeNames
+{
+ return [CPThemeNamesByInheritance copy];
+}
+
+/*!
+ Returns the closest matching theme for a given view. The matching proceeds as follows:
+
+ - The default theme class name for the class is retrieved.
+ - Starting with the last loaded theme and proceeding towards the default theme,
+ each theme is checked to see if it defines that theme class.
+ - If the theme defines the class name, that theme is returned.
+ - If no themes match, the default theme is returned.
+
+ @param aView The view to match with a theme
+ @return The first matching theme
+*/
++ (CPTheme)themeForView:(CPView)aView
+{
+ var count = CPThemeNamesByInheritance.length,
+ themeClass = [aView themeClass];
+
+ if (themeClass)
+ {
+ while (count--)
+ {
+ var theme = CPThemesByName[CPThemeNamesByInheritance[count]];
+
+ if ([theme._attributes containsKey:themeClass])
+ return theme;
+ }
+ }
+
+ return CPThemeDefaultTheme;
+}
+
- (id)initWithName:(CPString)aName
{
self = [super init];
@@ -86,6 +126,9 @@ var CPThemesByName = { },
_attributes = [CPDictionary dictionary];
CPThemesByName[_name] = self;
+
+ if (![CPThemeNamesByInheritance containsObject:_name])
+ CPThemeNamesByInheritance.push(_name);
}
return self;
@@ -299,6 +342,9 @@ var CPThemeNameKey = @"CPThemeNameKey",
_attributes = [aCoder decodeObjectForKey:CPThemeAttributesKey];
CPThemesByName[_name] = self;
+
+ if (![CPThemeNamesByInheritance containsObject:_name])
+ CPThemeNamesByInheritance.push(_name);
}
return self;
diff --git a/AppKit/CPView.j b/AppKit/CPView.j
index bd2a5be03..b152ffd9c 100644
--- a/AppKit/CPView.j
+++ b/AppKit/CPView.j
@@ -292,7 +292,7 @@ var CPViewFlags = { },
_DOMImageSizes = [];
#endif
- _theme = [CPTheme defaultTheme];
+ _theme = [CPTheme themeForView:self];
_themeState = CPThemeStateNormal;
[self setupViewFlags];