macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Integrating AppleScript and Cocoa
Pages: 1, 2, 3, 4

AppleScript's Object Hierarchy

If you are familiar with AppleScript, you might already see the link between the AppleScript syntax and this object heirarchy.




tell application "MyApp" 

	get the first word of the first paragraph of document 1 

end tell

This is a typical AppleScript snippet. The heirarchy here goes from the generic application object MyApp to the document object document 1 to paragraph object first paragraph to word object first word. These map, in AppleScript speak, to elements and their properties. Let's look at a little more AppleScript syntax, and then we'll put it all together.


tell application "Graphics App" 

	set the color of window 1 to "blue" 

end tell

Breakdown of "ScriptableApp"

line by line "activate" is a command to application "ScriptableApp"

the set command to AppleScript with the arguments a script variable "appName" and the results of the command "name" sent to the application.

the set command to AppleScript with the arguments a script variable "appVersion" and the results of the command "version" sent to the application.

the set command to AppleScript with the arguments a script variable "numWins" and the count property of the collection of window elements in the application.

the set command to AppleScript with the arguments a script variable "numDocs" and the count property of the collection of document elements in the application.

the set command to AppleScript with the arguments a script variable "w" and the index property of the last element of the collection of windows returned by the get command with the identifier of every sent to the application.

close is a command sent to the application.

The topmost scripting object is the application Graphics App. This script is looking for an element identified by the word window with the properties of that element being color and an index of 1 (this could have also been first, last, mid, or any collection identifier), and we send the set command to the application with the arguments of the property of the element identifier and the new value of that property.


tell application "ScriptableApp"

	activate 
	set appName to name 
	set appVersion to version 
	set numWins to count of windows 
	set numDocs to count of documents 
	set w to the last Abstract object of (get every window) 
	close w 
end tell

Now, this one is a little more complicated, but try to find the elements, properties, and commands, and which object is being asked to do what. You should try to imagine what the object hierarchy for this application might look like.

Adding AppleScript support to a Cocoa application is a matter of providing a map between the elements and their properties of a scriptable application, and the Cocoa objects or other objects that make up that application, including the application object iteslf. Now while this may seem daunting, we are fortunate that Apple has already done this for us with the Core Suite for the most common Cocoa objects used in applications that are normally scriptable.

Core Suite and "For Free"

In the first article, we set the key NSAppleScriptEnabled to YES in the ScriptableApp's info.plist and gained a lot of scriptability right away. This scriptability comes from activating the Core Suite available to all Cocoa applications. The Core Suite provides a map for us.

Remember that our Cocoa application is a bunch of objects, primarily an instance of NSApplication (from main.m) and an instance of NSWindow (from MainMenu.nib). The window may be a little confusing, if you haven't looked at other tutorials on Cocoa and using Project Builder and Interface Builder.

You can use Interface Builder to create instances of UI objects, which are stored in .nib files and are loaded automatically when the application launches. This is all done graphically, so there is no corresponding source code viewable in Project Builder. There are some other objects floating around, like NSMenu, NSMenuItem, NSWindowController, and others, but they are not typically scriptable, so we will not focus on them. The Core Suite identifies certain Cocoa classes that will be scriptable. We can see these classes in a file called NSCoreSuite.scriptSuite, located at

/System/Library/Frameworks/Foundation.framework/Resources/NSCoreSuite.scriptSuite

You can look at this file in a text editor, or in a program called Property List Editor in the /Developer/Applications directory. This XML file has a lot of information in it, so I would recommend using the Property List Editor, just to make it easier to see what is going on.

NSCoreSuite.scriptSuite has several top-level keys: AppleEventCode, Classes, Commands, Enumerations, Name, and ValueTypes. For now, let us look at the Classes and Commands sections. The Classes mentioned are AbstractObject, NSApplication, NSColor, NSDocument, and NSWindow.

For Commands, we see Close, Copy, Count, Create, Delete, Exists, Get, Move, Open, Print, Quite, Save, snd Set. If you look at ScriptableApp's script dictionary, you'll see just these items. Every item has its own AppleEventCode associated with it, and if you look through the Classes, you'll see keys for the Superclass of the class and the SupportedCommands. Also, keep in mind that these classes can inherit attributes and commands from their Superclass, as each of the later classes do from AbstractObject.

Screenshot
NSCoreSuite.scriptSuite in Property List Editor

The Commands section matches each command up with a Cocoa object that is a subclass of NSScriptCommand. This is the CommandClass key found in each command.

For example, Copy is matched with an NSCloneCommand object. Each time a command is used in a script, an object of the corresponding type is created to ensure that the command is carried out. If you are more experienced with object-oriented programming, this may seem a little odd, as commands (methods) are usually defined along with their objects, so this breaks the OOP paradigm. However, AppleScript is designed to have a small number of commands that work on a large number of elements, so this arrangment works best for that idea.

The commands also define an AppleEventClassCode, in additional to the AppleEventCode, and their Arguments and return Type. A command may not have either arguments or return types, and if so, those keys are simply left blank. Return types are usually of the type NSString or NSNumber, but they can be other classes as well. There are many more items in this file, and we will talk more about them in later articles, especially when we start to create our own script suites, but now let us turn our focus more towards the AppleScript side.

Pages: 1, 2, 3, 4

Next Pagearrow