REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 072

DoRbScript: Part II

Last time I explained what RbScript was and showed how to create a simple dynamic plugin system for your program using RbScript.

But some of you may be wondering how that differs from using AppleScripts. Before we get to our project, DoRbScript, let's take a quick look at the differences between AppleScripts and RbScripts.

AppleScript versus RbScript

AppleScript is a language invented by Apple that is designed to communicate with programs via Apple Events. (Apple Events are an inter-application messaging system Apple created: a standardized way of different programs talking to each other.) AppleScripts have their own syntax, and that syntax can be expanded as each program can add its own verbs and nouns to the language. (The vocabulary of each program is called its Dictionary. More on that in a bit.)

This expandable nature of AppleScript makes it flexible and powerful, but it also makes it frustrating, since different programs can react differently to the same commands. For instance, one program may like the phrase "third word of the sixth paragraph of the first document" while another will generate an error. Once you're familiar with the way a particular program wants its AppleScript it can be great, but getting there can be a challenge.

REALbasic has decent support for AppleScript in that you can drag any AppleScript into your project window to add that script as a new REALbasic command. You can even pass information back and forth, though not as interactively as with an RbScript.

The biggest disadvantage of an AppleScript is that the only way to add to REALbasic is to drag one into your project file: there's no way to add a new script while your program is running. (Theoretically there are some workarounds to this, as there are OS calls to tell the System to compile an AppleScript, so you could use Declare statements to pass a fresh script to the OS, but I don't know if anyone's actually done that, and at any rate, it sounds fragile and complicated.)

You can, however, execute compiled AppleScripts -- these are often called "applets" and are small applications. You can run them with the folderItem.launch command. So if you make your program scriptable, it would be possible to have a Scripts menu that dynamically adds AppleScripts from a particular folder, and the user could add or remove such scripts at will. That would end up being very similar to what we did last time.

For most Mac users, the AppleScript approach makes more sense, since AppleScript is a standard and many people are used to it. However, since RbScripts are written in the REALbasic language, you may be more comfortable using it instead of having to learn AppleScript.

Also, making your application scriptable is no simple task. Depending on what your program does, making it scriptable could mean supporting dozens or even several hundred AppleScript commands. Some AppleScript support may not be possible due to limitations in how REALbasic handles Apple Events. If you go the RbScript route, you don't have to worry about those problems (but of course your users may not want to learn RbScript just to expand your app).

The bottom line is either approach can give you ways for other people to externally script your program: which approach you take is up to you.

The DoRBScript Project

The project we're going to create this time is unusual in that it will make use of both AppleScript and RbScript. In short, we're going to create a faceless scriptable program that will execute RbScripts and return the result.

To do this will involve several steps:

  1. Create the AppleScript "dictionary" for our app
  2. Create the app and handle the Apple Events sent to it
  3. Create an AppleScript to test the program

Creating the "aete" Resource

Our first step involves creating a "dictionary" of AppleScript terms our program understands. Normally this is a complex step. However, DoRBScript is a relatively simple program: it just does one thing (process an RbScript). So our dictionary only needs one command.

A program's AppleScript dictionary is stored in a special resource of type "aete" (note that it's lower case). Normally you edit resources in a program like Apple's ResEdit; however, it does not support editing aete resources out of the box (there are enhancements to ResEdit to allow it to edit aete resources, but they're unsupported and not ideal).

You could shell out $256 for Resorcerer, a sort of super-ResEdit which does everything (including aete editing). But if you'd prefer to go the cheap route, download the free EightyRez. EightyRez doesn't edit anything but aete resources, so it's not a general resource editor, but for aete resources it's pretty good. It's also only available in a Classic (Mac OS) version. But since you generally aren't editing aete resources every day, it's a good substitute until you can afford Resorcerer. For our example we'll use EightyRez.

EightyRez definitely has a "minimal" interface. Launch it and select "New" from the file menu. This will create a window like this:

I have no idea what any of these things mean. Just kidding!

Seriously, editing an aete resources can get really complicated and it's far too much to detail here. There are several good references on how to do make your app scriptable, including Matt Neuburg's book and REALbasic Developer magazine has a regular AppleScript column which covers stuff like this.

What we're going to do today is add a verb to our dictionary. To do that, we select the "Events" line and choose "New Event" from the edit menu. That brings up a blank window which we'll fill in like this:

What this is saying is that the command we are adding has an id (a four-character string) of "dorb" and belongs to the "misc" class of commands. The name of the command is "DoRBScript" -- that's the command we'll use in our AppleScript.

The "Description" and "Reply desc" fields are just comments -- they don't effect how the command works. But the "Reply type" and "Direct param Type" fields must be set to TEXT. That's telling AppleScript that the "DoRBScript" command requires a string as a parameter and that it returns a string. That's critical, because otherwise AppleScript doesn't know how the command works.

When you're done with this, save it. I named mine "dorbscript (aete 0)" but it doesn't really matter what you name it.

Remember, whatever's in your aete resource is what AppleScript calls your program's Dictionary. Try looking at the aete resources of programs you have installed on your computer (do not edit them, just look). For instance, the Tex-Edit word processor is known for having excellent scripting capability. When we look at it within EightyRez, we see this:

A specific command in EightyRez looks like this:

When we launch Script Editor and use the Open Dictionary command to look at Tex-Edit, we see a help file that looks strangely familiar:

See the relationship between aete and the Dictionary? It's much easier to read in the Dictionary window, but the basic info is the same as when we were editing the aete resource.

I've already created the full aete file used in the DoRBScript project, which you can download here.

Next Week

We create the scriptable DoRBScript application.

News

Were you interested in REALbasic Developer magazine but hesitant to purchase a full year's subscription? Guess what: you can now order copies of individual issues via our new Back Issues form!

It's a great way to try out an issue or two and see if you like it, or pick up an issue you missed because you subscribed late. Just follow this link to order a back issue: http://www.rbdeveloper.com/backissues.

Letters

This week we've got some questions from Tansu Onturk. He writes:

Dear Marc Zeedar:

I am a graphic designer who is also interested in writing some small, useful programs with RB. I am not a programmer but I can understand the lessons and examples in your tutorials when I read. I am reading your tutorials about RB at RealBasic University web page and please let me say that how useful your tutorials are for someone who does not have a background in programming like me. I really would like to say thank you for preparing that source pages.

I am writing this e-mail because I have some questions that I would like to ask to you. First one is, I am now trying to write a Download Manager program (Actuall I am just struggling to do it) but I am stuck. How can I make my programme to understand the changes happened in ListBox like adding a new item or deleting one or modifying the item (I mean modifying the text inside the item) and then make the FileSave enable according to that changes? I actually can able to save my ListBox with it's items by using CreateBinary Method (it opens a SaveDialog window and creates a file that I defined at RB FileTypes window when I click Save), however, I could not able to overwrite to it. So, my second question is, (as you guessed) How can I manage to overwrite several times on my file when I create one? (I mean I do not always want to see a SaveDialog window when I want to save right on my created file)

Thirdly, I have also a project to write a game engine (If I can finish my Download Manager first, of course). So, Is It possible to write a game engine with RB? Can I find a tutorial like yours or something like that to make it happen?

And finally, can I sometimes send e-mails to ask some question/s and/or to ask your assistance/s if you are not busy?

As a result, I know I have had lots of questions here but please forgive me about that. I am just a curious cat. So I would be grateful if you answer all of my questions. Thank's a lot.

Best Regards, Tansu Onturk

PS: My programme consists of one Main window and a ListBox on it in which all things are taking place such as adding a new text, deleting a text, etc. and of course divided into 3 columns (Name, Status and Time). If you need to see all the codes in my project to figure out whats going on, I can also send it through to you.

Wow, that's a lot of questions! But as a fellow graphic designer, I know what a challenge it is learning a new task like programming. Let me tackle a few of these questions and see what we can figure out.

If I understand your first problem correctly, you've got two key issues:

  1. Detecting events inside a listBox (so that you can enable/disable a "file save" button)
  2. Overwriting an existing binary file without having the Save As dialog each time

Both of these are fairly easy, though the first is a little more difficult to explain without seeing your exact code. What I'll do, though, is create my own example and hopefully you can learn enough from that to figure out how to modify your own code to work the same way.

So, we've got a ListBox and we want a "file save" button to change state (enabled or disabled) according to what happens in the ListBox. My example doesn't actually save anything, but it does toggle fileSaveButton:

This works by putting in this code in the CellAction event of listBox1:

  
if column = 1 then
// User edited the cell: update the button
fileSaveButton.enabled = true
label.text = "File not saved yet."
end if

In my example, the second column (column 1) is set to be inline editable. When the user clicks inside the cell to edit it, we assume they've made a change and enable the file save button.

Note that word "assume" -- we aren't bothering to check to see if the user actually changed any data, though we could: we'd have to compare the current value to the previous value, which we'd have had to have saved elsewhere. If the values are different, we know the user changed something, and then could set the fileSaveButton state.

Also, in a real program, you'd probably want to call a method here and not directly modify the button. That's because you probably will want to do several things, like set a flag for the "Save" menu item, and set the window's close box to "dirty" (under Mac OS X).

In Detail

In Mac OS X, the red close box (though it's now a circle, not a box ;-) has a dot in it when the current document has been modified and not saved:

This is a very useful feature, but you can't access it directly from REALbasic. You need to download the free Carbon Declare Library which includes tons of handy Mac OS X system calls, including SetWindowModified, which will mark the passed window's close widget as dirty (unsaved).

You can download this example program here.

The next part of your question, about saving over an existing file, is very simple. You just need to separate your saving system into two methods, not one. The first method is a "save as" method: it sets a folderItem from the Save As dialog. The second method just uses that folderItem and saves to that file.

Note that in these examples, we have this window property: theFile as folderItem.

The SaveAs method:

  
dim f as folderItem

f = getSaveFolderItem("", "The File Name")
if f <> nil then
theFile = f
save(theFile)
end if

Note that if the user hits cancel in the SaveAs routine we never set theFile: that's important if you use this routine as an actual "Save As" command, since you wouldn't want the folderItem of the current document set to nil if the user changed their mind and canceled. So we set their response to the temporary variable f and only set the theFile property if we're sure they've chosen a new file.

The Save method (which takes f as folderItem as a parameter):

  
if f <> nil then

// do your file save stuff here

end if

Now if you're still wondering about how to overwrite the old file, you shouldn't need to worry about that. Presumably you've got your data in memory (it's loaded into the ListBox or wherever you've got it stored) so all you have to do is recreate the file from scratch on disk the way you normally would (using the .CreateTextFile or .CreateBinaryFile methods) and it will write over the old file and save into it the current data.

As to your game engine question, I went to Google and did a search for realbasic "game engine" (note the important quotes) and it came with with hundreds of hits. There are several game engines created in REALbasic, and other game engines that let you create games with REALbasic, so I'd advise you to search around and see if there's a project out there that does something similar.

And feel free to write me, but just don't expect a quick response as I'm very busy. I'll sometimes respond to questions without publishing the letter, but in general I don't like to do that. Publishing your letter and my response helps thousands of people, while a personal response only benefits you.


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband