00001
00002 @import <Foundation/Foundation.j>
00003 @import <AppKit/AppKit.j>
00004 @import <AppKit/CPCib.j>
00005 @import <AppKit/CPTheme.j>
00006 @import <BlendKit/BlendKit.j>
00007
00008 var File = require("file");
00009
00010
00011 function main()
00012 {
00013 var index = 0,
00014 count = system.args.length,
00015
00016 outputFilePath = "",
00017 descriptorFiles = [],
00018 resourcesPath = nil,
00019 cibFiles = [],
00020 blendName = "Untitled";
00021
00022 for (; index < count; ++index)
00023 {
00024 var argument = system.args[index];
00025
00026 switch (argument)
00027 {
00028 case "-c":
00029 case "--cib": cibFiles.push(system.args[++index]);
00030 break;
00031
00032 case "-d":
00033 case "-descriptor": descriptorFiles.push(system.args[++index]);
00034 break;
00035
00036 case "-o": outputFilePath = system.args[++index];
00037 break;
00038
00039 case "-R": resourcesPath = system.args[++index];
00040 break;
00041
00042 default: jExtensionIndex = argument.indexOf(".j");
00043
00044 if ((jExtensionIndex > 0) && (jExtensionIndex === argument.length - ".j".length))
00045 descriptorFiles.push(argument);
00046 else
00047 cibFiles.push(argument);
00048 }
00049 }
00050
00051 if (descriptorFiles.length === 0)
00052 return buildBlendFromCibFiles(cibFiles);
00053
00054 objj_import(descriptorFiles, YES, function()
00055 {
00056 var themeDescriptorClasses = BKThemeDescriptorClasses(),
00057 count = [themeDescriptorClasses count];
00058
00059 while (count--)
00060 {
00061 var theClass = themeDescriptorClasses[count],
00062 themeTemplate = [[BKThemeTemplate alloc] init];
00063
00064 [themeTemplate setValue:[theClass themeName] forKey:@"name"];
00065
00066 var objectTemplates = BKThemeObjectTemplatesForClass(theClass),
00067 data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])),
00068 temporaryCibFile = Packages.java.io.File.createTempFile("temp", ".cib"),
00069 temporaryCibFilePath = String(temporaryCibFile.getAbsolutePath());
00070
00071 File.write(temporaryCibFilePath, [data string], { charset:"UTF8" });
00072
00073 cibFiles.push(temporaryCibFilePath);
00074 }
00075
00076 buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath);
00077 });
00078 }
00079
00080 function cibDataFromTopLevelObjects(objects)
00081 {
00082 var data = [CPData data],
00083 archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:data],
00084 objectData = [[_CPCibObjectData alloc] init];
00085
00086 objectData._fileOwner = [_CPCibCustomObject new];
00087 objectData._fileOwner._className = @"CPObject";
00088
00089 var index = 0,
00090 count = objects.length;
00091
00092 for (; index < count; ++index)
00093 {
00094 objectData._objectsValues[index] = objectData._fileOwner;
00095 objectData._objectsKeys[index] = objects[index];
00096 }
00097
00098 [archiver encodeObject:objectData forKey:@"CPCibObjectDataKey"];
00099
00100 [archiver finishEncoding];
00101
00102 return data;
00103 }
00104
00105 function getDirectory(aPath)
00106 {
00107 return (aPath).substr(0, (aPath).lastIndexOf('/') + 1)
00108 }
00109
00110 function buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath)
00111 {
00112 var resourcesFile = nil;
00113
00114 if (resourcesPath)
00115 resourcesFile = new Packages.java.io.File(resourcesPath);
00116
00117 var count = cibFiles.length,
00118 replacedFiles = [],
00119 staticContent = @"";
00120
00121 while (count--)
00122 {
00123 var theme = themeFromCibFile(new Packages.java.io.File(cibFiles[count])),
00124
00125
00126 filePath = [theme name] + ".keyedtheme",
00127 fileContents = [[CPKeyedArchiver archivedDataWithRootObject:theme] string];
00128
00129 replacedFiles.push(filePath);
00130
00131 staticContent += MARKER_PATH + ';' + filePath.length + ';' + filePath + MARKER_TEXT + ';' + fileContents.length + ';' + fileContents;
00132 }
00133
00134 staticContent = "@STATIC;1.0;" + staticContent;
00135
00136 var blendName = File.basename(outputFilePath),
00137 extension = File.extname(outputFilePath);
00138
00139 if (extension.length)
00140 blendName = blendName.substr(0, blendName.length - extension.length);
00141
00142 var infoDictionary = [CPDictionary dictionary],
00143 staticContentName = blendName + ".sj";
00144
00145 [infoDictionary setObject:blendName forKey:@"CPBundleName"];
00146 [infoDictionary setObject:blendName forKey:@"CPBundleIdentifier"];
00147 [infoDictionary setObject:replacedFiles forKey:@"CPBundleReplacedFiles"];
00148 [infoDictionary setObject:staticContentName forKey:@"CPBundleExecutable"];
00149
00150 var outputFile = new Packages.java.io.File(outputFilePath).getCanonicalFile();
00151
00152 outputFile.mkdirs();
00153
00154 File.write(outputFilePath + "/Info.plist", [CPPropertyListCreate280NorthData(infoDictionary) string], { charset:"UTF8" });
00155 File.write(outputFilePath + '/' + staticContentName, staticContent, { charset:"UTF8" });
00156
00157 if (resourcesPath)
00158 rsync(new Packages.java.io.File(resourcesPath), new Packages.java.io.File(outputFilePath));
00159 }
00160
00161 function themeFromCibFile(aFile)
00162 {
00163 var cib = [[CPCib alloc] initWithContentsOfURL:aFile.getCanonicalPath()],
00164 topLevelObjects = [];
00165
00166 [cib _setAwakenCustomResources:NO];
00167 [cib instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObject:topLevelObjects forKey:CPCibTopLevelObjects]];
00168
00169 var count = topLevelObjects.length,
00170 theme = nil,
00171 templates = [];
00172
00173 while (count--)
00174 {
00175 var object = topLevelObjects[count];
00176
00177 templates = templates.concat([object blendThemeObjectTemplates]);
00178
00179 if ([object isKindOfClass:[BKThemeTemplate class]])
00180 theme = [[CPTheme alloc] initWithName:[object valueForKey:@"name"]];
00181 }
00182
00183 print("Building " + [theme name] + " theme");
00184
00185 [templates makeObjectsPerformSelector:@selector(blendAddThemedObjectAttributesToTheme:) withObject:theme];
00186
00187 return theme;
00188 }
00189
00190 function rsync(srcFile, dstFile)
00191 {
00192 var src, dst;
00193
00194 if (String(java.lang.System.getenv("OS")).indexOf("Windows") < 0)
00195 {
00196 src = srcFile.getAbsolutePath();
00197 dst = dstFile.getAbsolutePath();
00198 }
00199 else
00200 {
00201 src = exec(["cygpath", "-u", srcFile.getAbsolutePath() + '/']);
00202 dst = exec(["cygpath", "-u", dstFile.getAbsolutePath() + "/Resources"]);
00203 }
00204
00205 if (srcFile.exists())
00206 exec(["rsync", "-avz", src, dst]);
00207 }
00208
00209 function exec( command, showOutput)
00210 {
00211 var line = "",
00212 output = "",
00213
00214 process = Packages.java.lang.Runtime.getRuntime().exec(command),
00215 reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getInputStream()));
00216
00217 while (line = reader.readLine())
00218 {
00219 if (showOutput)
00220 System.out.println(line);
00221
00222 output += line + '\n';
00223 }
00224
00225 reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getErrorStream()));
00226
00227 while (line = reader.readLine())
00228 System.out.println(line);
00229
00230 try
00231 {
00232 if (process.waitFor() != 0)
00233 System.err.println("exit value = " + process.exitValue());
00234 }
00235 catch (anException)
00236 {
00237 System.err.println(anException);
00238 }
00239
00240 return output;
00241 }
00242
00243 @implementation CPObject (BlendAdditions)
00244
00245 - (CPArray)blendThemeObjectTemplates
00246 {
00247 var theClass = [self class];
00248
00249 if ([theClass isKindOfClass:[BKThemeObjectTemplate class]])
00250 return [self];
00251
00252 if ([theClass isKindOfClass:[CPView class]])
00253 {
00254 var templates = [],
00255 subviews = [self subviews],
00256 count = [subviews count];
00257
00258 while (count--)
00259 templates = templates.concat([subviews[count] blendThemeObjectTemplates]);
00260
00261 return templates;
00262 }
00263
00264 return [];
00265 }
00266
00267 @end
00268
00269 @implementation BKThemeObjectTemplate (BlendAdditions)
00270
00271 - (void)blendAddThemedObjectAttributesToTheme:(CPTheme)aTheme
00272 {
00273 var themedObject = [self valueForKey:@"themedObject"];
00274
00275 if (!themedObject)
00276 {
00277 var subviews = [self subviews];
00278
00279 if ([subviews count] > 0)
00280 themedObject = subviews[0];
00281 }
00282
00283 if (themedObject)
00284 {
00285 print(" Recording themed properties for " + [themedObject className] + ".");
00286
00287 [aTheme takeThemeFromObject:themedObject];
00288 }
00289 }
00290
00291 @end