Tuesday, March 11, 2014

Smile as R.A.D.

Rapid Application (ish) Development Using Smile

Back in the day, when I was a burgeoning AppleScript experimenter (at some point I became a “developer”, but it was a bumpy road), FaceSpan was the Rapid Application Development Environment I loved. It was fast and easy and powerful. Those days are gone. FaceSpan was dropped by its developer and by its rescuer-developer. XCode AppleScript Application Development became the de facto AppleScript development platform beyond the Script Editor (and indeed, it is very powerful). Other players (Hypercard, Supercard, Ultracard, MegaUltraCard [okay, I made a couple of those up] Runtime Revolution, QuicKeys [oh, man, did I have fun with that one], RealBasic/Studio, FutureBasic) fell by the wayside, for various reasons (although a few of them still have a following, at least, or some measure of commercial success).
I’d like to put in a good word for what seems to be a somewhat overlooked diamond-well-out-of-the-rough: Smile.

Why Smile?

Smile is known (at least) as a sophisticated AppleScript Script Editor developed by Satimage (satimage.fr), a french company whose software products SmileLab and Smile have been around since, oh, I don’t know, the Pleistocene perhaps.

Brass Tacks.

I admit it. Attempts to adopt AppleScript/Cocoa App Development have met with some success and some frustration. It’s not the fault of Apple (um ... no, it’s not. Wait ... no, it’s not). It’s because I spread myself very thin across many disciplines, of which software development is a very thin and spackled emulsion indeed. I have to re-learn. I have to dig up old snippets of code and manuals. I have to troll websites like the wonderful stackoverflow.com.
In short, I miss the direct and, dare I say it, intuitive flow of FaceSpan.
I’ve used Smile to create interface-rich dialogs (or even super simple dialogs, like the one which is a simple progress bar that can be used to offer feedback for my more complex or time-consuming scripts).
One of these dialogs, which I call ScanButton,
was originally just a button to activate the scanimage binary (http://www.sane-project.org/sane-frontends.html), but which soon (soon? yeah, soon) became a fairly sophisticated interface to scan, including previewing and pre-scan cropping.
I made this because I bought a scanner on craigslist which probably fell off a truck, was twenty bucks, and was lacking in consistent OSX-friendly software, especially for doing batches of scan sequences (among other things, I do traditional animation, you see). So I wrote my own, and utilized Smile’s dialog development.

My latest endeavor came about because I was messing around with ffmpeg (www.ffmpeg.org) to do fast conversions of movies (quicktime, windows media, avi, mpeg) for a job I was working on. Long story short (am I still typing?), I decided that I wanted to give the company I was working for a GUI-enhanced script to help with their approvals and deliveries. I wanted to do it quickly. I wanted it to be fun (yes, I find Smile “fun”).
Somewhere in the annals of Smile documentation there is a feature that allows you to wrap a scripted Smile dialog into its own app. Man, I can’t tell you how many times I tried to use that feature and had it blow up. It seemed buggy and unreliable. Whether or not it is buggy and unreliable is not the purpose of this article. But when developing this movie-converter dialog, I thought, why not just have the company download and install Smile, give them the dialog file (which is basically a double-clickable plugin) and have them use that? Is it possible, I wondered, to modify Smile so that the dialog acts just like a stand-alone-type thing? Basically, yes. AppleScript is at the heart of Smile; it’s one of the most beautifully complete AppleScript-powered applications out there. All you have to do is add some code into your dialog’s on prepare, on deactivated, and on delete handlers (and, if you like, add an additional handler, as I did), and you can make the dialog the main attraction and limit the user’s control over Smile (but if they want to do more Smile-y things, they can open Smile by itself and go to town).

The Code Snippets

on prepare theDialog
set prepared to true
modifySmileUI(theDialog)
end prepare

to modifySmileUI(thisMainDialog)
set menuKillList to {2, 4, 5, 9, 10, 11}
repeat with m in menuKillList
set visible of menu m to false
end repeat
--then get rid of specific items:
set visible of menu item "Clear Console" of menu 3 to false
set visible of menu item "Compare" of menu 3 to false
set visible of menu item "Output to Console" of menu 3 to false
set visible of menu item "Edit Mode" of menu 3 to false
set visible of menu item 18 of menu 3 to false--menu item "Go to line…"
set visible of menu item 19 of menu 3 to false--menu item ""
set visible of menu item "Find definition" of menu 3 to false
set visible of menu item "Enter selection" of menu 3 to false
set visible of menu item "Smile dictionary" of menu 1 to false
--set visible of menu item "Preferences..." of menu 1 to false--not accessible
close (every window whose name is not (name of thisMainDialog))
end modifySmileUI

on deactivated
thisDlg
--keeps Prefs from being opened :
--DANGER! Do NOT close the Prefs window; this will crash Smile in a bad way.
if ("Preferences" is in (name of windows)) then
set visible of window "Preferences" to false
set index of window "MovieForge" to 1 --hmm.
end if
end deactivated

on delete theDialog
continue delete theDialog
quit
end delete

The AppleScript code above represents everything I use to make my dialog feel more like a stand-alone. I comment out the “modifySmileUI(theDialog)” line in the first handler until the dialog is ready to be delivered. I also comment out the “quit” line in the last handler until the dialog is ready to ship. When the dialog is complete, I un-comment out these lines and the dialog is ready to be double-clicked by users who have no interest in the inner-workings of the dialog or Smile. They just want an interface to use for their workflow-enhancing pleasure.

What It Does.

Handler #1, on prepare, is what the dialog does as it is creating itself. When the modifySmileUI line “goes live” (gets un-commented), it calls the modifySmileUI handler which turns off all unnecessary menus and menu items in Smile, so that only the “Smile”, “Edit” and “Help” menus are visible.
The on deactivated handler, called when another window opens in front of the dialog, has some rather hack-y code that prevents (more or less) Smile’s Preferences from being opened. The idea here is that Smile’s Preference’s are accessible when using Smile, but not when using my dialog. As you can read in the comment, my first attempts at this, which actually sent a close window event to the Preferences window, caused Smile to crash hard, so I dispensed with this idea and used the “set visible to false” technique, which isn’t ideal (the interface is a little confusing for a split-second, and afterward, the main dialog floats in a sort of frontmost-but-not-frontmost limbo until you click on it), but it works.
Finally, the last handler, on delete, handles what happens when you close the dialog by quitting Smile completely, so that quitting the dialog quits the whole shebang, and no one is the wiser.

© 2014 Christopher R Green