Acorn and JSTalk
March 27th, 2010 by ChrisLast month when planning for exhibiting our iPhone apps at Macworld Expo, we decided to use the fabulous services at MOO to create promotional materials to hand out at the show. We wanted to have a a simple way for attendees to take something with them with as a reminder of our iPhone apps. We also needed a method to hand out iTunes App Store promotional codes that could be used to redeem copies after the attendees went home.
Moo’s MiniCards were very affordable and sized just right for our purposes:

They are sized small enough that its not a burden to carry around the conference. Not everyone at Macworld wants to load up a bag full of chotskies, schwag and product materials! We found the MiniCard’s appearance and quality really attracted the attention of attendees. Also, critical to our needs each card can have one side that con be printed with a separate image. Perfect for making individual cards each have a unique promo code.
Apple allots developers 50 promotional codes per version of their application. In total we had four versions of Postage plus, SnoGlobe and RoseGlobe that we wanted to make a full set of 50 moo cards with a promo code on the back for. That was 300 unique images we needed to make and upload! Certainly a tedious process at best.
Lucky for us, we had some automation magic in our toolchest thanks to Flying Meat’s image editor Acorn and Gus’s excellent new technology project JSTalk. While there are plenty of Mac OS graphics tools that support AppleScript for automation, I have to be completely honest here. Every time I try to use AppleScript I find myself struggling with the syntax and terminology. Frequently I just give up and do whatever I was trying to accomplish manually after banging my head on the keyboard for a few hours.
JSTalk exposes Cocoa frameworks and applications for scripting and automation using JavaScript. It also performs some preprocessor shenanigans so you can write JavaScript that looks a lot like Objective-C. Being an Objective-C programmer for a good number of years now, I find this absolutely charming. I don’t have to bootstrap myself into learning a new language, especially not some crazy english-language hybrid that demoralizes me for weeks at time after it beats me over the head with my apparent lack of basic English language literacy.
While Acorn has built-in support for JSTalk, Gus has made it easy for other applications to add support as well. JSTalk also allows other applications without support to be automated using the Script Bridge.
To create the backs for our MiniCards, we started with a the image of the layout of the back of the card. Brad left an empty spot for the text :

Then I created a JSTalk script to drive Acorn. First the script reads in the promo codes from the file that iTunes Connect creates for you when you generate promo codes. Then for each of the codes, the script opens our layout image, creates a new text layer with the promo code and styles it properly. Finally, it saves the newly created image with a proper name.
Here is what the script looks like :
var codes = [NSString stringWithContentsOfFile:
@"/Users/twenty3/Desktop/SnoGlobePromoCodes.txt"];
var lines = [codes componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
var sourceFilePath = "/Users/twenty3/Desktop/"
var sourceFileName = "SnoGlobeMooCardsBack";
var sourceFileExtension = ".png";
var destinationFolder = "SnoGlobeMooBacks/";
for (i=0; i<[lines length]; i++)
{
var doc = acorn.open(sourceFilePath+sourceFileName+sourceFileExtension);
var layer = doc.layers()[0];
var wc = doc.windowController();
var shapeLayer = [wc addNewShapeLayer:nil];
var textArea = [shapeLayer addTextWithBounds:NSMakeRect(526, 106, 264, 40)];
var promoCodeText = [[NSMutableAttributedString alloc]
initWithString:[lines objectAtIndex:i]];
var promoCodeFont = [NSFont fontWithName:@"Menlo-Bold" size:30];
var promoCodeColor = [NSColor whiteColor];
var promoStyle = [[NSMutableParagraphStyle defaultParagraphStyle]
mutableCopyWithZone:NSDefaultMallocZone];
promoStyle.setAlignment(NSCenterTextAlignment);
var promoCodeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
promoCodeFont, NSFontAttributeName,
promoCodeColor, NSForegroundColorAttributeName,
nil ];
[promoCodeText setAttributes:promoCodeAttributes
range:NSMakeRange(0,[promoCodeText length])];
[textArea setContents: promoCodeText];
doc.dataOfType("public.png").writeToFile(
sourceFilePath + destinationFolder +
sourceFileName + i + sourceFileExtension );
doc.close();
}
[acorn activate];
Now, I got a little bi-polar there going back and forth between Objective-C style brackets and plain ol’ JavaScript style function calls. You can use whatever syntax makes the most sense to you personally though.
And here is a sample of one of the generated images:

Using this technique we generated all 300 images in something like 10 minutes. Add a little time to that to create the script and it added up to a whole lot of time saved. Plus, it was way more fun than the copy/paste dance it would have taken to do this by hand.
Count me in as a fan of JSTalk. Its such a cool technology and Gus has been kind enough to develop and distribute it completely free of charge! If you develop Mac apps you should think about dropping in support for JSTalk. If you have the need to do some automated image manipulation or creation, Acorn + JSTalk may be the perfect tool to tackle your problem.



