---
title: WWDC2000 Session 154
framework: wwdc
role: article
path: wwdc/wwdc2000-154
---

# WWDC2000 Session 154

## Transcript

Kind: captions Language: en I'm Chris Espinosa if you were at the earlier session apples you've heard a lot for me if I press the forward button and the Machine just dings what does that mean [Music] this session is going to be a lot different than the overview this morning this is a very code oriented session if you are looking to learn how to script in applescript now would be a fine time to debark this aircraft we are going to be talking about C++ code we're going to be talking about classes we're going to be talking about a lot of things that are only of interest to people who are writing applications that want to be scriptable if you want if you are a scripter don't hurt yourself by trying to listen to me go to ww a calm / applescript and download some of south ago IANS very very fine applescript guidebook modules on how to write apple scripts for those of the rest of you if you want to learn how to make a scriptable application in c or c++ you're in the right place good what you're going to learn in this session is why there are relatively few good scriptable applications on the Macintosh platform because it's hard there are a lot of bad scriptable applications on the Macintosh platform because it's easier to make a bad scriptable application than a good scriptable application frameworks can help frameworks can help by doing a lot of the work for you frameworks can hurt frameworks can hurt because you assume they're doing a lot of the work for you when they're not so we're going to tell what it does for you versus what you have to do yourself we're going to talk a lot about power plants there has been a very good power plant solution out there Greg Dow put a lot of work into making some good scripting classes in power plant and it's the most widely distributed and widely used application framework for Macintosh we're going to be focusing a lot on that and then we'll be covering some alternatives one of the alternatives I want to stress is a relatively new one which DTS put up just last week is the more OSL package if you're familiar with more files more Apple events more toolbox from dps which basically fills in for developers the functionality that developers want in the OS that the OS designers didn't put there well this is another in that long and esteem series of software code bases that does just that DPS has done a wonderful job of responding to what the most frequently asked developer gripes about how to write scriptable applications are and filling that in in a very coherent and manageable way great piece of work and I'm going to be walking you through that let's start with some background because I know that some of you are approaching script ability for the first time applescript and the open scripting architecture osa is a way for a high level language a user written script to send events to applications so that applications can act on those events and execute them and the biggest problem that we find the biggest sin that is committed is applications that simply expose a flat programmers API to the scripting language a whole lot of events and not a lot of information because what we found over the years with what is popular with scriptures in applescript is they don't just want to send a bunch of events to applications they want to get and set information within that application and the information they want to get in set is the information on the user's model the conf the conceptual model of the information inside that application rather than clicking a checkbox or pushing a button or choosing a menu item they want to get the value of something or they want to create a new user object somewhere in the document it's not you know an automation like a macro maker or playback or recording it's more like we want to make queries on the data in your application make intelligent decisions based on that data and then do something that manipulates the data not manipulating the application because most of the really really good process automation and workflow solutions that are built using Apple script are very very data-driven not command driven and that this is why the object model is so important and what is the object model the object model is the way that osa languages access the user-visible information in your application and it applies a human terminology to the programmatic elements inside your application okay the two biggest problem two biggest things people do is one is that they just provide an event interface and no object interface so that the users can't see the objects because of all these events and two is that they fail to give human names to the objects within their applications and just basically propagate the C++ identifier is up to the scripture levels and that that's confusing to people an object is can be but is not necessarily your concept of a programmatic object inside your application if you look at the model-view-controller paradigm for developing an object-oriented application what we're really talking about is the model we're not talking about the view we're not talking about how it's drawn on the screen and we're not talking about the controller how it's manipulated we're talking about the existence of the object and the properties that that object has those properties can be read and set preferably from the scripting language it's of a designated class so it can be told apart from other things of that class and that class may be in a hierarchy and it can share some things or inherit some things from other classes it can be a container of other objects like a window can contain data elements or a folder can contain files or a page can contain graphic objects or a paragraph can contain words or characters and it can be contained by other objects as well we script objects and the best scriptable applications are those that use as few verbs as possible to script all of the objects in your applications that's a subjective statement but I lay claim to it the way that applescript and OSA languages designate to your application what they're trying to act on is through this structure called an object specifier and an object specifiers possibly the most heinous data structure you're going to come across in McIntosh programming it can be incredibly complex it can be vague and ambiguous it can be very detailed in inappropriate places and there are 247 different variants that you have to special case to make sure that when somebody sends you an object specifier you understand really what they're talking about what it does is it drills down from the top level of your application down to a specific piece of data in your application and can get there through multiple of routes and you don't have necessarily have to have a strict containment tree so it can really go through pretty bizarre ways let me show you I'll show you a little later how complex and how weird object specifiers can be the way you get an object specifier is as an apple event record that is deeply nested it's going to look on the top level like oh this is easy it it's an apple event record with four parts to it but then one of those parts is an object specifier which has four parts to it which can be an object specifier that has four parts to it and and it can go on down and down and down the four parks are basically the container of the of object that's the from part the type of data that's being requested which is the want how to select a value from the container which is the key form and we'll be talking a lot about key forms and then using that key form which one to pick okay so if I say I want a folder one of startup disk that's basically from is startup disk want is a folder form is by absolute position and selection data is one okay so that's a surly simple object specifier but they can be more complex for example the object specifier the modification date a file to through file for of folder applications of startup disk is nested kind of like this and the top level on the outside you have you're looking for the property you want a property the selection is the code for that property which is the modification date and the container is you want the property of a file so the next thing is you want a file selected by the key form range the key form range is going to may make two parts come you want the selection data which itself is a record with the start and a stop and the starts going to be you want forum index you want a file from the current container index to and the stock is going to be you want to file index it's actually wrong that should be index for see how easy it is to make a mistake so you want start at to stop at four from the current container and then the last thing the from goes all the way down to the bottom there and is I by name the selection a folder the selection data is quote applications from the startup disk and the startup disks container is null which means it's rooted at the application so there are all told 123456 object specifiers nested to to create this apple this this object specifier from an applescript and then this is a parameter to an event which can be get the modification date set the modification date or this could be just a clause in a you know delete every file whose modification date you know etc so its object specifiers can be arbitrarily complex and if you tried to write code yourself to parse this you'd go fairly nuts I know because people have here are the basic key forms you know one of the reasons is the combinatorial problems of all of your containers against all of your object versus all of the key forms and so before you go into that you really need to know what the key forms are the most familiar one is by numeric index file one first page that's the form absolute position and the selection data you're going to get is usually an integer which is very nice now one of the things to remember is that you are in control of this so you can be expecting any selection data you wanted form absolute position so you could make form absolute position any arbitrary thing you could make it a string as long as long as it identifies what you're talking about applescript will tend to do that in the format absolute position if if you say for if you say five window quote untitled or folder quote preferences that's going to trigger the by name key form form name and your selection data for that is usually a string and it's usually going to be a string in the system script we don't have Unicode selection yet for that so it's going to be a string in the system script those are the two main ones and and if all you support is by numeric index and by name and you support them well that's okay for certain classes of unique ID is going to be interesting but it really had better be unique form unique ID means I want this thing regardless of what its index is because its index may change and what its name is because its name may change I mean to think of this if you have if you're writing a script that's trying to script a finder folder and you want to change its name and when you change its name its index changes in the list because the finder automatically resources the list by name you know how are you going to refer to that thing again if you've changed its name and if you don't know what the name is and don't know what the new index is you're really going to need to hold on to something and that's what the unique ID is for so what you'd ride in the finder is set X to ID of folder foo set name of folder foo to bar and then it's no longer folder foo its folder bar and its index is different but the idea is the same and then you can say folder ID em and you'll be able to work on that folder again those are the simple key forms the more complex ones tandel are before after another element that's relative position this is how you insert things in the list or a pin things to list it's usually used with text that's form relative position and form relative position is basically a tuple of a absolute position or any other reference any other object specifier and then a tag that that says before or after okay as a range of items is a pair of the start element and the stop element which both can be any arbitrary object specifiers and that's how you do you know page 1 through 3 of in quark for example or and then satisfying a test which is the most interesting one it's every folder whose name starts with or ends with dot jpg you know a very useful thing to do in the finder that's the form test in the form whose in order to make your object model really usable by all of these all of these key forms can be compiled by the applescript language and so users can use these you should document in your scripting terminology in your dictionary which objects support which key forms just to not mislead people applescript will pay no attention to that it will try to compile all of these key forms regardless of what you say in your terminology is generate these object specifiers it'll send them to your application and your application will either say I don't support this key form or do it right now too often applications don't say I don't support this key form and they don't do it right and they just take a wild stab and return an error and what we if there's one thing I'd like to come out of this session is people at least being honest with scripters both in their terminal and in their implementation what key forms are support supported on what objects and that's a hard thing to do because you have to know them all and know all their combinations because all of the example users can come up with wonderful wonderful phrase as an applescript that your application just can't handle like name of every track of a movie one who's enabled is true or modification date of every file of folders 1 through 2 of every folder whose name starts with a all of these generate valid object specifiers and your application if you say you've got an object modeling you've got all these objects you should be able to handle things like this how do you handle this the process of handling these is something called object resolution and basically when an event comes in and there's an object specifier in its parameter your first task is to resolve that object to some indication of what the thing is in your application that that object specifier represents what you have to do is have to descend in the structure until you find that from null which means oh that's the root object and then you have to back out looking at each key form and selection data in turn and then maybe walking back down and doing it again if it's like a rainstorm and you need to descend into those object specifiers and figure out what they mean descending from that root just basically unpack the object specifier until you get back to the oh and what they eventually want is the modification date or the you know file or though whatever so when you you walk until you find no and then you walk out until you get to the outermost object specifier and then you're done but that's a hard process it's recursive and it's got a lot of different cases sometimes the intermediate thing that's generated will be a list like a range so that at the next level you have to iterate over that range and do the same thing to it like the modification date of every file you can find every file and then you have to iterate over every file to get the modification date of that a lot of rules that you have to follow in order to do it right there arbitrarily complex you have to have baked typically a three-dimensional matrix of switch cases you have to have a switch for every containment relationship you have to have a switch for every key form supported by each containment relationship and you have to have a switch for every potential data type of the selection data you know the form name could have a name it could have the absolute position could be an integer the absolute position could be something other than an integer your ranges could be object specifiers it could be absolute position and there is our no good general rules about how to handle the weird corner cases a lot of this stuff isn't written down anywhere there's something provided with Apple system software called the object support library which has a routine called AE resolve which purports to help you resolve object specifiers it does this recursive walk down and walk back what you have to do is you have to invent a lot of handlers registers those handlers with the OSL and then handle the information as they call you back you have to create this token scheme whereby you associate the information in your application with these with these callbacks and so when you get called back you get past a token that says oh they're talking about this thing they're talking about this property of that object they're talking about this object and you have to manage that token scheme yourself including storing and disposing the tokens it's really a pain and then the OSL doesn't really do your key forms for you you have to do a lot of work yourself and so if you just rely on what OSL provides you end up with a very very sparse partial implementation so what do you do if it's so hard if it's so complicated and the system software gives you so little support what do you do well you do it badly which is what most of you have done and I don't blame you but there are tools now that help you do it well if your scripting with the framework the general process is that you create model objects in C++ that reflect your users view your scriptures view of your application okay so if you have a graphic object concept that a user can draw a graphic object you make a graphic object class in C++ and maybe you know you don't really have a graphic objectclass and C++ in your implementation but just create one whose implementation then specializes to you know Circle Square line or whatever but create something that you can hang off scripting then the general paradigm and this is used in almost every framework that off our prescriptive ility is that any incoming event like make new delete move whatever that operates on an object will become a call to a member function on that object and any Apple event properties like the size the dimensions the visible the color the descriptor can get at are just represented as data members of that object and then your elements your containment relationships become collection class collections on that object and so basically what you do is what I'd recommend doing is you start with your user model create your terminology then design a bunch of C++ objects that implement and C++ view of that terminology wire them up on the top side to the scripting engine of that framework on the bottom side to your actual implementation object and then try it out and see how it works and you may have to do a little tuning to get it all right but that's the order that i really recommend you start in from start from the user model of your application design your scripting terminology implement C++ objects that are structured like that terminology then wire them up to the scripting engine and then wire them to your actual implementation so that the script commands can flow all the way from the Scriptures view of the world to your actual objects in your C++ application and so this is how it works in power plant if you get power plant off the shelf and this has been true for years what you can do is if you have a C++ class and you derive it from the L model object class that becomes the equivalent of an apple event object model class and so in your terminology if it has class window if you look in power plant the window class and power plant derives from L model object and so it looks like a window to applescript the applescript window class the events are member functions so just as the window l model object in power plant has a lot of internal C++ method functions that member functions that it responds to it also responds to member functions that correlate to the standard suite of Apple event objects makes new delete for windows it's closed save save as so there's a correlation between the events that come in and the member functions on that class the parameters or arguments for those member functions properties of objects correlate to the data members on those classes power plant implements the containment relationships using their collection classes called el lifts and so everything every object that descends from El model object has a number of L list as basically FML list attached to it which is all the things that that object contains and so a window if you have a window that's populated with widgets and widgets also descend from l model object then your window class is going to have an l list of widget objects and then each widget object is going to have a data member that's that called M supermodel and that's going to be the window it belongs to ok so that's how you do the containment relationship with the l list on the container and the M supermodel on the contained and this makes it very very easy once you have your object model designed and your terminology designed to go in and write all these C++ classes that derive for male model object and have L lifts and have them super model data members and that makes your internal structure resemble the terminology that you've defined and power plant helps you out a lot in this by doing some of the stuff automatically especially the event registration basically first you you start with your terminology resource and I hope all of you have have learned how to create an editor terminology resource we could have a special clinic just on that because it's pretty hard but you add an apple event object model class to your terminology resource and you invent a four character code for your class w idg for your widget okay then you create the C++ class that has L model objects as a public ancestor and then you redefine the constructor on your w idg object on your widget object so it takes an L model object reference to its container and you pass that pointer to the AL model object constructor and when somebody says make new widget your constructor gets called and it just happens automatically it's very nice it's a very clean system in the constructor you've set the model kind to that for character code that you've defined in your terminology and that's how it gets linked and then in each container that has that class is an element this is the containment relationship you call set uses sub-model list to true and that says oh I'm a container I contain these things and then you'll get method calls you'll get member function calls on your objects that correspond to apple event calls that's sort of like handle if somebody makes a new thing of you like if you say make new widget that container object will get a call handle create element and that says oh you know this container the window wants a new widget created in it then there you go here's here's the new widget object that's been created here's the container that it's being created in do what you need to do in your low level code to draw it or initialize it or whatever you need to do once the object exists then getting and setting the class properties are very straightforward you again define your properties in your a été you create a four character code for each property on each object and then there's a method on each class called get AE property you just override that method and you switch off the floor character code and there you go so if you have a win if you have a widget that has color size shape property you have three four character codes for those your get AE property method will be called on your widget class it'll be called with the parameter that is the property code you just switch off that and say oh if I'm getting the size i return this if I'm getting the shape I return this if I'm getting the color I return this then you can go in and do the appropriate manipulation to get the right data you create an AE desk with the value and then you return that as the return value of get a property it's very straightforward again here's an example of it i mean you switch on the in property do three cases this is content filled and line width for example and you just get the appropriate value straight from the object where you synthesize it if it's necessary and then you call 80 create desk to put it into the right form that correlates to the class that you defined it as in your terminology you know if your terminology said that your contents are q directa our rectangle re CT then you'd better return it as a rectangle that would be good setting class properties is similar what they're what's going to come in to your set AE property is a property switch in a value in an 80 desk you write a switch statement that switches off the end property then you extract the value from the AE desk and coercive if necessary to the right one and then you set it is it can't be set you return an error if the set is successful then you return silently so here's a set IE property switch notice something in here there's a refresh call basically if your application has a user interface when a scriptor sets properties on an object you may want to update your visual display you may want your model to talk to your view to refresh the image if somebody set the bounds of something you wanted to redraw it so you have to call refresh to redraw it how to kee forms work in power plant power plant implements most key forms for free if you if it because l LIF are indexed list power plant knows how to get you know widget for of window to because it just goes down the L list and gets the fourth widget from that and sends them to that object form name works if you have a P name property a special case if you have a name property form name works everything else you really have to do yourself there's this method called get model token self which passes in the key form and you pretty much have to figure out from there how it works mostly they're pretty easy there's some sample code on the web I can give you a reference to it that implements form range doesn't implement it well but it basically implements it form unique ID is fairly straightforward who's clauses are kind of difficult though and how to events work well the good news is that power plant implements exists make delete count duplicate and move the basic standard event for any object that defends from L model object so these come for free which is really nice you just have to implement the constructors and destructors duplicate is fairly simple the difficult part for duplicate is that you've got to set the initial like making you've got to set the appropriate initial values for so for duplicate you've got to get the get the properties that are important of the object you're duplicating and then set them you know if you duplicate an object all the properties are not going to be identical the index will be different unique ID will be different for example so if you're duplicating a widget you need to get the important properties of widget of the old widget and then set the properties of the new widget to though to that set skipping the ones that are defined to be unique like the name perhaps like the index like the unique ID and then you've got a handle create element event in each container you know create have to happen into place if you're creating a widget in a window the widget has to know it's being created and the window has to know that a new widget has been created in it in order to get all the updating to happen right here's some code and this will be on the slides on the CD if you want to read it if it's too hard to read up here but basically this is the create element element event you switch on what class you're creating if your if your container can handle multiple different classes created in it then you know if it's if you're gonna create event to create this then you do a new that if that than you to a new this if it's not then you throw an error now what about custom events I mean it's all well and good to have an application that is just objects in the standard events and I really really applaud you if you can make an application that is nothing but objects in the standard events but you might want to do your own custom event I mean the finder does for like reset and restart and shut down that's pretty easy to once again you start by defining the events in your terminology resource and inventing a four character code and it's actually a pair of four character codes that event class and even type what you do in power plant is power plant has a resource called the aedt resource and the aedt resource is nothing but a table that maps event class code there's two long ends and that's all it is is just a table of event class code and long it and what happens is that when an apple event comes into a power plant application it gets looked up in this table the longing is generated and then you switch off of that long in because it's too hard to switch off of 244 care codes so it basically switches off the long it so if you want to create a custom event you know like a refresh event or something like that you event invented the clasp creatorcode for it you associate it with the number and then you in the switch statement in handle apple event you switch off of that number and then when that case is called you just execute your code their net and you do that on every object that can handle that event ok so if every object has its own refresh event you might want to have that handle apple event method and have that case in the handle apple event method for each object that handles a refresh event or you might want to have it for example if you've got a number of objects that can be refreshed you might want to just do it once and have all the other refreshable objects inherit from that so that you know you just assume the inherited capability and in many of the cases for the standard events that's exactly what power plant does is it doesn't implement it in the object itself but it just hands it off to the class that inherits from so here's an example here's a rotate event you switch on the apple event number if the case is eight you rotate then you call rotate if not then you call the inherited handle apple event so that you pass it up to the the superclass to see if it can handle it here's some things to remember about power plant number one is that power plant applications are by default scriptable in the most stupid possible way in that they support a small number of standard events on the window class only but they expose a full in some cases too full Apple event terminology that promises more than it actually delivers so for example the if you just build the demo power plant application it says it supports make new delete count create whatever on a whole bunch of objects and none of that support is actually in the code and that's bad so the first thing I want you to do is to trim or throw away the terminology resource in your power plant application treat it as if it's just you know start from scratch design your script ability then write a terminology resource from scratch and then implement that terminology that you could find because if you don't don't do that what's going to happen is the default terminology resource that gets compiled into your power plant application is going to promise that it supports all these events with all these objects which just aren't there and it's a source of great frustration for a lot of scriptures that you know they get a new application and they first thing they do is they drag it onto the script editor to see whether it's scriptable and this dictionary pops up and it's great I'll look at all these events there the standard suite they got all these objects and you look at it and it's just power plant and that's all it is and then you know it's not going to work so please from your power plant dictionary the second thing is I cannot possibly do power plant scripting justice in the time I have in this presentation but luckily on codewarrior pro and actually every version of cobra or back for several years there's been a very good introduction to doing script ability and power plant in the power plant advanced topics book that's in PDF form on the power plant tool documentation CD in the code warrior documentation CD it's there it's good read it study it these slides were basically stolen shamelessly from there it's good documentation and it will help get your head around the whole Apple events thing so if you mundt to code and power plant go to power plant advanced topics trim daet resource start with designing what you want the user to see build your terminology build some C++ objects that reflect that then wire them up both to the scripting interface through L model object and then to your actual implementation that's the way to go about it but what if I don't want to use power plant well you've got options one of the things you can do is you can manually extract L model object and the l list class and some of the other classes that are hanging on you can just extract them from power plant and compile them into your application now there are a lot of little threads that you may have to pick up of things that power plant depends upon but the power plant classes are extractable from power plant itself so you don't have to use their window model you don't have to use their drawings model their load and save you can just extract the classes and adapt them and use them as a model in your own application could be a lot of work but it does save you a lot of work so that's one thing you can do there's another framework an old venerable framework called sprocket by Steve cific that hasn't been updated for guests for years now but it's still available online at code welkom I believe and it supports some some decent apple event scripting it's some helper classes that that help you get your head around it it's not terribly up to date but it's a start if you want to commit to using objective c or java and deploying on mac OS 10 only you can use the coco framework there's some very good script ability in cocoa and you can go to the cocoa advanced topics presentation which is at three o'clock today to talk about that or you can use the mac app framework and i'm sure Tom Becker will be very happy to show you what script abilities in the mac app framework but there's one more opportunity which has just presented itself coming from our DTS group called more OSL moro SL is not a framework per se it's more like a support library that you can use from a sea application or a C++ application its carbon ready which if you want to deploy on Mac OS 9 and a quest 10 is very nice it'll get you there faster and it deploys all the way back to mac OS 8.5 and compiles all the way back to codewarrior pro 2 so those of you who are sticking back on earlier versions of code warrior and don't need don't want to use latest and greatest are not cut off from this functionality it supports it really does support doing a good object model really like the way that it goes about doing it and it's comprehensive it's tested and it comes with a good sample application that shows you how it works and I'm going to be demoing that a little while you can get it on developer apple com / sample code it's a little deeper in there but there's a at the moment there's a top-level link to it very small quick download go for it here's the theory of operation it's a little different from the way the power plant thing works you have to define your user classes in your user events and I recommend you do it the same way you start with the user model and then you define your terminology and figure out what your object model classes an object model events are going to be but then you make tables you make a table of all your classes and you make a table of all your events and then you make a table for each class of what events apply to that class and you build those in straight see struts fans of straight see struts you create an event table entry for each event on each class and it maps the event codes to classes they operate on and then it also has some bits that declare what's supposed to happen with the direct parameter whether it's required or optional whether this generates a reply or not things like that so you said a couple flags in these tables so basically the first thing your application does is creates all these tables that defines a script ability then you then more OSL does all of the registry with the object support librarian with the apple of handler for you it does it registers its handlers so you don't have to so when an event handler gets called or an object access or gets called moro FL takes control and it will call back to you when it needs to but you don't have to interact directly with the operating system which is very nice and in many cases the generic handlers the generic event handlers from where else L will do what you want with no further intervention which is actually pretty cool when your application process is an apple event more OSL resolves the direct cram parameter it calls o SI resolve for you it dispatches the event to the event handler for your class directly it's called class first dispatching it's it's the right way to do it and then the generic handler handles the event unless you've defined a specific handler for that event on your class in which case your specific handler gets called so let me show you just basically a class table entry there are three main parts to it there's an event ID which is you know here's the event that's coming in and then a couple of pointers to other tables a table for the properties and a table for all the events on that class and then for each class you must supply a couple of callback routines and you can supply others and just leave them null if you're not supplying them for each class you must write a counter routine that counts how many of those class there are in a container and then you can provide accessors that are get a class by unique ID you know gets get me from my container by unique ID by index by name and then there's get me or something of me there's a set me or something of me and then there's a coerced token and the tokens are pretty much the way that the OSL works the token is a representation of the internal object and tokens in more OSL are basically just pointers they can be a class pointer they can be a pointer that can be a handle but it's basically 32 bits that uniquely identify something in your application so then there's an event table entry and the event table is very straightforward it's just the the the four character codes for the event in the event class whether or not the direct object is required and whether or not there's a result in what action to take on the result and then in each class there's a table for weather where's the handler for the exists event the count event to get data event and the feds data event okay and then as you add more custom events to the event table you have to provide corresponding events in the class event handlers I mean it's really dumb dispatching the event table the master one and every class event table has to be in parallel that is if you add you know a rotate event to the event table entry you have to add a rotate event in the same position in every class event handler even if most of many of them are null because you can't rotate those but the one you have one that does support rotate that's the pointer to the rotate routine ok so the class event handler table should look like the event table entry customized for each class and then the property table off of each classes class is very straightforward it's property code and the bunch of flags that say what it does and the property access is actually done through the classes getter setter event with the same kind of switch statement if you provide a P properties property a property's property in your terminology which is you know the way things are done now Laurel OSL will automatically iterate over all of the properties in your property table and get them or set them on mass which is great it saves you the trouble of doing that if you provide a P inherits property in your terminology and you put it in your property table entry more OSL will automatically look in your container classes for properties that you don't support directly so if I have you know like in the finder there's a item and a file and items have names files don't have names files have like modification dates but they inherit names so in the in Morro South Carlin's there won't be a property table entry for name in the file object and more OSL will see the inherits and say oh I'm looking for the name property I don't look in the file object I look in the item object that inherits from and it'll do the right thing for you this is really very nice in terms of event handler more OSL does exist counts get object and set object for you it implements those generically and in most cases you really won't need to do anything to change your override those most of the key forms are handled automatically and this is good for two reasons one is that you you just don't have to implement like form range and several of the form test cases and second is you can read the source code and see how it ought to work if you so desire to see how it ought to work it's really great the only one that's not handled automatically in the current version of OSL is the form relative position before after and amend let me talk a little bit about tokens like I said tokens are the way that you relate an object specify a resolved object specifier to something in your application and the token is basically a token code and object code property code and then a pointer to something you know and this is a simple token definition that pointer to something can be like a window pointer pointer to a toolbox structure it can be a pointer to one of your C or C++ data structures or it can be a C++ object it's just 32 bits that your application if given a pointer can say oh this is a pointer and the object code reminds me what it's a pointer to that means I can do something with this data okay i can create it i can delete it i can get information from it whatever the only important thing about a pointer is that your application understands what it is a token tokens never leave your app they're never sent back to Apple script they're never sent anybody else so all that a token has to do is be created by and understandable by your application properties getters and setters it's very straightforward together if if somebody gives you a property token your getter ought to return and appropriate value if somebody says I want this property of this object you've got to return an AE desk that's that value it's all there is to it setter the same thing if somebody says here's up here's a token of an object here's the property and here's the new value I want you to set it to you should set that property somewhere in your application and return error or no that's all you need to do if there are other parameters on an apple event you have to extract them manually with good old a you get Prem desk and there's a useful more OSL routine to coerce it if it happens to be an object specifier it'll do the resolution for you you know this is useful for things like set name of file one to name a file to in that case the two parameter is an object specifier name of file too and so what it happens is the set command will resolve the direct parameter name of object one and give you a token and then it'll be set token to object specifier and then your senator will have to say well you know I don't know what this is it's an object specifier so you hand it off to coerce object mosl course object desk and it will take the two parameter the object specifier and it will call back inside your application and resolve that and get the name of file to and return the string and saying okay this is what you should set it to set name of set this token to this string and then you just do it because then you know what it is more ofl does deep object resolution which is really cool it's for cases like first file of every folder of every disc that's going to be a list and what that's going to be a list of is on every disc for every folder at the top level of every disc you want the first file of each of those folders and or the name of the first file of each of those folders and so Mauro SL has an object resolution algorithm that goes deep into those structures and creates one long list from that we could go into it it's well documented in the more OSL documentation so without further ado if we could have demo machine one up great when you download more OSL one of the first things you notice is you get a lot of the more is better classes with you you get more Apple events more windows more text details the demo application relies on a bunch of those but there are two main things the more OSL files relatively small most of the work is done in this 140 k txt file called moro slc there are a couple of separate files to the string comparisons which are a heinous and be the cause of many bug reports which quinn is filed basically saying applescript should either do this itself or have callbacks to do this because as you might know it's very hard for your application to do string comparisons the same way Apple script does string comparisons and that could be unexpected to users so we're taking that feedback and trying to do something with it there's a small source code file to manipulate tokens small source code file that some helper routines but really more OSL is itself a relatively small piece of code the second thing you'll find is a fully functional test application in codewarrior called test more OSL and the delightful thing about disc is it has almost no user interface at all so you won't be tempted to try to play with the UI it is mostly a scriptable application and so if we go to code warrior and open up should have more or less test tomorrow I shall die there we go here's the test application and there's one source file to the test application and the terminology resource and that's about it and then the rest are the more OSL sources and the test applications one file and what it does is it creates a model of a you have the application the application has windows and each window can have nodes in it and nodes are just simple rectangles and nodes can have subnodes in them and that is the user model so what we did was we created a user model windows nodes subnodes then did a terminology for it and came up with all the appropriate for character codes for all of the events in the class and things like that and then built those tables and wrote those accesses like we talked about so for example in the test moro slc file here's the here are all of the routines on the application because the application contains windows there's a getter setter counter and access by index routine and those are listed in its appropriate tables there's the events it handles open reopen oak open document quit and make so basically you have one routine for the getter setter counter and access and then one routine for each event it takes and the routines are pretty simple so here's the application get er I thought I'd set the text size on this and hit power plant there we go so here's your application getter and it gets a token in and if the token is a property then you switch on that property and if it's the version then you get the version property and return it if it's a unique ID then you return to unique ID and otherwise you say no such object it's a very simple getter so then there's a window class and the window has its getter setter and its event it responds to which is closed and so here's the handler for the window closed event which is basically handles the saving in parameter so it gets back and then closes the window with or without the save options it's a very simple handler so here's the document inside the window and the document handles make new ok and so this routine handles the make event when it determines we want to make a document and it creates a new properties record and this actually uses more some of the more is better window classes in order to put the window up on the screen but it basically creates the classes for that and then here are some of the custom objects here's the node and here's your node access by index since more since more OSL doesn't have like an L list structure it has to manage its own data structures itself it doesn't have collection classes to fall back on so it has it just basically has a index list of nodes with your node pointers and then it it finds it by index and if it doesn't find it then it says doesn't have an element of this type so you can see that the once you set up the more the more 0 itself structure actually implementing the apple event an object model handling very straight forward for every event and these specific things you have to do for every class you write one routine whose input to these and outputs your needs and then the rest of the stuff is just basically handled for you and it makes it a lot simpler let me show you this in action will is it running little debug this and run it and we can open up the script one of the things I love about this is that it comes with a test script which has some particularly heinous cases in it I mean it really exercises most of the code paths with within the test application and within more OSL itself so for example here's a lot of things that you should be able to send from applescript to your application and had your application handle you know set front most of window to true and make new document with properties and set position of no dispute but set position of some element of some document to a list make a new window with properties you know these are a bunch of things that you should support in your code if you have classes that support that support them and so we're going to open up the event log here show the event results and it's compile this gets the application there are a lot of test cases in here it's a big script and we're going to execute it against that application and here are all the test cases we're going to run and we're going to run it before the app lament times out and you can see as they scroll by here are a whole lot of object model events going to this application there's Gators there setters there's create new there's delete there is move there's duplicate and that relatively simple application okay it doesn't do anything with nodes it does very little with windows but that relatively simple application is handling all of these appli- and handling them well you can see some of the stuff we're doing here set set the properties property of a window to a list of properties which is knife set names of windows get names of startup disks exist files get ideas last window here the some key form which is supposedly take a random element from this list of element that's fully implemented so if we can go back to the slide machine and we'll wrap up here some other nice things about it the application and window classes are populated so if you're using the other more is better window classes then then you can just get that functionality for free for things like normal application and window properties and it knows about file objects which are another thing that Quinn filed a lot of bugs on is that sometimes applescript will send your application queries about system-wide objects like the name of a file given an FS spec and it expects you to handle that to be able to get the name of an ex FS back and return it and if you don't know that you're supposed to do that and nobody tells you you're supposed to do that it's a pain in the button it will result in a user bug report but more more OSL does that for you ok here's some notable emissions there's really no object management like I said there are no collection classes for your objects so you need to manage your objects yourself and you need to have the actual routines to do make new delete move and duplicate the objects yourself I mean the routines will call you but since it's not C++ it's not going to fire off constructors and destructors automatically you have to write that code yourself the print event is not implemented selections and insertion points generally the text classes are not supported you'll have to do that yourself like I said form relative position isn't implemented but we're going to try to twist somebody's arm to get that in and no support for things like properties of a built-in type like if the result of a get operation is a string and you ask for the class of that if you ask for class of version of application it won't handle that right but then again I know of relatively few applications that do and it also doesn't support class properties whose values are records or lifts and that's a philosophical decision and we're going to have a philosophical discussion about it so in summary if you want to use power plant power plant can provide easy scripting for your scriptable application there are some things you know a lot of things you have to do yourself but you can really get started by just over right you know inheriting from defending from L model objects and overriding a few handlers and you can get a scripting implementation started what I really recommend you do is you to trash the default dictionary implementation and you start from the beginning rather than just trying to like monkey with the sample application for mower mowers more OSL if you don't have a framework based application is really most appropriate for it it's the fastest way to get the basics done because all you do is write a few handlers install them in tables and there you go it assumes you're doing your own object management which most of you are doing anyway and it's very well comment and very well tested and we have some investment in it in that you know when we come out with a new dictate of how a new Apple script features supposed to be implemented like the properties property will try to get that into more OSL as sample okay we have a couple of sessions coming up in a very short period of time I think it's at three-thirty a feedback forum across the hall way on the other end for general feedback on applescript if you want to know more about doing scripting and cocoa you should go to the cocoa in depth session instead which is cross the street at specific auditorium long walk too bad but Mike Harris will give you a good show and what you can do in cocoa scripting same contact information for the last presentation but for codewarrior and power plant i recommend you contact Metro works technical support and for questions about more OSL DTF at apple com thanks very much for your attention yes you
