Acorn and JSTalk

March 27th, 2010 by Chris

Last 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:

Macworld MooCards Blog.png

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 :

PostageMooCardsBack.png

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 acorn = JSTalk.application("Acorn");

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:

PostageMooCardsBack0.png

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.

2 Responses to “Acorn and JSTalk”

  1. Mark Thalman Says:

    The problem I had with this code is it was ignoring the text alignment. To get the centering to work I had to add a line to the creation of the promoCodeAttributes dictionary.

    promoStyle, NSParagraphStyleAttributeName,

  2. Chris Says:

    Mark,

    At the time that we did the work, there was an issue with setting that attribute causing a problem in Acorn. I bet Gus has since addressed the problem. We worked around it by using a monospace font and knowing that we always had the same number of characters in our code. I forgot to pull out the creation of the paragraph style from the sample above!

    Glad to see that apparently works as expected now though.