Development • 53:01
Mac OS X "Tiger" includes Automator, a powerful new application that lets users automate repetitive tasks without having to write scripts.
Speakers: Todd Fernandez, Tim Bumgarner, Eric Peyton
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Ladies and gentlemen, please welcome Todd Fernandez. Well, good morning. Welcome to session 303, Developing for Automator. As I was just introduced, I'm Todd Fernandez, the Automator Engineering Manager. And I'm thrilled to be here with you this morning, representing the Automator team, to tell you what you need to know about how to take advantage of this exciting new technology for your applications.
So what I hope you take away from this session this morning is a much better understanding of what Automator is, including its key features and terminology, why it's important to you, and most importantly, how you can take advantage of this new technology for your applications. We'll cover the SDK and design guidelines to help you.
So I would like to set the stage a little bit by first talking about what things were like before yesterday. With current technology, it's been very difficult to take advantage and exploit powerful network effects of combining disparate applications into automated workflows. It's been possible with technology like AppleScript, but the problem has been that it requires a relatively large investment of time and resources to develop the necessary expertise. Small business and the vast majority of end users have not been able to take advantage of this power.
And in fact, even those of us that have the necessary expertise sometimes have to make the calculation, "Is it going to take me longer to write and debug a script or to just do what I need to do by hand?" Well, fortunately, Automator fundamentally changes this calculation and dramatically lowers the bar for automating tasks on Mac OS X. Now you don't need a map, you don't need an expert guide, that guru colleague or precocious nephew, to help you make the connections to get your data from application A to application B. For the first time, end users can seamlessly extend and combine applications on their own.
And in fact, once developers of complex and powerful applications start exposing their application technology through Automator, users will be able to take advantage of applications they never could before. Automator allows customers to take advantage of the best that every application has to offer for their benefit. Now this is where you come in.
I recently learned how to surf, and though you can tell from that awkward little leap that I still have a lot to learn about surfing, I do remember one important lesson from my instructor. And that is, when a great wave comes, you'd better catch it because you don't know when the next one's going to come.
This is a unique opportunity for you to attract new customers to your applications by allowing them to incorporate your application into Automator workflows. What we've seen with AppleScript is that once a customer incorporates your application into an automated workflow, they remain loyal. They do not want to have to go back and do things by hand.
And for existing customers, Automator is a breakthrough, and they are going to expect that their favorite applications work well with it. If they don't, they're going to be forced to look for third-party solutions, or if they have the necessary development or scripting expertise, to develop their own Automator actions. The problem for you is that then you lose control. You lose control over how your technology is presented and defined. So I'd like to encourage you to get in front of the curve, catch the wave, and get to the beach as soon as you can.
So we've been talking at a very high level. I'd like to come back to Earth and talk in a little bit more detail about what Automator is. Well, first we're calling it your own personal automation assistant. And what it consists of are four main pieces: an application to create workflows, A large set of pre-built actions that you can use to create those workflows, tools to create new workflows, this is where you come in, and a set of examples of both actions and workflows.
So, I've been throwing around words here, actions, workflows, Automator, and I expect that some of you who have installed the TigerSeed DVD may be puzzled and disappointed that Automator isn't there. Well, I have a confession to make. In fact, it is there, it's just called "Pipeline." So in fact it is there for you to start working with.
And I've been talking about actions and workflows and there are a couple of other changes like that which I'll come on to in a moment. Specifically, an action, so we can define it for everyone so you can have a productive conversation, is a discrete bit of functionality. This is what developers and scripters will create and what customers will use to build their workflows. An example, a very simple example that many people will need to use for their workflows is copy files. It takes input files and copies them to a new location.
Now, here's where we come into one of the additional terminologies. We also, in various places, as you'll see during my presentation, refer to actions as stages. And that currently is mostly on the developer side, but we will certainly be unifying on a single term for this concept. So where do users get actions? Well, first of all, we have over 120 in the Tiger seed today, and we plan to have quite a few more by the time we ship Tiger.
Some users will be able to create their own, and finally we get to where you come in. We hope that third parties will create their own set of actions for their own applications. You know your application best and can create a rich set of actions for your customers to take advantage of and attract new customers.
So a workflow is composed of actions. This is what users will create themselves. And here's a relatively simple example. I might want to email to the members of my address book group family a new archive of a copy of every image with keyword "family", "crops 15%" and "CPU filtered". Now you can think about how long that would take you to do manually, especially for more than a handful of pictures.
But with Automator, it's very simple. And I'll just point out the fact that the copy files example action I mentioned a couple slides ago appears here as one of the actions in this workflow. And in fact, this workflow is composed of six actions, which are highlighted in color, so you can get an idea of how they break down.
So now I'd like to give you a little tour of the Automator interface. You saw some of it yesterday in the keynote and in the developer tools overview. I'd like to show you a little bit more. Here's a new document. You can see the Filtered Action List. This is the list of actions that the user building the workflow can select from. And it's controlled by the search field and the action category filtering above.
I've already mentioned the search field that allows you to further filter the actions from the category you have selected. And this, the view control we didn't show yesterday, but this allows you to switch between filtering by category and filtering by keyword. Here we're showing an example of selecting the change and name keywords, which then shows us in the filtered action list the list of actions having to do with changing file names.
So again, the area to the right is where you actually construct your workflow, and I'd just like to step us through building a simple example. We're going to start off finding files, and in fact, this action takes advantage of the great new spotlight technology you heard about yesterday to find files on my computer. And I'm looking for files with "icon" in the name and that are TIFFs. So I find a bunch of files.
Now I want to scale these images to a common size. But what happens when I try to add the scale images action to my workflow is I get a warning from Automator, letting me know that this action can change the data that's being passed into it and asks me if I'd like to actually copy them first and add a copy files action, so I'm working with the copies and not the originals. So I'm going to say yes, I want to add that too. And now I've got three actions in my workflow and I'm scaling each image passed to the scale images action to 480 pixels. Next, let's use some fancy quartz technology and let's apply a blue filter.
And let's see, then we're going to convert the TIFFs to JPEG, and then we want to import them into iPhoto. And indicated here is once I've built my workflow, I can easily click the "Run" button to execute it. And once I've built and tested my workflow, I can save it. I can save it as a workflow document, and in that case I can either reopen it in Automator and run it from the tool itself, or I can save it to Scripts menu to run from there.
The other choice is to save it as an application. This opens up a lot of additional opportunities. First of all, then, it can be double-clicked and launched from Finder, but it can also be used as a droplet. You can then drop files on to feed the beginning of your workflow.
And still more, you can actually attach a workflow application as an alarm in iCal so you can schedule the execution of your workflows. And one more little tidbit, if you use Image Capture to download your digital photos from your digital camera, you can actually tell Image Capture to launch an application when it's done downloading your photos, which allows you to build in an image processing workflow right in Image Capture. So that's our little tour of the Automator interface. Now I'd like to give you a brief demo of creating a workflow. We switch to demo one.
And what I'd like to do since this is a developer conference is show you something that's focused on developers' needs. Now, we in the Automator team have over 120 action projects. And while you may not have that many projects for your application, although you may, I'm sure you have enough that you don't like to do things manually with them.
Automator can help you eliminate a lot of the drudgery in your development life. And it really has for us. We've used various Automator workflows as we've developed the application to simplify our lives. One very similar to what I'm going to show you today, and another that through most of our development life of Automator we've used to build the project, to start with the Xcode project files, bump the version, build the projects, package them up, and attach the Mac OS X package to a new email to the project team to send out routes every time we do a new build. This is just one simple example of how Automator can simplify your life.
So what I want to do for you today, is showing yet another feature. We've got a contextual menu in Finder which allows you to start building workflows directly from Finder. So I don't want to show you 120 projects, I've just got three here for an example. And what I want to do is build.
So let's switch over to the keyword interface just to show you that. And I'm going to select the right keyword this time. Drag over the "Build Xcode Project" action. And let's see, I just want to do a clean build. And then finally, I want to capture the build results in a new text edit document.
So, alright, let's go ahead and try running that workflow. So as you can see, each action is marked with a green check to let you know that it's completed successfully. Now we're building the projects, and here are our build results. Great, so we've built our three projects, but what I want to do is go back to Automator and save our workflow.
We're going to be using this throughout our demos today. And let's see, build projects. All right, and what I want to do now is go back and look at our build and see what we've got here. So here I'd like to explain that an Automator action is a standard Mac OS X bundle. It has the same contents that you'd expect. It's contents, resources.
And we've got a scripts folder here. This action is built using Apple Scripts, though you can use other development languages, which we'll show you during this session. And I want to look in the main.script and, oh, that's a problem. I don't want to ship the source of my action to my users. I need to strip that out.
The problem is I don't have an action to set a new build setting in Xcode, but in fact I will show you how to do that in a moment. So can we go back to slides please? So I showed you a very simple workflow, just three actions, but I've already found a hole in my workflow.
I want to build the projects, but they're not building the way I want, and I don't want to have to go through three. One thing, you could open each up in Xcode manually, add the new build setting, close it again, but for 120, you do not want to do that manually.
But I've now got a hole in my workflow, so how do I fill that in? Well, the easiest way is to just do it right there in Automator. You can add a run script action, which allows you to enter whatever Apple script you need to do what the action needs to do, right there in the interface. And you can use this as an easy way to prototype a new action.
Once you've done that and tested it and seen that it's useful to you, you may then want to turn it into a fully fledged
[Transcript missing]
So before we get to creating stages though, we need to talk a little bit about what is necessary in your application so that you can actually write Automator actions. And first, your application's technology needs to be either or both have a scripting dictionary which allows you to write Apple script-based actions, or APIs which would allow you to create actions using Cocoa.
So the framework for the rest of what you're going to see today is that if you need to make your application scriptable, you need to be familiar with Apple events and if your app is a Cocoa app, Cocoa scripting. But what I'm primarily going to talk about today are Apple Script Studio and Cocoa bindings and Xcode to actually build actions. Now all these technologies have lots of documentation on both the C:/DVD and the Apple website, and there are a number of sessions on all of these topics this week as well.
So with that, I've now promised you to, I'll show you how to fill in that workflow. Can we come back to demo one please? So let's clean things up here. So what we need to do is add a run script action to our workflow. We'll add that in right there, that's where we need it. Let's remove the comment we get. To save you watching me type, I'm just going to drag in this clipping of the code, compile it to format it.
And what we're doing here is we need to tell Xcode to do something, so we're relying on Xcode's scriptability. And all we need Xcode to do is open the projects that we pass in, and then use Xcode Scriptability to add a new build setting to the first target in my project. And what I'm going to do is add a build setting with the key "other_osa" flags and a value "-x". And what this option does when it's passed to OSACompile is strip out the source in the built product. So, let's go ahead and run that workflow.
So Xcode now is opening each project and adding that build setting and then now building the project and we're doing a clean so we remove the version that had the script in there. And here's our build results, and we can search through here to find, to make sure that the option has now been passed to OSA Compile, and there it is. And just to be paranoid, let's go back to Finder and look in our build products and make sure the script is no longer there.
and it's gone. So now this action is safe to send to our customers if we don't want them to see the source. So this is great. I've solved my immediate problem, but it's completely specific to the exact problem I'm trying to solve. You can imagine that you might want to set different build settings and different values at different times. So maybe this would be a useful action to create a fully fledged action.
and you'll see that soon. But before we get to that, we need to talk about the SDK. So what I hope you'll get out of this portion of the session is a better understanding of the various steps that go into building an action. From understanding the way the Xcode project is laid out, to building the user interface in IB, using Cocoa bindings to connect the elements of your user interface to your code.
And the demos we're going to show you today will be shown in both writing the code in AppleScript and Objective-C. And to do that, you need to know about the Automator APIs and public classes. And finally, the info P list that's part of the action is very important. It gives Automator a lot more information about how to present your action to the user.
But wait, there's more. I'll also touch briefly on how you test an Automator action and then how you install it. And finally, some design guidelines analogous to the Apple Human Interface guidelines that we've developed for making actions that will work and feel to users the way that the ones that we create will.
So the project layout, this is-- Actions are built using standard Xcode projects. And again, we've got the two templates today. and depending on which one you choose, you will get either a main script or a header and source file pair. A main.nib to hold your actions user interface if it needs one, it doesn't have to have one. You saw the new text edit document action doesn't have a user interface because there's no options that are necessary.
A description.rtfd which is a textual description of what your action does and that's what appears in the lower left hand corner of the Automator user interface. And finally the Info.plist which I mentioned a moment ago. And instead of telling you more about the rest of the steps in building an action, I'd like to ask Tim Bumgarner from the Automator team to come up and give you a demonstration of creating an action using AppleScript. Please welcome Tim.
Thank you, Todd. So what I'd like to do is we're going to go ahead and we're going to save this and we're going to close it off. We'll reuse that workflow. And we're going to take and replace the run script stage that he created, stage action. We're going to create that and replace that action with something that we create using Apple Script. And as he mentioned, we do have two templates for you. So if you were to go to the file menu of Xcode itself, and after it crashes, lucky me.
Thank heavens for G5s. Okay, so new project. We go to a new project and you'll see that there are two choices and you have to look for them. They're a little further down. They are down in the standard Apple plug-ins. You'll see that there's an AppleScript pipeline stage. This is the project template you'll want to use if you want to create it predominantly using AppleScript.
It doesn't preclude you to adding additional languages, but if you do want to include at least have your main run part of the stage or action be part of that, you'll want to use this template. If you want it to use Objective-C or other C-based languages, you would choose the Cocoa Pipeline stage.
But for our demo purposes, let's go ahead and open up a project that I've got sort of started so we don't have to watch me laboriously drag out user interface items. So I'm going to open up my project. And as he mentioned, it looks very, to those of you that have used AppleScript Studio, very similar. We have a scripts folder here that has our main script. Let me open up an editor window.
And we've got, of course, the other part that's interesting to us is our NIM. So I'm going to go ahead and look at the interface for this action that I'm about to write. And you can see that in his run script, what he did is he took a key and a value and he put it in the build settings of the first target of each project as it came in to the action. So what we're going to do is build this action so it can be used much more in a generic manner. At any time I decide I need to add a new setting or change an existing setting, I could use this action.
And you can see I've got it laid out. I've got the setting. This will be the name of the setting and the value that we might put in. And I've added one additional twist. I can not only choose that I want it for the first target, I can actually have it applied to all the targets that happen to be in that project. But the way that we put this together is that we will use this object you'll see down here in the project window.
This is the parameters object that gets passed to your action from one step to the next. So as your action gets executed, this is what's going to be passed to it. So what we're going to do is we're going to bind. If any of you got to see the Cocoa bindings or are experienced with it, we use Cocoa bindings in nearly all of our actions.
So I'm going to go to the info panel, go to the bindings, and on this first one I'm going to bind it to its value. And I know that I want to call this setting name. Go ahead and hit enter and bind that. I'll go to the value and we'll bind this to setting value.
And on the last one, it's not bound to its value. It's actually going to be bound to its index. We want to know that if it's going to pass an integer in as a parameter. Zero will be for first, one will be for all. So I'll go ahead and type in which target that I want. So everything is pretty well set.
That's all I need to do for the interface. Keeping in mind that this is the portion that's inside of each little action that you see. So we're just responsible as an action writer for the content. Automator takes care of making sure you end up in the right order and passing all the information that you need. So let's go back over and we're now going to edit our script.
And let's make this window a little larger. And you'll see that I have the, the template starts out with a simple on run. This is what gets executed as the stage, as the workflow is going through its process. And what comes in is the input is the output from the previous stage. And then the next thing that comes in is the parameters that the user set up in your UI for your action.
And so what I'm going to do is reuse Todd's little script because it's predominantly very much the same script. We're going to make a couple additions to it. So the first thing I need to do is get some values out of this. And then the second thing I need to do is get some values out of that parameters object. And let's see, we'll do a little one-handed typing here and put in a couple things. So we've got a setting name. We're going to pull that out of the parameters object. Let's check syntax so far.
And we've got the value, and we've got our target, and we coerce it to an integer just to make sure we get it in the format we want. The only thing that's left to do is, the way that the script was originally written was to only apply a fixed value. He was always passing in other OSA flags, and he was passing in a key. And he was always doing it to the first target. So what I want to do is grab this, and I'm going to replace it.
And I'm going to test that which target. If it's zero, that means I want to apply it just to the first target. So it looks very similar to what we just had, except for now I get to pass in the real value, or the value that's passed in our parameter, and also the name.
If I continue on, it says if which target is one, this means all. So I'm going to go through and I'm going to do a little repeat loop for each target in the specified project, and I'm going to do the same thing. I'm going to apply it there.
So let's finish off the rest of this. I'll go ahead and save that. And what I'm going to do is we use a custom executable as setup for you automatically in your template. So when it's time to run, what you can do is edit your argument setting. I'll bring up the inspector.
And you pass in the argument. Currently it's called "dash stage." It'll be "dash action" hopefully. And you just give it in quotes the name of your stage, your built product that you're building. And what we'll do is when I run this, Automator looks for that argument. It's an optional launch argument. And it'll take your built version and use it inside of Automator.
Instead of having to worry about putting it, building it, copying it, to the right location so it can find it. It's much easier to do this. Particularly if you're doing Objective C or Cocoa programming, you can debug these very simply using the same process. So we've got our application. I'm going to go ahead and close that. Go back to our previously saved one.
And what I'm going to do is go ahead and go up here. We're going to delete this, ignore the little artifact. And I'm going to go find the one that I just created. I believe I called it "Set Build Settings." So I'm going to drag this in here. I'll put it in its place where it was before. I'm going to put other OSA flags.
And I'm going to pass that -x. And in this case, instead of just the first, I want to apply it to all. So I think everything looks good. I'll go ahead and build and run. And you'll see if you can right here in the back, it's actually opening each project in Xcode and setting the value.
It's now building those. And if I do the same sort of thing and search for "dash x" or "dash x," you'll see that it is indeed being passed to the OSI compile. So you can see how very simple it is now. I can put whatever build setting I need to apply to that. So it's very simple to take that prototype and wrap it up into a user interface and put it in using AppleScript. Thank you, Todd.
So now you've seen how to create an action using Apple Script. The next thing is to talk about how you create an action using Cocoa. And to do that, we need to discuss briefly the Cocoa APIs. So again, we see the name "Pipeline," but these are in the PipelineEngine.framework, and there are two public classes of interest to developers that want to create Pipeline Automator actions using Cocoa.
PE Stage is the abstract base class, but PE Bundle Stage, which is a subclass of PE Stage, is the stage that you will want to subclass from to create your own actions. and Eric Peiton, another one of our Automator engineers, will come up and show you how to build an action using Cocoa. Thanks, Todd.
So we saw Tim do the whole thing in AppleScript, and it was fast and it was quick and it was easy. It's just as easy to do the same kind of thing in Objective-C. However, instead of repeating what Todd and Tim have both done, I'm going to go ahead and create a different action that does something a little bit different.
What I'd like to do is, one of the things that all of this generates is this big text edit document at the end. Well, 95% of what's in that text edit document is what was successful. Well, you don't really care about what was successful in a build. That's great, fine, wonderful.
What you really are worried about is, what warnings did I get, what errors did I get during my build? So what I'd like to do is, I'd like to create a small action that parses through all that text, finds the warnings and errors, encapsulates that information, creates new text, and passes that to the text edit document that gets created.
And to do that, we're going to use a Cocoa Automator. So, we're going to use a Cocoa Automator action instead of an AppleScript one. Now, as Tim showed, you just go into Project, New, Cocoa Pipeline Stage in the seed and create your action. We'll do the exact same thing, and I'm going to go ahead and start off with a pre-built stage so that you can see it. We can go ahead and close this. We don't need that open right now.
pre-built one called create build report you'll notice it has the executable automator executable already set up for us and all that kind of stuff if you look in here in the classes you'll notice that there's a create build report dot h and a create build report dot m in the dot h you'll notice that it is a pe bundle stage as todd just mentioned in the last slide and in the code you'll notice that it it has a one method run with input from stage error now this method uh is all you really have to have to make one of these things of course you can extend and do as much as you want outside of this but this method is called at runtime when it's your turn to go we pass you the input from the previous stages or previous actions output we pass you who that person was in this case it's called pe stage and we pass you an empty dictionary which you can fill up with your error information that can be passed back then presented to the user if something happens during the flow that you want to return um before we add the code into here we need to go into the nib and do essentially the same thing that Tim did. And everything is managed using bindings.
This saves you the work of managing saving the preferences off. We take care of everything. If everything is bound correctly, there's nothing for you to do. You draw your interface, you hook it up to the bindings, and the parameters object, and you're done. In this case, we have included a checkbox, include warnings in the build report. And what this will allow you to do is if checked, it will show you the actual warnings in the build report instead of just the number of warnings. So we will go ahead and move that, go to the bindings. We will add a value, include warnings.
And we're going to go ahead and and we're done. We'll save off that nib and it's literally just as easy as that. You drop a checkbox, you add it to a binding, you're done. When Todd a little later talks about the InfoP-List, you'll be able to see how these defaults are set for these different bindings and everything for you in our InfoP-List. But for the most part, at this point, your interface is complete.
We'll go back to our code and For expediency's sake, instead of showing you all this code, I will go ahead and just copy and paste it here. And what I've got is I've got a run with input that's already filled out. The intention here is to take that data that is passed to us, coerce it into a string, parse through that string looking for specific tokens, count up the number of warnings and errors, create a new string that we want to show to the user, and then coerce that back into whatever needs to be passed to the next object in the flow.
We'll get a string out of what came in previously, which we call the build report here. It's the input. We go through, we course, we look for certain things that happen to be in the Xcode output. Of course, in your code, you might want to do something far more fancy using reg Xs and stuff like that, but this is just an example. We look for warnings.
We look for errors, we add them all up and create a new string, and then we return, and at the very end, you'll notice here, we return an NSAppleEventDescriptor descriptor with string. Now we're doing this because of something else you're going to learn about later. You declare your data types. In this type, we're saying we're a data blob, and a data blob is defined as our NSAppleEventDescriptor. There's more about this in the SDK, and it's not something that is germane to this exact situation. But let's go ahead and save and build.
and it should finish and run. And you notice when Automator starts here, "I should have a build report stage." So here you can see the build report stage. So let's go ahead and open up our previously built document. And we will... add our Create Build Report at the end of our workflow but before our new TextEdit document. You notice here that it's already automatically checked for us.
You'll see later that You'll see later that the defaults parameters we had set for our bundle have this already set to be on by default. Even though we didn't have to turn it on in the nib, we already read the defaults out of the bindings and set that. One thing we'll also do is we'll go ahead and disable the set build settings. We've already set the build settings in all these projects.
When I disabled it, I checked on the enable/disable box up there in the upper right hand corner of each of the actions. That action will be skipped over in the workflow. It will not execute and it's grayed out and stuff. You notice the little dash there instead of a number letting you know that it's disabled.
I should now be able to save and run this thing. What it will do is it will clean and build all my projects. It will create a build report. There we have our little build report. It threw away all of my projects. It threw away all the stuff we didn't care about. It left us with the total warnings, one, and a copy of the warnings, unused variable, unused variable. We don't write code with warnings, so we had to actually insert one. For your sake, of course. That's my demo. Back to you, Todd.
Thank you very much, Eric. I just wanted to underline two points that Eric made, but to make sure you get this. If you saw, there was no script smart group in Xcode there. There's no Apple script there at all. Now, we love Apple script, but if you prefer to work in Cocoa, that's great.
You can do that to create your Automator actions. The other thing to mention is that we've been showing Cocoa Bindings exclusively for managing the Actions User Interface. But in fact, you can use what you used in Cocoa before Cocoa Bindings existed, or you can use AppleScript Studio also, if you already know that technology.
So we've already made several references to the Info.plist of your action. And what I'd like to do now is give you a little roadmap for which keys are there and what they're used for. So there are four kind of basic keys. These are all strings, and they're reflected in various ways in the Automator user interface.
PL application is the first one, and this is used to specify which application that your action uses to do its work. And you can use that to search to find actions. PL category is again a string and you can use one of ours that are shown in the user interface or you can create your own which can be used by users to do searches for your actions.
PLIcon is used for the icon that appears next to the action's name in the filtered actions list. NPL name is used for both searches as well as for displaying the action in the filtered action list as you see on the screenshot. So let's get into one of the keys that's a little bit more complex and interesting. The accepts and provides dictionaries are the actions way of telling Automator what kinds of valid input it can handle, as well as what kind of output it provides.
So both of these dictionaries contain a types array which allows you to specify one or more type identifier strings, which I'll get to in a moment, again to tell Automator what kinds of data it handles. The accepts dictionary includes an additional key, an optional boolean, which tells Automator whether or not your action requires input to do its work. Some actions don't need any input to do what they're going to do, and you can tell Automator that in the accepts optional boolean. That will allow Automator to tell users whether or not a particular action can be used to start a workflow, for example.
So type identifiers. They're loosely based on Apple's uniform type identifiers. These are just a few examples, the first being the most general type that is the default that you will get when you create a new action project. And the, I guess we don't actually have it up there, but public.data is the type that is returned by the Create Build Report action that Eric just built. But this just gives you kind of a flavor. The complete list of current type identifiers is in the release notes on the seed DVD.
So a few more guidelines on accepts and provides dictionaries. You really want to keep in mind that the more other actions that your action works with, the more useful it's going to be to users. So you should really think about how interoperable it will be based on the types that you support. You should make the accepts and provides types as specific as you can. That gives Automator the maximum guidance so that it can provide guidance to users on which actions are appropriate to go next in the workflow they're building.
I've alluded to this, that the types is an array that you can specify multiple types, and you should definitely do that if your action can handle them. We have several actions in the seed that can handle multiple types such as iPhoto photos and albums. It can by itself extract the photos from an album that's passed in.
If your action doesn't need any input to do what it's going to do, for example, our log output action, which just allows you to see what the input from the previous action is in the workflow, you should just return the input you're given as the output and leave the types general, which is the default.
So, yet another kind of side issue here is that when you create actions for your own applications, your applications have different types than say iPhoto does, so you may want to create your own type identifier strings. And you can definitely do that. What you might want to do in addition, if you do that, is to create conversion actions.
And what conversion actions are, are to link actions whose types don't directly match. For example, in Sal's demo yesterday, you saw that he had an import images into iPhoto action, which returns iPhoto photo objects, and that as the input for the create new IVD slideshow action, which expects files. Now, why did that work? Because the IVD action doesn't know anything about iPhoto photos. Well, what happened is that we have a conversion action from iPhoto photos to files.
And the neat thing here is that, as you saw, there was no extra action inserted there. Automator automatically detected the need for it, but it invisibly adds it to the workflow, so the user needs to know neither that it's necessary or that it's there. And you can add these for the new types that you create.
One last detail there that's on the slide, which you can obviously read, but these are built exactly like any other Automator action. The only difference is once you build it, you need to change the extension of the bundle from .stage to .cstage. So the next key I'd like to talk about, and Eric mentioned this already, the PL default parameters.
This key is used to hold default values for the values that you're managing using Cocoa bindings. And this is why the checkbox that Eric added to the user interface was checked when we launched the action because we had a PL default parameter in there to set the value of the checkbox to true. and these are just based on the types for what the user interface element needs. These are just a few examples.
So I showed you the keyword interface in the first demo. This is an array of keywords. You can specify as many keywords as you like, and you can use the ones that we've created, which you can see in the interface, as well as create your own. Again, users can still search for keywords that don't appear in the keyword interface.
PL Required Resources is a little more complicated, but it's very useful. If your action needs some resource to be installed on the user's system for it to work properly, this allows you to tell Automator, "Hey, I need this thing or I can't work, so let the user know that I'm not going to work." There are three ways to do this. The first is shown here on the screen. You specify the type "application," and then you can specify the application's resource by its bundle ID, its display name, which is what's shown in Finder, and its version.
The warning screen shot shows what the user will see if they try to add such an action without that resource being present on the system. There are two additional ways to specify this. You can also specify it by creator code, and you just change the type from application to creator code, and then specify the creator code as the resource string. And finally, if it's not an application that you need on the system for this to work, it's some other file or folder of some sort, you can do that as well by specifying a required resource of type file and specifying the full path as the resource.
Now this I also showed in my first demo today. If you add an action that can lose data from what's passed into it, you need to tell Automator that with this PL warning key and the user will see a warning as shown here and as you saw earlier.
What you can do is propose a new action to be added before your action that will make the workflow safe. And that's what I did in my demo when I was going to scale images. Another example of crop images, you obviously could lose data from what's input. That would be a level 2. Level 1, we're using for reversible changes. For example, flipping an image. You can always flip it again to get back the original. And you can also specify exactly the way that warning will look, the message, the action that's proposed if necessary, and the button labels as well.
So those are the major steps in creating an Automator action. Now I'd like to just talk briefly about, well, OK, I've created this thing in Xcode. Now how do I make sure it works properly? Well, we've shown you this already. What you can do is add a custom executable to your action project, and with the seed, it will need to be a pipeline custom executable.
Add a launch argument, "dash stage" and then pass the project name "dot stage". And what this does is it passes that argument to pipeline when it runs and it will appear as if your action is already loaded in pipeline. This makes the development cycle much more efficient and very much like what you would be used to from building a normal application.
So once you've got Automator running and your new action is there, you need to test it in the context of a workflow. And when testing workflows, what you can do is use the log output action, which I've already mentioned, and you can add that in between each action that you want to see the input going into the next one to verify that your action is working properly.
If you also want to be able to pause or cancel the workflow at any step in there, you can add another action which is on your seed, confirmation dialog. And if you add this pair of actions between every action in your workflow, you can actually step through each step of the way, seeing the output as it goes into the input of the next stage.
So where do actions live? Well, the actions that we provide are in System Library Pipeline currently, and that again will obviously change. When you build your own actions, it depends on whether you want them to be available on a per user or a per machine basis, and you can then install them in the proper library folder.
So now that we've talked about from the beginning to end of building your action, I'd like to kind of back up and get you to think about some of the guidelines that you should think about as you're laying out your interface and even thinking about what should your action do.
So why do we need design guidelines? Well, we want to help you to achieve a consistent look and feel with every other action out there, both that we create and that your colleagues will create. We encourage you to use our actions as examples. You can see all of their user interfaces and how they operate, obviously, in workflows.
And we will ship as many examples as we can with the actual project source. The materials that you can download from connect.apple.com for this session include three example projects of actions that we've created. and the draft guidelines which cover a little bit more than what I'm going to talk about today are in your release notes on the Seed DVD.
So first, a little bit of philosophy about how we think about actions. We think that you really should try to keep them as small and discreet as possible. Keep separate actions separate. The better way to combine two different tasks is to combine two different actions in a workflow, not to kind of cram them together into one large, complex, single action. That's going to be both harder for users to understand what it does and to configure, and also it will probably make it less likely to be interoperable with other actions. So again, the overriding goal here is to keep it simple.
So a little bit about naming actions. We encourage you to use longer, more descriptive names. As you've seen in the filtered action list, there's quite a bit of real estate there for you to use a longer name. For example, "Add attachments to front mail message." That gives a very good description when a user's looking through the list. Is this really what I'm looking for? Do use plural objects. Actions should handle multiple objects.
It may be that you're only past one, but you should not have an action that only accepts one object. In that case, the name should match. The only time you should use a singular object is if the action accepts only a single object to multiple other objects. An example here is we've got a series of actions to change file names.
In the "Add date to file names" action, there's a single date that gets added to each file name. In that case, the date would be singular. Finally, don't use "s" in parentheses to indicate that your action handles one or more objects. Every action should handle multiple objects, so you don't need to let people know that it handles both one or more.
Again, in the interest of keeping it simple, you should minimize the use of boxes. There's one specific example I'll come onto in a moment where a box is a good idea, but you should try to keep it to a minimum. Your user interface should be as small and clean as possible. If you've got too many things that need separate boxes, you may want to think about splitting it up into multiple actions.
And as you've seen, we've got kind of more width and depth in the workflow area, so you want to minimize the use of vertical space. One good way to do that is avoid radio buttons and use pop-up menus instead, even for as little as two choices, because the pop-up menu is going to use less vertical space.
More on keeping it simple, you should avoid tab views. Again, this is a pretty good sign that your action is getting too complicated if you need a tab view. Again, there's an exception that we will have in one of the actions that we've created, crop images. When cropping images, you might want to crop by dimensions or by percentages, and as you can see in the screenshots, those two different types of cropping require very different user interfaces. And instead of having them both there in the action, one way to avoid that problem is to use a hidden tab view, and then when the user makes the top level choice, you can swap to the proper interface and keep things simple.
Another thing that will give users a lot of guidance is to provide feedback. And again, one example of that are progress indicators. We've got an action called "Create Events for People" that needs to populate a pop-up menu with the iCal calendars that the user already has on their system.
So when the user adds the action to the workflow, we need to ask iCal for those calendars to populate the pop-up menu. So there's a little progress indicator that lets the user know, "Hey, wait a second. Before you start trying to configure this action, I need to do something." Another way to provide feedback is to give the user an example of what actually the action is going to do to their data.
And there are two good examples here. This could be textually or graphically. The "Flip Images" action does it very well graphically by giving you an example image and then what it will look like after the action is through. And for the "Make Sequential File Names" action, down in the lower left hand corner, it gives you exactly what the resulting file names will look like based on the configuration that the user has chosen.
In that case, you should put these examples inside a box, this is the one exception, labeled "Example" and use the same font size and color that you've used in the rest of your user interface so it's not glaring. It's there for the user to find but not necessarily in their face.
So a little more guidelines about the guidance on the layout of your user interface. We do use 10 pixel margins around the outside of your Actions user interface. As Tim mentioned during his demo, you only have control over that piece of the user interface. Automator itself then needs to add around it the title bar and the other pieces that you've seen in the workflow area. And by using a consistent margin around the interface you control, that allows us to do a better job of making your Action look good when a user adds it to a workflow.
Use small controls and small text within the interface. Again, this helps to keep things, use little space so that users can fit more actions in the visible area in their workflow. Unless, of course, you've got one of our great new 30-inch displays, in which case that's really not relevant anymore.
And we encourage you again to follow the Apple Human Interface Guidelines wherever possible. One thing to avoid, and we've confessed here, this one is still in your seat and hasn't been cleaned up yet, but don't repeat what's in the title in the user interface that you create. That just, again, wastes space. The user can read the title and understand that this is about changing the case of file names.
Finally, one thing that many actions need to do is ask the user for a location to either save a file or find a file or folder. And we'd like to standardize this across actions so users know what to expect. This gives you an idea of what that should look like. A pop-up menu with standard locations as well as three additional options. A "Choose" option, which allows a user to choose another arbitrary folder on their system.
A "Prompt User" which, as Sal showed in his demo yesterday, will allow the, when the workflow is executed, will then prompt the user that's running it to enter the selection at that time. And finally, a "Temporary Items" option, which means that this is for files that are only needed during the context of the workflow and then will be removed by Automator at the end of the workflow execution.
And what we will do to help you standardize this is we will provide a widget in a pipeline IB palette, well it will be called an Automator IB palette when you see it, that you can just drag out into your user interface and it will be configured properly to meet the guidelines. This is not in the seed yet, but we will give this to you.
So to sum up, I hope that you've learned and understand much better what Automator is, why it's important to you, and how you can develop for Automator using your application's technology. We really want users to be able to use Automator to automate all sorts of interesting tasks on Mac OS X, and the more applications that have actions, the easier it will be for them to do that.
So you have a few actions items, as it were. Make your application scriptable if it is not, so that you and your customers can create actions using AppleScript. To create a set of APIs that you can use or your customers can use to create actions using Cocoa. And to create a great set of actions that make your application look good and allow customers to incorporate it into their automated workflows, and therefore you've got a customer for life.
So we have some hours when the Automator team will be available to speak with you to answer any questions you may have this afternoon in the Mac OS X labs and tomorrow morning. There's not a lot of documentation yet available. There are release notes on your C:/DVD and updated release notes in the materials for this session, as well as a tutorial and the sample code I mentioned earlier.
[Transcript missing]