| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 071
DoRbScript: Part IThis week's project was developed from an unusual question from Naveen:
Most people want to do the opposite of what you're wanting because REALbasic gives you a more powerful programming environment than AppleScript. Therefore most would base their app in REALbasic and use AppleScripts as support tools. What you want is the opposite, which is a little unusual. The good news is that's it's doable, though it might be more complex than you want to bother with. The way you'd go about doing this is to create a scriptable REALbasic program. When you send it a certain command, via an Apple Event in AppleScript, your program would respond accordingly and return the value you want. Even better is to use an RBScript as you suggest. By passing the script to the program, it could compile and run it and return the result to your AppleScript. How do you do this? Well, it's not that difficult. In fact, I wrote a program to do this in just a few minutes! It's called DoRBScript and it's our next project. To do this we'll learn how to make a scriptable application, as well as learning about RbScript.
What is RbScript?Before we begin with DoRBScript, let's explore RbScripts. A few of you may be wondering what RbScript is -- it's not a heavily promoted feature of REALbasic. An RbScript is code in REALbasic syntax. That's convienent, since, presumably, you're already familiar with how to write code REALbasic understands. But the key difference between normal REALbasic code and an RbScript is that an RbScript can be processed and executed by your application while it's running. Normally, when you write code in REALbasic, that code is compiled and translated into machine code and saved as a compiled application on your hard drive. Once it's been converted to machine code, it's no longer in REALbasic syntax format, so it's not easy to change. But what if you wanted to add a way for users (or yourself) to modify your program on the fly? For example, many programs today use "plugins" to expand the capabilities of the program. Plugins are small components that can be added or removed independent of the main program. Programmers like them because it's easier to modify a small plugin than release a whole new edition of a program. Users like them because they can add just the features they need to a program. Sometimes the plugins are written by third parties, or the user themselves. For a REALbasic programmer, a plugin system should allow plugins to be written in REALbasic. That's one of the best uses for RbScript. An RbScript is just code -- if you set up your program to run that code, the user could change that code, add new code, etc., just like a plugin system. Writing code in RbScript is a little different than normal RB programming. Normally in RB your code is located in many places and tied in tight with the app's interface (i.e. code for a pushButton is inside the pushButton). There are also certain REALbasic features that aren't available to RbScripts. In an RbScript, all the code is in that single script. You can still create methods and such, but they aren't in their own method box. The same goes for custom classes: an RbScript doesn't have access to the project window for a custom class object. Also, your code is also separated from any interface objects -- you can't build a window with pushButtons, for instance. These differences can be confusing if you've gotten used to the REALbasic Way of doing things. There are also differences in how you get data to and from an RbScript. Remember, an RbScript doesn't have an interface. But you need some way to pass information between the script and the running program. The solution is two new RbScript events, input and print. In your script, when you want to send info out of your program, you use the print command. That calls the print event of your RbScript object, which the running program can handle. To get data into your script, you include the input command, which triggers the input event of your RbScript object. The input command has a string parameter which you can use to tell the input event what kind of data you're wanting. The input and print commands act as a messaging system between your running program and the RbScript. Here's an example of a very simple RbScript that adds two numbers. Note that the script doesn't know what the numbers are: they come from the running program. The running program could get those numbers from the user, from a data file, or wherever: the script doesn't really care.
Note that because both print and input use strings as their data format, we must convert our results to text or numbers to use them (the val() and str() functions). As an example, I took the above RbScript and placed it inside a simple REALbasic project (download it here). Here's what it looks like running: ![]() The REALbasic program just passes the data in the editFields to the script, and puts the response of the script into the result staticText. For instance, here's the code for the input event:
This returns the appropriate editField text based on which number is being requested (first or second). As you can see, this could support all sorts of different information requests just by changing this parsing routine. The print event just ouputs the result to a staticText called result. result.text = msg Note that we've completely separated what happens to the data by putting it in a separate script. If we wanted to expand this program, we could load the RbScript from a text file: different text files (scripts) could do different things to the data (add, multiply, divide, etc.). In fact, let's do that. I've created a folder of scripts that add, divide, multiple, and subtract the two values. I then added a popupMenu that loads those scripts so the user can choose which script to run from the popup. Here's the Open event of popupMenu1:
First this finds the Scripts folder, then it steps through each file in that folder and attempts to load it as a text file (script). If it's successful (it's a text file), it adds the file's name to popupMenu1. The loadFile routine simply reads in the passed file as a text file:
The most important thing here is I've got a window property called scripts that's an array of string. This routine adds whatever text is read from the file to a new item in the array (the key scripts.append in.readAll line). The advantage of loading stuff into an array in advance is that it's simpler. For instance, when the user chooses a different script from the popup, we do this (this is the Change event of popupMenu1):
All we're doing here is passing the text of the saved script (in the scripts array) to the rbScript1 object. This changes what code rbScript1 will run. Because the index of our scripts array matches the listIndex of popupMenu1, we can just use me.listIndex as the index. One disadvantage of this particular approach is that the contents of the Scripts folder are only loaded when the program is launched: a better approach might be to update the popupMenu whenever the program is moved to the foreground, in case the user added a new script while the program was running. Once the scripts are loaded, the user can choose a script from the popup menu, and when the user clicks the "Go" button, the appropriate script is run: ![]() Very cool! There really isn't any limit to what these scripts can do, either: they could do much more complicated math and you wouldn't have to change the main program at all! However, since the main program only allows for two numbers to be input, and is expected only a little bit of text for the result, you'd most likely need to modify it to support more elaborate scripts. But the basic principle is the same. If you would like the complete REALbasic project file for this second example, including the scripts folder, you may download it here.
Next WeekWe learn how to make an application scriptable!
NewsHuge news last week from REAL Software: the next version of REALbasic will run on Microsoft Windows as well as Macintosh! This will mean that Windows users will be able to create Macintosh applications just as easily as Mac REALbasic users can create Windows apps today. I'd been expecting this to happen eventually, but that this will happen early next year is a surprise. Wondering what this means to you (presumably), a Macintosh user? Primarily it means that REALbasic will be a stronger product. REAL Software is not moving away from the Macintosh at all: this is just going to expand REALbasic's influence by being a truly cross-platform development solution. It should significantly increase sales for REAL Software, which is good for everyone using REALbasic. I also believe this is good for Macintosh: Windows developers, interested in Mac OS X, but reluctant to invest Mac OS X-only Cocoa, will now have a development system that they can use on their familiar Windows platform, which will create apps for Windows, Mac OS, and Mac OS X. This means more Mac programs for everyone. Programs that today are Windows-only will eventually be cross-platform. More Mac developers is awesome for the platform. This move should help everyone, including increasing the readership for REALbasic University and REALbasic Developer magazine. Are you wondering how the Windows version of REALbasic will work? REAL Software has posted a FAQ on their website, but here are the answers to a few key questions: Project files will be cross-platform. If you create a project on the Mac or Windows, you'll be able to move it to the other platform and continue editing it there. Very slick! Platform-specific features will be supported. On the Mac, there'll be many Jaguar-only features, and on Windows, there'll be support for Active X. This is good because apps created for each platform will be full apps, not semi-complete ones that only partially support the platform. Release is scheduled for first quarter 2003. From my talks with REAL Software, it appears REALbasic 5 will be released for the Mac first, quickly followed by the Windows version. Future versions will be released for both platforms simultaneously. This is an exciting announcement for anyone using REALbasic. If you're content just creating Mac applications, this won't effect you at all. But for many people -- including schools who want to teach programming -- this will mean many more REALbasic users and make REALbasic a more practical tool.
LettersNo letters this time. 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 See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
| |||||||||||||||||||||||||||