PageRenderTime 20ms CodeModel.GetById 13ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/AppKit/Themes/CommonJS/blendtask.j

http://github.com/cacaodev/cappuccino
Unknown | 258 lines | 194 code | 64 blank | 0 comment | 0 complexity | dd7b90e4981cdcbef153b5a20c430a24 MD5 | raw file
  1/*
  2 * blendtask.j
  3 * BlendKit
  4 *
  5 * Created by Francisco Tolmasky.
  6 * Copyright 2009, 280 North, Inc.
  7 *
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation; either
 11 * version 2.1 of the License, or (at your option) any later version.
 12 *
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16 * Lesser General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 21 */
 22
 23@import <Foundation/CPObject.j>
 24@import <Foundation/CPData.j>
 25@import <Foundation/CPKeyedArchiver.j>
 26@import <AppKit/CPCib.j>
 27@import <AppKit/_CPCibObjectData.j>
 28@import <BlendKit/BlendKit.j>
 29
 30
 31var FILE = require("file"),
 32    TERM = require("narwhal/term"),
 33    task = require("jake").task,
 34    filedir = require("jake").filedir,
 35    BundleTask = require("objective-j/jake/bundletask").BundleTask;
 36
 37
 38function BlendTask(aName)
 39{
 40    BundleTask.apply(this, arguments);
 41
 42    this._themeDescriptors = [];
 43    this._keyedThemes = [];
 44}
 45
 46BlendTask.__proto__ = BundleTask;
 47BlendTask.prototype.__proto__ = BundleTask.prototype;
 48
 49BlendTask.prototype.packageType = function()
 50{
 51    return "BLND";
 52};
 53
 54BlendTask.prototype.infoPlist = function()
 55{
 56    var infoPlist = BundleTask.prototype.infoPlist.apply(this, arguments);
 57
 58    infoPlist.setValueForKey("CPKeyedThemes", require("narwhal/util").unique(this._keyedThemes));
 59
 60    return infoPlist;
 61};
 62
 63BlendTask.prototype.themeDescriptors = function()
 64{
 65    return this._themeDescriptors;
 66};
 67
 68BlendTask.prototype.setThemeDescriptors = function(/*Array | FileList*/ themeDescriptors)
 69{
 70    this._themeDescriptors = themeDescriptors;
 71};
 72
 73BlendTask.prototype.defineTasks = function()
 74{
 75    this.defineThemeDescriptorTasks();
 76
 77    BundleTask.prototype.defineTasks.apply(this, arguments);
 78};
 79
 80BlendTask.prototype.defineSourceTasks = function()
 81{
 82};
 83
 84BlendTask.prototype.defineThemeDescriptorTasks = function()
 85{
 86    this.environments().forEach(function(anEnvironment)
 87    {
 88        var folder = anEnvironment.name() + ".environment",
 89            themeDescriptors = this.themeDescriptors(),
 90            resourcesPath = this.resourcesPath(),
 91            intermediatesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources"),
 92            staticPath = this.buildProductStaticPathForEnvironment(anEnvironment),
 93            keyedThemes = this._keyedThemes,
 94            themesTaskName = this.name() + ":themes";
 95
 96        this.enhance(themesTaskName);
 97
 98        themeDescriptors.forEach(function(/*CPString*/ themeDescriptorPath)
 99        {
100            objj_importFile(FILE.absolute(themeDescriptorPath), YES);
101        });
102
103        [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass)
104        {
105            var keyedThemePath = FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme");
106
107            filedir (keyedThemePath, themesTaskName);
108            filedir (staticPath, [keyedThemePath]);
109
110            keyedThemes.push([aClass themeName] + ".keyedtheme");
111        });
112
113        task (themesTaskName, function()
114        {
115            [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass)
116            {
117                var themeTemplate = [[BKThemeTemplate alloc] init];
118
119                [themeTemplate setValue:[aClass themeName] forKey:@"name"];
120
121                var objectTemplates = [aClass themedObjectTemplates],
122                    data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])),
123                    fileContents = themeFromCibData(data);
124
125                // No filedir in this case, so we have to make it ourselves.
126                FILE.mkdirs(intermediatesPath);
127                // FIXME: MARKER_TEXT isn't global, so we use "t;".
128                FILE.write(FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme"), "t;" + fileContents.length + ";" + fileContents, { charset:"UTF-8" });
129            });
130        });
131    }, this);
132};
133
134function cibDataFromTopLevelObjects(objects)
135{
136    var data = [CPData data],
137        archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:data],
138        objectData = [[_CPCibObjectData alloc] init];
139
140    objectData._fileOwner = [_CPCibCustomObject new];
141    objectData._fileOwner._className = @"CPObject";
142
143    var index = 0,
144        count = objects.length;
145
146    for (; index < count; ++index)
147    {
148        objectData._objectsValues[index] = objectData._fileOwner;
149        objectData._objectsKeys[index] = objects[index];
150    }
151
152    [archiver encodeObject:objectData forKey:@"CPCibObjectDataKey"];
153
154    [archiver finishEncoding];
155
156    return data;
157}
158
159function themeFromCibData(data)
160{
161    var cib = [[CPCib alloc] initWithData:data],
162        topLevelObjects = [];
163
164    [cib _setAwakenCustomResources:NO];
165    [cib instantiateCibWithExternalNameTable:@{ CPCibTopLevelObjects: topLevelObjects }];
166
167    var count = topLevelObjects.length,
168        theme = nil,
169        templates = [];
170
171    while (count--)
172    {
173        var object = topLevelObjects[count];
174
175        templates = templates.concat([object blendThemeObjectTemplates]);
176
177        if ([object isKindOfClass:[BKThemeTemplate class]])
178            theme = [[CPTheme alloc] initWithName:[object valueForKey:@"name"]];
179    }
180
181    TERM.stream.print("Building \0green(" + [theme name] + "\0) theme");
182
183    [templates makeObjectsPerformSelector:@selector(blendAddThemedObjectAttributesToTheme:) withObject:theme];
184
185    return [[CPKeyedArchiver archivedDataWithRootObject:theme] rawString];
186}
187
188@implementation CPCib (BlendAdditions)
189
190- (id)initWithData:(CPData)aData
191{
192    self = [super init];
193
194    if (self)
195        _data = aData;
196
197    return self;
198}
199
200@end
201
202@implementation CPObject (BlendAdditions)
203
204- (CPArray)blendThemeObjectTemplates
205{
206    var theClass = [self class];
207
208    if ([theClass isKindOfClass:[BKThemedObjectTemplate class]])
209        return [self];
210
211    if ([theClass isKindOfClass:[CPView class]])
212    {
213        var templates = [],
214            subviews = [self subviews],
215            count = [subviews count];
216
217        while (count--)
218            templates = templates.concat([subviews[count] blendThemeObjectTemplates]);
219
220        return templates;
221    }
222
223    return [];
224}
225
226@end
227
228@implementation BKThemedObjectTemplate (BlendAdditions)
229
230- (void)blendAddThemedObjectAttributesToTheme:(CPTheme)aTheme
231{
232    var themedObject = [self valueForKey:@"themedObject"];
233
234    if (!themedObject)
235    {
236        var subviews = [self subviews];
237
238        if ([subviews count] > 0)
239            themedObject = subviews[0];
240    }
241
242    if (themedObject)
243    {
244        TERM.stream.print(" Recording themed properties for \0purple(" + [themedObject className] + "\0).");
245
246        [aTheme takeThemeFromObject:themedObject];
247    }
248}
249
250@end
251
252exports.BlendTask = BlendTask;
253
254exports.blend = function(aName, aFunction)
255{
256    // No .apply necessary because the parameters aren't variable.
257    return BlendTask.defineTask(aName, aFunction);
258};